Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/z/codegen/J9UnresolvedDataSnippet.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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
23
#pragma csect(CODE,"J9ZUnresolvedDataSnippet#C")
24
#pragma csect(STATIC,"J9ZUnresolvedDataSnippet#S")
25
#pragma csect(TEST,"J9ZUnresolvedDataSnippet#T")
26
27
28
#include "codegen/UnresolvedDataSnippet.hpp"
29
#include "codegen/UnresolvedDataSnippet_inlines.hpp"
30
31
#include <stddef.h>
32
#include <stdint.h>
33
#include "codegen/CodeGenerator.hpp"
34
#include "codegen/InstOpCode.hpp"
35
#include "codegen/Instruction.hpp"
36
#include "codegen/MemoryReference.hpp"
37
#include "codegen/RealRegister.hpp"
38
#include "codegen/Register.hpp"
39
#include "codegen/RegisterDependency.hpp"
40
#include "codegen/RegisterPair.hpp"
41
#include "codegen/Relocation.hpp"
42
#include "compile/Compilation.hpp"
43
#include "compile/ResolvedMethod.hpp"
44
#include "compile/SymbolReferenceTable.hpp"
45
#include "control/Options.hpp"
46
#include "control/Options_inlines.hpp"
47
#include "env/IO.hpp"
48
#include "env/TRMemory.hpp"
49
#include "env/jittypes.h"
50
#include "il/DataTypes.hpp"
51
#include "il/LabelSymbol.hpp"
52
#include "il/Node.hpp"
53
#include "il/StaticSymbol.hpp"
54
#include "il/StaticSymbol_inlines.hpp"
55
#include "il/Symbol.hpp"
56
#include "il/SymbolReference.hpp"
57
#include "infra/Assert.hpp"
58
#include "ras/Debug.hpp"
59
#include "runtime/J9Runtime.hpp"
60
#include "env/CompilerEnv.hpp"
61
62
namespace TR { class S390WritableDataSnippet; }
63
64
J9::Z::UnresolvedDataSnippet::UnresolvedDataSnippet(
65
TR::CodeGenerator *cg,
66
TR::Node *node,
67
TR::SymbolReference *symRef,
68
bool isStore,
69
bool canCauseGC) :
70
J9::UnresolvedDataSnippet(cg, node, symRef, isStore, canCauseGC),
71
_branchInstruction(NULL),
72
_dataReferenceInstruction(NULL),
73
_dataSymbolReference(symRef),
74
_unresolvedData(NULL),
75
_memoryReference(NULL),
76
_isStore(isStore)
77
{
78
TR_ASSERT( (symRef != NULL), " UDS: _dataSymbolRef is NULL !");
79
}
80
81
82
uint8_t *
83
J9::Z::UnresolvedDataSnippet::getAddressOfDataReference()
84
{
85
return (uint8_t *) (_branchInstruction->getNext())->getBinaryEncoding();
86
}
87
88
89
TR::Instruction *
90
J9::Z::UnresolvedDataSnippet::setDataReferenceInstruction(TR::Instruction *i)
91
{
92
// For instance data snippets, we need to guarantee that the branch
93
// is right before the load/store it needs to update.
94
if (isInstanceData())
95
{
96
// Return address register may be used if unresolved offset is > 4k.
97
// PicBuilder will patch the base register of the load/store with RA register,
98
// which will contain the sum of original base register and resolved offset.
99
// Since this introduces some internal control flow, we need to ensure all registers
100
// used in the control flow are added as dependencies.
101
// We can have up to 6 dependencies:
102
// 1. Branch RA register.
103
// 2. Base Register for MR.
104
// 3. Index Register for MR.
105
// 4-6 "target" register. 2-3 dependencies requires for STM/LM.
106
107
TR::Instruction* brInstr = getBranchInstruction();
108
if (brInstr != NULL && brInstr->getNext() != i)
109
{
110
// Remove _branchInstruction
111
brInstr->getPrev()->setNext(brInstr->getNext());
112
brInstr->getNext()->setPrev(brInstr->getPrev());
113
114
// Insert before current instruction
115
brInstr->setPrev(i->getPrev());
116
brInstr->setNext(i);
117
brInstr->getPrev()->setNext(brInstr);
118
i->setPrev(brInstr);
119
}
120
121
TR::RegisterDependencyConditions* dependencies = new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0, 6, cg());
122
123
// The instruction after the branch should be our memory access instruction.
124
TR::Instruction *memRefInstr = i;
125
126
TR::MemoryReference* memRef = memRefInstr->getMemoryReference();
127
TR_ASSERT(memRef != NULL, "Unexpected instruction for unresolved data sequence.\n");
128
129
TR::Register* baseReg = memRef->getBaseRegister();
130
TR::Register* indexReg = memRef->getIndexRegister();
131
132
if (baseReg != NULL && baseReg->getRealRegister() == NULL) // BaseReg may be a real Reg GPR0.
133
dependencies->addPostCondition(baseReg, TR::RealRegister::AssignAny);
134
if (indexReg != NULL && indexReg != baseReg)
135
dependencies->addPostCondition(indexReg, TR::RealRegister::AssignAny);
136
137
TR::Register* targetReg = memRefInstr->getRegisterOperand(1);
138
if (targetReg != NULL && targetReg != baseReg && targetReg != indexReg)
139
{
140
// Handle Register Pairs
141
TR::RegisterPair* targetRegPair = targetReg->getRegisterPair();
142
if (targetRegPair != NULL)
143
{
144
// Force any register pairs used by LM/STM into GPR0:GPR1, to avoid potential issues
145
// between register pairs and real register dependencies.
146
dependencies->addPostCondition(targetRegPair->getHighOrder(), TR::RealRegister::GPR0);
147
dependencies->addPostCondition(targetRegPair->getLowOrder(), TR::RealRegister::GPR1);
148
}
149
else
150
{
151
dependencies->addPostCondition(targetReg, TR::RealRegister::AssignAny);
152
}
153
}
154
// Return Address Register may be used to patch long offsets.
155
TR::RegisterDependencyConditions* brDependencies = brInstr->getDependencyConditions();
156
TR::Register* returnReg = brDependencies->searchPostConditionRegister(cg()->getReturnAddressRegister());
157
TR_ASSERT(returnReg != NULL, "Expect return address register in reg deps.");
158
dependencies->addPostCondition(returnReg, cg()->getReturnAddressRegister());
159
160
memRefInstr->setDependencyConditions(dependencies);
161
}
162
return _dataReferenceInstruction = i;
163
}
164
165
166
uint8_t *
167
J9::Z::UnresolvedDataSnippet::emitSnippetBody()
168
{
169
TR::Compilation *comp = cg()->comp();
170
uint8_t * cursor = cg()->getBinaryBufferCursor();
171
TR::SymbolReference * glueRef;
172
173
//Grab the snippet's start point
174
getSnippetLabel()->setCodeLocation(cursor);
175
176
// setup the address of the picbuilder function
177
178
if (getDataSymbol()->getShadowSymbol() != NULL)
179
{
180
if (resolveForStore())
181
{
182
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedInstanceDataStoreGlue);
183
}
184
else
185
{
186
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedInstanceDataGlue);
187
}
188
}
189
else if (getDataSymbol()->isClassObject())
190
{
191
if (getDataSymbol()->addressIsCPIndexOfStatic())
192
{
193
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedClassGlue2);
194
}
195
else
196
{
197
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedClassGlue);
198
}
199
}
200
else if (getDataSymbol()->isConstString())
201
{
202
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStringGlue);
203
}
204
else if (getDataSymbol()->isConstMethodType())
205
{
206
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodTypeGlue);
207
}
208
else if (getDataSymbol()->isConstMethodHandle())
209
{
210
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodHandleGlue);
211
}
212
else if (getDataSymbol()->isCallSiteTableEntry())
213
{
214
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedCallSiteTableEntryGlue);
215
}
216
else if (getDataSymbol()->isMethodTypeTableEntry())
217
{
218
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_interpreterUnresolvedMethodTypeTableEntryGlue);
219
}
220
else if (getDataSymbol()->isConstantDynamic())
221
{
222
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390jitResolveConstantDynamicGlue);
223
}
224
else // must be static data
225
{
226
if (resolveForStore())
227
{
228
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStaticDataStoreGlue);
229
}
230
else
231
{
232
glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interpreterUnresolvedStaticDataGlue);
233
}
234
}
235
236
// Generate RIOFF if RI is supported.
237
cursor = generateRuntimeInstrumentationOnOffInstruction(cg(), cursor, TR::InstOpCode::RIOFF);
238
239
// TODO: We could use LRL / LGRL here but the JIT does not guarantee that the Data Constant be 4 / 8 byte aligned,
240
// so we cannot make use of these instructions in general. We should explore the idea of aligning 4 / 8 byte data
241
// constants in the literal pool to a(n) 4 / 8 byte boundary such that these instructions can be exploited.
242
243
// Snippet body
244
*(int16_t *) cursor = 0x0de0; // BASR r14,0
245
cursor += 2;
246
247
if (comp->target().is64Bit())
248
{
249
// LG r14,8(,r14)
250
*(uint32_t *) cursor = 0xe3e0e008;
251
cursor += 4;
252
*(uint16_t *) cursor = 0x0004;
253
cursor += 2;
254
}
255
else
256
{
257
*(int32_t *) cursor = 0x58e0e006; // L r14,6(,r14)
258
cursor += 4;
259
}
260
261
*(int16_t *) cursor = 0x0dee; // BASR r14,r14
262
cursor += 2;
263
264
// PicBuilder function address
265
*(uintptr_t *) cursor = (uintptr_t) glueRef->getMethodAddress();
266
AOTcgDiag1(comp, "add TR_AbsoluteHelperAddress cursor=%x\n", cursor);
267
cg()->addProjectSpecializedRelocation(cursor, (uint8_t *)glueRef, NULL, TR_AbsoluteHelperAddress,
268
__FILE__, __LINE__, getNode());
269
cursor += sizeof(uintptr_t);
270
271
// code cache RA
272
*(uintptr_t *) cursor = (uintptr_t) (getBranchInstruction()->getNext())->getBinaryEncoding();
273
AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);
274
cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,
275
__FILE__, __LINE__, getNode());
276
cursor += sizeof(uintptr_t);
277
278
// cp
279
if (getDataSymbolReference()->getSymbol()->isCallSiteTableEntry())
280
{
281
*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToCallSiteTableEntrySymbol()->getCallSiteIndex();
282
}
283
else if (getDataSymbol()->isMethodTypeTableEntry())
284
{
285
*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToMethodTypeTableEntrySymbol()->getMethodTypeIndex();
286
}
287
else // constant pool index
288
{
289
*(int32_t *)cursor = getDataSymbolReference()->getCPIndex();
290
}
291
292
cursor += 4;
293
294
// address of constant pool
295
*(uintptr_t *) cursor = (uintptr_t) getDataSymbolReference()->getOwningMethod(comp)->constantPool();
296
AOTcgDiag1(comp, "add TR_ConstantPool cursor=%x\n", cursor);
297
cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, *(uint8_t **)cursor, getNode() ? (uint8_t *)(intptr_t)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool, cg()),
298
__FILE__, __LINE__, getNode());
299
cursor += sizeof(uintptr_t);
300
301
// referencing instruction that needs patching
302
if (getDataReferenceInstruction() != NULL)
303
{
304
*(uintptr_t *) cursor = (uintptr_t) (getDataReferenceInstruction()->getBinaryEncoding());
305
}
306
else
307
{
308
*(uintptr_t *) cursor = (uintptr_t) (getBranchInstruction()->getNext())->getBinaryEncoding();
309
}
310
AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);
311
cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,
312
__FILE__, __LINE__, getNode());
313
cursor += sizeof(uintptr_t);
314
315
// Literal Pool Address to patch.
316
*(uintptr_t *) cursor = 0x0;
317
setLiteralPoolPatchAddress(cursor);
318
AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);
319
cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,
320
__FILE__, __LINE__, getNode());
321
cursor += sizeof(uintptr_t);
322
323
324
// Instance data load and stores require patching of the displacement field
325
// of the respective load / store instruction. In the event that the
326
// resolved offset is greater than displacement, we provide an out-of-line
327
// instruction sequence to allow for large displacement calculation.
328
// The sequence that is generated is:
329
// DC Address of Offset
330
// DC Offset to patch BRCL to helper
331
// BASR R14, 0
332
// L/LGF R14, Offset(R14)
333
// AR/AGR R14, Rbase
334
// BRCL Return to mainline code
335
// -- Padding for word alignment --
336
// DC _ResolvedOffset // 32-bits
337
// where Load/Store is the original load/store instruction in mainline
338
// sequence, and Rtarget, Rbase and Rindex are its respective real registers.
339
// The sequence will return to the point after the mainline instruction.
340
if (isInstanceData()) {
341
TR::Instruction* loadStore = getDataReferenceInstruction();
342
TR_ASSERT( getDataReferenceInstruction() != NULL, "Expected data reference instruction.");
343
TR::MemoryReference* mr = loadStore->getMemoryReference();
344
TR_ASSERT(mr != NULL , "Memory Reference expected.");
345
TR::RealRegister::RegNum base = (mr->getBaseRegister() ? toRealRegister(mr->getBaseRegister())->getRegisterNumber() : TR::RealRegister::NoReg);
346
347
// Get PC for relative load of the resolved offset.
348
uint8_t* offsetMarker = cursor; // DC Address of Offset
349
cursor += sizeof(intptr_t);
350
351
// Get PC for relative load of the resolved offset.
352
// We need to use getNext - 6 because the branch instruction may have padding before it.
353
*(int32_t *) cursor = (int32_t)((cursor + sizeof(int32_t) - getBranchInstruction()->getNext()->getBinaryEncoding() + 6) / 2);
354
cursor += sizeof(int32_t);
355
356
// Get PC for relative load of the resolved offset.
357
*(int16_t *) cursor = 0x0de0; // BASR R14, 0
358
cursor += sizeof(int16_t);
359
360
// Load the resolved offset into R14.
361
// Add the resolved offset into base register.
362
uint8_t* offsetLoad = cursor;
363
if (comp->target().is64Bit())
364
{
365
*(int32_t *) cursor = 0xe3e0e000; // 64Bit: LGF R14, (R14)
366
cursor += sizeof(int32_t);
367
*(int16_t *) cursor = 0x0014;
368
cursor += sizeof(int16_t);
369
370
*(int32_t *) cursor = 0xb90800e0; // 64Bit: AGR R14, Rbase
371
TR::RealRegister::setRegisterField((uint32_t*)cursor, 0, base);
372
cursor += sizeof(int32_t);
373
}
374
else
375
{
376
*(int32_t *) cursor = 0x58e0e000; // 31Bit: L R14,6(R14)
377
cursor += sizeof(int32_t);
378
379
*(uint32_t *) cursor = (int32_t)0x1ae00000; // 31Bit: AR R14, Rbase
380
TR::RealRegister::setRegisterField((uint32_t*)cursor, 4, base);
381
cursor += sizeof(int16_t);
382
}
383
384
uint8_t* returnAddress = (getBranchInstruction()->getNext())->getBinaryEncoding();
385
// Return to instruction after load.
386
*(int16_t *) cursor = 0xC0F4; // BRCL return address
387
cursor += sizeof(int16_t);
388
*(int32_t *) cursor = (int32_t)((returnAddress - (cursor - 2)) / 2);
389
cursor += sizeof(int32_t);
390
391
// Padding to ensure resolved offset slot is aligned.
392
if ((uintptr_t)cursor % 4 != 0)
393
cursor += sizeof(int16_t);
394
395
*(int32_t *) cursor = (int32_t)0x0badbeef; // DC Offset
396
397
// Store pointer to resolved offset slot
398
// code cache RA
399
*(uintptr_t *) offsetMarker = (uintptr_t) cursor;
400
AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress offsetMarker=%x\n", offsetMarker);
401
cg()->addProjectSpecializedRelocation(offsetMarker, NULL, NULL, TR_AbsoluteMethodAddress,
402
__FILE__, __LINE__, getNode());
403
404
*(int32_t *) offsetLoad |= (cursor-offsetLoad);
405
406
cursor += sizeof(int32_t);
407
408
}
409
410
return cursor;
411
}
412
413
414
uint32_t
415
J9::Z::UnresolvedDataSnippet::getLength(int32_t estimatedSnippetStart)
416
{
417
TR::Compilation *comp = cg()->comp();
418
uint32_t length = (comp->target().is64Bit() ? (14 + 5 * sizeof(uintptr_t)) : (12 + 5 * sizeof(uintptr_t)));
419
// For instance snippets, we have the out-of-line sequence
420
if (isInstanceData())
421
length += (comp->target().is64Bit()) ? 36 : 28;
422
423
length += getRuntimeInstrumentationOnOffInstructionLength(cg());
424
return length;
425
}
426
427
428
void
429
TR_Debug::print(TR::FILE *pOutFile, TR::UnresolvedDataSnippet * snippet)
430
{
431
432
uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();
433
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Unresolved Data Snippet");
434
435
bufferPos = printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF
436
437
// TODO: We could use LRL / LGRL here but the JIT does not guarantee that the Data Constant be 4 / 8 byte aligned,
438
// so we cannot make use of these instructions in general. We should explore the idea of aligning 4 / 8 byte data
439
// constants in the literal pool to a(n) 4 / 8 byte boundary such that these instructions can be exploited.
440
441
printPrefix(pOutFile, NULL, bufferPos, 2);
442
trfprintf(pOutFile, "BASR \tGPR14, 0");
443
bufferPos += 2;
444
445
if (_comp->target().is64Bit())
446
{
447
printPrefix(pOutFile, NULL, bufferPos, 6);
448
trfprintf(pOutFile, "LG \tGPR14, 6(,GPR14)");
449
bufferPos += 6;
450
}
451
else
452
{
453
printPrefix(pOutFile, NULL, bufferPos, 4);
454
trfprintf(pOutFile, "L \tGPR14, 6(,GPR14)");
455
bufferPos += 4;
456
}
457
458
printPrefix(pOutFile, NULL, bufferPos, 2);
459
trfprintf(pOutFile, "BASR \tGPR14, GPR14");
460
bufferPos += 2;
461
462
TR::SymbolReference * glueRef;
463
if (snippet->getDataSymbol()->getShadowSymbol())
464
{
465
if (snippet->resolveForStore())
466
{
467
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedInstanceDataStoreGlue);
468
}
469
else
470
{
471
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedInstanceDataGlue);
472
}
473
}
474
else if (snippet->getDataSymbol()->isClassObject())
475
{
476
if (snippet->getDataSymbol()->addressIsCPIndexOfStatic())
477
{
478
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedClassGlue2);
479
}
480
else
481
{
482
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedClassGlue);
483
}
484
}
485
else if (snippet->getDataSymbol()->isConstString())
486
{
487
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStringGlue);
488
}
489
else if (snippet->getDataSymbol()->isConstMethodHandle())
490
{
491
glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodHandleGlue);
492
}
493
else if (snippet->getDataSymbol()->isConstMethodType())
494
{
495
glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeGlue);
496
}
497
else if (snippet->getDataSymbol()->isCallSiteTableEntry())
498
{
499
glueRef = _cg->getSymRef(TR_interpreterUnresolvedCallSiteTableEntryGlue);
500
}
501
else if (snippet->getDataSymbol()->isMethodTypeTableEntry())
502
{
503
glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeTableEntryGlue);
504
}
505
else if (snippet->getDataSymbol()->isConstantDynamic())
506
{
507
glueRef = _cg->getSymRef(TR_S390jitResolveConstantDynamicGlue);
508
}
509
else // the data symbol is static
510
{
511
if (snippet->resolveForStore())
512
{
513
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticDataStoreGlue);
514
}
515
else
516
{
517
glueRef = _cg->getSymRef(TR_S390interpreterUnresolvedStaticDataGlue);
518
}
519
}
520
521
522
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
523
trfprintf(pOutFile, "DC \t%s", getName(glueRef));
524
bufferPos += sizeof(intptr_t);
525
526
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
527
trfprintf(pOutFile, "DC \t%p \t# Return Address",
528
(intptr_t) (snippet->getBranchInstruction()->getNext())->getBinaryEncoding());
529
bufferPos += sizeof(intptr_t);
530
531
printPrefix(pOutFile, NULL, bufferPos, 4);
532
trfprintf(pOutFile, "DC \t0x%08x \t# Constant Pool Index", snippet->getDataSymbolReference()->getCPIndex());
533
bufferPos += 4;
534
535
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
536
trfprintf(pOutFile, "DC \t0x%p \t# Address Of Constant Pool",
537
(intptr_t) getOwningMethod(snippet->getDataSymbolReference())->constantPool());
538
bufferPos += sizeof(intptr_t);
539
540
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
541
uintptr_t addr;
542
543
if (snippet->getDataReferenceInstruction() != NULL)
544
{
545
addr = (uintptr_t) (snippet->getDataReferenceInstruction()->getBinaryEncoding());
546
}
547
else
548
{
549
addr = (uintptr_t) (snippet->getBranchInstruction()->getNext())->getBinaryEncoding();
550
}
551
trfprintf(pOutFile, "DC \t0x%p \t# Address Of Ref. Instruction", addr);
552
553
bufferPos += sizeof(intptr_t);
554
555
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
556
trfprintf(pOutFile, "DC \t0x%p \t# Address Of Literal Pool Slot",
557
(intptr_t)(snippet->getLiteralPoolSlot()));
558
bufferPos += sizeof(intptr_t);
559
560
// Snippet has out-of-line sequence for large offsets for instance data
561
if (snippet->isInstanceData())
562
{
563
printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));
564
trfprintf(pOutFile, "DC \t0x%p \t# Address to large offset slot",
565
(intptr_t)((intptr_t*)bufferPos));
566
bufferPos += sizeof(intptr_t);
567
568
printPrefix(pOutFile, NULL, bufferPos, sizeof(int32_t));
569
trfprintf(pOutFile, "DC \t0x%p \t# Displacement from helper branch to out-of-line sequence",
570
(int32_t)((intptr_t)bufferPos + sizeof(int32_t) - (intptr_t)snippet->getBranchInstruction()->getBinaryEncoding() +6));
571
bufferPos += sizeof(int32_t);
572
573
printPrefix(pOutFile, NULL, bufferPos, 2);
574
trfprintf(pOutFile, "BASR \tGPR14, 0");
575
bufferPos += 2;
576
577
if (_comp->target().is64Bit())
578
{
579
printPrefix(pOutFile, NULL, bufferPos, 6);
580
trfprintf(pOutFile, "LGF \tGPR14, Offset(,GPR14)");
581
bufferPos += 6;
582
printPrefix(pOutFile, NULL, bufferPos, 4);
583
trfprintf(pOutFile, "AGR \tGPR14, GPRbase");
584
bufferPos += 4;
585
}
586
else
587
{
588
printPrefix(pOutFile, NULL, bufferPos, 4);
589
trfprintf(pOutFile, "L \tGPR14, Offset(,GPR14)");
590
bufferPos += 4;
591
printPrefix(pOutFile, NULL, bufferPos, 2);
592
trfprintf(pOutFile, "AR \tGPR14, GPRbase");
593
bufferPos += 2;
594
}
595
596
printPrefix(pOutFile, NULL, bufferPos, 6);
597
trfprintf(pOutFile, "BRCL \t<%p>\t# Return to Main Code",
598
snippet->getBranchInstruction()->getNext()->getBinaryEncoding());
599
bufferPos += 6;
600
601
if ((uintptr_t)bufferPos % 4 != 0)
602
{
603
printPrefix(pOutFile, NULL, bufferPos, 2);
604
trfprintf(pOutFile, "\t\t# 2 byte padding");
605
bufferPos += 2;
606
}
607
608
printPrefix(pOutFile, NULL, bufferPos, sizeof(int32_t));
609
trfprintf(pOutFile, "DC \t0x%p \t# Offset slot",
610
(int32_t)(*(int32_t*)bufferPos));
611
bufferPos += sizeof(int32_t);
612
}
613
}
614
615
bool
616
J9::Z::UnresolvedDataSnippet::isInstanceData()
617
{
618
return getDataSymbol()->getShadowSymbol() != NULL;
619
}
620
621
622
TR::S390WritableDataSnippet *
623
J9::Z::UnresolvedDataSnippet::createUnresolvedData(
624
TR::CodeGenerator *cg,
625
TR::Node * n)
626
{
627
_unresolvedData = cg->CreateWritableConstant(n);
628
return _unresolvedData;
629
}
630
631