blob: 5da552cf8801a307eeef1025848996e047fd67ad [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
buzbeecbd6d442012-11-17 14:11:25 -080024/* Convert an instruction to a NOP */
25void oatNopLIR( LIR* lir)
26{
27 lir->flags.isNop = true;
28}
29
buzbee31a4a6f2012-02-28 15:36:15 -080030void setMemRefType(LIR* lir, bool isLoad, int memType)
31{
buzbeeeaf09bc2012-11-15 14:51:41 -080032 uint64_t *maskPtr;
33 uint64_t mask = ENCODE_MEM;;
Bill Buzbeea114add2012-05-03 15:00:40 -070034 DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
35 if (isLoad) {
36 maskPtr = &lir->useMask;
37 } else {
38 maskPtr = &lir->defMask;
39 }
40 /* Clear out the memref flags */
41 *maskPtr &= ~mask;
42 /* ..and then add back the one we need */
43 switch (memType) {
44 case kLiteral:
45 DCHECK(isLoad);
46 *maskPtr |= ENCODE_LITERAL;
47 break;
48 case kDalvikReg:
49 *maskPtr |= ENCODE_DALVIK_REG;
50 break;
51 case kHeapRef:
52 *maskPtr |= ENCODE_HEAP_REF;
53 break;
54 case kMustNotAlias:
55 /* Currently only loads can be marked as kMustNotAlias */
56 DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
57 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
58 break;
59 default:
60 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
61 }
buzbee31a4a6f2012-02-28 15:36:15 -080062}
63
64/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080065 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080066 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080067void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080068{
Bill Buzbeea114add2012-05-03 15:00:40 -070069 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080070
Bill Buzbeea114add2012-05-03 15:00:40 -070071 /*
72 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
73 * access.
74 */
buzbeeec137432012-11-13 12:13:16 -080075 lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit);
buzbee31a4a6f2012-02-28 15:36:15 -080076}
77
buzbeeeaf09bc2012-11-15 14:51:41 -080078uint64_t oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeb046e162012-10-30 15:48:42 -070079{
80 return getRegMaskCommon(cUnit, reg);
81}
82
buzbee31a4a6f2012-02-28 15:36:15 -080083/*
84 * Mark the corresponding bit(s).
85 */
buzbeeeaf09bc2012-11-15 14:51:41 -080086inline void setupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -080087{
buzbeeb046e162012-10-30 15:48:42 -070088 *mask |= getRegMaskCommon(cUnit, reg);
89}
90
91/* Exported version of setupRegMask */
buzbeeeaf09bc2012-11-15 14:51:41 -080092void oatSetupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbeeb046e162012-10-30 15:48:42 -070093{
94 setupRegMask(cUnit, mask, reg);
buzbee31a4a6f2012-02-28 15:36:15 -080095}
96
97/*
98 * Set up the proper fields in the resource mask
99 */
buzbeeb046e162012-10-30 15:48:42 -0700100void setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -0800101{
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 int opcode = lir->opcode;
buzbee31a4a6f2012-02-28 15:36:15 -0800103
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 if (opcode <= 0) {
105 lir->useMask = lir->defMask = 0;
106 return;
107 }
buzbee31a4a6f2012-02-28 15:36:15 -0800108
buzbeeec137432012-11-13 12:13:16 -0800109 uint64_t flags = EncodingMap[opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800110
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 if (flags & NEEDS_FIXUP) {
112 lir->flags.pcRelFixup = true;
113 }
buzbee31a4a6f2012-02-28 15:36:15 -0800114
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 /* Get the starting size of the instruction's template */
116 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 /* Set up the mask for resources that are updated */
119 if (flags & (IS_LOAD | IS_STORE)) {
120 /* Default to heap - will catch specialized classes later */
121 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
122 }
buzbee31a4a6f2012-02-28 15:36:15 -0800123
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 /*
125 * Conservatively assume the branch here will call out a function that in
126 * turn will trash everything.
127 */
128 if (flags & IS_BRANCH) {
129 lir->defMask = lir->useMask = ENCODE_ALL;
130 return;
131 }
buzbee31a4a6f2012-02-28 15:36:15 -0800132
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700134 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 }
buzbee31a4a6f2012-02-28 15:36:15 -0800136
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700138 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 }
buzbee31a4a6f2012-02-28 15:36:15 -0800140
buzbee31a4a6f2012-02-28 15:36:15 -0800141
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 if (flags & SETS_CCODES) {
143 lir->defMask |= ENCODE_CCODE;
144 }
buzbee31a4a6f2012-02-28 15:36:15 -0800145
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
147 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800148
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 for (i = 0; i < 4; i++) {
150 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700151 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 }
buzbee31a4a6f2012-02-28 15:36:15 -0800153 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 }
buzbee31a4a6f2012-02-28 15:36:15 -0800155
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 if (flags & USES_CCODES) {
157 lir->useMask |= ENCODE_CCODE;
158 }
buzbee31a4a6f2012-02-28 15:36:15 -0800159
buzbeeb046e162012-10-30 15:48:42 -0700160 // Handle target-specific actions
161 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800162}
163
164/*
buzbee5de34942012-03-01 14:51:57 -0800165 * Debugging macros
166 */
167#define DUMP_RESOURCE_MASK(X)
168#define DUMP_SSA_REP(X)
169
170/* Pretty-print a LIR instruction */
buzbeecbd6d442012-11-17 14:11:25 -0800171void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* lir, unsigned char* baseAddr)
buzbee5de34942012-03-01 14:51:57 -0800172{
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 int offset = lir->offset;
174 int dest = lir->operands[0];
175 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800176
Bill Buzbeea114add2012-05-03 15:00:40 -0700177 /* Handle pseudo-ops individually, and all regular insns as a group */
178 switch (lir->opcode) {
179 case kPseudoMethodEntry:
180 LOG(INFO) << "-------- method entry "
181 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
182 break;
183 case kPseudoMethodExit:
184 LOG(INFO) << "-------- Method_Exit";
185 break;
186 case kPseudoBarrier:
187 LOG(INFO) << "-------- BARRIER";
188 break;
189 case kPseudoExtended:
buzbeecbd6d442012-11-17 14:11:25 -0800190 LOG(INFO) << "-------- " << reinterpret_cast<char*>(dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 break;
192 case kPseudoSSARep:
buzbeecbd6d442012-11-17 14:11:25 -0800193 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << reinterpret_cast<char*>(dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700194 break;
195 case kPseudoEntryBlock:
196 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
197 break;
198 case kPseudoDalvikByteCodeBoundary:
199 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
buzbeecbd6d442012-11-17 14:11:25 -0800200 << lir->dalvikOffset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 break;
202 case kPseudoExitBlock:
203 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
204 break;
205 case kPseudoPseudoAlign4:
buzbeecbd6d442012-11-17 14:11:25 -0800206 LOG(INFO) << reinterpret_cast<uintptr_t>(baseAddr) + offset << " (0x" << std::hex
Bill Buzbeea114add2012-05-03 15:00:40 -0700207 << offset << "): .align4";
208 break;
209 case kPseudoEHBlockLabel:
210 LOG(INFO) << "Exception_Handling:";
211 break;
212 case kPseudoTargetLabel:
213 case kPseudoNormalBlockLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800214 LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 break;
216 case kPseudoThrowTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800217 LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 break;
219 case kPseudoIntrinsicRetry:
buzbeecbd6d442012-11-17 14:11:25 -0800220 LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 break;
222 case kPseudoSuspendTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800223 LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 break;
buzbee8320f382012-09-11 16:29:42 -0700225 case kPseudoSafepointPC:
226 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
227 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700228 case kPseudoExportedPC:
229 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
230 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 case kPseudoCaseLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800232 LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 << std::hex << lir->operands[0] << "|" << std::dec <<
234 lir->operands[0];
235 break;
236 default:
237 if (lir->flags.isNop && !dumpNop) {
238 break;
239 } else {
240 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
241 lir, baseAddr));
242 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
243 , lir, baseAddr));
244 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
buzbeecbd6d442012-11-17 14:11:25 -0800245 reinterpret_cast<unsigned int>(baseAddr + offset),
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 op_name.c_str(), op_operands.c_str(),
247 lir->flags.isNop ? "(nop)" : "");
248 }
249 break;
250 }
buzbee5de34942012-03-01 14:51:57 -0800251
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
253 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
254 }
255 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
256 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
257 }
buzbee5de34942012-03-01 14:51:57 -0800258}
259
260void oatDumpPromotionMap(CompilationUnit *cUnit)
261{
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
263 for (int i = 0; i < numRegs; i++) {
264 PromotionMap vRegMap = cUnit->promotionMap[i];
265 std::string buf;
266 if (vRegMap.fpLocation == kLocPhysReg) {
buzbeef0504cd2012-11-13 16:31:10 -0800267 StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask());
buzbee5de34942012-03-01 14:51:57 -0800268 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700269
270 std::string buf3;
271 if (i < cUnit->numDalvikRegisters) {
272 StringAppendF(&buf3, "%02d", i);
273 } else if (i == cUnit->methodSReg) {
274 buf3 = "Method*";
275 } else {
276 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
277 }
278
279 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
280 vRegMap.coreLocation == kLocPhysReg ?
281 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
282 vRegMap.coreReg : oatSRegOffset(cUnit, i),
283 buf.c_str());
284 }
buzbee5de34942012-03-01 14:51:57 -0800285}
286
Bill Buzbeea5b30242012-09-28 07:19:44 -0700287/* Dump a mapping table */
288void dumpMappingTable(const char* table_name, const std::string& descriptor,
289 const std::string& name, const std::string& signature,
290 const std::vector<uint32_t>& v) {
291 if (v.size() > 0) {
292 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
293 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
294 std::replace(line.begin(), line.end(), ';', '_');
295 LOG(INFO) << line;
296 for (uint32_t i = 0; i < v.size(); i+=2) {
297 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
298 LOG(INFO) << line;
299 }
300 LOG(INFO) <<" };\n\n";
301 }
302}
303
buzbee5de34942012-03-01 14:51:57 -0800304/* Dump instructions and constant pool contents */
305void oatCodegenDump(CompilationUnit* cUnit)
306{
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 LOG(INFO) << "Dumping LIR insns for "
308 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
309 LIR* lirInsn;
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800311
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
313 LOG(INFO) << "Ins : " << cUnit->numIns;
314 LOG(INFO) << "Outs : " << cUnit->numOuts;
315 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
316 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
317 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
318 LOG(INFO) << "Frame size : " << cUnit->frameSize;
319 LOG(INFO) << "code size is " << cUnit->totalSize <<
320 " bytes, Dalvik size is " << insnsSize * 2;
321 LOG(INFO) << "expansion factor: "
buzbeecbd6d442012-11-17 14:11:25 -0800322 << static_cast<float>(cUnit->totalSize) / static_cast<float>(insnsSize * 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 oatDumpPromotionMap(cUnit);
324 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
325 oatDumpLIRInsn(cUnit, lirInsn, 0);
326 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
buzbeecbd6d442012-11-17 14:11:25 -0800328 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lirInsn->offset, lirInsn->offset,
329 lirInsn->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 }
buzbee5de34942012-03-01 14:51:57 -0800331
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 const DexFile::MethodId& method_id =
333 cUnit->dex_file->GetMethodId(cUnit->method_idx);
334 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
335 std::string name(cUnit->dex_file->GetMethodName(method_id));
336 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800337
Bill Buzbeea5b30242012-09-28 07:19:44 -0700338 // Dump mapping tables
339 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
340 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800341}
342
buzbeea2ebdd72012-03-04 14:57:06 -0800343
344LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800346{
buzbeecbd6d442012-11-17 14:11:25 -0800347 LIR* insn = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
Bill Buzbeea114add2012-05-03 15:00:40 -0700348 insn->dalvikOffset = dalvikOffset;
349 insn->opcode = opcode;
350 insn->operands[0] = op0;
351 insn->operands[1] = op1;
352 insn->operands[2] = op2;
353 insn->operands[3] = op3;
354 insn->operands[4] = op4;
355 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700356 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700357 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
358 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700360 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 }
362 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800363}
364
buzbee5de34942012-03-01 14:51:57 -0800365/*
buzbee31a4a6f2012-02-28 15:36:15 -0800366 * The following are building blocks to construct low-level IRs with 0 - 4
367 * operands.
368 */
buzbee5de34942012-03-01 14:51:57 -0800369LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800370{
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
buzbeecbd6d442012-11-17 14:11:25 -0800372 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
374 << cUnit->currentDalvikOffset;
375 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
buzbeecbd6d442012-11-17 14:11:25 -0800376 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800378}
379
buzbee5de34942012-03-01 14:51:57 -0800380LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800382{
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
buzbeecbd6d442012-11-17 14:11:25 -0800384 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
386 << cUnit->currentDalvikOffset;
387 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
buzbeecbd6d442012-11-17 14:11:25 -0800388 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700389 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800390}
391
buzbee5de34942012-03-01 14:51:57 -0800392LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800394{
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
buzbeecbd6d442012-11-17 14:11:25 -0800396 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700397 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
398 << cUnit->currentDalvikOffset;
399 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
buzbeecbd6d442012-11-17 14:11:25 -0800400 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800402}
403
buzbee5de34942012-03-01 14:51:57 -0800404LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800406{
Bill Buzbeea114add2012-05-03 15:00:40 -0700407 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
buzbeecbd6d442012-11-17 14:11:25 -0800408 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
410 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800411 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2);
412 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800414}
415
buzbee5de34942012-03-01 14:51:57 -0800416LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800418{
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
buzbeecbd6d442012-11-17 14:11:25 -0800420 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
422 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800423 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info);
424 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 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))
buzbeecbd6d442012-11-17 14:11:25 -0800432 << EncodingMap[opcode].name << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
434 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800435 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info1, info2);
436 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700437 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800438}
439
buzbee31a4a6f2012-02-28 15:36:15 -0800440/*
441 * Search the existing constants in the literal pool for an exact or close match
442 * within specified delta (greater or equal to 0).
443 */
444LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
445{
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 while (dataTarget) {
buzbeecbd6d442012-11-17 14:11:25 -0800447 if ((static_cast<unsigned>(value - dataTarget->operands[0])) <= delta)
448 return dataTarget;
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 dataTarget = dataTarget->next;
450 }
451 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800452}
453
454/* Search the existing constants in the literal pool for an exact wide match */
455LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
456{
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 bool loMatch = false;
458 LIR* loTarget = NULL;
459 while (dataTarget) {
buzbeecbd6d442012-11-17 14:11:25 -0800460 if (loMatch && (dataTarget->operands[0] == valHi)) {
461 return loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800462 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 loMatch = false;
buzbeecbd6d442012-11-17 14:11:25 -0800464 if (dataTarget->operands[0] == valLo) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 loMatch = true;
466 loTarget = dataTarget;
467 }
468 dataTarget = dataTarget->next;
469 }
470 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800471}
472
473/*
474 * The following are building blocks to insert constants into the pool or
475 * instruction streams.
476 */
477
buzbee5de34942012-03-01 14:51:57 -0800478/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700479LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800480{
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 /* Add the constant to the literal pool */
482 if (constantListP) {
buzbeecbd6d442012-11-17 14:11:25 -0800483 LIR* newValue = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocData));
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 newValue->operands[0] = value;
485 newValue->next = *constantListP;
buzbeecbd6d442012-11-17 14:11:25 -0800486 *constantListP = newValue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 return newValue;
488 }
489 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800490}
491
492/* Add a 64-bit constant to the constant pool or mixed with code */
493LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800495{
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 addWordData(cUnit, constantListP, valHi);
497 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800498}
499
Ian Rogersab058bb2012-03-11 22:19:38 -0700500void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 buf.push_back( data & 0xff);
502 buf.push_back( (data >> 8) & 0xff);
503 buf.push_back( (data >> 16) & 0xff);
504 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800505}
506
Ian Rogersab058bb2012-03-11 22:19:38 -0700507void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 while (buf.size() < offset) {
509 buf.push_back(0);
510 }
buzbeee3acd072012-02-25 17:03:10 -0800511}
512
Brian Carlstromf5822582012-03-19 22:34:31 -0700513bool IsDirect(int invokeType) {
514 InvokeType type = static_cast<InvokeType>(invokeType);
515 return type == kStatic || type == kDirect;
516}
517
buzbeee3acd072012-02-25 17:03:10 -0800518/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800519void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800520{
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
522 LIR* dataLIR = cUnit->literalList;
523 while (dataLIR != NULL) {
524 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
525 dataLIR = NEXT_LIR(dataLIR);
526 }
527 // Push code and method literals, record offsets for the compiler to patch.
528 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700529 while (dataLIR != NULL) {
530 uint32_t target = dataLIR->operands[0];
531 cUnit->compiler->AddCodePatch(cUnit->dex_file,
532 cUnit->method_idx,
533 cUnit->invoke_type,
534 target,
535 static_cast<InvokeType>(dataLIR->operands[1]),
536 cUnit->codeBuffer.size());
537 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
538 // unique based on target to ensure code deduplication works
539 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
540 pushWord(cUnit->codeBuffer, unique_patch_value);
541 dataLIR = NEXT_LIR(dataLIR);
542 }
543 dataLIR = cUnit->methodLiteralList;
544 while (dataLIR != NULL) {
545 uint32_t target = dataLIR->operands[0];
546 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700548 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700550 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700552 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
553 // unique based on target to ensure code deduplication works
554 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
555 pushWord(cUnit->codeBuffer, unique_patch_value);
556 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 }
buzbeee3acd072012-02-25 17:03:10 -0800558}
559
560/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800561void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800562{
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 GrowableListIterator iterator;
564 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
565 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800566 SwitchTable* tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext( &iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 if (tabRec == NULL) break;
568 alignBuffer(cUnit->codeBuffer, tabRec->offset);
569 /*
570 * For Arm, our reference point is the address of the bx
571 * instruction that does the launch, so we have to subtract
572 * the auto pc-advance. For other targets the reference point
573 * is a label, so we can use the offset as-is.
574 */
buzbeeb046e162012-10-30 15:48:42 -0700575 int bxOffset = INVALID_OFFSET;
576 switch (cUnit->instructionSet) {
577 case kThumb2:
578 bxOffset = tabRec->anchor->offset + 4;
579 break;
580 case kX86:
581 bxOffset = 0;
582 break;
583 case kMips:
584 bxOffset = tabRec->anchor->offset;
585 break;
586 default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
587 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700588 if (cUnit->printMe) {
589 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800590 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
buzbeecbd6d442012-11-17 14:11:25 -0800592 const int* keys = reinterpret_cast<const int*>(&(tabRec->table[2]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 for (int elems = 0; elems < tabRec->table[1]; elems++) {
594 int disp = tabRec->targets[elems]->offset - bxOffset;
595 if (cUnit->printMe) {
596 LOG(INFO) << " Case[" << elems << "] key: 0x"
597 << std::hex << keys[elems] << ", disp: 0x"
598 << std::hex << disp;
599 }
600 pushWord(cUnit->codeBuffer, keys[elems]);
601 pushWord(cUnit->codeBuffer,
602 tabRec->targets[elems]->offset - bxOffset);
603 }
604 } else {
605 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
606 static_cast<int>(Instruction::kPackedSwitchSignature));
607 for (int elems = 0; elems < tabRec->table[1]; elems++) {
608 int disp = tabRec->targets[elems]->offset - bxOffset;
609 if (cUnit->printMe) {
610 LOG(INFO) << " Case[" << elems << "] disp: 0x"
611 << std::hex << disp;
612 }
613 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
614 }
615 }
616 }
buzbeee3acd072012-02-25 17:03:10 -0800617}
618
619/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800620void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800621{
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 GrowableListIterator iterator;
623 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
624 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800625 FillArrayData *tabRec =
626 reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext( &iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 if (tabRec == NULL) break;
628 alignBuffer(cUnit->codeBuffer, tabRec->offset);
629 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
630 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
631 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800632 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700633 }
buzbeee3acd072012-02-25 17:03:10 -0800634}
635
buzbee31a4a6f2012-02-28 15:36:15 -0800636int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800637{
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 for (;lir != NULL; lir = lir->next) {
639 lir->offset = offset;
640 offset += 4;
641 }
642 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800643}
644
buzbee6459e7c2012-10-02 14:42:41 -0700645// Make sure we have a code address for every declared catch entry
646bool verifyCatchEntries(CompilationUnit* cUnit)
647{
648 bool success = true;
649 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
650 uint32_t dexPc = *it;
651 bool found = false;
652 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
653 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
654 found = true;
655 break;
656 }
657 }
658 if (!found) {
659 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
660 success = false;
661 }
662 }
663 // Now, try in the other direction
664 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
665 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
666 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
667 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
668 success = false;
669 }
670 }
671 if (!success) {
672 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
673 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
674 << cUnit->dex2pcMappingTable.size()/2;
675 }
676 return success;
677}
678
Bill Buzbeea5b30242012-09-28 07:19:44 -0700679void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800680{
buzbeecbd6d442012-11-17 14:11:25 -0800681 for (LIR* tgtLIR = cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
buzbee8320f382012-09-11 16:29:42 -0700682 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700683 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
684 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
685 }
686 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
687 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
688 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800689 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 }
buzbee6459e7c2012-10-02 14:42:41 -0700691 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700692 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
693 cUnit->dex2pcMappingTable.size());
694 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
695 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
696 cUnit->pc2dexMappingTable.begin(),
697 cUnit->pc2dexMappingTable.end());
698 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
699 cUnit->dex2pcMappingTable.begin(),
700 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800701}
702
Ian Rogers0c7abda2012-09-19 13:33:42 -0700703class NativePcToReferenceMapBuilder {
704 public:
705 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
706 size_t entries, uint32_t max_native_offset,
707 size_t references_width) : entries_(entries),
708 references_width_(references_width), in_use_(entries),
709 table_(table) {
710 // Compute width in bytes needed to hold max_native_offset.
711 native_offset_width_ = 0;
712 while (max_native_offset != 0) {
713 native_offset_width_++;
714 max_native_offset >>= 8;
715 }
716 // Resize table and set up header.
717 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700718 CHECK_LT(native_offset_width_, 1U << 3);
719 (*table)[0] = native_offset_width_ & 7;
720 CHECK_LT(references_width_, 1U << 13);
721 (*table)[0] |= (references_width_ << 3) & 0xFF;
722 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700723 CHECK_LT(entries, 1U << 16);
724 (*table)[2] = entries & 0xFF;
725 (*table)[3] = (entries >> 8) & 0xFF;
726 }
727
728 void AddEntry(uint32_t native_offset, const uint8_t* references) {
729 size_t table_index = TableIndex(native_offset);
730 while (in_use_[table_index]) {
731 table_index = (table_index + 1) % entries_;
732 }
733 in_use_[table_index] = true;
734 SetNativeOffset(table_index, native_offset);
735 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
736 SetReferences(table_index, references);
737 }
738
739 private:
740 size_t TableIndex(uint32_t native_offset) {
741 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
742 }
743
744 uint32_t GetNativeOffset(size_t table_index) {
745 uint32_t native_offset = 0;
746 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
747 for (size_t i = 0; i < native_offset_width_; i++) {
748 native_offset |= (*table_)[table_offset + i] << (i * 8);
749 }
750 return native_offset;
751 }
752
753 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
754 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
755 for (size_t i = 0; i < native_offset_width_; i++) {
756 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
757 }
758 }
759
760 void SetReferences(size_t table_index, const uint8_t* references) {
761 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
762 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
763 }
764
765 size_t EntryWidth() const {
766 return native_offset_width_ + references_width_;
767 }
768
769 // Number of entries in the table.
770 const size_t entries_;
771 // Number of bytes used to encode the reference bitmap.
772 const size_t references_width_;
773 // Number of bytes used to encode a native offset.
774 size_t native_offset_width_;
775 // Entries that are in use.
776 std::vector<bool> in_use_;
777 // The table we're building.
778 std::vector<uint8_t>* const table_;
779};
780
781static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700782 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700783 uint32_t max_native_offset = 0;
784 for (size_t i = 0; i < mapping_table.size(); i += 2) {
785 uint32_t native_offset = mapping_table[i + 0];
786 if (native_offset > max_native_offset) {
787 max_native_offset = native_offset;
788 }
789 }
790 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
791 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
792 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
793 // Compute native offset to references size.
794 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
795 mapping_table.size() / 2, max_native_offset,
796 dex_gc_map.RegWidth());
797
798 for (size_t i = 0; i < mapping_table.size(); i += 2) {
799 uint32_t native_offset = mapping_table[i + 0];
800 uint32_t dex_pc = mapping_table[i + 1];
801 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700802 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
803 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700804 }
805}
806
buzbeee3acd072012-02-25 17:03:10 -0800807/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800808int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800809{
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
811 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
812 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
813 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800814}
815
buzbee31a4a6f2012-02-28 15:36:15 -0800816int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800817{
Bill Buzbeea114add2012-05-03 15:00:40 -0700818 GrowableListIterator iterator;
819 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
820 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800821 SwitchTable *tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 if (tabRec == NULL) break;
823 tabRec->offset = offset;
824 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
825 offset += tabRec->table[1] * (sizeof(int) * 2);
826 } else {
827 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
828 static_cast<int>(Instruction::kPackedSwitchSignature));
829 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800830 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 }
832 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800833}
834
buzbee31a4a6f2012-02-28 15:36:15 -0800835int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800836{
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 GrowableListIterator iterator;
838 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
839 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800840 FillArrayData *tabRec =
841 reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 if (tabRec == NULL) break;
843 tabRec->offset = offset;
844 offset += tabRec->size;
845 // word align
846 offset = (offset + 3) & ~3;
847 }
848 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800849}
850
851/*
852 * Walk the compilation unit and assign offsets to instructions
853 * and literals and compute the total size of the compiled unit.
854 */
855void oatAssignOffsets(CompilationUnit* cUnit)
856{
Bill Buzbeea114add2012-05-03 15:00:40 -0700857 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800858
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 /* Const values have to be word aligned */
860 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800861
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 /* Set up offsets for literals */
863 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800864
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800868
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800872}
873
874/*
875 * Go over each instruction in the list and calculate the offset from the top
876 * before sending them off to the assembler. If out-of-range branch distance is
877 * seen rearrange the instructions a bit to correct it.
878 */
879void oatAssembleLIR(CompilationUnit* cUnit)
880{
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 oatAssignOffsets(cUnit);
882 /*
883 * Assemble here. Note that we generate code with optimistic assumptions
884 * and if found now to work, we'll have to redo the sequence and retry.
885 */
buzbeee3acd072012-02-25 17:03:10 -0800886
Bill Buzbeea114add2012-05-03 15:00:40 -0700887 while (true) {
888 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
889 if (res == kSuccess) {
890 break;
891 } else {
892 cUnit->assemblerRetries++;
893 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
894 oatCodegenDump(cUnit);
895 LOG(FATAL) << "Assembler error - too many retries";
896 }
897 // Redo offsets and try again
898 oatAssignOffsets(cUnit);
899 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800900 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700901 }
buzbeee3acd072012-02-25 17:03:10 -0800902
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 // Install literals
904 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800905
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 // Install switch tables
907 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800908
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 // Install fill array data
910 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800911
Ian Rogers0c7abda2012-09-19 13:33:42 -0700912 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700913 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700914
915 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800916}
917
buzbee31a4a6f2012-02-28 15:36:15 -0800918/*
919 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
920 * offset vaddr. This label will be used to fix up the case
921 * branch table during the assembly phase. Be sure to set
922 * all resource flags on this to prevent code motion across
923 * target boundaries. KeyVal is just there for debugging.
924 */
925LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
926{
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 SafeMap<unsigned int, LIR*>::iterator it;
928 it = cUnit->boundaryMap.find(vaddr);
929 if (it == cUnit->boundaryMap.end()) {
930 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
931 }
buzbeecbd6d442012-11-17 14:11:25 -0800932 LIR* newLabel = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 newLabel->dalvikOffset = vaddr;
934 newLabel->opcode = kPseudoCaseLabel;
935 newLabel->operands[0] = keyVal;
buzbeecbd6d442012-11-17 14:11:25 -0800936 oatInsertLIRAfter(it->second, newLabel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800938}
939
940void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
941{
buzbeeeaf09bc2012-11-15 14:51:41 -0800942 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 int baseVaddr = tabRec->vaddr;
buzbeecbd6d442012-11-17 14:11:25 -0800944 const int *targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 int entries = table[1];
946 int lowKey = s4FromSwitchData(&table[2]);
947 for (int i = 0; i < entries; i++) {
buzbeecbd6d442012-11-17 14:11:25 -0800948 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], i + lowKey);
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 }
buzbee31a4a6f2012-02-28 15:36:15 -0800950}
951
952void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
953{
buzbeeeaf09bc2012-11-15 14:51:41 -0800954 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 int baseVaddr = tabRec->vaddr;
956 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -0800957 const int* keys = reinterpret_cast<const int*>(&table[2]);
958 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 for (int i = 0; i < entries; i++) {
buzbeecbd6d442012-11-17 14:11:25 -0800960 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], keys[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700961 }
buzbee31a4a6f2012-02-28 15:36:15 -0800962}
963
964void oatProcessSwitchTables(CompilationUnit* cUnit)
965{
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 GrowableListIterator iterator;
967 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
968 while (true) {
969 SwitchTable *tabRec =
buzbeecbd6d442012-11-17 14:11:25 -0800970 reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 if (tabRec == NULL) break;
972 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
973 markPackedCaseLabels(cUnit, tabRec);
974 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
975 markSparseCaseLabels(cUnit, tabRec);
976 } else {
977 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800978 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 }
buzbee31a4a6f2012-02-28 15:36:15 -0800980}
981
buzbeeeaf09bc2012-11-15 14:51:41 -0800982void dumpSparseSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 /*
984 * Sparse switch data format:
985 * ushort ident = 0x0200 magic value
986 * ushort size number of entries in the table; > 0
987 * int keys[size] keys, sorted low-to-high; 32-bit aligned
988 * int targets[size] branch targets, relative to switch opcode
989 *
990 * Total size is (2+size*4) 16-bit code units.
991 */
buzbee31a4a6f2012-02-28 15:36:15 -0800992{
buzbeeeaf09bc2012-11-15 14:51:41 -0800993 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -0800995 const int* keys = reinterpret_cast<const int*>(&table[2]);
996 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
998 << ", entries: " << std::dec << entries;
999 for (int i = 0; i < entries; i++) {
1000 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1001 }
buzbee31a4a6f2012-02-28 15:36:15 -08001002}
1003
buzbeeeaf09bc2012-11-15 14:51:41 -08001004void dumpPackedSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 /*
1006 * Packed switch data format:
1007 * ushort ident = 0x0100 magic value
1008 * ushort size number of entries in the table
1009 * int first_key first (and lowest) switch case value
1010 * int targets[size] branch targets, relative to switch opcode
1011 *
1012 * Total size is (4+size*2) 16-bit code units.
1013 */
buzbee31a4a6f2012-02-28 15:36:15 -08001014{
buzbeeeaf09bc2012-11-15 14:51:41 -08001015 uint16_t ident = table[0];
buzbeecbd6d442012-11-17 14:11:25 -08001016 const int* targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 int entries = table[1];
1018 int lowKey = s4FromSwitchData(&table[2]);
1019 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1020 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1021 for (int i = 0; i < entries; i++) {
1022 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1023 << targets[i];
1024 }
buzbee31a4a6f2012-02-28 15:36:15 -08001025}
buzbeee3acd072012-02-25 17:03:10 -08001026
buzbeed1643e42012-09-05 14:06:51 -07001027/*
1028 * Set up special LIR to mark a Dalvik byte-code instruction start and
1029 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1030 * which we split a single Dalvik instruction, only the first MIR op
1031 * associated with a Dalvik PC should be entered into the map.
1032 */
1033LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1034{
buzbeecbd6d442012-11-17 14:11:25 -08001035 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(instStr));
buzbeed1643e42012-09-05 14:06:51 -07001036 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1037 cUnit->boundaryMap.Put(offset, res);
1038 }
1039 return res;
1040}
buzbeee3acd072012-02-25 17:03:10 -08001041
buzbeed1643e42012-09-05 14:06:51 -07001042}
1043 // namespace art