Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/p/codegen/CallSnippet.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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 "p/codegen/CallSnippet.hpp"
24
25
#include "codegen/Linkage.hpp"
26
#include "codegen/Linkage_inlines.hpp"
27
#include "codegen/Machine.hpp"
28
#include "codegen/RealRegister.hpp"
29
#include "codegen/SnippetGCMap.hpp"
30
#include "compile/ResolvedMethod.hpp"
31
#include "env/CompilerEnv.hpp"
32
#include "env/IO.hpp"
33
#include "env/J2IThunk.hpp"
34
#include "env/jittypes.h"
35
#include "il/Node.hpp"
36
#include "il/Node_inlines.hpp"
37
#include "p/codegen/PPCAOTRelocation.hpp"
38
#include "p/codegen/PPCTableOfConstants.hpp"
39
#include "runtime/CodeCacheManager.hpp"
40
41
uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
42
{
43
int32_t intArgNum=0, floatArgNum=0, offset;
44
TR::Compilation *comp = cg->comp();
45
TR::InstOpCode::Mnemonic storeGPROp= comp->target().is64Bit() ? TR::InstOpCode::std : TR::InstOpCode::stw;
46
TR::Machine *machine = cg->machine();
47
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
48
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
49
int32_t argStart = callNode->getFirstArgumentIndex();
50
51
if (linkageProperties.getRightToLeft())
52
offset = linkage->getOffsetToFirstParm();
53
else
54
offset = argSize+linkage->getOffsetToFirstParm();
55
56
for (int i=argStart; i<callNode->getNumChildren();i++)
57
{
58
TR::Node *child = callNode->getChild(i);
59
switch (child->getDataType())
60
{
61
case TR::Int8:
62
case TR::Int16:
63
case TR::Int32:
64
if (!linkageProperties.getRightToLeft())
65
offset -= TR::Compiler->om.sizeofReferenceAddress();
66
if (intArgNum < linkageProperties.getNumIntArgRegs())
67
{
68
buffer = storeArgumentItem(TR::InstOpCode::stw, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
69
}
70
intArgNum++;
71
if (linkageProperties.getRightToLeft())
72
offset += TR::Compiler->om.sizeofReferenceAddress();
73
break;
74
case TR::Address:
75
if (!linkageProperties.getRightToLeft())
76
offset -= TR::Compiler->om.sizeofReferenceAddress();
77
if (intArgNum < linkageProperties.getNumIntArgRegs())
78
{
79
buffer = storeArgumentItem(storeGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
80
}
81
intArgNum++;
82
if (linkageProperties.getRightToLeft())
83
offset += TR::Compiler->om.sizeofReferenceAddress();
84
break;
85
case TR::Int64:
86
if (!linkageProperties.getRightToLeft())
87
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
88
if (intArgNum < linkageProperties.getNumIntArgRegs())
89
{
90
buffer = storeArgumentItem(storeGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
91
if (comp->target().is32Bit())
92
{
93
if (intArgNum < linkageProperties.getNumIntArgRegs()-1)
94
{
95
buffer = storeArgumentItem(TR::InstOpCode::stw, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum+1)), offset+4, cg);
96
}
97
}
98
}
99
intArgNum += comp->target().is64Bit() ? 1 : 2;
100
if (linkageProperties.getRightToLeft())
101
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
102
break;
103
case TR::Float:
104
if (!linkageProperties.getRightToLeft())
105
offset -= TR::Compiler->om.sizeofReferenceAddress();
106
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
107
{
108
buffer = storeArgumentItem(TR::InstOpCode::stfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
109
}
110
floatArgNum++;
111
if (linkageProperties.getRightToLeft())
112
offset += TR::Compiler->om.sizeofReferenceAddress();
113
break;
114
case TR::Double:
115
if (!linkageProperties.getRightToLeft())
116
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
117
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
118
{
119
buffer = storeArgumentItem(TR::InstOpCode::stfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
120
}
121
floatArgNum++;
122
if (linkageProperties.getRightToLeft())
123
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
124
break;
125
}
126
}
127
return(buffer);
128
}
129
130
uint8_t *TR::PPCCallSnippet::setUpArgumentsInRegister(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
131
{
132
int32_t intArgNum=0, floatArgNum=0, offset;
133
TR::Machine *machine = cg->machine();
134
TR::Compilation *comp = cg->comp();
135
TR::InstOpCode::Mnemonic loadGPROp= comp->target().is64Bit() ? TR::InstOpCode::ld : TR::InstOpCode::lwz;
136
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
137
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
138
int32_t argStart = callNode->getFirstArgumentIndex();
139
140
if (linkageProperties.getRightToLeft())
141
offset = linkage->getOffsetToFirstParm();
142
else
143
offset = argSize+linkage->getOffsetToFirstParm();
144
145
for (int i=argStart; i<callNode->getNumChildren();i++)
146
{
147
TR::Node *child = callNode->getChild(i);
148
switch (child->getDataType())
149
{
150
case TR::Int8:
151
case TR::Int16:
152
case TR::Int32:
153
if (!linkageProperties.getRightToLeft())
154
offset -= TR::Compiler->om.sizeofReferenceAddress();
155
if (intArgNum < linkageProperties.getNumIntArgRegs())
156
{
157
buffer = loadArgumentItem(TR::InstOpCode::lwz, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
158
}
159
intArgNum++;
160
if (linkageProperties.getRightToLeft())
161
offset += TR::Compiler->om.sizeofReferenceAddress();
162
break;
163
case TR::Address:
164
if (!linkageProperties.getRightToLeft())
165
offset -= TR::Compiler->om.sizeofReferenceAddress();
166
if (intArgNum < linkageProperties.getNumIntArgRegs())
167
{
168
buffer = loadArgumentItem(loadGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
169
}
170
intArgNum++;
171
if (linkageProperties.getRightToLeft())
172
offset += TR::Compiler->om.sizeofReferenceAddress();
173
break;
174
case TR::Int64:
175
if (!linkageProperties.getRightToLeft())
176
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
177
if (intArgNum < linkageProperties.getNumIntArgRegs())
178
{
179
buffer = loadArgumentItem(loadGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
180
if (comp->target().is32Bit() && (intArgNum < linkageProperties.getNumIntArgRegs()-1))
181
{
182
buffer = loadArgumentItem(TR::InstOpCode::lwz, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum+1)), offset+4, cg);
183
}
184
}
185
intArgNum += comp->target().is64Bit() ? 1 : 2;
186
if (linkageProperties.getRightToLeft())
187
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
188
break;
189
case TR::Float:
190
if (!linkageProperties.getRightToLeft())
191
offset -= TR::Compiler->om.sizeofReferenceAddress();
192
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
193
{
194
buffer = loadArgumentItem(TR::InstOpCode::lfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
195
}
196
floatArgNum++;
197
if (linkageProperties.getRightToLeft())
198
offset += TR::Compiler->om.sizeofReferenceAddress();
199
break;
200
case TR::Double:
201
if (!linkageProperties.getRightToLeft())
202
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
203
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
204
{
205
buffer = loadArgumentItem(TR::InstOpCode::lfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
206
}
207
floatArgNum++;
208
if (linkageProperties.getRightToLeft())
209
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
210
break;
211
}
212
}
213
return(buffer);
214
}
215
216
int32_t TR::PPCCallSnippet::instructionCountForArguments(TR::Node *callNode, TR::CodeGenerator *cg)
217
{
218
TR::Compilation *comp = cg->comp();
219
int32_t intArgNum=0, floatArgNum=0, count=0;
220
const TR::PPCLinkageProperties &linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention())->getProperties();
221
int32_t argStart = callNode->getFirstArgumentIndex();
222
223
for (int i=argStart; i<callNode->getNumChildren();i++)
224
{
225
TR::Node *child = callNode->getChild(i);
226
switch (child->getDataType())
227
{
228
case TR::Int8:
229
case TR::Int16:
230
case TR::Int32:
231
case TR::Address:
232
if (intArgNum < linkage.getNumIntArgRegs())
233
{
234
count++;
235
}
236
intArgNum++;
237
break;
238
case TR::Int64:
239
if (intArgNum < linkage.getNumIntArgRegs())
240
{
241
count++;
242
if (comp->target().is32Bit() && (intArgNum < linkage.getNumIntArgRegs()-1))
243
{
244
count++;
245
}
246
}
247
intArgNum += comp->target().is64Bit() ? 1 : 2;
248
break;
249
case TR::Float:
250
if (floatArgNum < linkage.getNumFloatArgRegs())
251
{
252
count++;
253
}
254
floatArgNum++;
255
break;
256
case TR::Double:
257
if (floatArgNum < linkage.getNumFloatArgRegs())
258
{
259
count++;
260
}
261
floatArgNum++;
262
break;
263
}
264
}
265
return(count);
266
}
267
268
TR_RuntimeHelper TR::PPCCallSnippet::getInterpretedDispatchHelper(
269
TR::SymbolReference *methodSymRef,
270
TR::DataType type,
271
bool isSynchronised,
272
bool& isNativeStatic,
273
TR::CodeGenerator *cg)
274
{
275
TR::Compilation * comp = cg->comp();
276
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
277
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
278
bool isJitInduceOSRCall = false;
279
if (methodSymbol->isHelper() &&
280
methodSymRef->isOSRInductionHelper())
281
{
282
isJitInduceOSRCall = true;
283
}
284
285
bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp);
286
if (methodSymRef->isUnresolved() || forceUnresolvedDispatch)
287
{
288
TR_ASSERT(!isJitInduceOSRCall || !forceUnresolvedDispatch, "calling jitInduceOSR is not supported yet under AOT\n");
289
290
if (methodSymbol->isSpecial())
291
return TR_PPCinterpreterUnresolvedSpecialGlue;
292
else if (methodSymbol->isStatic())
293
return TR_PPCinterpreterUnresolvedStaticGlue;
294
else
295
return TR_PPCinterpreterUnresolvedDirectVirtualGlue;
296
}
297
else if (methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative())
298
{
299
isNativeStatic = true;
300
return TR_PPCnativeStaticHelper;
301
}
302
else if (isJitInduceOSRCall)
303
return (TR_RuntimeHelper) methodSymRef->getReferenceNumber();
304
else
305
{
306
switch (type)
307
{
308
case TR::NoType:
309
return isSynchronised?TR_PPCinterpreterSyncVoidStaticGlue: TR_PPCinterpreterVoidStaticGlue;
310
case TR::Int32:
311
return isSynchronised?TR_PPCinterpreterSyncGPR3StaticGlue:TR_PPCinterpreterGPR3StaticGlue;
312
case TR::Address:
313
if (comp->target().is64Bit())
314
return isSynchronised?TR_PPCinterpreterSyncGPR3GPR4StaticGlue:TR_PPCinterpreterGPR3GPR4StaticGlue;
315
else
316
return isSynchronised?TR_PPCinterpreterSyncGPR3StaticGlue:TR_PPCinterpreterGPR3StaticGlue;
317
case TR::Int64:
318
return isSynchronised?TR_PPCinterpreterSyncGPR3GPR4StaticGlue:TR_PPCinterpreterGPR3GPR4StaticGlue;
319
case TR::Float:
320
return isSynchronised?TR_PPCinterpreterSyncFPR0FStaticGlue:TR_PPCinterpreterFPR0FStaticGlue;
321
case TR::Double:
322
return isSynchronised?TR_PPCinterpreterSyncFPR0DStaticGlue:TR_PPCinterpreterFPR0DStaticGlue;
323
default:
324
TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n",
325
comp->getDebug()->getName(type));
326
return (TR_RuntimeHelper)0;
327
}
328
}
329
}
330
331
uint8_t *TR::PPCCallSnippet::emitSnippetBody()
332
{
333
334
uint8_t *cursor = cg()->getBinaryBufferCursor();
335
TR::Node *callNode = getNode();
336
TR::SymbolReference *methodSymRef = (_realMethodSymbolReference)?_realMethodSymbolReference:callNode->getSymbolReference();
337
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
338
TR::SymbolReference *glueRef;
339
bool isNativeStatic = false;
340
TR::Compilation *comp = cg()->comp();
341
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
342
343
getSnippetLabel()->setCodeLocation(cursor);
344
345
// Flush in-register arguments back to the stack for interpreter
346
cursor = flushArgumentsToStack(cursor, callNode, getSizeOfArguments(), cg());
347
348
TR_RuntimeHelper runtimeHelper = getInterpretedDispatchHelper(methodSymRef, callNode->getDataType(),
349
methodSymbol->isSynchronised(), isNativeStatic, cg());
350
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(runtimeHelper);
351
352
intptr_t helperAddress = (intptr_t)glueRef->getMethodAddress();
353
if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)cursor))
354
{
355
helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);
356
TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)cursor),
357
"Helper address is out of range");
358
}
359
360
// 'b glueRef' for jitInduceOSRAtCurrentPC, 'bl glueRef' otherwise
361
// we use "b" for induceOSR because we want the helper to think that it's been called from the mainline code and not from the snippet.
362
int32_t branchInstruction = (glueRef->isOSRInductionHelper()) ? 0x48000000 : 0x48000001;
363
*(int32_t *)cursor = branchInstruction | ((helperAddress - (intptr_t)cursor) & 0x03fffffc);
364
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,(uint8_t *)glueRef,TR_HelperAddress, cg()),
365
__FILE__, __LINE__, callNode);
366
367
cursor += PPC_INSTRUCTION_LENGTH;
368
369
if (isNativeStatic)
370
{
371
// Rather than placing the return address as data after the 'bl', place a 'b' back to main line code
372
// This insures that all 'blr's return to their corresponding 'bl's
373
*(int32_t *)cursor = 0x48000000 | ((intptr_t)(getCallRA() - (intptr_t)cursor) & 0x03fffffc);
374
TR_ASSERT(gcMap().isGCSafePoint() && gcMap().getStackMap(), "Native static call snippets must have GC maps when preserving the link stack");
375
gcMap().registerStackMap(cursor - PPC_INSTRUCTION_LENGTH, cg());
376
cursor += PPC_INSTRUCTION_LENGTH;
377
378
// Padding; VM helper depends this gap being present
379
if (comp->target().is64Bit())
380
{
381
*(int32_t *)cursor = 0xdeadc0de;
382
cursor += PPC_INSTRUCTION_LENGTH;
383
}
384
}
385
else
386
{
387
// Store the code cache RA
388
*(intptr_t *)cursor = (intptr_t)getCallRA();
389
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,NULL,TR_AbsoluteMethodAddress, cg()),
390
__FILE__, __LINE__, callNode);
391
392
cursor += TR::Compiler->om.sizeofReferenceAddress();
393
}
394
//induceOSRAtCurrentPC is implemented in the VM, and it knows, by looking at the current PC, what method it needs to
395
//continue execution in interpreted mode. Therefore, it doesn't need the method pointer.
396
if (!glueRef->isOSRInductionHelper())
397
{
398
bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp);
399
400
// Store the method pointer: it is NULL for unresolved
401
if (methodSymRef->isUnresolved() || forceUnresolvedDispatch)
402
{
403
*(intptr_t *)cursor = 0;
404
if (comp->getOption(TR_EnableHCR))
405
{
406
cg()->jitAddPicToPatchOnClassRedefinition((void*)-1, (void *)cursor, true);
407
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation((uint8_t *)cursor, NULL,(uint8_t *)needsFullSizeRuntimeAssumption,
408
TR_HCR, cg()),__FILE__, __LINE__,
409
getNode());
410
}
411
}
412
else
413
{
414
*(intptr_t *)cursor = (intptr_t)methodSymbol->getMethodAddress();
415
if (comp->getOption(TR_EnableHCR))
416
cg()->jitAddPicToPatchOnClassRedefinition((void *)methodSymbol->getMethodAddress(), (void *)cursor);
417
418
if (comp->compileRelocatableCode())
419
{
420
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,
421
(uint8_t *)methodSymbol->getMethodAddress(),
422
(uint8_t *)TR::SymbolType::typeMethod,
423
TR_SymbolFromManager,
424
cg()), __FILE__, __LINE__, getNode());
425
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,
426
(uint8_t *)methodSymbol->getMethodAddress(),
427
TR_ResolvedTrampolines,
428
cg()), __FILE__, __LINE__, getNode());
429
}
430
}
431
}
432
cursor += TR::Compiler->om.sizeofReferenceAddress();
433
434
// Lock word initialized to 0
435
*(int32_t *)cursor = 0;
436
437
return (cursor+4);
438
}
439
440
uint32_t TR::PPCCallSnippet::getLength(int32_t estimatedSnippetStart)
441
{
442
return((instructionCountForArguments(getNode(), cg())*4) + 2*TR::Compiler->om.sizeofReferenceAddress() + 8);
443
}
444
445
uint8_t *TR::PPCUnresolvedCallSnippet::emitSnippetBody()
446
{
447
TR::Compilation *comp = cg()->comp();
448
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
449
uint8_t *cursor = TR::PPCCallSnippet::emitSnippetBody();
450
451
TR::SymbolReference *methodSymRef = (_realMethodSymbolReference)?_realMethodSymbolReference:getNode()->getSymbolReference();
452
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
453
int32_t helperLookupOffset;
454
455
switch (getNode()->getDataType())
456
{
457
case TR::NoType:
458
helperLookupOffset = 0;
459
break;
460
case TR::Int32:
461
helperLookupOffset = TR::Compiler->om.sizeofReferenceAddress();
462
break;
463
case TR::Address:
464
if (comp->target().is64Bit())
465
helperLookupOffset = 2*TR::Compiler->om.sizeofReferenceAddress();
466
else
467
helperLookupOffset = TR::Compiler->om.sizeofReferenceAddress();
468
break;
469
case TR::Int64:
470
helperLookupOffset = 2*TR::Compiler->om.sizeofReferenceAddress();
471
break;
472
case TR::Float:
473
helperLookupOffset = 3*TR::Compiler->om.sizeofReferenceAddress();
474
break;
475
case TR::Double:
476
helperLookupOffset = 4*TR::Compiler->om.sizeofReferenceAddress();
477
break;
478
}
479
480
*(uint32_t *)cursor = (helperLookupOffset<<24) | methodSymRef->getCPIndexForVM();
481
482
cursor += 4;
483
*(intptr_t *)cursor = (intptr_t)methodSymRef->getOwningMethod(comp)->constantPool();
484
485
if (comp->compileRelocatableCode() && comp->getOption(TR_TraceRelocatableDataDetailsCG))
486
{
487
traceMsg(comp, "<relocatableDataTrampolinesCG>\n");
488
traceMsg(comp, "%s\n", comp->signature());
489
traceMsg(comp, "%-8s", "cpIndex");
490
traceMsg(comp, "cp\n");
491
traceMsg(comp, "%-8x", methodSymRef->getCPIndexForVM());
492
traceMsg(comp, "%x\n", methodSymRef->getOwningMethod(comp)->constantPool());
493
traceMsg(comp, "</relocatableDataTrampolinesCG>\n");
494
}
495
496
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,
497
*(uint8_t **)cursor,
498
getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
499
TR_Trampolines, cg()),
500
__FILE__, __LINE__, getNode());
501
502
cursor += TR::Compiler->om.sizeofReferenceAddress();
503
504
*(int32_t *)cursor = 0;
505
return cursor+4;
506
}
507
508
uint32_t TR::PPCUnresolvedCallSnippet::getLength(int32_t estimatedSnippetStart)
509
{
510
return TR::PPCCallSnippet::getLength(estimatedSnippetStart) + 8 + TR::Compiler->om.sizeofReferenceAddress();
511
}
512
513
uint8_t *TR::PPCVirtualSnippet::emitSnippetBody()
514
{
515
return(NULL);
516
}
517
518
uint32_t TR::PPCVirtualSnippet::getLength(int32_t estimatedSnippetStart)
519
{
520
return(0);
521
}
522
523
uint8_t *TR::PPCVirtualUnresolvedSnippet::emitSnippetBody()
524
{
525
uint8_t *cursor = cg()->getBinaryBufferCursor();
526
TR::Compilation *comp = cg()->comp();
527
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
528
TR::Node *callNode = getNode();
529
TR::SymbolReference *glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_PPCvirtualUnresolvedHelper);
530
void *thunk = fej9->getJ2IThunk(callNode->getSymbolReference()->getSymbol()->castToMethodSymbol()->getMethod(), comp);
531
uint8_t *j2iThunkRelocationPoint;
532
533
// We want the data in the snippet to be naturally aligned
534
if (comp->target().is64Bit() && (((uint64_t)cursor % TR::Compiler->om.sizeofReferenceAddress()) == 4))
535
{
536
*(int32_t *)cursor = 0xdeadc0de;
537
cursor += 4;
538
}
539
540
getSnippetLabel()->setCodeLocation(cursor);
541
542
intptr_t helperAddress = (intptr_t)glueRef->getMethodAddress();
543
if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)cursor))
544
{
545
helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);
546
TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)cursor),
547
"Helper address is out of range");
548
}
549
550
// bl glueRef
551
*(int32_t *)cursor = 0x48000001 | ((helperAddress - (intptr_t)cursor) & 0x03fffffc);
552
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,(uint8_t *)glueRef,TR_HelperAddress, cg()),
553
__FILE__, __LINE__, callNode);
554
cursor += 4;
555
556
/*
557
* Place a 'b' back to the main line code after the 'bl'.
558
* This is used to have 'blr's return to their corresponding 'bl's when handling private nestmate calls.
559
* Ideally, 'blr's return to their corresponding 'bl's in other cases as well but currently that does not happen.
560
*/
561
intptr_t distance = (intptr_t)getReturnLabel()->getCodeLocation() - (intptr_t)cursor;
562
*(int32_t *)cursor = 0x48000000 | (distance & 0x03fffffc);
563
564
TR_ASSERT(gcMap().isGCSafePoint() && gcMap().getStackMap(), "Virtual call snippets must have GC maps when preserving the link stack");
565
gcMap().registerStackMap(cursor - 4, cg());
566
cursor += 4;
567
568
// Store the code cache RA
569
*(intptr_t *)cursor = (intptr_t)getReturnLabel()->getCodeLocation();
570
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,NULL,TR_AbsoluteMethodAddress, cg()),
571
__FILE__, __LINE__, callNode);
572
573
cursor += TR::Compiler->om.sizeofReferenceAddress();
574
575
// GJ - Swizzled the order of the following lines to conform to helper
576
intptr_t cpAddr = (intptr_t)callNode->getSymbolReference()->getOwningMethod(comp)->constantPool();
577
*(intptr_t *)cursor = cpAddr;
578
j2iThunkRelocationPoint = cursor;
579
580
cursor += TR::Compiler->om.sizeofReferenceAddress();
581
582
*(uintptr_t *)cursor = callNode->getSymbolReference()->getCPIndexForVM();
583
cursor += TR::Compiler->om.sizeofReferenceAddress();
584
585
/*
586
* Reserved spot to hold J9Method pointer of the callee.
587
* This is used for private nestmate calls.
588
*/
589
*(intptr_t *)cursor = (intptr_t)0;
590
cursor += sizeof(intptr_t);
591
592
/*
593
* J2I thunk address.
594
* This is used for private nestmate calls.
595
*/
596
*(intptr_t*)cursor = (intptr_t)thunk;
597
598
auto info =
599
(TR_RelocationRecordInformation *)comp->trMemory()->allocateMemory(
600
sizeof (TR_RelocationRecordInformation),
601
heapAlloc);
602
603
// data1 = constantPool
604
info->data1 = cpAddr;
605
606
// data2 = inlined site index
607
info->data2 = callNode ? callNode->getInlinedSiteIndex() : (uintptr_t)-1;
608
609
// data3 = distance in bytes from Constant Pool Pointer to J2I Thunk
610
info->data3 = (intptr_t)cursor - (intptr_t)j2iThunkRelocationPoint;
611
612
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(j2iThunkRelocationPoint, (uint8_t *)info, NULL, TR_J2IVirtualThunkPointer, cg()),
613
__FILE__, __LINE__, callNode);
614
615
cursor += sizeof(intptr_t);
616
617
*(int32_t *)cursor = 0; // Lock word
618
cursor += sizeof(int32_t);
619
620
return cursor;
621
}
622
623
uint32_t TR::PPCVirtualUnresolvedSnippet::getLength(int32_t estimatedSnippetStart)
624
{
625
/*
626
* 4 = Code alignment may add 4 to the length. To be conservative it is always part of the estimate.
627
* 8 = Two instructions. One bl and one b instruction.
628
* 5 address fields:
629
* - Call Site RA
630
* - Constant Pool Pointer
631
* - Constant Pool Index
632
* - Private J9Method pointer
633
* - J2I thunk address
634
* 4 = Lockword
635
*/
636
return(4 + 8 + (5 * TR::Compiler->om.sizeofReferenceAddress()) + 4);
637
}
638
639
uint8_t *TR::PPCInterfaceCallSnippet::emitSnippetBody()
640
{
641
uint8_t *cursor = cg()->getBinaryBufferCursor();
642
uint8_t *blAddress;
643
TR::Node *callNode = getNode();
644
TR::Compilation *comp = cg()->comp();
645
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
646
TR::SymbolReference *glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_PPCinterfaceCallHelper);
647
void *thunk = fej9->getJ2IThunk(callNode->getSymbolReference()->getSymbol()->castToMethodSymbol()->getMethod(), comp);
648
uint8_t *j2iThunkRelocationPoint;
649
650
// We want the data in the snippet to be naturally aligned
651
if (comp->target().is64Bit() && (((uint64_t)cursor % TR::Compiler->om.sizeofReferenceAddress()) == 0))
652
{
653
// icallVMprJavaSendPatchupVirtual needs to determine if it was called for virtual dispatch as opposed to interface dispatch
654
// To do that it checks for 'mtctr r12' at -8(LR), which points here when it's called for interface dispatch in 64 bit mode
655
// We make sure it doesn't contain that particular bit pattern by accident (which can actually happen)
656
*(int32_t *)cursor = 0xdeadc0de;
657
cursor += 4;
658
}
659
660
getSnippetLabel()->setCodeLocation(cursor);
661
662
intptr_t helperAddress = (intptr_t)glueRef->getMethodAddress();
663
if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)cursor))
664
{
665
helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);
666
TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)cursor),
667
"Helper address is out of range");
668
}
669
670
// bl glueRef
671
*(int32_t *)cursor = 0x48000001 | ((helperAddress - (intptr_t)cursor) & 0x03fffffc);
672
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *)glueRef, TR_HelperAddress, cg()),
673
__FILE__, __LINE__, callNode);
674
blAddress = cursor;
675
cursor += PPC_INSTRUCTION_LENGTH;
676
677
// Rather than placing the return address as data after the 'bl', place a 'b' back to main line code
678
// This insures that all 'blr's return to their corresponding 'bl's
679
intptr_t distance = (intptr_t)getReturnLabel()->getCodeLocation() - (intptr_t)cursor;
680
*(int32_t *)cursor = 0x48000000 | (distance & 0x03fffffc);
681
682
TR_ASSERT(gcMap().isGCSafePoint() && gcMap().getStackMap(), "Interface call snippets must have GC maps when preserving the link stack");
683
gcMap().registerStackMap(cursor - PPC_INSTRUCTION_LENGTH, cg());
684
cursor += PPC_INSTRUCTION_LENGTH;
685
686
// Padding; jitLookupInterfaceMethod depends on this gap being present
687
if (comp->target().is64Bit())
688
{
689
*(int32_t *)cursor = 0xdeadc0de;
690
cursor += PPC_INSTRUCTION_LENGTH;
691
}
692
693
intptr_t cpAddr = (intptr_t)callNode->getSymbolReference()->getOwningMethod(comp)->constantPool();
694
*(intptr_t *)cursor = cpAddr;
695
j2iThunkRelocationPoint = cursor;
696
697
cursor += TR::Compiler->om.sizeofReferenceAddress();
698
699
*(uintptr_t *)cursor = callNode->getSymbolReference()->getCPIndexForVM();
700
cursor += TR::Compiler->om.sizeofReferenceAddress();
701
702
// Add two slots for interface class & iTable index, keeping cp/cpindex around
703
((uintptr_t *)cursor)[0] = 0;
704
((uintptr_t *)cursor)[1] = 0;
705
cursor += 2*TR::Compiler->om.sizeofReferenceAddress();
706
707
if (comp->target().is64Bit())
708
{
709
if (!comp->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P10))
710
{
711
if (getTOCOffset() != PTOC_FULL_INDEX)
712
{
713
TR_PPCTableOfConstants::setTOCSlot(getTOCOffset(), (uintptr_t)cursor);
714
}
715
else
716
{
717
int32_t *patchAddr = (int32_t *)getLowerInstruction()->getBinaryEncoding();
718
intptr_t addrValue = (intptr_t)cursor;
719
if (!comp->compileRelocatableCode()
720
#ifdef J9VM_OPT_JITSERVER
721
&& !comp->isOutOfProcessCompilation()
722
#endif
723
)
724
{
725
// If the high nibble is 0 and the next nibble's high bit is clear, change the first instruction to a nop and the third to a li
726
// Next nibble's high bit needs to be clear in order to use li (because li will sign extend the immediate)
727
if ((addrValue >> 48) == 0 && ((addrValue >> 32) & 0x8000) == 0)
728
{
729
*patchAddr |= addrValue & 0x0000ffff;
730
addrValue = cg()->hiValue(addrValue);
731
uint32_t ori = *(patchAddr-2);
732
uint32_t li = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::li) | (ori & 0x03e00000);
733
*(patchAddr-2) = li | ((addrValue>>16) & 0x0000ffff);
734
*(patchAddr-3) |= addrValue & 0x0000ffff;
735
*(patchAddr-4) = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::nop);
736
}
737
else
738
{
739
*patchAddr |= addrValue & 0x0000ffff;
740
addrValue = cg()->hiValue(addrValue);
741
*(patchAddr-2) |= (addrValue>>16) & 0x0000ffff;
742
*(patchAddr-3) |= addrValue & 0x0000ffff;
743
*(patchAddr-4) |= (addrValue>>32) & 0x0000ffff;
744
}
745
}
746
else
747
{
748
// We must take this path for all compiles that need to generate relocatable code (ex. AOT, outOfProcess).
749
// The immediate fields of relocatable instructions must be clear. This is because when performing the relocation,
750
// we OR the new address into the fields. So if the fields are not already clear, then OR'ing the new address can
751
// result in garbage data.
752
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::BeforeBinaryEncodingExternalRelocation(getUpperInstruction(),
753
(uint8_t *)(addrValue),
754
(uint8_t *)fixedSequence4,
755
TR_FixedSequenceAddress2,
756
cg()),
757
__FILE__, __LINE__, callNode);
758
}
759
}
760
}
761
}
762
else
763
{
764
// Patch up the main line codes
765
int32_t *patchAddress1 = (int32_t *)getUpperInstruction()->getBinaryEncoding();
766
*patchAddress1 |= cg()->hiValue((int32_t)(intptr_t)cursor) & 0x0000ffff;
767
int32_t *patchAddress2 = (int32_t *)getLowerInstruction()->getBinaryEncoding();
768
*patchAddress2 |= (int32_t)(intptr_t)cursor & 0x0000ffff;
769
TR_RelocationRecordInformation *recordInfo = ( TR_RelocationRecordInformation *)comp->trMemory()->allocateMemory(sizeof( TR_RelocationRecordInformation), heapAlloc);
770
recordInfo->data3 = orderedPairSequence1;
771
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalOrderedPair32BitRelocation((uint8_t *)patchAddress1,
772
(uint8_t *)patchAddress2,
773
(uint8_t *)recordInfo,
774
TR_AbsoluteMethodAddressOrderedPair, cg()),
775
__FILE__, __LINE__, callNode);
776
}
777
778
// Initialize for: two class ptrs, two target addrs
779
// Initialize target addrs with the address of the bl. see 134322
780
*(intptr_t *)cursor = -1;
781
*(intptr_t *)(cursor+TR::Compiler->om.sizeofReferenceAddress()) = (intptr_t)blAddress;
782
*(intptr_t *)(cursor+2*TR::Compiler->om.sizeofReferenceAddress()) = -1;
783
*(intptr_t *)(cursor+3*TR::Compiler->om.sizeofReferenceAddress()) = (intptr_t)blAddress;
784
785
// Register for relation of the 1st target address
786
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor+TR::Compiler->om.sizeofReferenceAddress(), NULL, TR_AbsoluteMethodAddress, cg()),
787
__FILE__, __LINE__, callNode);
788
789
// Register for relocation of the 2nd target address
790
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor+3*TR::Compiler->om.sizeofReferenceAddress(), NULL, TR_AbsoluteMethodAddress, cg()),
791
__FILE__, __LINE__, callNode);
792
793
cursor += 4 * TR::Compiler->om.sizeofReferenceAddress();
794
795
/*
796
* J2I thunk address.
797
* This is used for private nestmate calls.
798
*/
799
*(intptr_t*)cursor = (intptr_t)thunk;
800
801
if (comp->compileRelocatableCode())
802
{
803
auto info =
804
(TR_RelocationRecordInformation *)comp->trMemory()->allocateMemory(
805
sizeof (TR_RelocationRecordInformation),
806
heapAlloc);
807
808
// data1 = constantPool
809
info->data1 = cpAddr;
810
811
// data2 = inlined site index
812
info->data2 = callNode ? callNode->getInlinedSiteIndex() : (uintptr_t)-1;
813
814
// data3 = distance in bytes from Constant Pool Pointer to J2I Thunk
815
info->data3 = (intptr_t)cursor - (intptr_t)j2iThunkRelocationPoint;
816
817
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(j2iThunkRelocationPoint, (uint8_t *)info, NULL, TR_J2IVirtualThunkPointer, cg()),
818
__FILE__, __LINE__, callNode);
819
}
820
cursor += sizeof(intptr_t);
821
822
823
return cursor;
824
}
825
826
uint32_t TR::PPCInterfaceCallSnippet::getLength(int32_t estimatedSnippetStart)
827
{
828
/*
829
* 4 = Code alignment may add 4 to the length. To be conservative it is always part of the estimate.
830
* 8 = Two instructions. One bl and one b instruction.
831
* 0 or 4 = Padding. Only needed under 64 bit.
832
* 9 address fields:
833
* - CP Pointer
834
* - CP Index
835
* - Interface Class Pointer
836
* - ITable Index (may also contain a tagged J9Method* when handling nestmates)
837
* - First Class Pointer
838
* - First Class Target
839
* - Second Class Pointer
840
* - Second Class Target
841
* - J2I thunk address
842
*/
843
return(4 + 8 + (cg()->comp()->target().is64Bit() ? 4 : 0) + (9 * TR::Compiler->om.sizeofReferenceAddress()));
844
}
845
846
uint8_t *TR::PPCCallSnippet::generateVIThunk(TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
847
{
848
TR::Compilation * comp = cg->comp();
849
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
850
int32_t codeSize = 4*(instructionCountForArguments(callNode, cg) + (comp->target().is64Bit()?7:4)) + 8; // Additional 4 bytes to hold size of thunk
851
uint8_t *thunk, *buffer, *returnValue;
852
intptr_t dispatcher;
853
int32_t sizeThunk;
854
855
switch (callNode->getDataType())
856
{
857
case TR::NoType:
858
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtual0)->getMethodAddress();
859
break;
860
case TR::Int32:
861
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtual1)->getMethodAddress();
862
break;
863
case TR::Address:
864
if (comp->target().is64Bit())
865
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtualJ)->getMethodAddress();
866
else
867
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtual1)->getMethodAddress();
868
break;
869
case TR::Int64:
870
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtualJ)->getMethodAddress();
871
break;
872
case TR::Float:
873
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtualF)->getMethodAddress();
874
break;
875
case TR::Double:
876
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(TR_PPCicallVMprJavaSendVirtualD)->getMethodAddress();
877
break;
878
default:
879
TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n",
880
comp->getDebug()->getName(callNode->getDataType()));
881
}
882
883
if (comp->target().is32Bit() && (((dispatcher&0x80008000) == 0x80008000) || comp->compileRelocatableCode()) )
884
codeSize += 4;
885
886
if (comp->compileRelocatableCode())
887
thunk = (uint8_t *)comp->trMemory()->allocateMemory(codeSize, heapAlloc);
888
else
889
thunk = (uint8_t *)cg->allocateCodeMemory(codeSize, true, false);
890
buffer = returnValue = thunk + 8;
891
892
buffer = flushArgumentsToStack(buffer, callNode, argSize, cg);
893
*((int32_t *)thunk + 1)= buffer - returnValue; // patch offset for AOT relocation
894
895
// NOTE: modification of the layout of the following will require a corresponding change in AOT relocation code (codert/ppc/AOTRelocations.cpp)
896
if (comp->target().is64Bit())
897
{
898
// todo64: fix me, I'm just a temporary kludge
899
// lis gr4, upper 16-bits
900
*(int32_t *)buffer = 0x3c800000 | ((dispatcher>>48) & 0x0000ffff);
901
buffer += 4;
902
903
// ori gr4, gr4, next 16-bits
904
*(int32_t *)buffer = 0x60840000 | ((dispatcher>>32) & 0x0000ffff);
905
buffer += 4;
906
907
// rldicr gr4, gr4, 32, 31
908
*(int32_t *)buffer = 0x788403e6;
909
buffer += 4;
910
911
// oris gr4, gr4, next 16-bits
912
*(int32_t *)buffer = 0x64840000 | ((dispatcher>>16) & 0x0000ffff);
913
buffer += 4;
914
915
// ori gr4, gr4, last 16-bits
916
*(int32_t *)buffer = 0x60840000 | (dispatcher & 0x0000ffff);
917
buffer += 4;
918
}
919
else
920
{
921
// For POWER4 which has a problem with the CTR/LR cache when the upper
922
// bits are not 0 extended.. Use li/oris when the 16th bit is off
923
if( !(dispatcher & 0x00008000) )
924
{
925
// li r4, lower
926
*(int32_t *)buffer = 0x38800000 | (dispatcher & 0x0000ffff);
927
buffer += 4;
928
// oris r4, r4, upper
929
*(int32_t *)buffer = 0x64840000 | ((dispatcher>>16) & 0x0000ffff);
930
buffer += 4;
931
}
932
else
933
{
934
// lis gr4, upper
935
*(int32_t *)buffer = 0x3c800000 |
936
(((dispatcher>>16) + (dispatcher&(1<<15)?1:0)) & 0x0000ffff);
937
buffer += 4;
938
939
// addi gr4, gr4, lower
940
*(int32_t *)buffer = 0x38840000 | (dispatcher & 0x0000ffff);
941
buffer += 4;
942
// Now, if highest bit is on we need to clear the sign extend bits on 64bit CPUs
943
// ** POWER4 pref fix **
944
if( dispatcher & 0x80000000 )
945
{
946
// rlwinm r4,r4,sh=0,mb=0,me=31
947
*(int32_t *)buffer = 0x5484003e;
948
buffer += 4;
949
}
950
}
951
}
952
953
// mtctr gr4
954
*(int32_t *)buffer = 0x7c8903a6;
955
buffer += 4;
956
957
// bcctr
958
*(int32_t *)buffer = 0x4e800420;
959
buffer += 4;
960
961
sizeThunk = buffer - returnValue;
962
if (comp->target().is32Bit() && comp->compileRelocatableCode() && !((dispatcher&0x80008000) == 0x80008000)) // Make size of thunk larger for AOT even if extra instruction is not generated at compile time. The extra instruction could be needed for the runtime address.
963
sizeThunk += 4;
964
965
// patch size of thunk
966
*(int32_t *)thunk = sizeThunk;
967
968
ppcCodeSync(thunk, codeSize);
969
970
return(returnValue);
971
}
972
973
TR_J2IThunk *TR::PPCCallSnippet::generateInvokeExactJ2IThunk(TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg, char *signature)
974
{
975
TR::Compilation *comp = cg->comp();
976
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
977
int32_t codeSize = 4*(instructionCountForArguments(callNode, cg) + (comp->target().is64Bit()?7:4)) + 8; // Additional 4 bytes to hold size of thunk
978
intptr_t dispatcher;
979
int32_t sizeThunk;
980
981
TR_J2IThunkTable *thunkTable = comp->getPersistentInfo()->getInvokeExactJ2IThunkTable();
982
TR_J2IThunk *thunk = TR_J2IThunk::allocate(codeSize, signature, cg, thunkTable);
983
uint8_t *buffer = thunk->entryPoint();
984
985
TR::SymbolReference *dispatcherSymbol;
986
switch (callNode->getDataType())
987
{
988
case TR::NoType:
989
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact0);
990
break;
991
case TR::Int32:
992
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact1);
993
break;
994
case TR::Address:
995
if (comp->target().is64Bit())
996
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactJ);
997
else
998
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact1);
999
break;
1000
case TR::Int64:
1001
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactJ);
1002
break;
1003
case TR::Float:
1004
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactF);
1005
break;
1006
case TR::Double:
1007
dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactD);
1008
break;
1009
default:
1010
TR_ASSERT(0, "Bad return data type '%s' for call node [" POINTER_PRINTF_FORMAT "]\n",
1011
comp->getDebug()->getName(callNode->getDataType()),
1012
callNode);
1013
}
1014
1015
dispatcher = (intptr_t)(cg->fej9()->getInvokeExactThunkHelperAddress(comp, dispatcherSymbol, callNode->getDataType()));
1016
1017
if ( comp->target().is32Bit() && (((dispatcher&0x80008000) == 0x80008000) || comp->compileRelocatableCode()) )
1018
codeSize += 4;
1019
1020
buffer = flushArgumentsToStack(buffer, callNode, argSize, cg);
1021
1022
// NOTE: modification of the layout of the following will require a corresponding change in AOT relocation code (codert/ppc/AOTRelocations.cpp)
1023
if (comp->target().is64Bit())
1024
{
1025
// todo64: fix me, I'm just a temporary kludge
1026
// lis gr4, upper 16-bits
1027
*(int32_t *)buffer = 0x3c800000 | ((dispatcher>>48) & 0x0000ffff);
1028
buffer += 4;
1029
1030
// ori gr4, gr4, next 16-bits
1031
*(int32_t *)buffer = 0x60840000 | ((dispatcher>>32) & 0x0000ffff);
1032
buffer += 4;
1033
1034
// rldicr gr4, gr4, 32, 31
1035
*(int32_t *)buffer = 0x788403e6;
1036
buffer += 4;
1037
1038
// oris gr4, gr4, next 16-bits
1039
*(int32_t *)buffer = 0x64840000 | ((dispatcher>>16) & 0x0000ffff);
1040
buffer += 4;
1041
1042
// ori gr4, gr4, last 16-bits
1043
*(int32_t *)buffer = 0x60840000 | (dispatcher & 0x0000ffff);
1044
buffer += 4;
1045
}
1046
else
1047
{
1048
// For POWER4 which has a problem with the CTR/LR cache when the upper
1049
// bits are not 0 extended.. Use li/oris when the 16th bit is off
1050
if( !(dispatcher & 0x00008000) )
1051
{
1052
// li r4, lower
1053
*(int32_t *)buffer = 0x38800000 | (dispatcher & 0x0000ffff);
1054
buffer += 4;
1055
// oris r4, r4, upper
1056
*(int32_t *)buffer = 0x64840000 | ((dispatcher>>16) & 0x0000ffff);
1057
buffer += 4;
1058
}
1059
else
1060
{
1061
// lis gr4, upper
1062
*(int32_t *)buffer = 0x3c800000 |
1063
(((dispatcher>>16) + (dispatcher&(1<<15)?1:0)) & 0x0000ffff);
1064
buffer += 4;
1065
1066
// addi gr4, gr4, lower
1067
*(int32_t *)buffer = 0x38840000 | (dispatcher & 0x0000ffff);
1068
buffer += 4;
1069
// Now, if highest bit is on we need to clear the sign extend bits on 64bit CPUs
1070
// ** POWER4 pref fix **
1071
if( dispatcher & 0x80000000 )
1072
{
1073
// rlwinm r4,r4,sh=0,mb=0,me=31
1074
*(int32_t *)buffer = 0x5484003e;
1075
buffer += 4;
1076
}
1077
}
1078
}
1079
1080
// mtctr gr4
1081
*(int32_t *)buffer = 0x7c8903a6;
1082
buffer += 4;
1083
1084
// bcctr
1085
*(int32_t *)buffer = 0x4e800420;
1086
buffer += 4;
1087
1088
ppcCodeSync(thunk->entryPoint(), codeSize);
1089
1090
return(thunk);
1091
}
1092
1093
1094
uint8_t *
1095
TR_Debug::printPPCArgumentsFlush(TR::FILE *pOutFile, TR::Node *node, uint8_t *cursor, int32_t argSize)
1096
{
1097
char *storeGPROpName;
1098
int32_t offset = 0,
1099
intArgNum = 0,
1100
floatArgNum = 0;
1101
1102
if (_comp->target().is64Bit())
1103
{
1104
storeGPROpName="std";
1105
}
1106
else
1107
{
1108
storeGPROpName="stw";
1109
}
1110
1111
TR::MethodSymbol *methodSymbol = node->getSymbol()->castToMethodSymbol();
1112
TR::Linkage* linkage = _cg->getLinkage(methodSymbol->getLinkageConvention());
1113
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
1114
1115
TR::Machine *machine = _cg->machine();
1116
TR::RealRegister *stackPtr = _cg->getStackPointerRegister();
1117
1118
if (linkageProperties.getRightToLeft())
1119
offset = linkage->getOffsetToFirstParm();
1120
else
1121
offset = argSize + linkage->getOffsetToFirstParm();
1122
1123
for (int i = node->getFirstArgumentIndex(); i < node->getNumChildren(); i++)
1124
{
1125
TR::Node *child = node->getChild(i);
1126
switch (child->getDataType())
1127
{
1128
case TR::Int8:
1129
case TR::Int16:
1130
case TR::Int32:
1131
if (!linkageProperties.getRightToLeft())
1132
offset -= sizeof(intptr_t);
1133
if (intArgNum < linkageProperties.getNumIntArgRegs())
1134
{
1135
printPrefix(pOutFile, NULL, cursor, 4);
1136
trfprintf(pOutFile, "stw [");
1137
print(pOutFile, stackPtr, TR_WordReg);
1138
trfprintf(pOutFile, ", %d], ", offset);
1139
print(pOutFile, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), TR_WordReg);
1140
cursor += 4;
1141
}
1142
intArgNum++;
1143
if (linkageProperties.getRightToLeft())
1144
offset += sizeof(intptr_t);
1145
break;
1146
case TR::Address:
1147
if (!linkageProperties.getRightToLeft())
1148
offset -= sizeof(intptr_t);
1149
if (intArgNum < linkageProperties.getNumIntArgRegs())
1150
{
1151
printPrefix(pOutFile, NULL, cursor, 4);
1152
trfprintf(pOutFile, "%s [", storeGPROpName);
1153
print(pOutFile, stackPtr, TR_WordReg);
1154
trfprintf(pOutFile, ", %d], ", offset);
1155
print(pOutFile, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), TR_WordReg);
1156
cursor += 4;
1157
}
1158
intArgNum++;
1159
if (linkageProperties.getRightToLeft())
1160
offset += sizeof(intptr_t);
1161
break;
1162
case TR::Int64:
1163
if (!linkageProperties.getRightToLeft())
1164
offset -= 2*sizeof(intptr_t);
1165
if (intArgNum < linkageProperties.getNumIntArgRegs())
1166
{
1167
printPrefix(pOutFile, NULL, cursor, 4);
1168
trfprintf(pOutFile, "%s [", storeGPROpName);
1169
print(pOutFile, stackPtr, TR_WordReg);
1170
trfprintf(pOutFile, ", %d], ", offset);
1171
print(pOutFile, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), TR_WordReg);
1172
cursor += 4;
1173
if (_comp->target().is32Bit() && (intArgNum < linkageProperties.getNumIntArgRegs() - 1))
1174
{
1175
printPrefix(pOutFile, NULL, cursor, 4);
1176
trfprintf(pOutFile, "stw [");
1177
print(pOutFile, stackPtr, TR_WordReg);
1178
trfprintf(pOutFile, ", %d], ", offset + 4);
1179
print(pOutFile, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum + 1)), TR_WordReg);
1180
cursor += 4;
1181
}
1182
}
1183
if (_comp->target().is64Bit())
1184
intArgNum += 1;
1185
else
1186
intArgNum += 2;
1187
if (linkageProperties.getRightToLeft())
1188
offset += 2*sizeof(intptr_t);
1189
break;
1190
case TR::Float:
1191
if (!linkageProperties.getRightToLeft())
1192
offset -= sizeof(intptr_t);
1193
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
1194
{
1195
printPrefix(pOutFile, NULL, cursor, 4);
1196
trfprintf(pOutFile, "stfs [");
1197
print(pOutFile, stackPtr, TR_WordReg);
1198
trfprintf(pOutFile, ", %d], ", offset);
1199
print(pOutFile, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), TR_WordReg);
1200
cursor += 4;
1201
}
1202
floatArgNum++;
1203
if (linkageProperties.getRightToLeft())
1204
offset += sizeof(intptr_t);
1205
break;
1206
case TR::Double:
1207
if (!linkageProperties.getRightToLeft())
1208
offset -= 2*sizeof(intptr_t);
1209
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
1210
{
1211
printPrefix(pOutFile, NULL, cursor, 4);
1212
trfprintf(pOutFile, "stfd [");
1213
print(pOutFile, stackPtr, TR_WordReg);
1214
trfprintf(pOutFile, ", %d], ", offset);
1215
print(pOutFile, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), TR_WordReg);
1216
cursor += 4;
1217
}
1218
floatArgNum++;
1219
if (linkageProperties.getRightToLeft())
1220
offset += 2*sizeof(intptr_t);
1221
break;
1222
}
1223
}
1224
return(cursor);
1225
}
1226
1227
void
1228
TR_Debug::print(TR::FILE *pOutFile, TR::PPCCallSnippet * snippet)
1229
{
1230
TR::Compilation *comp = _cg->comp();
1231
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
1232
uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();
1233
TR::Node *callNode = snippet->getNode();
1234
TR::SymbolReference *methodSymRef = snippet->getRealMethodSymbolReference() ? snippet->getRealMethodSymbolReference() :
1235
callNode->getSymbolReference();
1236
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
1237
TR::SymbolReference *glueRef = NULL;
1238
const char *labelString = NULL;
1239
bool isNativeStatic = false;
1240
1241
bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp);
1242
if (methodSymbol->isHelper() &&
1243
methodSymRef->isOSRInductionHelper())
1244
{
1245
labelString = "Induce OSR Call Snippet";
1246
glueRef = methodSymRef;
1247
}
1248
else if (methodSymRef->isUnresolved() || forceUnresolvedDispatch)
1249
{
1250
labelString = "Unresolved Direct Call Snippet";
1251
if (methodSymbol->isSpecial())
1252
{
1253
glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedSpecialGlue);
1254
}
1255
else if (methodSymbol->isStatic())
1256
{
1257
glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedStaticGlue);
1258
}
1259
else
1260
{
1261
glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedDirectVirtualGlue);
1262
}
1263
}
1264
else
1265
{
1266
if (methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative())
1267
{
1268
labelString = "Native Static Direct Call Snippet";
1269
glueRef = _cg->getSymRef(TR_PPCnativeStaticHelper);
1270
isNativeStatic = true;
1271
}
1272
else
1273
{
1274
labelString = methodSymbol->isJNI() ? "Interpreted JNI Direct Call Snippet" : "Interpreted Direct Call Snippet";
1275
bool synchronised = methodSymbol->isSynchronised();
1276
switch (callNode->getDataType())
1277
{
1278
case TR::NoType:
1279
if (synchronised)
1280
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncVoidStaticGlue);
1281
else
1282
glueRef = _cg->getSymRef(TR_PPCinterpreterVoidStaticGlue);
1283
break;
1284
1285
case TR::Int32:
1286
if (synchronised)
1287
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncGPR3StaticGlue);
1288
else
1289
glueRef = _cg->getSymRef(TR_PPCinterpreterGPR3StaticGlue);
1290
break;
1291
1292
case TR::Address:
1293
if (_comp->target().is64Bit())
1294
{
1295
if (synchronised)
1296
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncGPR3GPR4StaticGlue);
1297
else
1298
glueRef = _cg->getSymRef(TR_PPCinterpreterGPR3GPR4StaticGlue);
1299
}
1300
else
1301
{
1302
if (synchronised)
1303
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncGPR3StaticGlue);
1304
else
1305
glueRef = _cg->getSymRef(TR_PPCinterpreterGPR3StaticGlue);
1306
}
1307
break;
1308
1309
case TR::Int64:
1310
if (synchronised)
1311
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncGPR3GPR4StaticGlue);
1312
else
1313
glueRef = _cg->getSymRef(TR_PPCinterpreterGPR3GPR4StaticGlue);
1314
break;
1315
1316
case TR::Float:
1317
if (synchronised)
1318
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncFPR0FStaticGlue);
1319
else
1320
glueRef = _cg->getSymRef(TR_PPCinterpreterFPR0FStaticGlue);
1321
break;
1322
1323
case TR::Double:
1324
if (synchronised)
1325
glueRef = _cg->getSymRef(TR_PPCinterpreterSyncFPR0DStaticGlue);
1326
else
1327
glueRef = _cg->getSymRef(TR_PPCinterpreterFPR0DStaticGlue);
1328
break;
1329
1330
default:
1331
TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n",
1332
getName(callNode->getDataType()));
1333
}
1334
}
1335
}
1336
1337
TR_ASSERT(glueRef && labelString, "Expecting to have symref and label string at this point");
1338
1339
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, labelString);
1340
1341
cursor = printPPCArgumentsFlush(pOutFile, callNode, cursor, snippet->getSizeOfArguments());
1342
1343
char *info = "";
1344
int32_t distance;
1345
if (isBranchToTrampoline(glueRef, cursor, distance))
1346
info = " Through trampoline";
1347
1348
printPrefix(pOutFile, NULL, cursor, 4);
1349
distance = *((int32_t *) cursor) & 0x03fffffc;
1350
distance = (distance << 6) >> 6; // sign extend
1351
trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, info);
1352
cursor += 4;
1353
1354
if (isNativeStatic)
1355
{
1356
printPrefix(pOutFile, NULL, cursor, 4);
1357
distance = *((int32_t *) cursor) & 0x03fffffc;
1358
distance = (distance << 6) >> 6; // sign extend
1359
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, " back to program code");
1360
cursor += 4;
1361
1362
if (_comp->target().is64Bit())
1363
{
1364
printPrefix(pOutFile, NULL, cursor, 4);
1365
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Padding", *(int32_t *)cursor);
1366
cursor += 4;
1367
}
1368
}
1369
else
1370
{
1371
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1372
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Call Site RA", snippet->getCallRA());
1373
cursor += sizeof(intptr_t);
1374
}
1375
1376
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1377
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Method Pointer", *(uintptr_t *)cursor);
1378
cursor += sizeof(intptr_t);
1379
1380
printPrefix(pOutFile, NULL, cursor, 4);
1381
trfprintf(pOutFile, ".long \t0x%08x\t\t; Lock Word For Compilation", *(int32_t *)cursor);
1382
}
1383
1384
void
1385
TR_Debug::print(TR::FILE *pOutFile, TR::PPCUnresolvedCallSnippet * snippet)
1386
{
1387
uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation() + snippet->getLength(0) - (8+sizeof(intptr_t));
1388
1389
TR::SymbolReference *methodSymRef = snippet->getNode()->getSymbolReference();
1390
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
1391
1392
int32_t helperLookupOffset;
1393
switch (snippet->getNode()->getDataType())
1394
{
1395
case TR::NoType:
1396
helperLookupOffset = 0;
1397
break;
1398
case TR::Int32:
1399
case TR::Address:
1400
helperLookupOffset = 4;
1401
break;
1402
case TR::Int64:
1403
helperLookupOffset = 8;
1404
break;
1405
case TR::Float:
1406
helperLookupOffset = 12;
1407
break;
1408
case TR::Double:
1409
helperLookupOffset = 16;
1410
break;
1411
}
1412
1413
print(pOutFile, (TR::PPCCallSnippet *) snippet);
1414
1415
printPrefix(pOutFile, NULL, cursor, 4);
1416
trfprintf(pOutFile,
1417
".long \t0x%08x\t\t; Offset | Flag | CP Index",
1418
(helperLookupOffset << 24) | methodSymRef->getCPIndexForVM());
1419
cursor += 4;
1420
1421
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1422
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Pointer To Constant Pool", *(intptr_t *)cursor);
1423
cursor += sizeof(intptr_t);
1424
1425
printPrefix(pOutFile, NULL, cursor, 4);
1426
trfprintf(pOutFile, ".long \t0x%08x\t\t; Lock Word For Resolution", *(int32_t *)cursor);
1427
}
1428
1429
void
1430
TR_Debug::print(TR::FILE *pOutFile, TR::PPCVirtualSnippet * snippet)
1431
{
1432
}
1433
1434
void
1435
TR_Debug::print(TR::FILE *pOutFile, TR::PPCVirtualUnresolvedSnippet * snippet)
1436
{
1437
uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();
1438
TR::Node *callNode = snippet->getNode();
1439
1440
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Virtual Unresolved Call Snippet");
1441
1442
char *info = "";
1443
int32_t distance;
1444
if (isBranchToTrampoline(_cg->getSymRef(TR_PPCvirtualUnresolvedHelper), cursor, distance))
1445
info = " Through trampoline";
1446
1447
printPrefix(pOutFile, NULL, cursor, 4);
1448
distance = *((int32_t *) cursor) & 0x03fffffc;
1449
distance = (distance << 6) >> 6; // sign extend
1450
trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, info);
1451
cursor += 4;
1452
1453
printPrefix(pOutFile, NULL, cursor, 4);
1454
distance = *((int32_t *) cursor) & 0x03fffffc;
1455
distance = (distance << 6) >> 6; // sign extend
1456
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; Back to program code", (intptr_t)cursor + distance);
1457
cursor += 4;
1458
1459
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1460
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Call Site RA", (intptr_t)snippet->getReturnLabel()->getCodeLocation());
1461
cursor += sizeof(intptr_t);
1462
1463
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1464
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Constant Pool Pointer", (intptr_t)getOwningMethod(callNode->getSymbolReference())->constantPool());
1465
cursor += sizeof(intptr_t);
1466
1467
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1468
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Constant Pool Index", callNode->getSymbolReference()->getCPIndexForVM());
1469
cursor += sizeof(intptr_t);
1470
1471
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1472
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Private J9Method pointer", *(intptr_t *)cursor);
1473
cursor += sizeof(intptr_t);
1474
1475
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1476
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; J2I thunk address for private", *(intptr_t *)cursor);
1477
cursor += sizeof(intptr_t);
1478
1479
printPrefix(pOutFile, NULL, cursor, 4);
1480
trfprintf(pOutFile, ".long \t0x%08x\t\t; Lock Word For Resolution", *(int32_t *)cursor);
1481
}
1482
1483
void
1484
TR_Debug::print(TR::FILE *pOutFile, TR::PPCInterfaceCallSnippet * snippet)
1485
{
1486
uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();
1487
TR::Node *callNode = snippet->getNode();
1488
1489
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Call Snippet");
1490
1491
char *info = "";
1492
int32_t distance;
1493
if (isBranchToTrampoline(_cg->getSymRef(TR_PPCinterfaceCallHelper), cursor, distance))
1494
info = " Through trampoline";
1495
1496
printPrefix(pOutFile, NULL, cursor, 4);
1497
distance = *((int32_t *) cursor) & 0x03fffffc;
1498
distance = (distance << 6) >> 6; // sign extend
1499
trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, info);
1500
cursor += 4;
1501
1502
printPrefix(pOutFile, NULL, cursor, 4);
1503
distance = *((int32_t *) cursor) & 0x03fffffc;
1504
distance = (distance << 6) >> 6; // sign extend
1505
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; Back to program code", (intptr_t)cursor + distance);
1506
cursor += 4;
1507
1508
if (_comp->target().is64Bit())
1509
{
1510
printPrefix(pOutFile, NULL, cursor, 4);
1511
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Padding", *(int32_t *)cursor);
1512
cursor += 4;
1513
}
1514
1515
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1516
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Constant Pool Pointer", *(uintptr_t*)cursor);
1517
cursor += sizeof(intptr_t);
1518
1519
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1520
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Constant Pool Index", *(uintptr_t*)cursor);
1521
cursor += sizeof(intptr_t);
1522
1523
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1524
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Interface Class Pointer", *(uintptr_t*)cursor);
1525
cursor += sizeof(intptr_t);
1526
1527
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1528
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; ITable Index", *(uintptr_t*)cursor);
1529
cursor += sizeof(intptr_t);
1530
1531
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1532
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; First Class Pointer", *(int32_t *)cursor);
1533
cursor += sizeof(intptr_t);
1534
1535
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1536
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; First Class Target", *(int32_t *)cursor);
1537
cursor += sizeof(intptr_t);
1538
1539
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1540
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Second Class Pointer", *(int32_t *)cursor);
1541
cursor += sizeof(intptr_t);
1542
1543
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1544
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Second Class Target", *(int32_t *)cursor);
1545
cursor += sizeof(intptr_t);
1546
1547
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
1548
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; J2I thunk address for private", *(intptr_t *)cursor);
1549
}
1550
1551
1552