blob: 6ce48abb5cdc55c5a5766744d414b52a6f8211af [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ian Rogers0c7abda2012-09-19 13:33:42 -070017#include "gc_map.h"
18#include "verifier/dex_gc_map.h"
19#include "verifier/method_verifier.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080020#include "codegen_util.h"
Ian Rogers0c7abda2012-09-19 13:33:42 -070021
buzbeee3acd072012-02-25 17:03:10 -080022namespace art {
23
buzbee31a4a6f2012-02-28 15:36:15 -080024void setMemRefType(LIR* lir, bool isLoad, int memType)
25{
buzbeeeaf09bc2012-11-15 14:51:41 -080026 uint64_t *maskPtr;
27 uint64_t mask = ENCODE_MEM;;
Bill Buzbeea114add2012-05-03 15:00:40 -070028 DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
29 if (isLoad) {
30 maskPtr = &lir->useMask;
31 } else {
32 maskPtr = &lir->defMask;
33 }
34 /* Clear out the memref flags */
35 *maskPtr &= ~mask;
36 /* ..and then add back the one we need */
37 switch (memType) {
38 case kLiteral:
39 DCHECK(isLoad);
40 *maskPtr |= ENCODE_LITERAL;
41 break;
42 case kDalvikReg:
43 *maskPtr |= ENCODE_DALVIK_REG;
44 break;
45 case kHeapRef:
46 *maskPtr |= ENCODE_HEAP_REF;
47 break;
48 case kMustNotAlias:
49 /* Currently only loads can be marked as kMustNotAlias */
50 DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
51 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
52 break;
53 default:
54 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
55 }
buzbee31a4a6f2012-02-28 15:36:15 -080056}
57
58/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080059 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080060 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080061void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080062{
Bill Buzbeea114add2012-05-03 15:00:40 -070063 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080064
Bill Buzbeea114add2012-05-03 15:00:40 -070065 /*
66 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
67 * access.
68 */
buzbeeec137432012-11-13 12:13:16 -080069 lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit);
buzbee31a4a6f2012-02-28 15:36:15 -080070}
71
buzbeeeaf09bc2012-11-15 14:51:41 -080072uint64_t oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeb046e162012-10-30 15:48:42 -070073{
74 return getRegMaskCommon(cUnit, reg);
75}
76
buzbee31a4a6f2012-02-28 15:36:15 -080077/*
78 * Mark the corresponding bit(s).
79 */
buzbeeeaf09bc2012-11-15 14:51:41 -080080inline void setupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -080081{
buzbeeb046e162012-10-30 15:48:42 -070082 *mask |= getRegMaskCommon(cUnit, reg);
83}
84
85/* Exported version of setupRegMask */
buzbeeeaf09bc2012-11-15 14:51:41 -080086void oatSetupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbeeb046e162012-10-30 15:48:42 -070087{
88 setupRegMask(cUnit, mask, reg);
buzbee31a4a6f2012-02-28 15:36:15 -080089}
90
91/*
92 * Set up the proper fields in the resource mask
93 */
buzbeeb046e162012-10-30 15:48:42 -070094void setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -080095{
Bill Buzbeea114add2012-05-03 15:00:40 -070096 int opcode = lir->opcode;
buzbee31a4a6f2012-02-28 15:36:15 -080097
Bill Buzbeea114add2012-05-03 15:00:40 -070098 if (opcode <= 0) {
99 lir->useMask = lir->defMask = 0;
100 return;
101 }
buzbee31a4a6f2012-02-28 15:36:15 -0800102
buzbeeec137432012-11-13 12:13:16 -0800103 uint64_t flags = EncodingMap[opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800104
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 if (flags & NEEDS_FIXUP) {
106 lir->flags.pcRelFixup = true;
107 }
buzbee31a4a6f2012-02-28 15:36:15 -0800108
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 /* Get the starting size of the instruction's template */
110 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800111
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 /* Set up the mask for resources that are updated */
113 if (flags & (IS_LOAD | IS_STORE)) {
114 /* Default to heap - will catch specialized classes later */
115 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
116 }
buzbee31a4a6f2012-02-28 15:36:15 -0800117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 /*
119 * Conservatively assume the branch here will call out a function that in
120 * turn will trash everything.
121 */
122 if (flags & IS_BRANCH) {
123 lir->defMask = lir->useMask = ENCODE_ALL;
124 return;
125 }
buzbee31a4a6f2012-02-28 15:36:15 -0800126
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700128 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 }
buzbee31a4a6f2012-02-28 15:36:15 -0800130
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700132 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 }
buzbee31a4a6f2012-02-28 15:36:15 -0800134
buzbee31a4a6f2012-02-28 15:36:15 -0800135
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 if (flags & SETS_CCODES) {
137 lir->defMask |= ENCODE_CCODE;
138 }
buzbee31a4a6f2012-02-28 15:36:15 -0800139
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
141 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 for (i = 0; i < 4; i++) {
144 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700145 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbee31a4a6f2012-02-28 15:36:15 -0800147 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 }
buzbee31a4a6f2012-02-28 15:36:15 -0800149
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 if (flags & USES_CCODES) {
151 lir->useMask |= ENCODE_CCODE;
152 }
buzbee31a4a6f2012-02-28 15:36:15 -0800153
buzbeeb046e162012-10-30 15:48:42 -0700154 // Handle target-specific actions
155 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800156}
157
158/*
buzbee5de34942012-03-01 14:51:57 -0800159 * Debugging macros
160 */
161#define DUMP_RESOURCE_MASK(X)
162#define DUMP_SSA_REP(X)
163
164/* Pretty-print a LIR instruction */
165void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
166{
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 LIR* lir = (LIR*) arg;
168 int offset = lir->offset;
169 int dest = lir->operands[0];
170 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800171
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 /* Handle pseudo-ops individually, and all regular insns as a group */
173 switch (lir->opcode) {
174 case kPseudoMethodEntry:
175 LOG(INFO) << "-------- method entry "
176 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
177 break;
178 case kPseudoMethodExit:
179 LOG(INFO) << "-------- Method_Exit";
180 break;
181 case kPseudoBarrier:
182 LOG(INFO) << "-------- BARRIER";
183 break;
184 case kPseudoExtended:
185 LOG(INFO) << "-------- " << (char* ) dest;
186 break;
187 case kPseudoSSARep:
188 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
189 break;
190 case kPseudoEntryBlock:
191 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
192 break;
193 case kPseudoDalvikByteCodeBoundary:
194 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
195 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
196 break;
197 case kPseudoExitBlock:
198 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
199 break;
200 case kPseudoPseudoAlign4:
201 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
202 << offset << "): .align4";
203 break;
204 case kPseudoEHBlockLabel:
205 LOG(INFO) << "Exception_Handling:";
206 break;
207 case kPseudoTargetLabel:
208 case kPseudoNormalBlockLabel:
209 LOG(INFO) << "L" << (void*)lir << ":";
210 break;
211 case kPseudoThrowTarget:
212 LOG(INFO) << "LT" << (void*)lir << ":";
213 break;
214 case kPseudoIntrinsicRetry:
215 LOG(INFO) << "IR" << (void*)lir << ":";
216 break;
217 case kPseudoSuspendTarget:
218 LOG(INFO) << "LS" << (void*)lir << ":";
219 break;
buzbee8320f382012-09-11 16:29:42 -0700220 case kPseudoSafepointPC:
221 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
222 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700223 case kPseudoExportedPC:
224 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
225 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 case kPseudoCaseLabel:
227 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
228 << std::hex << lir->operands[0] << "|" << std::dec <<
229 lir->operands[0];
230 break;
231 default:
232 if (lir->flags.isNop && !dumpNop) {
233 break;
234 } else {
235 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
236 lir, baseAddr));
237 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
238 , lir, baseAddr));
239 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
240 (unsigned int)(baseAddr + offset),
241 op_name.c_str(), op_operands.c_str(),
242 lir->flags.isNop ? "(nop)" : "");
243 }
244 break;
245 }
buzbee5de34942012-03-01 14:51:57 -0800246
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
248 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
249 }
250 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
251 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
252 }
buzbee5de34942012-03-01 14:51:57 -0800253}
254
255void oatDumpPromotionMap(CompilationUnit *cUnit)
256{
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
258 for (int i = 0; i < numRegs; i++) {
259 PromotionMap vRegMap = cUnit->promotionMap[i];
260 std::string buf;
261 if (vRegMap.fpLocation == kLocPhysReg) {
buzbeef0504cd2012-11-13 16:31:10 -0800262 StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask());
buzbee5de34942012-03-01 14:51:57 -0800263 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700264
265 std::string buf3;
266 if (i < cUnit->numDalvikRegisters) {
267 StringAppendF(&buf3, "%02d", i);
268 } else if (i == cUnit->methodSReg) {
269 buf3 = "Method*";
270 } else {
271 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
272 }
273
274 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
275 vRegMap.coreLocation == kLocPhysReg ?
276 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
277 vRegMap.coreReg : oatSRegOffset(cUnit, i),
278 buf.c_str());
279 }
buzbee5de34942012-03-01 14:51:57 -0800280}
281
Bill Buzbeea5b30242012-09-28 07:19:44 -0700282/* Dump a mapping table */
283void dumpMappingTable(const char* table_name, const std::string& descriptor,
284 const std::string& name, const std::string& signature,
285 const std::vector<uint32_t>& v) {
286 if (v.size() > 0) {
287 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
288 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
289 std::replace(line.begin(), line.end(), ';', '_');
290 LOG(INFO) << line;
291 for (uint32_t i = 0; i < v.size(); i+=2) {
292 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
293 LOG(INFO) << line;
294 }
295 LOG(INFO) <<" };\n\n";
296 }
297}
298
buzbee5de34942012-03-01 14:51:57 -0800299/* Dump instructions and constant pool contents */
300void oatCodegenDump(CompilationUnit* cUnit)
301{
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 LOG(INFO) << "Dumping LIR insns for "
303 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
304 LIR* lirInsn;
305 LIR* thisLIR;
306 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800307
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
309 LOG(INFO) << "Ins : " << cUnit->numIns;
310 LOG(INFO) << "Outs : " << cUnit->numOuts;
311 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
312 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
313 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
314 LOG(INFO) << "Frame size : " << cUnit->frameSize;
315 LOG(INFO) << "code size is " << cUnit->totalSize <<
316 " bytes, Dalvik size is " << insnsSize * 2;
317 LOG(INFO) << "expansion factor: "
318 << (float)cUnit->totalSize / (float)(insnsSize * 2);
319 oatDumpPromotionMap(cUnit);
320 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
321 oatDumpLIRInsn(cUnit, lirInsn, 0);
322 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
324 thisLIR = (LIR*) lirInsn;
325 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
326 thisLIR->offset, thisLIR->offset,
327 thisLIR->operands[0]);
328 }
buzbee5de34942012-03-01 14:51:57 -0800329
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 const DexFile::MethodId& method_id =
331 cUnit->dex_file->GetMethodId(cUnit->method_idx);
332 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
333 std::string name(cUnit->dex_file->GetMethodName(method_id));
334 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800335
Bill Buzbeea5b30242012-09-28 07:19:44 -0700336 // Dump mapping tables
337 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
338 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800339}
340
buzbeea2ebdd72012-03-04 14:57:06 -0800341
342LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800344{
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
346 insn->dalvikOffset = dalvikOffset;
347 insn->opcode = opcode;
348 insn->operands[0] = op0;
349 insn->operands[1] = op1;
350 insn->operands[2] = op2;
351 insn->operands[3] = op3;
352 insn->operands[4] = op4;
353 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700354 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700355 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
356 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700358 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 }
360 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800361}
362
buzbee5de34942012-03-01 14:51:57 -0800363/*
buzbee31a4a6f2012-02-28 15:36:15 -0800364 * The following are building blocks to construct low-level IRs with 0 - 4
365 * operands.
366 */
buzbee5de34942012-03-01 14:51:57 -0800367LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800368{
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
370 << EncodingMap[opcode].name << " " << (int)opcode << " "
371 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
372 << cUnit->currentDalvikOffset;
373 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
374 oatAppendLIR(cUnit, (LIR*) insn);
375 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800376}
377
buzbee5de34942012-03-01 14:51:57 -0800378LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800380{
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
382 << EncodingMap[opcode].name << " " << (int)opcode << " "
383 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
384 << cUnit->currentDalvikOffset;
385 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
386 oatAppendLIR(cUnit, (LIR*) insn);
387 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800388}
389
buzbee5de34942012-03-01 14:51:57 -0800390LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800392{
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
394 << EncodingMap[opcode].name << " " << (int)opcode << " "
395 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
396 << cUnit->currentDalvikOffset;
397 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
398 oatAppendLIR(cUnit, (LIR*) insn);
399 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800400}
401
buzbee5de34942012-03-01 14:51:57 -0800402LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800404{
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
406 << EncodingMap[opcode].name << " " << (int)opcode << " "
407 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
408 << cUnit->currentDalvikOffset;
409 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
410 src2);
411 oatAppendLIR(cUnit, (LIR*) insn);
412 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800413}
414
buzbee5de34942012-03-01 14:51:57 -0800415LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800417{
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
419 << EncodingMap[opcode].name << " " << (int)opcode << " "
420 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
421 << cUnit->currentDalvikOffset;
422 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
423 src2, info);
424 oatAppendLIR(cUnit, (LIR*) insn);
425 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800426}
buzbee31a4a6f2012-02-28 15:36:15 -0800427
Ian Rogersb5d09b22012-03-06 22:14:17 -0800428LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800430{
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
432 << EncodingMap[opcode].name << " " << (int)opcode << " "
433 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
434 << cUnit->currentDalvikOffset;
435 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
436 src2, info1, info2);
437 oatAppendLIR(cUnit, (LIR*) insn);
438 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800439}
440
buzbee31a4a6f2012-02-28 15:36:15 -0800441/*
442 * Search the existing constants in the literal pool for an exact or close match
443 * within specified delta (greater or equal to 0).
444 */
445LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
446{
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 while (dataTarget) {
448 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
449 return (LIR* ) dataTarget;
450 dataTarget = dataTarget->next;
451 }
452 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800453}
454
455/* Search the existing constants in the literal pool for an exact wide match */
456LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
457{
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 bool loMatch = false;
459 LIR* loTarget = NULL;
460 while (dataTarget) {
461 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
462 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800463 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 loMatch = false;
465 if (((LIR*)dataTarget)->operands[0] == valLo) {
466 loMatch = true;
467 loTarget = dataTarget;
468 }
469 dataTarget = dataTarget->next;
470 }
471 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800472}
473
474/*
475 * The following are building blocks to insert constants into the pool or
476 * instruction streams.
477 */
478
buzbee5de34942012-03-01 14:51:57 -0800479/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700480LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800481{
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 /* Add the constant to the literal pool */
483 if (constantListP) {
484 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
485 newValue->operands[0] = value;
486 newValue->next = *constantListP;
487 *constantListP = (LIR*) newValue;
488 return newValue;
489 }
490 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800491}
492
493/* Add a 64-bit constant to the constant pool or mixed with code */
494LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800496{
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 addWordData(cUnit, constantListP, valHi);
498 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800499}
500
Ian Rogersab058bb2012-03-11 22:19:38 -0700501void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 buf.push_back( data & 0xff);
503 buf.push_back( (data >> 8) & 0xff);
504 buf.push_back( (data >> 16) & 0xff);
505 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800506}
507
Ian Rogersab058bb2012-03-11 22:19:38 -0700508void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 while (buf.size() < offset) {
510 buf.push_back(0);
511 }
buzbeee3acd072012-02-25 17:03:10 -0800512}
513
Brian Carlstromf5822582012-03-19 22:34:31 -0700514bool IsDirect(int invokeType) {
515 InvokeType type = static_cast<InvokeType>(invokeType);
516 return type == kStatic || type == kDirect;
517}
518
buzbeee3acd072012-02-25 17:03:10 -0800519/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800520void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800521{
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
523 LIR* dataLIR = cUnit->literalList;
524 while (dataLIR != NULL) {
525 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
526 dataLIR = NEXT_LIR(dataLIR);
527 }
528 // Push code and method literals, record offsets for the compiler to patch.
529 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700530 while (dataLIR != NULL) {
531 uint32_t target = dataLIR->operands[0];
532 cUnit->compiler->AddCodePatch(cUnit->dex_file,
533 cUnit->method_idx,
534 cUnit->invoke_type,
535 target,
536 static_cast<InvokeType>(dataLIR->operands[1]),
537 cUnit->codeBuffer.size());
538 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
539 // unique based on target to ensure code deduplication works
540 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
541 pushWord(cUnit->codeBuffer, unique_patch_value);
542 dataLIR = NEXT_LIR(dataLIR);
543 }
544 dataLIR = cUnit->methodLiteralList;
545 while (dataLIR != NULL) {
546 uint32_t target = dataLIR->operands[0];
547 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700549 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700551 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700553 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
554 // unique based on target to ensure code deduplication works
555 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
556 pushWord(cUnit->codeBuffer, unique_patch_value);
557 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 }
buzbeee3acd072012-02-25 17:03:10 -0800559}
560
561/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800562void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800563{
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 GrowableListIterator iterator;
565 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
566 while (true) {
567 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
568 &iterator);
569 if (tabRec == NULL) break;
570 alignBuffer(cUnit->codeBuffer, tabRec->offset);
571 /*
572 * For Arm, our reference point is the address of the bx
573 * instruction that does the launch, so we have to subtract
574 * the auto pc-advance. For other targets the reference point
575 * is a label, so we can use the offset as-is.
576 */
buzbeeb046e162012-10-30 15:48:42 -0700577 int bxOffset = INVALID_OFFSET;
578 switch (cUnit->instructionSet) {
579 case kThumb2:
580 bxOffset = tabRec->anchor->offset + 4;
581 break;
582 case kX86:
583 bxOffset = 0;
584 break;
585 case kMips:
586 bxOffset = tabRec->anchor->offset;
587 break;
588 default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
589 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 if (cUnit->printMe) {
591 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800592 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
594 int* keys = (int*)&(tabRec->table[2]);
595 for (int elems = 0; elems < tabRec->table[1]; elems++) {
596 int disp = tabRec->targets[elems]->offset - bxOffset;
597 if (cUnit->printMe) {
598 LOG(INFO) << " Case[" << elems << "] key: 0x"
599 << std::hex << keys[elems] << ", disp: 0x"
600 << std::hex << disp;
601 }
602 pushWord(cUnit->codeBuffer, keys[elems]);
603 pushWord(cUnit->codeBuffer,
604 tabRec->targets[elems]->offset - bxOffset);
605 }
606 } else {
607 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
608 static_cast<int>(Instruction::kPackedSwitchSignature));
609 for (int elems = 0; elems < tabRec->table[1]; elems++) {
610 int disp = tabRec->targets[elems]->offset - bxOffset;
611 if (cUnit->printMe) {
612 LOG(INFO) << " Case[" << elems << "] disp: 0x"
613 << std::hex << disp;
614 }
615 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
616 }
617 }
618 }
buzbeee3acd072012-02-25 17:03:10 -0800619}
620
621/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800622void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800623{
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 GrowableListIterator iterator;
625 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
626 while (true) {
627 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
628 &iterator);
629 if (tabRec == NULL) break;
630 alignBuffer(cUnit->codeBuffer, tabRec->offset);
631 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
632 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
633 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800634 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 }
buzbeee3acd072012-02-25 17:03:10 -0800636}
637
buzbee31a4a6f2012-02-28 15:36:15 -0800638int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800639{
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 for (;lir != NULL; lir = lir->next) {
641 lir->offset = offset;
642 offset += 4;
643 }
644 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800645}
646
buzbee6459e7c2012-10-02 14:42:41 -0700647// Make sure we have a code address for every declared catch entry
648bool verifyCatchEntries(CompilationUnit* cUnit)
649{
650 bool success = true;
651 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
652 uint32_t dexPc = *it;
653 bool found = false;
654 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
655 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
656 found = true;
657 break;
658 }
659 }
660 if (!found) {
661 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
662 success = false;
663 }
664 }
665 // Now, try in the other direction
666 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
667 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
668 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
669 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
670 success = false;
671 }
672 }
673 if (!success) {
674 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
675 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
676 << cUnit->dex2pcMappingTable.size()/2;
677 }
678 return success;
679}
680
Bill Buzbeea5b30242012-09-28 07:19:44 -0700681void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800682{
buzbee8320f382012-09-11 16:29:42 -0700683 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
684 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700685 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
686 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
687 }
688 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
689 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
690 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800691 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 }
buzbee6459e7c2012-10-02 14:42:41 -0700693 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700694 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
695 cUnit->dex2pcMappingTable.size());
696 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
697 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
698 cUnit->pc2dexMappingTable.begin(),
699 cUnit->pc2dexMappingTable.end());
700 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
701 cUnit->dex2pcMappingTable.begin(),
702 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800703}
704
Ian Rogers0c7abda2012-09-19 13:33:42 -0700705class NativePcToReferenceMapBuilder {
706 public:
707 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
708 size_t entries, uint32_t max_native_offset,
709 size_t references_width) : entries_(entries),
710 references_width_(references_width), in_use_(entries),
711 table_(table) {
712 // Compute width in bytes needed to hold max_native_offset.
713 native_offset_width_ = 0;
714 while (max_native_offset != 0) {
715 native_offset_width_++;
716 max_native_offset >>= 8;
717 }
718 // Resize table and set up header.
719 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700720 CHECK_LT(native_offset_width_, 1U << 3);
721 (*table)[0] = native_offset_width_ & 7;
722 CHECK_LT(references_width_, 1U << 13);
723 (*table)[0] |= (references_width_ << 3) & 0xFF;
724 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700725 CHECK_LT(entries, 1U << 16);
726 (*table)[2] = entries & 0xFF;
727 (*table)[3] = (entries >> 8) & 0xFF;
728 }
729
730 void AddEntry(uint32_t native_offset, const uint8_t* references) {
731 size_t table_index = TableIndex(native_offset);
732 while (in_use_[table_index]) {
733 table_index = (table_index + 1) % entries_;
734 }
735 in_use_[table_index] = true;
736 SetNativeOffset(table_index, native_offset);
737 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
738 SetReferences(table_index, references);
739 }
740
741 private:
742 size_t TableIndex(uint32_t native_offset) {
743 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
744 }
745
746 uint32_t GetNativeOffset(size_t table_index) {
747 uint32_t native_offset = 0;
748 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
749 for (size_t i = 0; i < native_offset_width_; i++) {
750 native_offset |= (*table_)[table_offset + i] << (i * 8);
751 }
752 return native_offset;
753 }
754
755 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
756 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
757 for (size_t i = 0; i < native_offset_width_; i++) {
758 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
759 }
760 }
761
762 void SetReferences(size_t table_index, const uint8_t* references) {
763 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
764 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
765 }
766
767 size_t EntryWidth() const {
768 return native_offset_width_ + references_width_;
769 }
770
771 // Number of entries in the table.
772 const size_t entries_;
773 // Number of bytes used to encode the reference bitmap.
774 const size_t references_width_;
775 // Number of bytes used to encode a native offset.
776 size_t native_offset_width_;
777 // Entries that are in use.
778 std::vector<bool> in_use_;
779 // The table we're building.
780 std::vector<uint8_t>* const table_;
781};
782
783static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700784 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700785 uint32_t max_native_offset = 0;
786 for (size_t i = 0; i < mapping_table.size(); i += 2) {
787 uint32_t native_offset = mapping_table[i + 0];
788 if (native_offset > max_native_offset) {
789 max_native_offset = native_offset;
790 }
791 }
792 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
793 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
794 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
795 // Compute native offset to references size.
796 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
797 mapping_table.size() / 2, max_native_offset,
798 dex_gc_map.RegWidth());
799
800 for (size_t i = 0; i < mapping_table.size(); i += 2) {
801 uint32_t native_offset = mapping_table[i + 0];
802 uint32_t dex_pc = mapping_table[i + 1];
803 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700804 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
805 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700806 }
807}
808
buzbeee3acd072012-02-25 17:03:10 -0800809/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800810int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800811{
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
813 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
814 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
815 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800816}
817
buzbee31a4a6f2012-02-28 15:36:15 -0800818int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800819{
Bill Buzbeea114add2012-05-03 15:00:40 -0700820 GrowableListIterator iterator;
821 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
822 while (true) {
823 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
824 &iterator);
825 if (tabRec == NULL) break;
826 tabRec->offset = offset;
827 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
828 offset += tabRec->table[1] * (sizeof(int) * 2);
829 } else {
830 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
831 static_cast<int>(Instruction::kPackedSwitchSignature));
832 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800833 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 }
835 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800836}
837
buzbee31a4a6f2012-02-28 15:36:15 -0800838int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800839{
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 GrowableListIterator iterator;
841 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
842 while (true) {
843 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
844 &iterator);
845 if (tabRec == NULL) break;
846 tabRec->offset = offset;
847 offset += tabRec->size;
848 // word align
849 offset = (offset + 3) & ~3;
850 }
851 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800852}
853
854/*
855 * Walk the compilation unit and assign offsets to instructions
856 * and literals and compute the total size of the compiled unit.
857 */
858void oatAssignOffsets(CompilationUnit* cUnit)
859{
Bill Buzbeea114add2012-05-03 15:00:40 -0700860 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800861
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 /* Const values have to be word aligned */
863 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800864
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 /* Set up offsets for literals */
866 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800867
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800869
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800873
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800875}
876
877/*
878 * Go over each instruction in the list and calculate the offset from the top
879 * before sending them off to the assembler. If out-of-range branch distance is
880 * seen rearrange the instructions a bit to correct it.
881 */
882void oatAssembleLIR(CompilationUnit* cUnit)
883{
Bill Buzbeea114add2012-05-03 15:00:40 -0700884 oatAssignOffsets(cUnit);
885 /*
886 * Assemble here. Note that we generate code with optimistic assumptions
887 * and if found now to work, we'll have to redo the sequence and retry.
888 */
buzbeee3acd072012-02-25 17:03:10 -0800889
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 while (true) {
891 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
892 if (res == kSuccess) {
893 break;
894 } else {
895 cUnit->assemblerRetries++;
896 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
897 oatCodegenDump(cUnit);
898 LOG(FATAL) << "Assembler error - too many retries";
899 }
900 // Redo offsets and try again
901 oatAssignOffsets(cUnit);
902 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800903 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 }
buzbeee3acd072012-02-25 17:03:10 -0800905
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 // Install literals
907 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800908
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 // Install switch tables
910 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800911
Bill Buzbeea114add2012-05-03 15:00:40 -0700912 // Install fill array data
913 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800914
Ian Rogers0c7abda2012-09-19 13:33:42 -0700915 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700916 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700917
918 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800919}
920
buzbee31a4a6f2012-02-28 15:36:15 -0800921/*
922 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
923 * offset vaddr. This label will be used to fix up the case
924 * branch table during the assembly phase. Be sure to set
925 * all resource flags on this to prevent code motion across
926 * target boundaries. KeyVal is just there for debugging.
927 */
928LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
929{
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 SafeMap<unsigned int, LIR*>::iterator it;
931 it = cUnit->boundaryMap.find(vaddr);
932 if (it == cUnit->boundaryMap.end()) {
933 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
934 }
935 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
936 newLabel->dalvikOffset = vaddr;
937 newLabel->opcode = kPseudoCaseLabel;
938 newLabel->operands[0] = keyVal;
939 oatInsertLIRAfter(it->second, (LIR*)newLabel);
940 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800941}
942
943void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
944{
buzbeeeaf09bc2012-11-15 14:51:41 -0800945 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 int baseVaddr = tabRec->vaddr;
947 int *targets = (int*)&table[4];
948 int entries = table[1];
949 int lowKey = s4FromSwitchData(&table[2]);
950 for (int i = 0; i < entries; i++) {
951 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
952 i + lowKey);
953 }
buzbee31a4a6f2012-02-28 15:36:15 -0800954}
955
956void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
957{
buzbeeeaf09bc2012-11-15 14:51:41 -0800958 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 int baseVaddr = tabRec->vaddr;
960 int entries = table[1];
961 int* keys = (int*)&table[2];
962 int* targets = &keys[entries];
963 for (int i = 0; i < entries; i++) {
964 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
965 keys[i]);
966 }
buzbee31a4a6f2012-02-28 15:36:15 -0800967}
968
969void oatProcessSwitchTables(CompilationUnit* cUnit)
970{
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 GrowableListIterator iterator;
972 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
973 while (true) {
974 SwitchTable *tabRec =
975 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
976 if (tabRec == NULL) break;
977 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
978 markPackedCaseLabels(cUnit, tabRec);
979 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
980 markSparseCaseLabels(cUnit, tabRec);
981 } else {
982 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800983 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 }
buzbee31a4a6f2012-02-28 15:36:15 -0800985}
986
buzbeeeaf09bc2012-11-15 14:51:41 -0800987void dumpSparseSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 /*
989 * Sparse switch data format:
990 * ushort ident = 0x0200 magic value
991 * ushort size number of entries in the table; > 0
992 * int keys[size] keys, sorted low-to-high; 32-bit aligned
993 * int targets[size] branch targets, relative to switch opcode
994 *
995 * Total size is (2+size*4) 16-bit code units.
996 */
buzbee31a4a6f2012-02-28 15:36:15 -0800997{
buzbeeeaf09bc2012-11-15 14:51:41 -0800998 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 int entries = table[1];
1000 int* keys = (int*)&table[2];
1001 int* targets = &keys[entries];
1002 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1003 << ", entries: " << std::dec << entries;
1004 for (int i = 0; i < entries; i++) {
1005 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1006 }
buzbee31a4a6f2012-02-28 15:36:15 -08001007}
1008
buzbeeeaf09bc2012-11-15 14:51:41 -08001009void dumpPackedSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 /*
1011 * Packed switch data format:
1012 * ushort ident = 0x0100 magic value
1013 * ushort size number of entries in the table
1014 * int first_key first (and lowest) switch case value
1015 * int targets[size] branch targets, relative to switch opcode
1016 *
1017 * Total size is (4+size*2) 16-bit code units.
1018 */
buzbee31a4a6f2012-02-28 15:36:15 -08001019{
buzbeeeaf09bc2012-11-15 14:51:41 -08001020 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 int* targets = (int*)&table[4];
1022 int entries = table[1];
1023 int lowKey = s4FromSwitchData(&table[2]);
1024 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1025 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1026 for (int i = 0; i < entries; i++) {
1027 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1028 << targets[i];
1029 }
buzbee31a4a6f2012-02-28 15:36:15 -08001030}
buzbeee3acd072012-02-25 17:03:10 -08001031
buzbeed1643e42012-09-05 14:06:51 -07001032/*
1033 * Set up special LIR to mark a Dalvik byte-code instruction start and
1034 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1035 * which we split a single Dalvik instruction, only the first MIR op
1036 * associated with a Dalvik PC should be entered into the map.
1037 */
1038LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1039{
1040 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1041 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1042 cUnit->boundaryMap.Put(offset, res);
1043 }
1044 return res;
1045}
buzbeee3acd072012-02-25 17:03:10 -08001046
buzbeed1643e42012-09-05 14:06:51 -07001047}
1048 // namespace art