Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/arm/codegen/CallSnippet.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 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 "codegen/CallSnippet.hpp"
24
#include "codegen/Linkage.hpp"
25
#include "codegen/Linkage_inlines.hpp"
26
#include "codegen/Machine.hpp"
27
#include "codegen/Register.hpp"
28
#include "codegen/ARMAOTRelocation.hpp"
29
#include "env/CompilerEnv.hpp"
30
#include "env/J2IThunk.hpp"
31
#include "env/VMJ9.h"
32
#include "codegen/CodeGenerator.hpp" /* @@@@ */
33
#include "il/Node.hpp"
34
#include "il/Node_inlines.hpp"
35
36
#define TR_ARM_ARG_SLOT_SIZE 4
37
38
static uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
39
{
40
uint32_t intArgNum=0, floatArgNum=0, offset;
41
TR::Machine *machine = cg->machine();
42
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
43
const TR::ARMLinkageProperties &linkageProperties = linkage->getProperties();
44
int32_t argStart = callNode->getFirstArgumentIndex();
45
46
if (linkageProperties.getRightToLeft())
47
offset = linkage->getOffsetToFirstParm();
48
else
49
offset = argSize+linkage->getOffsetToFirstParm();
50
51
for (int i=argStart; i<callNode->getNumChildren();i++)
52
{
53
TR::Node *child = callNode->getChild(i);
54
switch (child->getDataType())
55
{
56
case TR::Int8:
57
case TR::Int16:
58
case TR::Int32:
59
case TR::Address:
60
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
61
case TR::Float:
62
#endif
63
if (!linkageProperties.getRightToLeft())
64
offset -= 4;
65
if (intArgNum < linkageProperties.getNumIntArgRegs())
66
{
67
buffer = storeArgumentItem(TR::InstOpCode::str, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
68
}
69
intArgNum++;
70
if (linkageProperties.getRightToLeft())
71
offset += 4;
72
break;
73
case TR::Int64:
74
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
75
case TR::Double:
76
#endif
77
if (!linkageProperties.getRightToLeft())
78
offset -= 8;
79
if (intArgNum < linkageProperties.getNumIntArgRegs())
80
{
81
buffer = storeArgumentItem(TR::InstOpCode::str, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
82
if (intArgNum < linkageProperties.getNumIntArgRegs()-1)
83
{
84
buffer = storeArgumentItem(TR::InstOpCode::str, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum+1)), offset+4, cg);
85
}
86
}
87
intArgNum += 2;
88
if (linkageProperties.getRightToLeft())
89
offset += 8;
90
break;
91
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
92
case TR::Float:
93
/* TODO
94
if (!linkageProperties.getRightToLeft())
95
offset -= 4;
96
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
97
{
98
buffer = storeArgumentItem(TR::InstOpCode::stfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
99
}
100
floatArgNum++;
101
if (linkageProperties.getRightToLeft())
102
offset += 4;
103
*/
104
break;
105
case TR::Double:
106
/* TODO
107
if (!linkageProperties.getRightToLeft())
108
offset -= 8;
109
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
110
{
111
buffer = storeArgumentItem(TR::InstOpCode::stfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
112
}
113
floatArgNum++;
114
if (linkageProperties.getRightToLeft())
115
offset += 8;
116
*/
117
break;
118
#endif
119
}
120
}
121
return(buffer);
122
}
123
124
static int32_t instructionCountForArguments(TR::Node *callNode, TR::CodeGenerator *cg)
125
{
126
uint32_t intArgNum=0, floatArgNum=0, count=0;
127
const TR::ARMLinkageProperties &linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention())->getProperties();
128
int32_t argStart = callNode->getFirstArgumentIndex();
129
130
for (int i=argStart; i<callNode->getNumChildren();i++)
131
{
132
TR::Node *child = callNode->getChild(i);
133
switch (child->getDataType())
134
{
135
case TR::Int8:
136
case TR::Int16:
137
case TR::Int32:
138
case TR::Address:
139
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
140
case TR::Float:
141
#endif
142
if (intArgNum < linkage.getNumIntArgRegs())
143
{
144
count++;
145
}
146
intArgNum++;
147
break;
148
case TR::Int64:
149
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
150
case TR::Double:
151
#endif
152
if (intArgNum < linkage.getNumIntArgRegs())
153
{
154
count++;
155
if (intArgNum < linkage.getNumIntArgRegs()-1)
156
{
157
count++;
158
}
159
}
160
intArgNum += 2;
161
break;
162
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
163
case TR::Float:
164
if (floatArgNum < linkage.getNumFloatArgRegs())
165
{
166
count++;
167
}
168
floatArgNum++;
169
break;
170
case TR::Double:
171
if (floatArgNum < linkage.getNumFloatArgRegs())
172
{
173
count++;
174
}
175
floatArgNum++;
176
break;
177
#endif
178
}
179
}
180
return(count);
181
}
182
183
TR_RuntimeHelper
184
TR::ARMCallSnippet::getHelper()
185
{
186
TR::Compilation * comp = cg()->comp();
187
TR_J9VMBase *fej9 = (TR_J9VMBase *) (cg()->fe());
188
TR::Node *callNode = getNode();
189
TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
190
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
191
TR::SymbolReference *glueRef = NULL;
192
193
if (methodSymRef->isUnresolved() || comp->compileRelocatableCode())
194
{
195
if (methodSymbol->isSpecial())
196
return TR_ARMinterpreterUnresolvedSpecialGlue;
197
if (methodSymbol->isStatic())
198
return TR_ARMinterpreterUnresolvedStaticGlue;
199
return TR_ARMinterpreterUnresolvedDirectVirtualGlue;
200
}
201
202
bool synchronised = methodSymbol->isSynchronised();
203
204
if (methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative())
205
return TR_ARMnativeStaticHelper;
206
207
TR::DataType dataType = callNode->getDataType();
208
switch (dataType)
209
{
210
case TR::NoType:
211
if (synchronised)
212
return TR_ARMinterpreterSyncVoidStaticGlue;
213
return TR_ARMinterpreterVoidStaticGlue;
214
215
case TR::Int32:
216
case TR::Address:
217
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
218
case TR::Float:
219
#endif
220
if (synchronised)
221
return TR_ARMinterpreterSyncGPR3StaticGlue;
222
return TR_ARMinterpreterGPR3StaticGlue;
223
224
case TR::Int64:
225
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
226
case TR::Double:
227
#endif
228
if (synchronised)
229
return TR_ARMinterpreterSyncGPR3GPR4StaticGlue;
230
return TR_ARMinterpreterGPR3GPR4StaticGlue;
231
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
232
case TR::Float:
233
if (synchronised)
234
return TR_ARMinterpreterSyncFPR0FStaticGlue;
235
return TR_ARMinterpreterFPR0FStaticGlue;
236
237
case TR::Double:
238
if (synchronised)
239
return TR_ARMinterpreterSyncFPR0DStaticGlue;
240
return TR_ARMinterpreterFPR0DStaticGlue;
241
#endif
242
default:
243
TR_ASSERT(false, "Bad return data type for a call node. DataType was %s\n",
244
cg()->getDebug()->getName(dataType));
245
return (TR_RuntimeHelper)0;
246
}
247
}
248
249
uint8_t *TR::ARMCallSnippet::emitSnippetBody()
250
{
251
TR_J9VMBase *fej9 = (TR_J9VMBase *) (cg()->fe());
252
uint8_t *cursor = cg()->getBinaryBufferCursor();
253
TR::Node *callNode = getNode();
254
TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
255
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
256
TR::SymbolReference *glueRef;
257
TR::Compilation *comp = cg()->comp();
258
void *trmpln = NULL;
259
260
getSnippetLabel()->setCodeLocation(cursor);
261
262
// Flush in-register arguments back to the stack for interpreter
263
cursor = flushArgumentsToStack(cursor, callNode, getSizeOfArguments(), cg());
264
265
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(getHelper());
266
267
// bl glueRef
268
*(int32_t *)cursor = encodeHelperBranchAndLink(glueRef, cursor, callNode, cg());
269
cursor += 4;
270
271
// Store the code cache RA
272
*(int32_t *)cursor = (intptr_t)getCallRA();
273
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
274
cursor,
275
NULL,
276
TR_AbsoluteMethodAddress, cg()), __FILE__, __LINE__, getNode());
277
cursor += 4;
278
279
// Store the method pointer: it is NULL for unresolved
280
if (methodSymRef->isUnresolved() || comp->compileRelocatableCode())
281
{
282
*(int32_t *)cursor = 0;
283
if (comp->getOption(TR_EnableHCR))
284
{
285
cg()->jitAddPicToPatchOnClassRedefinition((void*)-1, (void *)cursor, true);
286
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation((uint8_t *)cursor, NULL,(uint8_t *)needsFullSizeRuntimeAssumption,
287
TR_HCR, cg()),__FILE__, __LINE__,
288
getNode());
289
}
290
}
291
else
292
{
293
*(int32_t *)cursor = (uintptr_t)methodSymbol->getMethodAddress();
294
if (comp->getOption(TR_EnableHCR))
295
cg()->jitAddPicToPatchOnClassRedefinition((void *)methodSymbol->getMethodAddress(), (void *)cursor);
296
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *)methodSymRef,
297
getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
298
TR_MethodObject, cg()),
299
__FILE__, __LINE__, callNode);
300
/*
301
TR_RelocationRecordInformation *recordInfo = ( TR_RelocationRecordInformation *)comp->trMemory()->allocateMemory(sizeof( TR_RelocationRecordInformation), heapAlloc);
302
recordInfo->data1 = (uintptr_t)methodSymRef;
303
recordInfo->data2 = (uintptr_t)(getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1);
304
recordInfo->data3 = (uintptr_t)fixedSequence1;
305
306
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
307
cursor,
308
(uint8_t *)recordInfo,
309
TR_MethodObject, cg()), __FILE__, __LINE__, getNode());
310
*/
311
}
312
cursor += TR::Compiler->om.sizeofReferenceAddress();
313
314
// Lock word initialized to 0
315
*(int32_t *)cursor = 0;
316
317
return (cursor+4);
318
}
319
320
uint32_t TR::ARMCallSnippet::getLength(int32_t estimatedSnippetStart)
321
{
322
return((instructionCountForArguments(getNode(), cg()) + 4) * 4);
323
}
324
325
326
uint8_t *TR::ARMUnresolvedCallSnippet::emitSnippetBody()
327
{
328
TR_J9VMBase *fej9 = (TR_J9VMBase *) (cg()->fe());
329
uint8_t *cursor = TR::ARMCallSnippet::emitSnippetBody();
330
331
TR::SymbolReference *methodSymRef = getNode()->getSymbolReference();
332
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
333
int32_t helperLookupOffset;
334
335
TR::Compilation* comp = cg()->comp();
336
337
switch (getNode()->getDataType())
338
{
339
case TR::NoType:
340
helperLookupOffset = 0;
341
break;
342
case TR::Int32:
343
case TR::Address:
344
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
345
case TR::Float:
346
#endif
347
helperLookupOffset = 4;
348
break;
349
case TR::Int64:
350
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
351
case TR::Double:
352
#endif
353
helperLookupOffset = 8;
354
break;
355
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
356
case TR::Float:
357
helperLookupOffset = 12;
358
break;
359
case TR::Double:
360
helperLookupOffset = 16;
361
break;
362
#endif
363
}
364
365
*(int32_t *)cursor = (helperLookupOffset<<24) | methodSymRef->getCPIndexForVM();
366
cursor += 4;
367
*(int32_t *)cursor = (intptr_t)methodSymRef->getOwningMethod(comp)->constantPool();
368
369
if (comp->compileRelocatableCode() && comp->getOption(TR_TraceRelocatableDataDetailsCG))
370
{
371
traceMsg(comp, "<relocatableDataTrampolinesCG>\n");
372
traceMsg(comp, "%s\n", comp->signature());
373
traceMsg(comp, "%-8s", "cpIndex");
374
traceMsg(comp, "cp\n");
375
traceMsg(comp, "%-8x", methodSymRef->getCPIndexForVM());
376
traceMsg(comp, "%x\n", methodSymRef->getOwningMethod(comp)->constantPool());
377
traceMsg(comp, "</relocatableDataTrampolinesCG>\n");
378
}
379
380
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
381
cursor,
382
*(uint8_t **)cursor,
383
getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
384
TR_Trampolines, cg()), __FILE__, __LINE__, getNode());
385
386
return cursor+4;
387
}
388
389
uint32_t TR::ARMUnresolvedCallSnippet::getLength(int32_t estimatedSnippetStart)
390
{
391
return TR::ARMCallSnippet::getLength(estimatedSnippetStart) + 8;
392
}
393
394
uint8_t *TR::ARMVirtualUnresolvedSnippet::emitSnippetBody()
395
{
396
uint8_t *cursor = cg()->getBinaryBufferCursor();
397
TR::SymbolReference *methodSymRef = getNode()->getSymbolReference();
398
TR::SymbolReference *glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_ARMvirtualUnresolvedHelper);
399
400
TR::Compilation* comp = cg()->comp();
401
402
getSnippetLabel()->setCodeLocation(cursor);
403
404
// bl glueRef
405
*(int32_t *)cursor = encodeHelperBranchAndLink(glueRef, cursor, getNode(), cg());
406
cursor += 4;
407
408
// Store the code cache RA
409
*(int32_t *)cursor = (intptr_t)getReturnLabel()->getCodeLocation();
410
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
411
cursor,
412
NULL,
413
TR_AbsoluteMethodAddress, cg()), __FILE__, __LINE__, getNode());
414
cursor += 4;
415
416
// CP
417
*(int32_t *)cursor = (intptr_t)methodSymRef->getOwningMethod(comp)->constantPool();
418
419
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
420
cursor,
421
*(uint8_t **)cursor,
422
getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
423
TR_Thunks, cg()), __FILE__, __LINE__, getNode());
424
425
cursor += 4;
426
427
// CP index
428
*(int32_t *)cursor = methodSymRef->getCPIndexForVM();
429
430
return (cursor + 4);
431
}
432
433
uint32_t TR::ARMVirtualUnresolvedSnippet::getLength(int32_t estimatedSnippetStart)
434
{
435
return 16;
436
}
437
438
uint8_t *TR::ARMInterfaceCallSnippet::emitSnippetBody()
439
{
440
uint8_t *cursor = cg()->getBinaryBufferCursor();
441
TR::SymbolReference *methodSymRef = getNode()->getSymbolReference();
442
TR::SymbolReference *glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_ARMinterfaceCallHelper);
443
444
getSnippetLabel()->setCodeLocation(cursor);
445
446
// bl glueRef
447
*(int32_t *)cursor = encodeHelperBranchAndLink(glueRef, cursor, getNode(), cg());
448
cursor += 4;
449
450
// Store the code cache RA
451
*(int32_t *)cursor = (intptr_t)getReturnLabel()->getCodeLocation();
452
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
453
cursor,
454
NULL,
455
TR_AbsoluteMethodAddress, cg()), __FILE__, __LINE__, getNode());
456
cursor += 4;
457
458
*(int32_t *)cursor = (intptr_t)methodSymRef->getOwningMethod(cg()->comp())->constantPool();
459
460
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(
461
cursor,
462
*(uint8_t **)cursor,
463
getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,
464
TR_Thunks, cg()), __FILE__, __LINE__, getNode());
465
466
cursor += 4;
467
468
*(int32_t *)cursor = methodSymRef->getCPIndexForVM();
469
cursor += 4;
470
471
// Add 2 more slots for resolved values
472
*(int32_t *)cursor = 0;
473
cursor += 4;
474
*(int32_t *)cursor = 0;
475
cursor += 4;
476
477
#if 0
478
// AOT TODO
479
// Patch up the main line codes
480
int32_t *patchAddress1 = NULL; // TODO (int32_t *)getUpperInstruction()->getBinaryEncoding();
481
*patchAddress1 |= (((int32_t)cursor>>16) + (((int32_t)cursor & (1<<15))?1:0)) & 0x0000ffff;
482
483
int32_t *patchAddress2 = NULL; // TODO (int32_t *)getLowerInstruction()->getBinaryEncoding();
484
*patchAddress2 |= (int32_t)cursor & 0x0000ffff;
485
cg()->addRelocation(new (cg()->trHeapMemory()) TR::ExternalOrderedPair32BitRelocation(
486
(uint8_t *)patchAddress1,
487
(uint8_t *)patchAddress2,
488
NULL,
489
TR_AbsoluteMethodAddress));
490
#endif
491
492
return cursor;
493
}
494
495
uint32_t TR::ARMInterfaceCallSnippet::getLength(int32_t estimatedSnippetStart)
496
{
497
return 24;
498
}
499
500
uint8_t *TR::ARMCallSnippet::generateVIThunk(TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
501
{
502
TR_J9VMBase *fej9 = (TR_J9VMBase *) (cg->fe());
503
int32_t codeSize = 4*(instructionCountForArguments(callNode, cg) + 2) + 8; // Additional 4 bytes to hold size of thunk
504
uint8_t *thunk, *buffer, *returnValue;
505
int32_t dispatcher;
506
507
if (cg->comp()->compileRelocatableCode())
508
thunk = (uint8_t *)TR::comp()->trMemory()->allocateMemory(codeSize, heapAlloc);
509
else
510
thunk = (uint8_t *)cg->allocateCodeMemory(codeSize, true, false);
511
buffer = returnValue = thunk + 8;
512
TR_RuntimeHelper helper;
513
TR::DataType dataType = callNode->getDataType();
514
515
switch (dataType)
516
{
517
case TR::NoType:
518
helper = TR_ARMicallVMprJavaSendVirtual0;
519
break;
520
case TR::Int32:
521
case TR::Address:
522
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
523
case TR::Float:
524
#endif
525
helper = TR_ARMicallVMprJavaSendVirtual1;
526
break;
527
case TR::Int64:
528
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
529
case TR::Double:
530
#endif
531
helper = TR_ARMicallVMprJavaSendVirtualJ;
532
break;
533
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
534
case TR::Float:
535
helper = TR_ARMicallVMprJavaSendVirtualF;
536
break;
537
case TR::Double:
538
helper = TR_ARMicallVMprJavaSendVirtualD;
539
break;
540
#endif
541
default:
542
TR_ASSERT(false, "Bad return data type for a call node. DataType was %s\n",
543
cg->getDebug()->getName(dataType));
544
}
545
546
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(helper)->getMethodAddress();
547
548
buffer = flushArgumentsToStack(buffer, callNode, argSize, cg);
549
550
*(int32_t *)buffer = 0xE51FF004; // ldr r15, [r15, #-4]
551
buffer += 4;
552
553
*((int32_t *)thunk + 1) = buffer - returnValue; // patch offset for AOT relocation
554
555
*(int32_t *)buffer = dispatcher; // address of transition target
556
buffer += 4;
557
558
*(int32_t *)thunk = buffer - returnValue; // patch size of thunk
559
560
#ifdef TR_HOST_ARM
561
armCodeSync(thunk, codeSize);
562
#endif
563
564
return(returnValue);
565
}
566
567
TR_J2IThunk *TR::ARMCallSnippet::generateInvokeExactJ2IThunk(TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg, char *signature)
568
{
569
int32_t codeSize = 4*(instructionCountForArguments(callNode, cg) + 2) + 8; // Additional 4 bytes to hold size of thunk
570
int32_t dispatcher;
571
TR_J2IThunkTable *thunkTable = TR::comp()->getPersistentInfo()->getInvokeExactJ2IThunkTable();
572
TR_J2IThunk *thunk = TR_J2IThunk::allocate(codeSize, signature, cg, thunkTable);
573
uint8_t *buffer = thunk->entryPoint();
574
575
TR_RuntimeHelper helper;
576
TR::DataType dataType = callNode->getDataType();
577
578
switch (dataType)
579
{
580
case TR::NoType:
581
helper = TR_icallVMprJavaSendInvokeExact0;
582
break;
583
case TR::Int32:
584
case TR::Address:
585
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
586
case TR::Float:
587
#endif
588
helper = TR_icallVMprJavaSendInvokeExact1;
589
break;
590
case TR::Int64:
591
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
592
case TR::Double:
593
#endif
594
helper = TR_icallVMprJavaSendInvokeExactJ;
595
break;
596
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
597
case TR::Float:
598
helper = TR_icallVMprJavaSendInvokeExactF;
599
break;
600
case TR::Double:
601
helper = TR_icallVMprJavaSendInvokeExactD;
602
break;
603
#endif
604
default:
605
TR_ASSERT(false, "Bad return data type for a call node. DataType was %s\n",
606
cg->getDebug()->getName(dataType));
607
}
608
609
dispatcher = (intptr_t)cg->symRefTab()->findOrCreateRuntimeHelper(helper)->getMethodAddress();
610
611
buffer = flushArgumentsToStack(buffer, callNode, argSize, cg);
612
613
*(int32_t *)buffer = 0xE51FF004; // ldr r15, [r15, #-4]
614
buffer += 4;
615
616
*(int32_t *)buffer = dispatcher; // address of transition target
617
buffer += 4;
618
619
#ifdef TR_HOST_ARM
620
armCodeSync(thunk->entryPoint(), codeSize);
621
#endif
622
623
return(thunk);
624
}
625
626
627