Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/arm/codegen/ARMRecompilation.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/ARMRecompilation.hpp"
24
25
#include <stdint.h>
26
#include "arm/codegen/ARMRecompilationSnippet.hpp"
27
#include "codegen/CodeGenerator.hpp"
28
#include "codegen/GenerateInstructions.hpp"
29
#include "codegen/Snippet.hpp"
30
#include "env/jittypes.h"
31
#include "env/VMJ9.h"
32
#include "il/Node.hpp"
33
#include "il/Node_inlines.hpp"
34
#include "il/TreeTop.hpp"
35
#include "il/TreeTop_inlines.hpp"
36
37
// Allocate a machine-specific recompilation processor for this compilation
38
//
39
TR::Recompilation *TR_ARMRecompilation::allocate(TR::Compilation *comp)
40
{
41
if (comp->isRecompilationEnabled())
42
return new (comp->trHeapMemory()) TR_ARMRecompilation(comp);
43
else
44
return NULL;
45
}
46
47
TR_ARMRecompilation::TR_ARMRecompilation(TR::Compilation * comp)
48
: TR::Recompilation(comp)
49
{
50
_countingSupported = true;
51
setupMethodInfo();
52
}
53
54
TR_PersistentMethodInfo *TR_ARMRecompilation::getExistingMethodInfo(TR_ResolvedMethod *method)
55
{
56
int8_t *startPC = (int8_t *)method->startAddressForInterpreterOfJittedMethod();
57
TR_PersistentMethodInfo *info = getJittedBodyInfoFromPC(startPC)->getMethodInfo();
58
return(info);
59
}
60
61
TR::Instruction *TR_ARMRecompilation::generatePrePrologue()
62
{
63
TR_J9VMBase *fej9 = (TR_J9VMBase *)(_compilation->fe());
64
// If in Full Speed Debug, allow to go through
65
if (!couldBeCompiledAgain() && !_compilation->getOption(TR_FullSpeedDebug))
66
return(NULL);
67
68
// gr12 may contain the vtable offset, and must be preserved here
69
// see PicBuilder.s and Recompilation.s
70
TR::Instruction *cursor=NULL;
71
TR::Machine *machine = cg()->machine();
72
TR::Register *gr4 = machine->getRealRegister(TR::RealRegister::gr4);
73
TR::Register *lr = machine->getRealRegister(TR::RealRegister::gr14); // link register
74
TR::Node *firstNode = _compilation->getStartTree()->getNode();
75
TR::SymbolReference *recompileMethodSymRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_ARMsamplingRecompileMethod);
76
TR_PersistentJittedBodyInfo *info = getJittedBodyInfo();
77
78
79
// force creation of switch to interpreter pre prologue if in Full Speed Debug
80
if (cg()->mustGenerateSwitchToInterpreterPrePrologue())
81
{
82
cursor = cg()->generateSwitchToInterpreterPrePrologue(cursor, firstNode);
83
}
84
85
if (couldBeCompiledAgain())
86
{
87
// gr4 must contain the saved LR; see Recompilation.s
88
if(useSampling())
89
{
90
cursor = new (cg()->trHeapMemory()) TR::ARMTrg1Src1Instruction(cursor, TR::InstOpCode::mov, firstNode, gr4, lr, cg());
91
cursor = generateImmSymInstruction(cg(), TR::InstOpCode::bl, firstNode, (uintptr_t)recompileMethodSymRef->getMethodAddress(), new (cg()->trHeapMemory()) TR::RegisterDependencyConditions((uint8_t)0, 0, cg()->trMemory()), recompileMethodSymRef, NULL, cursor);
92
}
93
cursor = new (cg()->trHeapMemory()) TR::ARMImmInstruction(cursor, TR::InstOpCode::dd, firstNode, (int32_t)(intptr_t)info, cg());
94
cursor->setNeedsAOTRelocation();
95
((TR::ARMImmInstruction *)cursor)->setReloKind(TR_BodyInfoAddress);
96
97
cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode, 0, cursor);
98
}
99
return(cursor);
100
}
101
102
TR::Instruction *TR_ARMRecompilation::generatePrologue(TR::Instruction *cursor)
103
{
104
if (couldBeCompiledAgain())
105
{
106
// gr12 may contain the vtable offset, and must be preserved here
107
// see PicBuilder.s and Recompilation.s
108
TR::Machine *machine = cg()->machine();
109
TR::Register *gr4 = machine->getRealRegister(TR::RealRegister::gr4);
110
TR::Register *gr5 = machine->getRealRegister(TR::RealRegister::gr5);
111
TR::Register *lr = machine->getRealRegister(TR::RealRegister::gr14); // link register
112
TR::Node *firstNode = _compilation->getStartTree()->getNode();
113
intptr_t addr = (intptr_t)getCounterAddress();
114
TR::LabelSymbol *snippetLabel = TR::LabelSymbol::create(cg()->trHeapMemory(), cg());
115
intParts localVal(addr);
116
117
TR_ARMOperand2 *op2_3 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte3(), 24);
118
TR_ARMOperand2 *op2_2 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte2(), 16);
119
TR_ARMOperand2 *op2_1 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte1(), 8);
120
TR_ARMOperand2 *op2_0 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte0(), 0);
121
cursor = generateTrg1Src1Instruction(cg(), TR::InstOpCode::mov, firstNode, gr5, op2_3, cursor);
122
cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_2, cursor);
123
cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_1, cursor);
124
cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_0, cursor);
125
126
cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldr, firstNode, gr4, new (cg()->trHeapMemory()) TR::MemoryReference(gr5, 0, cg()), cursor);
127
128
if (!isProfilingCompilation())
129
{
130
cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::sub_r, firstNode, gr4, gr4, 1, 0, cursor);
131
cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::str, firstNode,
132
new (cg()->trHeapMemory()) TR::MemoryReference(gr5, (int32_t)0, cg()), gr4, cursor);
133
}
134
else
135
{
136
// This only applies to JitProfiling, as JProfiling uses sampling
137
TR_ASSERT(_compilation->getProfilingMode() == JitProfiling, "JProfiling should use sampling to trigger recompilation");
138
139
cursor = generateSrc1ImmInstruction(cg(), TR::InstOpCode::cmp, firstNode, gr4, 0, 0, cursor);
140
// this is just padding for consistent code length
141
cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::orr, firstNode, gr5, gr5, gr5, cursor);
142
}
143
144
// gr4 must contain the saved LR; see Recompilation.s
145
cursor = generateTrg1Src1Instruction(cg(), TR::InstOpCode::mov, firstNode, gr4, lr, cursor);
146
// the instruction below is replaced after successful recompilation
147
cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::orr, firstNode, gr5, gr5, gr5, cursor);
148
cursor = generateConditionalBranchInstruction(cg(), firstNode, ARMConditionCodeLT, snippetLabel, cursor);
149
150
TR::Snippet *snippet = new (cg()->trHeapMemory()) TR::ARMRecompilationSnippet(snippetLabel, cursor, cg());
151
cg()->addSnippet(snippet);
152
}
153
return(cursor);
154
}
155
156
157