Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/x/codegen/GuardedDevirtualSnippet.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
#include "x/codegen/GuardedDevirtualSnippet.hpp"
24
25
#include <stddef.h>
26
#include <stdint.h>
27
#include "codegen/CodeGenerator.hpp"
28
#include "env/FrontEnd.hpp"
29
#include "codegen/MemoryReference.hpp"
30
#include "codegen/RealRegister.hpp"
31
#include "codegen/RegisterConstants.hpp"
32
#include "codegen/Snippet.hpp"
33
#include "codegen/SnippetGCMap.hpp"
34
#include "compile/Compilation.hpp"
35
#include "env/CompilerEnv.hpp"
36
#include "env/IO.hpp"
37
#include "env/jittypes.h"
38
#include "il/LabelSymbol.hpp"
39
#include "il/Node.hpp"
40
#include "il/Symbol.hpp"
41
#include "il/SymbolReference.hpp"
42
#include "ras/Debug.hpp"
43
#include "x/codegen/RestartSnippet.hpp"
44
45
namespace TR { class Block; }
46
namespace TR { class MethodSymbol; }
47
namespace TR { class Register; }
48
49
TR::X86GuardedDevirtualSnippet::X86GuardedDevirtualSnippet(TR::CodeGenerator * cg,
50
TR::Node * node,
51
TR::LabelSymbol *restartlab,
52
TR::LabelSymbol *snippetlab,
53
int32_t vftoffset,
54
TR::Block *currentBlock,
55
TR::Register *classRegister)
56
: TR::X86RestartSnippet(cg, node, restartlab, snippetlab, true),
57
_vtableOffset(vftoffset),
58
_currentBlock(currentBlock),
59
_classObjectRegister(classRegister)
60
{
61
}
62
63
64
TR::X86GuardedDevirtualSnippet *TR::X86GuardedDevirtualSnippet::getGuardedDevirtualSnippet()
65
{
66
return this;
67
}
68
69
uint8_t *TR::X86GuardedDevirtualSnippet::emitSnippetBody()
70
{
71
uint8_t *buffer = cg()->getBinaryBufferCursor();
72
getSnippetLabel()->setCodeLocation(buffer);
73
TR::Compilation *comp = cg()->comp();
74
75
if (_classObjectRegister == NULL)
76
{
77
if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
78
*buffer++ = 0x48; // Rex prefix for 64-bit mov
79
80
*(uint16_t *)buffer = 0x788b; // prepare for mov edi, [eax + class_offset]
81
buffer += 2;
82
83
*(uint8_t *)buffer = (uint8_t) TR::Compiler->om.offsetOfObjectVftField(); // mov edi, [eax + class_offset]
84
buffer += 1;
85
86
uintptr_t vftMask = TR::Compiler->om.maskOfObjectVftField();
87
if (~vftMask != 0)
88
{
89
if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
90
*buffer++ = 0x48; // Rex prefix
91
92
// and edi, vftMask
93
//
94
*(uint16_t *)buffer = 0xe781;
95
buffer += 2;
96
*(uint32_t *)buffer = vftMask;
97
buffer += 4;
98
}
99
100
// two opcode bytes for call [edi + Imm] instruction
101
*(uint16_t *)buffer = 0x97ff;
102
buffer += 2;
103
}
104
else
105
{
106
if (comp->target().is64Bit())
107
{
108
uint8_t rex = toRealRegister(_classObjectRegister)->rexBits(TR::RealRegister::REX_B, false);
109
if (rex)
110
*buffer++ = rex;
111
}
112
113
// two opcode bytes for call [reg + Imm] instruction, fix the low 3 bits (later)
114
// depending on what register the class object is in. For now, leave it zero
115
*(uint16_t *)buffer = 0x90ff;
116
buffer++;
117
118
// use SIB-byte encoding if necessary
119
if (toRealRegister(_classObjectRegister)->needsSIB())
120
{
121
*buffer++ |= IA32SIBPresent;
122
*buffer = IA32SIBNoIndex;
123
}
124
125
// now must get the class register and add its encoding to the low order 3 bits
126
// of the second opcode byte (0x90);
127
TR::RealRegister *classObjectRegister = toRealRegister(_classObjectRegister);
128
classObjectRegister->setRMRegisterFieldInModRM(buffer++);
129
}
130
131
132
// set the immediate offset field to be the vtable index
133
*(int32_t *)buffer = _vtableOffset; // call [reg + vtable offset]
134
buffer += 4;
135
136
gcMap().registerStackMap(buffer, cg());
137
138
return genRestartJump(buffer);
139
}
140
141
142
void
143
TR_Debug::print(TR::FILE *pOutFile, TR::X86GuardedDevirtualSnippet * snippet)
144
{
145
if (pOutFile == NULL)
146
return;
147
148
uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation();
149
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet), "out of line full virtual call sequence");
150
151
char regLetter = (_comp->target().is64Bit())? 'r' : 'e';
152
153
#if defined(TR_TARGET_64BIT)
154
TR::Node *callNode = snippet->getNode();
155
TR::SymbolReference *methodSymRef = snippet->getRealMethodSymbolReference();
156
if (!methodSymRef)
157
methodSymRef = callNode->getSymbolReference();
158
TR::MethodSymbol *methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();
159
// Show effect of loadArgumentsIfNecessary on devirtualized VMInternalNatives.
160
if (snippet->isLoadArgumentsNecessary(methodSymbol))
161
bufferPos = printArgumentFlush(pOutFile, callNode, false, bufferPos);
162
#endif
163
164
if (!snippet->getClassObjectRegister())
165
{
166
int movSize = (_comp->target().is64Bit())? 3 : 2;
167
168
printPrefix(pOutFile, NULL, bufferPos, movSize);
169
trfprintf(pOutFile, "mov \t%cdi, [%cax]\t\t%s Load Class Object",
170
regLetter, regLetter,
171
commentString());
172
bufferPos += movSize;
173
174
printPrefix(pOutFile, NULL, bufferPos, 6);
175
trfprintf(pOutFile, "call\t[%cdi %d]\t\t%s call through vtable slot %d", regLetter, snippet->getVTableOffset(),
176
commentString(), -snippet->getVTableOffset() >> 2);
177
bufferPos += 6;
178
}
179
else
180
{
181
TR::RealRegister *classObjectRegister = toRealRegister(snippet->getClassObjectRegister());
182
#if defined(TR_TARGET_64BIT)
183
int callSize = 6;
184
if (toRealRegister(classObjectRegister)->rexBits(TR::RealRegister::REX_B, false))
185
callSize++;
186
if (toRealRegister(classObjectRegister)->needsSIB())
187
callSize++;
188
TR_RegisterSizes regSize = TR_DoubleWordReg;
189
#else
190
int callSize = 6;
191
TR_RegisterSizes regSize = TR_WordReg;
192
#endif
193
194
printPrefix(pOutFile, NULL, bufferPos, callSize);
195
trfprintf(pOutFile,
196
"call\t[%s %d]\t\t%s call through vtable slot %d",
197
getName(classObjectRegister, regSize),
198
snippet->getVTableOffset(),
199
commentString(),
200
-snippet->getVTableOffset() >> 2);
201
bufferPos += callSize;
202
}
203
204
printRestartJump(pOutFile, snippet, bufferPos);
205
}
206
207
208
uint32_t TR::X86GuardedDevirtualSnippet::getLength(int32_t estimatedSnippetStart)
209
{
210
TR::Compilation *comp = cg()->comp();
211
uint32_t fixedLength;
212
if (_classObjectRegister)
213
{
214
fixedLength = 6 + (toRealRegister(_classObjectRegister)->needsSIB()? 1 : 0);
215
if (comp->target().is64Bit())
216
{
217
uint8_t rex = toRealRegister(_classObjectRegister)->rexBits(TR::RealRegister::REX_B, false);
218
if (rex)
219
fixedLength++;
220
}
221
}
222
else
223
{
224
int32_t delta = 0;
225
delta = 1;
226
uintptr_t vftMask = TR::Compiler->om.maskOfObjectVftField();
227
if (~vftMask != 0)
228
delta += 6 + (comp->target().is64Bit()? 1 /* Rex */ : 0);
229
230
fixedLength = 8 + delta + (comp->target().is64Bit()? 1 /* Rex */ : 0);
231
}
232
return fixedLength + estimateRestartJumpLength(estimatedSnippetStart + fixedLength);
233
}
234
235
236
237
238
239
240
241
242