-
Notifications
You must be signed in to change notification settings - Fork 746
/
Copy pathFastJNI_java_lang_Throwable.cpp
130 lines (124 loc) · 5.74 KB
/
FastJNI_java_lang_Throwable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*******************************************************************************
* Copyright IBM Corp. and others 2001
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#include "fastJNI.h"
#include "j9protos.h"
#include "j9consts.h"
#include "j9jclnls.h"
#include "objhelp.h"
#include "VMHelpers.hpp"
#include "ObjectAllocationAPI.hpp"
#include "ObjectAccessBarrierAPI.hpp"
extern "C" {
/* java.lang.Throwable: public native Throwable fillInStackTrace(); */
j9object_t JNICALL
Fast_java_lang_Throwable_fillInStackTrace(J9VMThread *currentThread, j9object_t receiver)
{
J9JavaVM *vm = currentThread->javaVM;
/* Don't fill in stack traces if -XX:-StackTraceInThrowable is in effect */
if (0 == (vm->runtimeFlags & J9_RUNTIME_OMIT_STACK_TRACES)) {
MM_ObjectAllocationAPI objectAllocate(currentThread);
MM_ObjectAccessBarrierAPI objectAccessBarrier(currentThread);
/* If the disableWritableStackTrace field is set to false,
* continue filling in the stack trace.
*/
if (!J9VMJAVALANGTHROWABLE_DISABLEWRITABLESTACKTRACE(currentThread, receiver)) {
j9object_t walkback = (j9object_t)J9VMJAVALANGTHROWABLE_WALKBACK(currentThread, receiver);
J9StackWalkState *walkState = currentThread->stackWalkState;
UDATA walkFlags = J9_STACKWALK_CACHE_PCS | J9_STACKWALK_WALK_TRANSLATE_PC |
J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_SKIP_INLINES;
/* Do not hide exception frames if fillInStackTrace is called on an exception which already
* has a stack trace. In the out of memory case, there is a bit indicating that we should
* explicitly override this behaviour, since we've precached the stack trace array.
*/
if ((NULL == walkback) || (currentThread->privateFlags & J9_PRIVATE_FLAGS_FILL_EXISTING_TRACE)) {
walkFlags |= J9_STACKWALK_HIDE_EXCEPTION_FRAMES;
walkState->restartException = receiver;
}
walkState->flags = walkFlags;
walkState->skipCount = 1; /* skip the INL frame */
#if JAVA_SPEC_VERSION >= 15
J9Class *receiverClass = J9OBJECT_CLAZZ(currentThread, receiver);
if (J9VMJAVALANGNULLPOINTEREXCEPTION_OR_NULL(vm) == receiverClass) {
walkState->skipCount = 2; /* skip the INL & NullPointerException.fillInStackTrace() frames */
}
#endif /* JAVA_SPEC_VERSION >= 15 */
walkState->walkThread = currentThread;
UDATA walkRC = vm->walkStackFrames(currentThread, walkState);
UDATA framesWalked = walkState->framesWalked;
UDATA *cachePointer = walkState->cache;
if (J9_STACKWALK_RC_NONE != walkRC) {
/* Avoid infinite recursion if already throwing OOM */
if (currentThread->privateFlags & J9_PRIVATE_FLAGS_OUT_OF_MEMORY) {
goto recursiveOOM;
}
setNativeOutOfMemoryError(currentThread, J9NLS_JCL_FAILED_TO_CREATE_STACK_TRACE);
goto done;
}
/* If there is no stack trace in the exception, or we are not in the out of memory case,
* allocate a new stack trace. The cached receiver object is invalid after this point.
*/
if ((NULL == walkback) || (0 == (currentThread->privateFlags & J9_PRIVATE_FLAGS_FILL_EXISTING_TRACE))) {
#if defined(J9VM_ENV_DATA64)
J9Class *arrayClass = vm->longArrayClass;
#else
J9Class *arrayClass = vm->intArrayClass;
#endif
walkback = objectAllocate.inlineAllocateIndexableObject(currentThread, arrayClass, (U_32)framesWalked, false);
if (NULL == walkback) {
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, receiver);
walkback = vm->memoryManagerFunctions->J9AllocateIndexableObject(currentThread, arrayClass, (U_32)framesWalked, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
receiver = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
if (J9_UNEXPECTED(NULL == walkback)) {
setHeapOutOfMemoryError(currentThread);
goto done;
}
}
} else {
/* Using existing array - be sure not to overrun it */
UDATA maxSize = J9INDEXABLEOBJECT_SIZE(currentThread, walkback);
if (framesWalked > maxSize) {
framesWalked = maxSize;
}
}
for (UDATA i = 0; i < framesWalked; ++i) {
#if defined(J9VM_ENV_DATA64)
objectAccessBarrier.inlineIndexableObjectStoreI64(currentThread, walkback, i, cachePointer[i]);
#else
objectAccessBarrier.inlineIndexableObjectStoreI32(currentThread, walkback, i, cachePointer[i]);
#endif
}
freeStackWalkCaches(currentThread, walkState);
recursiveOOM:
J9VMJAVALANGTHROWABLE_SET_WALKBACK(currentThread, receiver, walkback);
J9VMJAVALANGTHROWABLE_SET_STACKTRACE(currentThread, receiver, NULL);
}
}
done:
return receiver;
}
J9_FAST_JNI_METHOD_TABLE(java_lang_Throwable)
#if !defined(J9ZOS390) // TODO - retest to see if ZOS compiler bug is gone now
J9_FAST_JNI_METHOD("fillInStackTrace", "()Ljava/lang/Throwable;", Fast_java_lang_Throwable_fillInStackTrace,
J9_FAST_JNI_RETAIN_VM_ACCESS | J9_FAST_JNI_DO_NOT_WRAP_OBJECTS)
#endif
J9_FAST_JNI_METHOD_TABLE_END
}