Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/codert_vm/CodertVMHelpers.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "j9protos.h"
24
#include "jitprotos.h"
25
#include "stackwalk.h"
26
#include "rommeth.h"
27
#include "VMHelpers.hpp"
28
#include "AtomicSupport.hpp"
29
#include "MethodMetaData.h"
30
#include "ut_j9codertvm.h"
31
32
extern "C" {
33
34
/* Until the JIT deletes references to these */
35
void * jitExitInterpreterX = NULL;
36
void * jitExitInterpreterY = NULL;
37
#if defined(J9VM_ENV_CALL_VIA_TABLE)
38
void init_codert_vm_fntbl(J9JavaVM *javaVM) {}
39
#endif /* J9VM_ENV_CALL_VIA_TABLE */
40
41
void
42
initializeDirectJNI(J9JavaVM *vm)
43
{
44
vm->jniSendTarget = J9_BCLOOP_ENCODE_SEND_TARGET(J9_BCLOOP_SEND_TARGET_COUNT_AND_SEND_JNI_NATIVE);
45
}
46
47
#if defined(J9SW_NEEDS_JIT_2_INTERP_THUNKS)
48
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendPatchupVirtual);
49
#else /* J9SW_NEEDS_JIT_2_INTERP_THUNKS */
50
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtual0);
51
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtual1);
52
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualJ);
53
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualF);
54
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualD);
55
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualL);
56
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSync0);
57
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSync1);
58
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncJ);
59
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncF);
60
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncD);
61
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncL);
62
J9_EXTERN_BUILDER_SYMBOL(icallVMprJavaSendNativeVirtual);
63
#endif /* J9SW_NEEDS_JIT_2_INTERP_THUNKS */
64
J9_EXTERN_BUILDER_SYMBOL(jitFillOSRBufferReturn);
65
J9_EXTERN_BUILDER_SYMBOL(returnFromJIT0);
66
J9_EXTERN_BUILDER_SYMBOL(returnFromJIT1);
67
J9_EXTERN_BUILDER_SYMBOL(returnFromJITJ);
68
J9_EXTERN_BUILDER_SYMBOL(returnFromJITF);
69
J9_EXTERN_BUILDER_SYMBOL(returnFromJITD);
70
#if defined(J9VM_ENV_DATA64)
71
J9_EXTERN_BUILDER_SYMBOL(returnFromJITL);
72
#endif /* J9VM_ENV_DATA64 */
73
J9_EXTERN_BUILDER_SYMBOL(returnFromJITConstructor0);
74
J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreter0);
75
J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreter1);
76
J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterJ);
77
J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterF);
78
J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterD);
79
80
static void *i2jReturnTable[16] = {0};
81
82
void *jit2InterpreterSendTargetTable[13] = {0};
83
84
static J9Method* jitGetExceptionCatcher(J9VMThread *currentThread, void *handlerPC, J9JITExceptionTable *metaData, IDATA *location);
85
86
void
87
initializeCodertFunctionTable(J9JavaVM *javaVM)
88
{
89
J9JITConfig *jitConfig = javaVM->jitConfig;
90
jitConfig->i2jReturnTable = (void*)&i2jReturnTable;
91
i2jReturnTable[0] = J9_BUILDER_SYMBOL(returnFromJIT0);
92
i2jReturnTable[1] = J9_BUILDER_SYMBOL(returnFromJIT1);
93
i2jReturnTable[2] = J9_BUILDER_SYMBOL(returnFromJITJ);
94
i2jReturnTable[3] = J9_BUILDER_SYMBOL(returnFromJITF);
95
i2jReturnTable[4] = J9_BUILDER_SYMBOL(returnFromJITD);
96
#if defined(J9VM_ENV_DATA64)
97
i2jReturnTable[5] = J9_BUILDER_SYMBOL(returnFromJITL);
98
#else /* J9VM_ENV_DATA64 */
99
i2jReturnTable[5] = J9_BUILDER_SYMBOL(returnFromJIT1);
100
#endif /* J9VM_ENV_DATA64 */
101
i2jReturnTable[6] = J9_BUILDER_SYMBOL(returnFromJITF);
102
i2jReturnTable[7] = J9_BUILDER_SYMBOL(returnFromJITD);
103
i2jReturnTable[8] = J9_BUILDER_SYMBOL(returnFromJITConstructor0);
104
#if defined(J9SW_NEEDS_JIT_2_INTERP_THUNKS)
105
void *patchupVirtual = J9_BUILDER_SYMBOL(icallVMprJavaSendPatchupVirtual);
106
jitConfig->patchupVirtual = patchupVirtual;
107
for (UDATA i = 0; i < (sizeof(jit2InterpreterSendTargetTable) / sizeof(void*)); ++i) {
108
jit2InterpreterSendTargetTable[i] = patchupVirtual;
109
}
110
#else /* J9SW_NEEDS_JIT_2_INTERP_THUNKS */
111
jit2InterpreterSendTargetTable[0] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtual0);
112
jit2InterpreterSendTargetTable[1] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtual1);
113
jit2InterpreterSendTargetTable[2] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualJ);
114
jit2InterpreterSendTargetTable[3] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualF);
115
jit2InterpreterSendTargetTable[4] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualD);
116
jit2InterpreterSendTargetTable[5] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualL);
117
jit2InterpreterSendTargetTable[6] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSync0);
118
jit2InterpreterSendTargetTable[7] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSync1);
119
jit2InterpreterSendTargetTable[8] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncJ);
120
jit2InterpreterSendTargetTable[9] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncF);
121
jit2InterpreterSendTargetTable[10] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncD);
122
jit2InterpreterSendTargetTable[11] = J9_BUILDER_SYMBOL(icallVMprJavaSendVirtualSyncL);
123
jit2InterpreterSendTargetTable[12] = J9_BUILDER_SYMBOL(icallVMprJavaSendNativeVirtual);
124
#endif /* J9SW_NEEDS_JIT_2_INTERP_THUNKS */
125
jitConfig->j2iInvokeWithArguments = (void*)-1;
126
jitConfig->jitFillOSRBufferReturn = J9_BUILDER_SYMBOL(jitFillOSRBufferReturn);
127
jitConfig->jitExitInterpreter0 = J9_BUILDER_SYMBOL(jitExitInterpreter0);
128
jitConfig->jitExitInterpreter1 = J9_BUILDER_SYMBOL(jitExitInterpreter1);
129
jitConfig->jitExitInterpreterJ = J9_BUILDER_SYMBOL(jitExitInterpreterJ);
130
jitConfig->jitExitInterpreterF = J9_BUILDER_SYMBOL(jitExitInterpreterF);
131
jitConfig->jitExitInterpreterD = J9_BUILDER_SYMBOL(jitExitInterpreterD);
132
jitConfig->i2jTransition = J9_BCLOOP_ENCODE_SEND_TARGET(J9_BCLOOP_SEND_TARGET_I2J_TRANSITION);
133
jitConfig->setUpForDLT = setUpForDLT;
134
jitConfig->i2jMHTransition = (void*)-3;
135
jitConfig->runJITHandler = (void*)-5;
136
jitConfig->performDLT = (void*)-7;
137
jitConfig->jitGetExceptionCatcher = jitGetExceptionCatcher;
138
initPureCFunctionTable(javaVM);
139
}
140
141
#if defined(J9VM_JIT_GC_ON_RESOLVE_SUPPORT)
142
143
static void
144
jitEmptyObjectSlotIterator(J9VMThread *vmThread, J9StackWalkState *walkState, j9object_t *objectSlot, const void *stackLocation)
145
{
146
}
147
148
void
149
jitCheckScavengeOnResolve(J9VMThread *currentThread)
150
{
151
UDATA oldState = currentThread->omrVMThread->vmState;
152
currentThread->omrVMThread->vmState = J9VMSTATE_SNW_STACK_VALIDATE;
153
J9JavaVM *vm = currentThread->javaVM;
154
J9JITConfig *jitConfig = vm->jitConfig;
155
jitConfig->gcCount += 1;
156
if (jitConfig->gcCount >= jitConfig->gcOnResolveThreshold) {
157
if (jitConfig->gcCount == jitConfig->gcOnResolveThreshold) {
158
PORT_ACCESS_FROM_JAVAVM(vm);
159
j9tty_printf(PORTLIB, "\n<JIT: scavenge on resolve enabled gc #%d>", jitConfig->gcCount);
160
}
161
J9StackWalkState walkState;
162
walkState.objectSlotWalkFunction = jitEmptyObjectSlotIterator;
163
walkState.walkThread = currentThread;
164
walkState.flags = J9_STACKWALK_ITERATE_O_SLOTS;
165
vm->walkStackFrames(currentThread, &walkState);
166
}
167
currentThread->omrVMThread->vmState = oldState;
168
}
169
170
#endif /* J9VM_JIT_GC_ON_RESOLVE_SUPPORT */
171
172
void
173
jitMarkMethodReadyForDLT(J9VMThread *currentThread, J9Method *method)
174
{
175
VM_AtomicSupport::bitOr((UDATA*)&method->constantPool, J9_STARTPC_DLT_READY);
176
}
177
178
void
179
jitMethodFailedTranslation(J9VMThread *currentThread, J9Method *method)
180
{
181
J9JITConfig *jitConfig = currentThread->javaVM->jitConfig;
182
if (J9_ARE_NO_BITS_SET(jitConfig->runtimeFlags, J9JIT_TOSS_CODE)) {
183
/* Natives are already set correctly before the translation attempt */
184
if (J9_ARE_NO_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers, J9AccNative)) {
185
method->extra = (void*)(UDATA)(IDATA)J9_JIT_NEVER_TRANSLATE;
186
}
187
}
188
}
189
190
void
191
jitMethodTranslated(J9VMThread *currentThread, J9Method *method, void *jitStartAddress)
192
{
193
J9JavaVM *vm = currentThread->javaVM;
194
J9JITConfig *jitConfig = vm->jitConfig;
195
if (J9_ARE_NO_BITS_SET(jitConfig->runtimeFlags, J9JIT_TOSS_CODE)) {
196
if (jitMethodIsBreakpointed(currentThread, method)) {
197
jitBreakpointedMethodCompiled(currentThread, method, jitStartAddress);
198
}
199
/* Slam in the start PC, which also marks the method as having been translated */
200
method->extra = jitStartAddress;
201
method->methodRunAddress = J9_BCLOOP_ENCODE_SEND_TARGET(J9_BCLOOP_SEND_TARGET_I2J_TRANSITION);
202
/* update vTables for virtual methods */
203
if (J9ROMMETHOD_HAS_VTABLE(J9_ROM_METHOD_FROM_RAM_METHOD(method))) {
204
J9Class *currentClass = J9_CLASS_FROM_METHOD(method);
205
if (J9ROMCLASS_IS_INTERFACE(currentClass->romClass)) {
206
currentClass = J9VMJAVALANGOBJECT_OR_NULL(vm);
207
}
208
UDATA initialClassDepth = VM_VMHelpers::getClassDepth(currentClass);
209
void *j2jAddress = VM_VMHelpers::jitToJitStartAddress(jitStartAddress);
210
do {
211
J9VTableHeader* vTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(currentClass);
212
213
/* get number of real methods in Interpreter vTable */
214
UDATA vTableWriteIndex = vTableHeader->size;
215
if (0 != vTableWriteIndex) {
216
/* initialize pointer to first real vTable method */
217
void **vTableWriteCursor = (void**)JIT_VTABLE_START_ADDRESS(currentClass);
218
J9Method **vTableReadCursor = J9VTABLE_FROM_HEADER(vTableHeader);
219
220
while (0 != vTableWriteIndex) {
221
if (method == *vTableReadCursor) {
222
*vTableWriteCursor = j2jAddress;
223
}
224
vTableReadCursor += 1;
225
vTableWriteCursor -= 1;
226
vTableWriteIndex -= 1;
227
}
228
}
229
currentClass = currentClass->subclassTraversalLink;
230
} while (VM_VMHelpers::getClassDepth(currentClass) > initialClassDepth);
231
}
232
}
233
}
234
235
J9_EXTERN_BUILDER_SYMBOL(jitTranslateNewInstanceMethod);
236
J9_EXTERN_BUILDER_SYMBOL(jitInterpretNewInstanceMethod);
237
238
void*
239
jitNewInstanceMethodStartAddress(J9VMThread *currentThread, J9Class *clazz)
240
{
241
void *addr = NULL;
242
addr = (void*)clazz->romableAotITable;
243
if (addr == J9_BUILDER_SYMBOL(jitTranslateNewInstanceMethod)) {
244
addr = NULL;
245
}
246
return addr;
247
}
248
249
void
250
jitNewInstanceMethodTranslated(J9VMThread *currentThread, J9Class *clazz, void *jitStartAddress)
251
{
252
clazz->romableAotITable = (UDATA)VM_VMHelpers::jitToJitStartAddress(jitStartAddress);
253
}
254
255
void
256
jitNewInstanceMethodTranslateFailed(J9VMThread *currentThread, J9Class *clazz)
257
{
258
clazz->romableAotITable = (UDATA)J9_BUILDER_SYMBOL(jitInterpretNewInstanceMethod);
259
}
260
261
UDATA
262
jitTranslateMethod(J9VMThread *currentThread, J9Method *method)
263
{
264
UDATA oldState = currentThread->omrVMThread->vmState;
265
currentThread->omrVMThread->vmState = J9VMSTATE_JIT;
266
J9JavaVM *vm = currentThread->javaVM;
267
J9JITConfig *jitConfig = vm->jitConfig;
268
UDATA jitStartPC = jitConfig->entryPoint(jitConfig, currentThread, method, 0);
269
currentThread->omrVMThread->vmState = oldState;
270
return jitStartPC;
271
}
272
273
UDATA
274
jitUpdateCount(J9VMThread *currentThread, J9Method *method, UDATA oldCount, UDATA newCount)
275
{
276
return oldCount == VM_AtomicSupport::lockCompareExchange((UDATA*)&method->extra, oldCount, newCount);
277
}
278
279
typedef void (*overrideCallback)(J9VMThread*, UDATA, J9Method*, J9Method*);
280
281
void
282
jitUpdateInlineAttribute(J9VMThread *currentThread, J9Class * classPtr, void *jitCallBack)
283
{
284
/* Do not walk interface classes */
285
if (J9_ARE_NO_BITS_SET(classPtr->romClass->modifiers, J9AccInterface)) {
286
J9Class *superclass = VM_VMHelpers::getSuperclass(classPtr);
287
/* Methods in Object never override anything */
288
if (NULL != superclass) {
289
/* Skip the count field and the first method in the table (not a real method) */
290
J9VTableHeader *superVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(superclass);
291
UDATA methodCount = superVTableHeader->size;
292
J9Method **superMethods = J9VTABLE_FROM_HEADER(superVTableHeader);
293
J9Method **subMethods = J9VTABLE_FROM_RAM_CLASS(classPtr);
294
/* Walk all methods which could possibly be overridden */
295
while (0 != methodCount) {
296
J9Method *superMethod = *superMethods;
297
J9Method *subMethod = *subMethods;
298
/* If the subclass method is different from the superclass method, this is an override */
299
if (superMethod != subMethod) {
300
if (NULL != jitCallBack) {
301
((overrideCallback)jitCallBack)(currentThread, 0, superMethod, subMethod);
302
}
303
/* Mark the super method as overridden */
304
VM_AtomicSupport::bitOr((UDATA*)superMethod->constantPool, J9_STARTPC_METHOD_IS_OVERRIDDEN);
305
}
306
superMethods += 1;
307
subMethods += 1;
308
methodCount -= 1;
309
}
310
311
}
312
}
313
}
314
315
static J9Method*
316
jitGetExceptionCatcher(J9VMThread *currentThread, void *handlerPC, J9JITExceptionTable *metaData, IDATA *location)
317
{
318
J9Method *method = metaData->ramMethod;
319
void *stackMap = NULL;
320
void *inlineMap = NULL;
321
void *inlinedCallSite = NULL;
322
/* Note we need to add 1 to the JIT PC here in order to get the correct map at the exception handler
323
* because jitGetMapsFromPC is expecting a return address, so it subtracts 1. The value passed in is
324
* the start address of the compiled exception handler.
325
*/
326
jitGetMapsFromPC(currentThread, currentThread->javaVM, metaData, (UDATA)handlerPC + 1, &stackMap, &inlineMap);
327
Assert_CodertVM_false(NULL == inlineMap);
328
if (NULL != getJitInlinedCallInfo(metaData)) {
329
inlinedCallSite = getFirstInlinedCallSite(metaData, inlineMap);
330
if (NULL != inlinedCallSite) {
331
method = (J9Method*)getInlinedMethod(inlinedCallSite);
332
}
333
}
334
*location = (IDATA)getCurrentByteCodeIndexAndIsSameReceiver(metaData, inlineMap, inlinedCallSite, NULL);
335
return method;
336
}
337
338
} /* extern "C" */
339
340