Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/codert_vm/dlt.c
5986 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 2020 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
#include <string.h>
23
#include "j9.h"
24
#include "jitprotos.h"
25
#include "rommeth.h"
26
#include "stackwalk.h"
27
#include "ut_j9codertvm.h"
28
29
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
30
31
static UDATA
32
dltIterator(J9VMThread * currentThread, J9StackWalkState * walkState)
33
{
34
if (walkState->framesWalked == 2) {
35
walkState->userData1 = walkState->unwindSP;
36
walkState->userData2 = walkState->arg0EA;
37
walkState->userData3 = walkState->method;
38
}
39
40
return J9_STACKWALK_KEEP_ITERATING;
41
}
42
43
44
void *
45
setUpForDLT(J9VMThread * currentThread, J9StackWalkState * walkState)
46
{
47
J9JavaVM * vm = currentThread->javaVM;
48
J9DLTInformationBlock * dltBlock = &(currentThread->dltBlock);
49
UDATA * onStackTemps;
50
UDATA * copiedTemps;
51
void * dltEntry;
52
void * currentFrame;
53
UDATA * currentA0;
54
J9Method * currentMethod;
55
J9ROMMethod * romMethod;
56
UDATA argTempCount;
57
UDATA argCount;
58
J9JITExceptionTable * metaData;
59
UDATA * checkSP;
60
J9MonitorEnterRecord * enterRecord;
61
UDATA * relativeA0;
62
63
Trc_DLT_setUpForDLT_Entry(currentThread);
64
65
/* Fetch and clear DLT entrypoint address */
66
67
dltEntry = dltBlock->dltEntry;
68
dltBlock->dltEntry = NULL;
69
70
/* Walk past the current frame to collect the required information */
71
72
retry:
73
walkState->skipCount = 0;
74
walkState->maxFrames = 3; /* Generic special, frame to compile, caller */
75
walkState->walkThread = currentThread;
76
walkState->frameWalkFunction = dltIterator;
77
walkState->flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_COUNT_SPECIFIED | J9_STACKWALK_MAINTAIN_REGISTER_MAP;
78
vm->walkStackFrames(currentThread, walkState);
79
if (walkState->framesWalked != 3) {
80
Trc_DLT_setUpForDLT_Exit_MalformedStack(currentThread);
81
return NULL;
82
}
83
currentFrame = walkState->userData1;
84
currentA0 = walkState->userData2;
85
currentMethod = walkState->userData3;
86
87
/* Check for stack overflow */
88
89
metaData = jitGetExceptionTableFromPC(currentThread, (UDATA) dltEntry);
90
checkSP = walkState->sp - (metaData->totalFrameSize + J9SW_JIT_STACK_SLOTS_USED_BY_CALL);
91
if (checkSP < currentThread->stackOverflowMark2) {
92
#if defined(J9VM_INTERP_GROWABLE_STACKS)
93
/* If we are already handling an overflow, abandon the DLT */
94
95
if ((currentThread->privateFlags & J9_PRIVATE_FLAGS_STACK_OVERFLOW) == 0) {
96
J9JavaStack * stack = currentThread->stackObject;
97
UDATA bytesRequired = (UDATA)stack->end - (UDATA)checkSP;
98
UDATA maxSize = vm->stackSize;
99
100
/* If the required stack is more than the maximum, abandon the DLT */
101
102
if (bytesRequired <= maxSize) {
103
bytesRequired += vm->stackSizeIncrement;
104
if (bytesRequired > maxSize) {
105
bytesRequired = maxSize;
106
}
107
108
/* If the grow succeeds, restart the stack walk since all the stack pointers have moved */
109
110
if (vm->internalVMFunctions->growJavaStack(currentThread, bytesRequired) == 0) {
111
goto retry;
112
}
113
}
114
}
115
#endif
116
Trc_DLT_setUpForDLT_Exit_StackOverflow(currentThread);
117
return NULL;
118
}
119
120
/* Copy the temps into the buffer */
121
122
romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);
123
argTempCount = romMethod->tempCount;
124
if (romMethod->modifiers & J9AccSynchronized) {
125
++argTempCount;
126
} else if (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod)) {
127
++argTempCount;
128
}
129
argCount = romMethod->argCount;
130
argTempCount += argCount;
131
copiedTemps = dltBlock->inlineTempsBuffer;
132
if (argTempCount > (sizeof(dltBlock->inlineTempsBuffer) / sizeof(UDATA))) {
133
PORT_ACCESS_FROM_JAVAVM(vm);
134
135
copiedTemps = j9mem_allocate_memory(argTempCount * sizeof(UDATA), OMRMEM_CATEGORY_JIT);
136
if (copiedTemps == NULL) {
137
Trc_DLT_setUpForDLT_Exit_FailedTempAllocate(currentThread);
138
return NULL;
139
}
140
}
141
onStackTemps = currentA0 + 1 - argTempCount;
142
memcpy(copiedTemps, onStackTemps, argTempCount * sizeof(UDATA));
143
dltBlock->temps = copiedTemps;
144
145
/* Handle J2I and bytecode->bytecode differently */
146
147
if (walkState->jitInfo != NULL) {
148
J9I2JState * currentState;
149
150
Trc_DLT_setUpForDLT_Jitted_Caller(currentThread);
151
152
/* Fetch return address from J2I frame */
153
154
walkState->userData1 = ((J9SFJ2IFrame *) currentFrame)->returnAddress;
155
156
/* Copy walkState i2jState and j2iFrame values back to the current locations */
157
158
currentState = walkState->i2jState;
159
if (currentState != NULL) {
160
J9I2JState * elsState = &(currentThread->entryLocalStorage->i2jState);
161
162
elsState->pc = currentState->pc;
163
elsState->literals = currentState->literals;
164
elsState->a0 = currentState->a0;
165
elsState->returnSP = currentState->returnSP;
166
}
167
currentThread->j2iFrame = walkState->j2iFrame;
168
} else {
169
J9I2JState * elsState = &(currentThread->entryLocalStorage->i2jState);
170
UDATA * returnSP;
171
UDATA * sp;
172
U_32 infoWord = ((U_32 *) dltEntry)[-1];
173
174
Trc_DLT_setUpForDLT_Bytecode_Caller(currentThread);
175
176
if ((*(UDATA *) currentFrame) & J9_STACK_FLAGS_J2_IFRAME) {
177
Trc_DLT_setUpForDLT_Exit_MalformedStack(currentThread);
178
return NULL;
179
}
180
181
/* Fetch return address from I2J table */
182
183
walkState->userData1 = ((void **) vm->jitConfig->i2jReturnTable)[infoWord & 0x000F];
184
185
/* Set up I2J state and possibly move args for alignment */
186
187
elsState->a0 = walkState->arg0EA;
188
elsState->pc = walkState->pc;
189
elsState->literals = walkState->method;
190
sp = walkState->sp;
191
returnSP = sp + argCount;
192
returnSP = (UDATA *) ((UDATA) returnSP | J9_STACK_FLAGS_J2_IFRAME);
193
194
if (J9_ARE_ANY_BITS_SET((UDATA)sp, sizeof(UDATA))) {
195
Trc_DLT_setUpForDLT_Aligning_Arguments(currentThread);
196
memmove((walkState->sp = sp - 1), sp, argCount * sizeof(UDATA));
197
}
198
elsState->returnSP = returnSP;
199
}
200
201
currentThread->jitStackFrameFlags = 0;
202
203
/* Drop any monitor enter records for the frame which is being DLTed */
204
205
enterRecord = currentThread->monitorEnterRecords;
206
relativeA0 = CONVERT_TO_RELATIVE_STACK_OFFSET(currentThread, currentA0);
207
while ((enterRecord != NULL) && (enterRecord->arg0EA == relativeA0)) {
208
J9MonitorEnterRecord * next = enterRecord->next;
209
210
Trc_DLT_setUpForDLT_Discard_Enter_Record(currentThread, enterRecord, enterRecord->object);
211
pool_removeElement(currentThread->monitorEnterRecordPool, enterRecord);
212
enterRecord = next;
213
}
214
currentThread->monitorEnterRecords = enterRecord;
215
216
Trc_DLT_setUpForDLT_Exit_Success(currentThread, dltEntry);
217
return dltEntry;
218
}
219
220
#endif
221
222