blob: c6c8af160866f1ab74e58170898e1cbb5cb1b943 [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "../compiler_internals.h"
Ian Rogers0c7abda2012-09-19 13:33:42 -070018#include "gc_map.h"
19#include "verifier/dex_gc_map.h"
20#include "verifier/method_verifier.h"
buzbee1bc37c62012-11-20 13:35:41 -080021#include "ralloc_util.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080022#include "codegen_util.h"
Ian Rogers0c7abda2012-09-19 13:33:42 -070023
buzbeee3acd072012-02-25 17:03:10 -080024namespace art {
25
buzbeecbd6d442012-11-17 14:11:25 -080026/* Convert an instruction to a NOP */
27void oatNopLIR( LIR* lir)
28{
29 lir->flags.isNop = true;
30}
31
buzbee31a4a6f2012-02-28 15:36:15 -080032void setMemRefType(LIR* lir, bool isLoad, int memType)
33{
buzbeeeaf09bc2012-11-15 14:51:41 -080034 uint64_t *maskPtr;
35 uint64_t mask = ENCODE_MEM;;
buzbee1bc37c62012-11-20 13:35:41 -080036 DCHECK(getTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
Bill Buzbeea114add2012-05-03 15:00:40 -070037 if (isLoad) {
38 maskPtr = &lir->useMask;
39 } else {
40 maskPtr = &lir->defMask;
41 }
42 /* Clear out the memref flags */
43 *maskPtr &= ~mask;
44 /* ..and then add back the one we need */
45 switch (memType) {
46 case kLiteral:
47 DCHECK(isLoad);
48 *maskPtr |= ENCODE_LITERAL;
49 break;
50 case kDalvikReg:
51 *maskPtr |= ENCODE_DALVIK_REG;
52 break;
53 case kHeapRef:
54 *maskPtr |= ENCODE_HEAP_REF;
55 break;
56 case kMustNotAlias:
57 /* Currently only loads can be marked as kMustNotAlias */
buzbee1bc37c62012-11-20 13:35:41 -080058 DCHECK(!(getTargetInstFlags(lir->opcode) & IS_STORE));
Bill Buzbeea114add2012-05-03 15:00:40 -070059 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
60 break;
61 default:
62 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
63 }
buzbee31a4a6f2012-02-28 15:36:15 -080064}
65
66/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080067 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080068 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080069void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080070{
Bill Buzbeea114add2012-05-03 15:00:40 -070071 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080072
Bill Buzbeea114add2012-05-03 15:00:40 -070073 /*
74 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
75 * access.
76 */
buzbeeec137432012-11-13 12:13:16 -080077 lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit);
buzbee31a4a6f2012-02-28 15:36:15 -080078}
79
buzbeeeaf09bc2012-11-15 14:51:41 -080080uint64_t oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeb046e162012-10-30 15:48:42 -070081{
82 return getRegMaskCommon(cUnit, reg);
83}
84
buzbee31a4a6f2012-02-28 15:36:15 -080085/*
86 * Mark the corresponding bit(s).
87 */
buzbeeeaf09bc2012-11-15 14:51:41 -080088inline void setupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -080089{
buzbeeb046e162012-10-30 15:48:42 -070090 *mask |= getRegMaskCommon(cUnit, reg);
91}
92
93/* Exported version of setupRegMask */
buzbeeeaf09bc2012-11-15 14:51:41 -080094void oatSetupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
buzbeeb046e162012-10-30 15:48:42 -070095{
96 setupRegMask(cUnit, mask, reg);
buzbee31a4a6f2012-02-28 15:36:15 -080097}
98
99/*
100 * Set up the proper fields in the resource mask
101 */
buzbeeb046e162012-10-30 15:48:42 -0700102void setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -0800103{
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 int opcode = lir->opcode;
buzbee31a4a6f2012-02-28 15:36:15 -0800105
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 if (opcode <= 0) {
107 lir->useMask = lir->defMask = 0;
108 return;
109 }
buzbee31a4a6f2012-02-28 15:36:15 -0800110
buzbee1bc37c62012-11-20 13:35:41 -0800111 uint64_t flags = getTargetInstFlags(opcode);
buzbee31a4a6f2012-02-28 15:36:15 -0800112
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 if (flags & NEEDS_FIXUP) {
114 lir->flags.pcRelFixup = true;
115 }
buzbee31a4a6f2012-02-28 15:36:15 -0800116
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 /* Get the starting size of the instruction's template */
118 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800119
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 /* Set up the mask for resources that are updated */
121 if (flags & (IS_LOAD | IS_STORE)) {
122 /* Default to heap - will catch specialized classes later */
123 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
124 }
buzbee31a4a6f2012-02-28 15:36:15 -0800125
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 /*
127 * Conservatively assume the branch here will call out a function that in
128 * turn will trash everything.
129 */
130 if (flags & IS_BRANCH) {
131 lir->defMask = lir->useMask = ENCODE_ALL;
132 return;
133 }
buzbee31a4a6f2012-02-28 15:36:15 -0800134
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700136 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 }
buzbee31a4a6f2012-02-28 15:36:15 -0800138
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700140 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700141 }
buzbee31a4a6f2012-02-28 15:36:15 -0800142
buzbee31a4a6f2012-02-28 15:36:15 -0800143
Bill Buzbeea114add2012-05-03 15:00:40 -0700144 if (flags & SETS_CCODES) {
145 lir->defMask |= ENCODE_CCODE;
146 }
buzbee31a4a6f2012-02-28 15:36:15 -0800147
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
149 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800150
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 for (i = 0; i < 4; i++) {
152 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700153 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 }
buzbee31a4a6f2012-02-28 15:36:15 -0800155 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 }
buzbee31a4a6f2012-02-28 15:36:15 -0800157
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 if (flags & USES_CCODES) {
159 lir->useMask |= ENCODE_CCODE;
160 }
buzbee31a4a6f2012-02-28 15:36:15 -0800161
buzbeeb046e162012-10-30 15:48:42 -0700162 // Handle target-specific actions
163 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800164}
165
166/*
buzbee5de34942012-03-01 14:51:57 -0800167 * Debugging macros
168 */
169#define DUMP_RESOURCE_MASK(X)
170#define DUMP_SSA_REP(X)
171
172/* Pretty-print a LIR instruction */
buzbeecbd6d442012-11-17 14:11:25 -0800173void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* lir, unsigned char* baseAddr)
buzbee5de34942012-03-01 14:51:57 -0800174{
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 int offset = lir->offset;
176 int dest = lir->operands[0];
177 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800178
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 /* Handle pseudo-ops individually, and all regular insns as a group */
180 switch (lir->opcode) {
181 case kPseudoMethodEntry:
182 LOG(INFO) << "-------- method entry "
183 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
184 break;
185 case kPseudoMethodExit:
186 LOG(INFO) << "-------- Method_Exit";
187 break;
188 case kPseudoBarrier:
189 LOG(INFO) << "-------- BARRIER";
190 break;
191 case kPseudoExtended:
buzbeecbd6d442012-11-17 14:11:25 -0800192 LOG(INFO) << "-------- " << reinterpret_cast<char*>(dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 break;
194 case kPseudoSSARep:
buzbeecbd6d442012-11-17 14:11:25 -0800195 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << reinterpret_cast<char*>(dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700196 break;
197 case kPseudoEntryBlock:
198 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
199 break;
200 case kPseudoDalvikByteCodeBoundary:
201 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
buzbeecbd6d442012-11-17 14:11:25 -0800202 << lir->dalvikOffset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 break;
204 case kPseudoExitBlock:
205 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
206 break;
207 case kPseudoPseudoAlign4:
buzbeecbd6d442012-11-17 14:11:25 -0800208 LOG(INFO) << reinterpret_cast<uintptr_t>(baseAddr) + offset << " (0x" << std::hex
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 << offset << "): .align4";
210 break;
211 case kPseudoEHBlockLabel:
212 LOG(INFO) << "Exception_Handling:";
213 break;
214 case kPseudoTargetLabel:
215 case kPseudoNormalBlockLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800216 LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 break;
218 case kPseudoThrowTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800219 LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 break;
221 case kPseudoIntrinsicRetry:
buzbeecbd6d442012-11-17 14:11:25 -0800222 LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 break;
224 case kPseudoSuspendTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800225 LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 break;
buzbee8320f382012-09-11 16:29:42 -0700227 case kPseudoSafepointPC:
228 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
229 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700230 case kPseudoExportedPC:
231 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
232 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 case kPseudoCaseLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800234 LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 << std::hex << lir->operands[0] << "|" << std::dec <<
236 lir->operands[0];
237 break;
238 default:
239 if (lir->flags.isNop && !dumpNop) {
240 break;
241 } else {
buzbee1bc37c62012-11-20 13:35:41 -0800242 std::string op_name(buildInsnString(getTargetInstName(lir->opcode),
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 lir, baseAddr));
buzbee1bc37c62012-11-20 13:35:41 -0800244 std::string op_operands(buildInsnString(getTargetInstFmt(lir->opcode),
245 lir, baseAddr));
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
buzbeecbd6d442012-11-17 14:11:25 -0800247 reinterpret_cast<unsigned int>(baseAddr + offset),
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 op_name.c_str(), op_operands.c_str(),
249 lir->flags.isNop ? "(nop)" : "");
250 }
251 break;
252 }
buzbee5de34942012-03-01 14:51:57 -0800253
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
255 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
256 }
257 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
258 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
259 }
buzbee5de34942012-03-01 14:51:57 -0800260}
261
262void oatDumpPromotionMap(CompilationUnit *cUnit)
263{
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
265 for (int i = 0; i < numRegs; i++) {
266 PromotionMap vRegMap = cUnit->promotionMap[i];
267 std::string buf;
268 if (vRegMap.fpLocation == kLocPhysReg) {
buzbeef0504cd2012-11-13 16:31:10 -0800269 StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask());
buzbee5de34942012-03-01 14:51:57 -0800270 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700271
272 std::string buf3;
273 if (i < cUnit->numDalvikRegisters) {
274 StringAppendF(&buf3, "%02d", i);
275 } else if (i == cUnit->methodSReg) {
276 buf3 = "Method*";
277 } else {
278 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
279 }
280
281 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
282 vRegMap.coreLocation == kLocPhysReg ?
283 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
284 vRegMap.coreReg : oatSRegOffset(cUnit, i),
285 buf.c_str());
286 }
buzbee5de34942012-03-01 14:51:57 -0800287}
288
Bill Buzbeea5b30242012-09-28 07:19:44 -0700289/* Dump a mapping table */
290void dumpMappingTable(const char* table_name, const std::string& descriptor,
291 const std::string& name, const std::string& signature,
292 const std::vector<uint32_t>& v) {
293 if (v.size() > 0) {
294 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
295 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
296 std::replace(line.begin(), line.end(), ';', '_');
297 LOG(INFO) << line;
298 for (uint32_t i = 0; i < v.size(); i+=2) {
299 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
300 LOG(INFO) << line;
301 }
302 LOG(INFO) <<" };\n\n";
303 }
304}
305
buzbee5de34942012-03-01 14:51:57 -0800306/* Dump instructions and constant pool contents */
307void oatCodegenDump(CompilationUnit* cUnit)
308{
Bill Buzbeea114add2012-05-03 15:00:40 -0700309 LOG(INFO) << "Dumping LIR insns for "
310 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
311 LIR* lirInsn;
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800313
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
315 LOG(INFO) << "Ins : " << cUnit->numIns;
316 LOG(INFO) << "Outs : " << cUnit->numOuts;
317 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
318 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
319 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
320 LOG(INFO) << "Frame size : " << cUnit->frameSize;
321 LOG(INFO) << "code size is " << cUnit->totalSize <<
322 " bytes, Dalvik size is " << insnsSize * 2;
323 LOG(INFO) << "expansion factor: "
buzbeecbd6d442012-11-17 14:11:25 -0800324 << static_cast<float>(cUnit->totalSize) / static_cast<float>(insnsSize * 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 oatDumpPromotionMap(cUnit);
326 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
327 oatDumpLIRInsn(cUnit, lirInsn, 0);
328 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
buzbeecbd6d442012-11-17 14:11:25 -0800330 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lirInsn->offset, lirInsn->offset,
331 lirInsn->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 }
buzbee5de34942012-03-01 14:51:57 -0800333
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 const DexFile::MethodId& method_id =
335 cUnit->dex_file->GetMethodId(cUnit->method_idx);
336 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
337 std::string name(cUnit->dex_file->GetMethodName(method_id));
338 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800339
Bill Buzbeea5b30242012-09-28 07:19:44 -0700340 // Dump mapping tables
341 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
342 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800343}
344
buzbeea2ebdd72012-03-04 14:57:06 -0800345
346LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800348{
buzbeecbd6d442012-11-17 14:11:25 -0800349 LIR* insn = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 insn->dalvikOffset = dalvikOffset;
351 insn->opcode = opcode;
352 insn->operands[0] = op0;
353 insn->operands[1] = op1;
354 insn->operands[2] = op2;
355 insn->operands[3] = op3;
356 insn->operands[4] = op4;
357 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700358 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700359 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
360 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700362 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 }
364 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800365}
366
buzbee5de34942012-03-01 14:51:57 -0800367/*
buzbee31a4a6f2012-02-28 15:36:15 -0800368 * The following are building blocks to construct low-level IRs with 0 - 4
369 * operands.
370 */
buzbee5de34942012-03-01 14:51:57 -0800371LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800372{
buzbee1bc37c62012-11-20 13:35:41 -0800373 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & NO_OPERAND))
374 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
376 << cUnit->currentDalvikOffset;
377 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
buzbeecbd6d442012-11-17 14:11:25 -0800378 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800380}
381
buzbee5de34942012-03-01 14:51:57 -0800382LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800384{
buzbee1bc37c62012-11-20 13:35:41 -0800385 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & IS_UNARY_OP))
386 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
388 << cUnit->currentDalvikOffset;
389 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
buzbeecbd6d442012-11-17 14:11:25 -0800390 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800392}
393
buzbee5de34942012-03-01 14:51:57 -0800394LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800396{
buzbee1bc37c62012-11-20 13:35:41 -0800397 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & IS_BINARY_OP))
398 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
400 << cUnit->currentDalvikOffset;
401 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
buzbeecbd6d442012-11-17 14:11:25 -0800402 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800404}
405
buzbee5de34942012-03-01 14:51:57 -0800406LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700407 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800408{
buzbee1bc37c62012-11-20 13:35:41 -0800409 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & IS_TERTIARY_OP))
410 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
412 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800413 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2);
414 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800416}
417
buzbee5de34942012-03-01 14:51:57 -0800418LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800420{
buzbee1bc37c62012-11-20 13:35:41 -0800421 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & IS_QUAD_OP))
422 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
424 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800425 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info);
426 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800428}
buzbee31a4a6f2012-02-28 15:36:15 -0800429
Ian Rogersb5d09b22012-03-06 22:14:17 -0800430LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800432{
buzbee1bc37c62012-11-20 13:35:41 -0800433 DCHECK(isPseudoOpcode(opcode) || (getTargetInstFlags(opcode) & IS_QUIN_OP))
434 << getTargetInstName(opcode) << " " << opcode << " "
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
436 << cUnit->currentDalvikOffset;
buzbeecbd6d442012-11-17 14:11:25 -0800437 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info1, info2);
438 oatAppendLIR(cUnit, insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700439 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800440}
441
buzbee31a4a6f2012-02-28 15:36:15 -0800442/*
443 * Search the existing constants in the literal pool for an exact or close match
444 * within specified delta (greater or equal to 0).
445 */
446LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
447{
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 while (dataTarget) {
buzbeecbd6d442012-11-17 14:11:25 -0800449 if ((static_cast<unsigned>(value - dataTarget->operands[0])) <= delta)
450 return dataTarget;
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 dataTarget = dataTarget->next;
452 }
453 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800454}
455
456/* Search the existing constants in the literal pool for an exact wide match */
457LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
458{
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 bool loMatch = false;
460 LIR* loTarget = NULL;
461 while (dataTarget) {
buzbeecbd6d442012-11-17 14:11:25 -0800462 if (loMatch && (dataTarget->operands[0] == valHi)) {
463 return loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800464 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 loMatch = false;
buzbeecbd6d442012-11-17 14:11:25 -0800466 if (dataTarget->operands[0] == valLo) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 loMatch = true;
468 loTarget = dataTarget;
469 }
470 dataTarget = dataTarget->next;
471 }
472 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800473}
474
475/*
476 * The following are building blocks to insert constants into the pool or
477 * instruction streams.
478 */
479
buzbee5de34942012-03-01 14:51:57 -0800480/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700481LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800482{
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 /* Add the constant to the literal pool */
484 if (constantListP) {
buzbeecbd6d442012-11-17 14:11:25 -0800485 LIR* newValue = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocData));
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 newValue->operands[0] = value;
487 newValue->next = *constantListP;
buzbeecbd6d442012-11-17 14:11:25 -0800488 *constantListP = newValue;
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 return newValue;
490 }
491 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800492}
493
494/* Add a 64-bit constant to the constant pool or mixed with code */
495LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800497{
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 addWordData(cUnit, constantListP, valHi);
499 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800500}
501
Ian Rogersab058bb2012-03-11 22:19:38 -0700502void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 buf.push_back( data & 0xff);
504 buf.push_back( (data >> 8) & 0xff);
505 buf.push_back( (data >> 16) & 0xff);
506 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800507}
508
Ian Rogersab058bb2012-03-11 22:19:38 -0700509void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 while (buf.size() < offset) {
511 buf.push_back(0);
512 }
buzbeee3acd072012-02-25 17:03:10 -0800513}
514
Brian Carlstromf5822582012-03-19 22:34:31 -0700515bool IsDirect(int invokeType) {
516 InvokeType type = static_cast<InvokeType>(invokeType);
517 return type == kStatic || type == kDirect;
518}
519
buzbeee3acd072012-02-25 17:03:10 -0800520/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800521void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800522{
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
524 LIR* dataLIR = cUnit->literalList;
525 while (dataLIR != NULL) {
526 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
527 dataLIR = NEXT_LIR(dataLIR);
528 }
529 // Push code and method literals, record offsets for the compiler to patch.
530 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700531 while (dataLIR != NULL) {
532 uint32_t target = dataLIR->operands[0];
533 cUnit->compiler->AddCodePatch(cUnit->dex_file,
534 cUnit->method_idx,
535 cUnit->invoke_type,
536 target,
537 static_cast<InvokeType>(dataLIR->operands[1]),
538 cUnit->codeBuffer.size());
539 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
540 // unique based on target to ensure code deduplication works
541 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
542 pushWord(cUnit->codeBuffer, unique_patch_value);
543 dataLIR = NEXT_LIR(dataLIR);
544 }
545 dataLIR = cUnit->methodLiteralList;
546 while (dataLIR != NULL) {
547 uint32_t target = dataLIR->operands[0];
548 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700550 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700552 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700554 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
555 // unique based on target to ensure code deduplication works
556 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
557 pushWord(cUnit->codeBuffer, unique_patch_value);
558 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 }
buzbeee3acd072012-02-25 17:03:10 -0800560}
561
562/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800563void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800564{
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 GrowableListIterator iterator;
566 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
567 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800568 SwitchTable* tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext( &iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 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) {
buzbeecbd6d442012-11-17 14:11:25 -0800594 const int* keys = reinterpret_cast<const int*>(&(tabRec->table[2]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 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) {
buzbeecbd6d442012-11-17 14:11:25 -0800627 FillArrayData *tabRec =
628 reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext( &iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 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{
buzbeecbd6d442012-11-17 14:11:25 -0800683 for (LIR* tgtLIR = cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
buzbee8320f382012-09-11 16:29:42 -0700684 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) {
buzbeecbd6d442012-11-17 14:11:25 -0800823 SwitchTable *tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 if (tabRec == NULL) break;
825 tabRec->offset = offset;
826 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
827 offset += tabRec->table[1] * (sizeof(int) * 2);
828 } else {
829 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
830 static_cast<int>(Instruction::kPackedSwitchSignature));
831 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800832 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700833 }
834 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800835}
836
buzbee31a4a6f2012-02-28 15:36:15 -0800837int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800838{
Bill Buzbeea114add2012-05-03 15:00:40 -0700839 GrowableListIterator iterator;
840 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
841 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -0800842 FillArrayData *tabRec =
843 reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700844 if (tabRec == NULL) break;
845 tabRec->offset = offset;
846 offset += tabRec->size;
847 // word align
848 offset = (offset + 3) & ~3;
849 }
850 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800851}
852
853/*
854 * Walk the compilation unit and assign offsets to instructions
855 * and literals and compute the total size of the compiled unit.
856 */
857void oatAssignOffsets(CompilationUnit* cUnit)
858{
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800860
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 /* Const values have to be word aligned */
862 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800863
Bill Buzbeea114add2012-05-03 15:00:40 -0700864 /* Set up offsets for literals */
865 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800868
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800872
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800874}
875
876/*
877 * Go over each instruction in the list and calculate the offset from the top
878 * before sending them off to the assembler. If out-of-range branch distance is
879 * seen rearrange the instructions a bit to correct it.
880 */
881void oatAssembleLIR(CompilationUnit* cUnit)
882{
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 oatAssignOffsets(cUnit);
884 /*
885 * Assemble here. Note that we generate code with optimistic assumptions
886 * and if found now to work, we'll have to redo the sequence and retry.
887 */
buzbeee3acd072012-02-25 17:03:10 -0800888
Bill Buzbeea114add2012-05-03 15:00:40 -0700889 while (true) {
890 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
891 if (res == kSuccess) {
892 break;
893 } else {
894 cUnit->assemblerRetries++;
895 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
896 oatCodegenDump(cUnit);
897 LOG(FATAL) << "Assembler error - too many retries";
898 }
899 // Redo offsets and try again
900 oatAssignOffsets(cUnit);
901 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800902 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 }
buzbeee3acd072012-02-25 17:03:10 -0800904
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 // Install literals
906 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800907
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 // Install switch tables
909 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800910
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 // Install fill array data
912 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800913
Ian Rogers0c7abda2012-09-19 13:33:42 -0700914 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700915 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700916
917 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800918}
919
buzbee31a4a6f2012-02-28 15:36:15 -0800920/*
921 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
922 * offset vaddr. This label will be used to fix up the case
923 * branch table during the assembly phase. Be sure to set
924 * all resource flags on this to prevent code motion across
925 * target boundaries. KeyVal is just there for debugging.
926 */
927LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
928{
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 SafeMap<unsigned int, LIR*>::iterator it;
930 it = cUnit->boundaryMap.find(vaddr);
931 if (it == cUnit->boundaryMap.end()) {
932 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
933 }
buzbeecbd6d442012-11-17 14:11:25 -0800934 LIR* newLabel = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 newLabel->dalvikOffset = vaddr;
936 newLabel->opcode = kPseudoCaseLabel;
937 newLabel->operands[0] = keyVal;
buzbeecbd6d442012-11-17 14:11:25 -0800938 oatInsertLIRAfter(it->second, newLabel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700939 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800940}
941
942void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
943{
buzbeeeaf09bc2012-11-15 14:51:41 -0800944 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 int baseVaddr = tabRec->vaddr;
buzbeecbd6d442012-11-17 14:11:25 -0800946 const int *targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 int entries = table[1];
948 int lowKey = s4FromSwitchData(&table[2]);
949 for (int i = 0; i < entries; i++) {
buzbeecbd6d442012-11-17 14:11:25 -0800950 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], i + lowKey);
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 }
buzbee31a4a6f2012-02-28 15:36:15 -0800952}
953
954void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
955{
buzbeeeaf09bc2012-11-15 14:51:41 -0800956 const uint16_t* table = tabRec->table;
Bill Buzbeea114add2012-05-03 15:00:40 -0700957 int baseVaddr = tabRec->vaddr;
958 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -0800959 const int* keys = reinterpret_cast<const int*>(&table[2]);
960 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -0700961 for (int i = 0; i < entries; i++) {
buzbeecbd6d442012-11-17 14:11:25 -0800962 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], keys[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 }
buzbee31a4a6f2012-02-28 15:36:15 -0800964}
965
966void oatProcessSwitchTables(CompilationUnit* cUnit)
967{
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 GrowableListIterator iterator;
969 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
970 while (true) {
971 SwitchTable *tabRec =
buzbeecbd6d442012-11-17 14:11:25 -0800972 reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 if (tabRec == NULL) break;
974 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
975 markPackedCaseLabels(cUnit, tabRec);
976 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
977 markSparseCaseLabels(cUnit, tabRec);
978 } else {
979 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800980 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 }
buzbee31a4a6f2012-02-28 15:36:15 -0800982}
983
buzbeeeaf09bc2012-11-15 14:51:41 -0800984void dumpSparseSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 /*
986 * Sparse switch data format:
987 * ushort ident = 0x0200 magic value
988 * ushort size number of entries in the table; > 0
989 * int keys[size] keys, sorted low-to-high; 32-bit aligned
990 * int targets[size] branch targets, relative to switch opcode
991 *
992 * Total size is (2+size*4) 16-bit code units.
993 */
buzbee31a4a6f2012-02-28 15:36:15 -0800994{
buzbeeeaf09bc2012-11-15 14:51:41 -0800995 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -0700996 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -0800997 const int* keys = reinterpret_cast<const int*>(&table[2]);
998 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1000 << ", entries: " << std::dec << entries;
1001 for (int i = 0; i < entries; i++) {
1002 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1003 }
buzbee31a4a6f2012-02-28 15:36:15 -08001004}
1005
buzbeeeaf09bc2012-11-15 14:51:41 -08001006void dumpPackedSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 /*
1008 * Packed switch data format:
1009 * ushort ident = 0x0100 magic value
1010 * ushort size number of entries in the table
1011 * int first_key first (and lowest) switch case value
1012 * int targets[size] branch targets, relative to switch opcode
1013 *
1014 * Total size is (4+size*2) 16-bit code units.
1015 */
buzbee31a4a6f2012-02-28 15:36:15 -08001016{
buzbeeeaf09bc2012-11-15 14:51:41 -08001017 uint16_t ident = table[0];
buzbeecbd6d442012-11-17 14:11:25 -08001018 const int* targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001019 int entries = table[1];
1020 int lowKey = s4FromSwitchData(&table[2]);
1021 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1022 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1023 for (int i = 0; i < entries; i++) {
1024 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1025 << targets[i];
1026 }
buzbee31a4a6f2012-02-28 15:36:15 -08001027}
buzbeee3acd072012-02-25 17:03:10 -08001028
buzbeed1643e42012-09-05 14:06:51 -07001029/*
1030 * Set up special LIR to mark a Dalvik byte-code instruction start and
1031 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1032 * which we split a single Dalvik instruction, only the first MIR op
1033 * associated with a Dalvik PC should be entered into the map.
1034 */
1035LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1036{
buzbeecbd6d442012-11-17 14:11:25 -08001037 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(instStr));
buzbeed1643e42012-09-05 14:06:51 -07001038 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1039 cUnit->boundaryMap.Put(offset, res);
1040 }
1041 return res;
1042}
buzbeee3acd072012-02-25 17:03:10 -08001043
buzbeed1643e42012-09-05 14:06:51 -07001044}
1045 // namespace art