blob: ccc2a83f7e1bf93131d1b6f2110afce84f1fe65a [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"
20
buzbeee3acd072012-02-25 17:03:10 -080021namespace art {
22
buzbee31a4a6f2012-02-28 15:36:15 -080023void setMemRefType(LIR* lir, bool isLoad, int memType)
24{
Bill Buzbeea114add2012-05-03 15:00:40 -070025 u8 *maskPtr;
26 u8 mask = ENCODE_MEM;;
27 DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
28 if (isLoad) {
29 maskPtr = &lir->useMask;
30 } else {
31 maskPtr = &lir->defMask;
32 }
33 /* Clear out the memref flags */
34 *maskPtr &= ~mask;
35 /* ..and then add back the one we need */
36 switch (memType) {
37 case kLiteral:
38 DCHECK(isLoad);
39 *maskPtr |= ENCODE_LITERAL;
40 break;
41 case kDalvikReg:
42 *maskPtr |= ENCODE_DALVIK_REG;
43 break;
44 case kHeapRef:
45 *maskPtr |= ENCODE_HEAP_REF;
46 break;
47 case kMustNotAlias:
48 /* Currently only loads can be marked as kMustNotAlias */
49 DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
50 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
51 break;
52 default:
53 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
54 }
buzbee31a4a6f2012-02-28 15:36:15 -080055}
56
57/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080058 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080059 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080060void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080061{
Bill Buzbeea114add2012-05-03 15:00:40 -070062 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080063
Bill Buzbeea114add2012-05-03 15:00:40 -070064 /*
65 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
66 * access.
67 */
68 lir->aliasInfo = regId;
69 if (is64bit) {
70 lir->aliasInfo |= 0x80000000;
71 }
buzbee31a4a6f2012-02-28 15:36:15 -080072}
73
74/*
75 * Decode the register id.
76 */
77inline u8 getRegMaskCommon(int reg)
78{
Bill Buzbeea114add2012-05-03 15:00:40 -070079 u8 seed;
80 int shift;
buzbee31a4a6f2012-02-28 15:36:15 -080081
jeffhaoe2962482012-06-28 11:29:57 -070082#if defined(TARGET_X86)
jeffhao854029c2012-07-23 17:31:30 -070083 int regId = reg & 0xf;
jeffhaoe2962482012-06-28 11:29:57 -070084 /*
85 * Double registers in x86 are just a single FP register
86 */
87 seed = 1;
88#else
jeffhao854029c2012-07-23 17:31:30 -070089 int regId = reg & 0x1f;
Bill Buzbeea114add2012-05-03 15:00:40 -070090 /*
91 * Each double register is equal to a pair of single-precision FP registers
92 */
93 seed = DOUBLEREG(reg) ? 3 : 1;
jeffhaoe2962482012-06-28 11:29:57 -070094#endif
Bill Buzbeea114add2012-05-03 15:00:40 -070095 /* FP register starts at bit position 16 */
96 shift = FPREG(reg) ? kFPReg0 : 0;
97 /* Expand the double register id into single offset */
98 shift += regId;
99 return (seed << shift);
buzbee31a4a6f2012-02-28 15:36:15 -0800100}
101
102/*
103 * Mark the corresponding bit(s).
104 */
105inline void setupRegMask(u8* mask, int reg)
106{
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 *mask |= getRegMaskCommon(reg);
buzbee31a4a6f2012-02-28 15:36:15 -0800108}
109
110/*
111 * Set up the proper fields in the resource mask
112 */
113void setupResourceMasks(LIR* lir)
114{
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 int opcode = lir->opcode;
116 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 if (opcode <= 0) {
119 lir->useMask = lir->defMask = 0;
120 return;
121 }
buzbee31a4a6f2012-02-28 15:36:15 -0800122
Bill Buzbeea114add2012-05-03 15:00:40 -0700123 flags = EncodingMap[lir->opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800124
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 if (flags & NEEDS_FIXUP) {
126 lir->flags.pcRelFixup = true;
127 }
buzbee31a4a6f2012-02-28 15:36:15 -0800128
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 /* Get the starting size of the instruction's template */
130 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800131
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 /* Set up the mask for resources that are updated */
133 if (flags & (IS_LOAD | IS_STORE)) {
134 /* Default to heap - will catch specialized classes later */
135 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
136 }
buzbee31a4a6f2012-02-28 15:36:15 -0800137
Bill Buzbeea114add2012-05-03 15:00:40 -0700138 /*
139 * Conservatively assume the branch here will call out a function that in
140 * turn will trash everything.
141 */
142 if (flags & IS_BRANCH) {
143 lir->defMask = lir->useMask = ENCODE_ALL;
144 return;
145 }
buzbee31a4a6f2012-02-28 15:36:15 -0800146
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 if (flags & REG_DEF0) {
148 setupRegMask(&lir->defMask, lir->operands[0]);
149 }
buzbee31a4a6f2012-02-28 15:36:15 -0800150
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 if (flags & REG_DEF1) {
152 setupRegMask(&lir->defMask, lir->operands[1]);
153 }
buzbee31a4a6f2012-02-28 15:36:15 -0800154
jeffhaoe2962482012-06-28 11:29:57 -0700155#if defined(TARGET_X86)
156 if (flags & REG_DEFA) {
157 setupRegMask(&lir->defMask, rAX);
158 }
159
160 if (flags & REG_DEFD) {
161 setupRegMask(&lir->defMask, rDX);
162 }
163#endif
164
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 if (flags & REG_DEF_SP) {
166 lir->defMask |= ENCODE_REG_SP;
167 }
buzbee31a4a6f2012-02-28 15:36:15 -0800168
buzbeea7678db2012-03-05 15:35:46 -0800169#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 if (flags & REG_DEF_LR) {
171 lir->defMask |= ENCODE_REG_LR;
172 }
buzbeea7678db2012-03-05 15:35:46 -0800173#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800174
jeffhaoe2962482012-06-28 11:29:57 -0700175#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 if (flags & REG_DEF_LIST0) {
177 lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
178 }
buzbee31a4a6f2012-02-28 15:36:15 -0800179
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 if (flags & REG_DEF_LIST1) {
181 lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
182 }
buzbee31a4a6f2012-02-28 15:36:15 -0800183
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 if (flags & REG_DEF_FPCS_LIST0) {
185 lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
186 }
buzbee31a4a6f2012-02-28 15:36:15 -0800187
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 if (flags & REG_DEF_FPCS_LIST2) {
189 for (int i = 0; i < lir->operands[2]; i++) {
190 setupRegMask(&lir->defMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800191 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700192 }
buzbee5de34942012-03-01 14:51:57 -0800193#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800194
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 if (flags & SETS_CCODES) {
196 lir->defMask |= ENCODE_CCODE;
197 }
buzbee31a4a6f2012-02-28 15:36:15 -0800198
199#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 /* Conservatively treat the IT block */
201 if (flags & IS_IT) {
202 lir->defMask = ENCODE_ALL;
203 }
buzbee31a4a6f2012-02-28 15:36:15 -0800204#endif
205
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
207 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800208
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 for (i = 0; i < 4; i++) {
210 if (flags & (1 << (kRegUse0 + i))) {
211 setupRegMask(&lir->useMask, lir->operands[i]);
212 }
buzbee31a4a6f2012-02-28 15:36:15 -0800213 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 }
buzbee31a4a6f2012-02-28 15:36:15 -0800215
jeffhaoe2962482012-06-28 11:29:57 -0700216#if defined(TARGET_X86)
217 if (flags & REG_USEA) {
218 setupRegMask(&lir->useMask, rAX);
219 }
220
221 if (flags & REG_USEC) {
222 setupRegMask(&lir->useMask, rCX);
223 }
224
225 if (flags & REG_USED) {
226 setupRegMask(&lir->useMask, rDX);
227 }
228#endif
229
buzbeea7678db2012-03-05 15:35:46 -0800230#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 if (flags & REG_USE_PC) {
232 lir->useMask |= ENCODE_REG_PC;
233 }
buzbeea7678db2012-03-05 15:35:46 -0800234#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800235
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 if (flags & REG_USE_SP) {
237 lir->useMask |= ENCODE_REG_SP;
238 }
buzbee31a4a6f2012-02-28 15:36:15 -0800239
jeffhaoe2962482012-06-28 11:29:57 -0700240#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 if (flags & REG_USE_LIST0) {
242 lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
243 }
buzbee31a4a6f2012-02-28 15:36:15 -0800244
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 if (flags & REG_USE_LIST1) {
246 lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
247 }
buzbee31a4a6f2012-02-28 15:36:15 -0800248
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 if (flags & REG_USE_FPCS_LIST0) {
250 lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
251 }
buzbee31a4a6f2012-02-28 15:36:15 -0800252
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 if (flags & REG_USE_FPCS_LIST2) {
254 for (int i = 0; i < lir->operands[2]; i++) {
255 setupRegMask(&lir->useMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800256 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 }
buzbee5de34942012-03-01 14:51:57 -0800258#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800259
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 if (flags & USES_CCODES) {
261 lir->useMask |= ENCODE_CCODE;
262 }
buzbee31a4a6f2012-02-28 15:36:15 -0800263
264#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700265 /* Fixup for kThumbPush/lr and kThumbPop/pc */
266 if (opcode == kThumbPush || opcode == kThumbPop) {
267 u8 r8Mask = getRegMaskCommon(r8);
268 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
269 lir->useMask &= ~r8Mask;
270 lir->useMask |= ENCODE_REG_LR;
271 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
272 lir->defMask &= ~r8Mask;
273 lir->defMask |= ENCODE_REG_PC;
buzbee31a4a6f2012-02-28 15:36:15 -0800274 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 }
buzbee31a4a6f2012-02-28 15:36:15 -0800276#endif
277}
278
279/*
buzbee5de34942012-03-01 14:51:57 -0800280 * Debugging macros
281 */
282#define DUMP_RESOURCE_MASK(X)
283#define DUMP_SSA_REP(X)
284
285/* Pretty-print a LIR instruction */
286void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
287{
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 LIR* lir = (LIR*) arg;
289 int offset = lir->offset;
290 int dest = lir->operands[0];
291 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800292
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 /* Handle pseudo-ops individually, and all regular insns as a group */
294 switch (lir->opcode) {
295 case kPseudoMethodEntry:
296 LOG(INFO) << "-------- method entry "
297 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
298 break;
299 case kPseudoMethodExit:
300 LOG(INFO) << "-------- Method_Exit";
301 break;
302 case kPseudoBarrier:
303 LOG(INFO) << "-------- BARRIER";
304 break;
305 case kPseudoExtended:
306 LOG(INFO) << "-------- " << (char* ) dest;
307 break;
308 case kPseudoSSARep:
309 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
310 break;
311 case kPseudoEntryBlock:
312 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
313 break;
314 case kPseudoDalvikByteCodeBoundary:
315 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
316 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
317 break;
318 case kPseudoExitBlock:
319 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
320 break;
321 case kPseudoPseudoAlign4:
322 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
323 << offset << "): .align4";
324 break;
325 case kPseudoEHBlockLabel:
326 LOG(INFO) << "Exception_Handling:";
327 break;
328 case kPseudoTargetLabel:
329 case kPseudoNormalBlockLabel:
330 LOG(INFO) << "L" << (void*)lir << ":";
331 break;
332 case kPseudoThrowTarget:
333 LOG(INFO) << "LT" << (void*)lir << ":";
334 break;
335 case kPseudoIntrinsicRetry:
336 LOG(INFO) << "IR" << (void*)lir << ":";
337 break;
338 case kPseudoSuspendTarget:
339 LOG(INFO) << "LS" << (void*)lir << ":";
340 break;
buzbee8320f382012-09-11 16:29:42 -0700341 case kPseudoSafepointPC:
342 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
343 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700344 case kPseudoExportedPC:
345 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
346 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 case kPseudoCaseLabel:
348 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
349 << std::hex << lir->operands[0] << "|" << std::dec <<
350 lir->operands[0];
351 break;
352 default:
353 if (lir->flags.isNop && !dumpNop) {
354 break;
355 } else {
356 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
357 lir, baseAddr));
358 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
359 , lir, baseAddr));
360 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
361 (unsigned int)(baseAddr + offset),
362 op_name.c_str(), op_operands.c_str(),
363 lir->flags.isNop ? "(nop)" : "");
364 }
365 break;
366 }
buzbee5de34942012-03-01 14:51:57 -0800367
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
369 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
370 }
371 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
372 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
373 }
buzbee5de34942012-03-01 14:51:57 -0800374}
375
376void oatDumpPromotionMap(CompilationUnit *cUnit)
377{
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
379 for (int i = 0; i < numRegs; i++) {
380 PromotionMap vRegMap = cUnit->promotionMap[i];
381 std::string buf;
382 if (vRegMap.fpLocation == kLocPhysReg) {
383 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800384 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700385
386 std::string buf3;
387 if (i < cUnit->numDalvikRegisters) {
388 StringAppendF(&buf3, "%02d", i);
389 } else if (i == cUnit->methodSReg) {
390 buf3 = "Method*";
391 } else {
392 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
393 }
394
395 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
396 vRegMap.coreLocation == kLocPhysReg ?
397 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
398 vRegMap.coreReg : oatSRegOffset(cUnit, i),
399 buf.c_str());
400 }
buzbee5de34942012-03-01 14:51:57 -0800401}
402
Bill Buzbeea5b30242012-09-28 07:19:44 -0700403/* Dump a mapping table */
404void dumpMappingTable(const char* table_name, const std::string& descriptor,
405 const std::string& name, const std::string& signature,
406 const std::vector<uint32_t>& v) {
407 if (v.size() > 0) {
408 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
409 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
410 std::replace(line.begin(), line.end(), ';', '_');
411 LOG(INFO) << line;
412 for (uint32_t i = 0; i < v.size(); i+=2) {
413 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
414 LOG(INFO) << line;
415 }
416 LOG(INFO) <<" };\n\n";
417 }
418}
419
buzbee5de34942012-03-01 14:51:57 -0800420/* Dump instructions and constant pool contents */
421void oatCodegenDump(CompilationUnit* cUnit)
422{
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 LOG(INFO) << "Dumping LIR insns for "
424 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
425 LIR* lirInsn;
426 LIR* thisLIR;
427 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800428
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
430 LOG(INFO) << "Ins : " << cUnit->numIns;
431 LOG(INFO) << "Outs : " << cUnit->numOuts;
432 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
433 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
434 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
435 LOG(INFO) << "Frame size : " << cUnit->frameSize;
436 LOG(INFO) << "code size is " << cUnit->totalSize <<
437 " bytes, Dalvik size is " << insnsSize * 2;
438 LOG(INFO) << "expansion factor: "
439 << (float)cUnit->totalSize / (float)(insnsSize * 2);
440 oatDumpPromotionMap(cUnit);
441 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
442 oatDumpLIRInsn(cUnit, lirInsn, 0);
443 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
445 thisLIR = (LIR*) lirInsn;
446 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
447 thisLIR->offset, thisLIR->offset,
448 thisLIR->operands[0]);
449 }
buzbee5de34942012-03-01 14:51:57 -0800450
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 const DexFile::MethodId& method_id =
452 cUnit->dex_file->GetMethodId(cUnit->method_idx);
453 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
454 std::string name(cUnit->dex_file->GetMethodName(method_id));
455 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800456
Bill Buzbeea5b30242012-09-28 07:19:44 -0700457 // Dump mapping tables
458 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
459 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800460}
461
buzbeea2ebdd72012-03-04 14:57:06 -0800462
463LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800465{
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
467 insn->dalvikOffset = dalvikOffset;
468 insn->opcode = opcode;
469 insn->operands[0] = op0;
470 insn->operands[1] = op1;
471 insn->operands[2] = op2;
472 insn->operands[3] = op3;
473 insn->operands[4] = op4;
474 insn->target = target;
475 oatSetupResourceMasks(insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700476 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
477 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700479 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 }
481 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800482}
483
buzbee5de34942012-03-01 14:51:57 -0800484/*
buzbee31a4a6f2012-02-28 15:36:15 -0800485 * The following are building blocks to construct low-level IRs with 0 - 4
486 * operands.
487 */
buzbee5de34942012-03-01 14:51:57 -0800488LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800489{
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
491 << EncodingMap[opcode].name << " " << (int)opcode << " "
492 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
493 << cUnit->currentDalvikOffset;
494 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
495 oatAppendLIR(cUnit, (LIR*) insn);
496 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800497}
498
buzbee5de34942012-03-01 14:51:57 -0800499LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800501{
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
503 << EncodingMap[opcode].name << " " << (int)opcode << " "
504 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
505 << cUnit->currentDalvikOffset;
506 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
507 oatAppendLIR(cUnit, (LIR*) insn);
508 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800509}
510
buzbee5de34942012-03-01 14:51:57 -0800511LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800513{
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
515 << EncodingMap[opcode].name << " " << (int)opcode << " "
516 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
517 << cUnit->currentDalvikOffset;
518 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
519 oatAppendLIR(cUnit, (LIR*) insn);
520 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800521}
522
buzbee5de34942012-03-01 14:51:57 -0800523LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700524 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800525{
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
527 << EncodingMap[opcode].name << " " << (int)opcode << " "
528 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
529 << cUnit->currentDalvikOffset;
530 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
531 src2);
532 oatAppendLIR(cUnit, (LIR*) insn);
533 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800534}
535
buzbee5de34942012-03-01 14:51:57 -0800536LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800538{
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
540 << EncodingMap[opcode].name << " " << (int)opcode << " "
541 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
542 << cUnit->currentDalvikOffset;
543 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
544 src2, info);
545 oatAppendLIR(cUnit, (LIR*) insn);
546 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800547}
buzbee31a4a6f2012-02-28 15:36:15 -0800548
Ian Rogersb5d09b22012-03-06 22:14:17 -0800549LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800551{
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
553 << EncodingMap[opcode].name << " " << (int)opcode << " "
554 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
555 << cUnit->currentDalvikOffset;
556 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
557 src2, info1, info2);
558 oatAppendLIR(cUnit, (LIR*) insn);
559 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800560}
561
buzbee31a4a6f2012-02-28 15:36:15 -0800562/*
563 * Search the existing constants in the literal pool for an exact or close match
564 * within specified delta (greater or equal to 0).
565 */
566LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
567{
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 while (dataTarget) {
569 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
570 return (LIR* ) dataTarget;
571 dataTarget = dataTarget->next;
572 }
573 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800574}
575
576/* Search the existing constants in the literal pool for an exact wide match */
577LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
578{
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 bool loMatch = false;
580 LIR* loTarget = NULL;
581 while (dataTarget) {
582 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
583 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800584 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 loMatch = false;
586 if (((LIR*)dataTarget)->operands[0] == valLo) {
587 loMatch = true;
588 loTarget = dataTarget;
589 }
590 dataTarget = dataTarget->next;
591 }
592 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800593}
594
595/*
596 * The following are building blocks to insert constants into the pool or
597 * instruction streams.
598 */
599
buzbee5de34942012-03-01 14:51:57 -0800600/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700601LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800602{
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 /* Add the constant to the literal pool */
604 if (constantListP) {
605 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
606 newValue->operands[0] = value;
607 newValue->next = *constantListP;
608 *constantListP = (LIR*) newValue;
609 return newValue;
610 }
611 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800612}
613
614/* Add a 64-bit constant to the constant pool or mixed with code */
615LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800617{
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 //FIXME: hard-coded little endian, need BE variant
619 // Insert high word into list first
620 addWordData(cUnit, constantListP, valHi);
621 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800622}
623
Ian Rogersab058bb2012-03-11 22:19:38 -0700624void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 buf.push_back( data & 0xff);
626 buf.push_back( (data >> 8) & 0xff);
627 buf.push_back( (data >> 16) & 0xff);
628 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800629}
630
Ian Rogersab058bb2012-03-11 22:19:38 -0700631void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 while (buf.size() < offset) {
633 buf.push_back(0);
634 }
buzbeee3acd072012-02-25 17:03:10 -0800635}
636
Brian Carlstromf5822582012-03-19 22:34:31 -0700637bool IsDirect(int invokeType) {
638 InvokeType type = static_cast<InvokeType>(invokeType);
639 return type == kStatic || type == kDirect;
640}
641
buzbeee3acd072012-02-25 17:03:10 -0800642/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800643void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800644{
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
646 LIR* dataLIR = cUnit->literalList;
647 while (dataLIR != NULL) {
648 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
649 dataLIR = NEXT_LIR(dataLIR);
650 }
651 // Push code and method literals, record offsets for the compiler to patch.
652 dataLIR = cUnit->codeLiteralList;
653 if (dataLIR != NULL) {
buzbeee3acd072012-02-25 17:03:10 -0800654 while (dataLIR != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 uint32_t target = dataLIR->operands[0];
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700656 cUnit->compiler->AddCodePatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700658 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700660 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 cUnit->codeBuffer.size());
662 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
663 // unique based on target to ensure code deduplication works
664 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
665 pushWord(cUnit->codeBuffer, unique_patch_value);
666 dataLIR = NEXT_LIR(dataLIR);
buzbeee3acd072012-02-25 17:03:10 -0800667 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 dataLIR = cUnit->methodLiteralList;
669 while (dataLIR != NULL) {
670 uint32_t target = dataLIR->operands[0];
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700671 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700672 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700673 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700675 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 cUnit->codeBuffer.size());
677 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
678 // unique based on target to ensure code deduplication works
679 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
680 pushWord(cUnit->codeBuffer, unique_patch_value);
681 dataLIR = NEXT_LIR(dataLIR);
Ian Rogers3fa13792012-03-18 15:53:45 -0700682 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 }
Ian Rogers3fa13792012-03-18 15:53:45 -0700684
buzbeee3acd072012-02-25 17:03:10 -0800685}
686
687/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800688void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800689{
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 GrowableListIterator iterator;
691 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
692 while (true) {
693 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
694 &iterator);
695 if (tabRec == NULL) break;
696 alignBuffer(cUnit->codeBuffer, tabRec->offset);
697 /*
698 * For Arm, our reference point is the address of the bx
699 * instruction that does the launch, so we have to subtract
700 * the auto pc-advance. For other targets the reference point
701 * is a label, so we can use the offset as-is.
702 */
buzbeec5159d52012-03-03 11:48:39 -0800703#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 int bxOffset = tabRec->anchor->offset + 4;
Ian Rogers7caad772012-03-30 01:07:54 -0700705#elif defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 int bxOffset = 0;
buzbeec5159d52012-03-03 11:48:39 -0800707#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700708 int bxOffset = tabRec->anchor->offset;
buzbeec5159d52012-03-03 11:48:39 -0800709#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 if (cUnit->printMe) {
711 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800712 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
714 int* keys = (int*)&(tabRec->table[2]);
715 for (int elems = 0; elems < tabRec->table[1]; elems++) {
716 int disp = tabRec->targets[elems]->offset - bxOffset;
717 if (cUnit->printMe) {
718 LOG(INFO) << " Case[" << elems << "] key: 0x"
719 << std::hex << keys[elems] << ", disp: 0x"
720 << std::hex << disp;
721 }
722 pushWord(cUnit->codeBuffer, keys[elems]);
723 pushWord(cUnit->codeBuffer,
724 tabRec->targets[elems]->offset - bxOffset);
725 }
726 } else {
727 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
728 static_cast<int>(Instruction::kPackedSwitchSignature));
729 for (int elems = 0; elems < tabRec->table[1]; elems++) {
730 int disp = tabRec->targets[elems]->offset - bxOffset;
731 if (cUnit->printMe) {
732 LOG(INFO) << " Case[" << elems << "] disp: 0x"
733 << std::hex << disp;
734 }
735 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
736 }
737 }
738 }
buzbeee3acd072012-02-25 17:03:10 -0800739}
740
741/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800742void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800743{
Bill Buzbeea114add2012-05-03 15:00:40 -0700744 GrowableListIterator iterator;
745 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
746 while (true) {
747 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
748 &iterator);
749 if (tabRec == NULL) break;
750 alignBuffer(cUnit->codeBuffer, tabRec->offset);
751 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
752 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
753 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800754 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700755 }
buzbeee3acd072012-02-25 17:03:10 -0800756}
757
buzbee31a4a6f2012-02-28 15:36:15 -0800758int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800759{
Bill Buzbeea114add2012-05-03 15:00:40 -0700760 for (;lir != NULL; lir = lir->next) {
761 lir->offset = offset;
762 offset += 4;
763 }
764 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800765}
766
buzbee6459e7c2012-10-02 14:42:41 -0700767// Make sure we have a code address for every declared catch entry
768bool verifyCatchEntries(CompilationUnit* cUnit)
769{
770 bool success = true;
771 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
772 uint32_t dexPc = *it;
773 bool found = false;
774 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
775 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
776 found = true;
777 break;
778 }
779 }
780 if (!found) {
781 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
782 success = false;
783 }
784 }
785 // Now, try in the other direction
786 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
787 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
788 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
789 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
790 success = false;
791 }
792 }
793 if (!success) {
794 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
795 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
796 << cUnit->dex2pcMappingTable.size()/2;
797 }
798 return success;
799}
800
Bill Buzbeea5b30242012-09-28 07:19:44 -0700801void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800802{
buzbee8320f382012-09-11 16:29:42 -0700803 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
804 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700805 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
806 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
807 }
808 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
809 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
810 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800811 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 }
buzbee6459e7c2012-10-02 14:42:41 -0700813 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700814 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
815 cUnit->dex2pcMappingTable.size());
816 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
817 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
818 cUnit->pc2dexMappingTable.begin(),
819 cUnit->pc2dexMappingTable.end());
820 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
821 cUnit->dex2pcMappingTable.begin(),
822 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800823}
824
Ian Rogers0c7abda2012-09-19 13:33:42 -0700825class NativePcToReferenceMapBuilder {
826 public:
827 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
828 size_t entries, uint32_t max_native_offset,
829 size_t references_width) : entries_(entries),
830 references_width_(references_width), in_use_(entries),
831 table_(table) {
832 // Compute width in bytes needed to hold max_native_offset.
833 native_offset_width_ = 0;
834 while (max_native_offset != 0) {
835 native_offset_width_++;
836 max_native_offset >>= 8;
837 }
838 // Resize table and set up header.
839 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700840 CHECK_LT(native_offset_width_, 1U << 3);
841 (*table)[0] = native_offset_width_ & 7;
842 CHECK_LT(references_width_, 1U << 13);
843 (*table)[0] |= (references_width_ << 3) & 0xFF;
844 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700845 CHECK_LT(entries, 1U << 16);
846 (*table)[2] = entries & 0xFF;
847 (*table)[3] = (entries >> 8) & 0xFF;
848 }
849
850 void AddEntry(uint32_t native_offset, const uint8_t* references) {
851 size_t table_index = TableIndex(native_offset);
852 while (in_use_[table_index]) {
853 table_index = (table_index + 1) % entries_;
854 }
855 in_use_[table_index] = true;
856 SetNativeOffset(table_index, native_offset);
857 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
858 SetReferences(table_index, references);
859 }
860
861 private:
862 size_t TableIndex(uint32_t native_offset) {
863 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
864 }
865
866 uint32_t GetNativeOffset(size_t table_index) {
867 uint32_t native_offset = 0;
868 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
869 for (size_t i = 0; i < native_offset_width_; i++) {
870 native_offset |= (*table_)[table_offset + i] << (i * 8);
871 }
872 return native_offset;
873 }
874
875 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
876 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
877 for (size_t i = 0; i < native_offset_width_; i++) {
878 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
879 }
880 }
881
882 void SetReferences(size_t table_index, const uint8_t* references) {
883 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
884 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
885 }
886
887 size_t EntryWidth() const {
888 return native_offset_width_ + references_width_;
889 }
890
891 // Number of entries in the table.
892 const size_t entries_;
893 // Number of bytes used to encode the reference bitmap.
894 const size_t references_width_;
895 // Number of bytes used to encode a native offset.
896 size_t native_offset_width_;
897 // Entries that are in use.
898 std::vector<bool> in_use_;
899 // The table we're building.
900 std::vector<uint8_t>* const table_;
901};
902
903static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700904 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700905 uint32_t max_native_offset = 0;
906 for (size_t i = 0; i < mapping_table.size(); i += 2) {
907 uint32_t native_offset = mapping_table[i + 0];
908 if (native_offset > max_native_offset) {
909 max_native_offset = native_offset;
910 }
911 }
912 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
913 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
914 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
915 // Compute native offset to references size.
916 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
917 mapping_table.size() / 2, max_native_offset,
918 dex_gc_map.RegWidth());
919
920 for (size_t i = 0; i < mapping_table.size(); i += 2) {
921 uint32_t native_offset = mapping_table[i + 0];
922 uint32_t dex_pc = mapping_table[i + 1];
923 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700924 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
925 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700926 }
927}
928
buzbeee3acd072012-02-25 17:03:10 -0800929/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800930int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800931{
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
933 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
934 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
935 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800936}
937
buzbee31a4a6f2012-02-28 15:36:15 -0800938int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800939{
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 GrowableListIterator iterator;
941 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
942 while (true) {
943 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
944 &iterator);
945 if (tabRec == NULL) break;
946 tabRec->offset = offset;
947 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
948 offset += tabRec->table[1] * (sizeof(int) * 2);
949 } else {
950 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
951 static_cast<int>(Instruction::kPackedSwitchSignature));
952 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800953 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700954 }
955 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800956}
957
buzbee31a4a6f2012-02-28 15:36:15 -0800958int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800959{
Bill Buzbeea114add2012-05-03 15:00:40 -0700960 GrowableListIterator iterator;
961 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
962 while (true) {
963 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
964 &iterator);
965 if (tabRec == NULL) break;
966 tabRec->offset = offset;
967 offset += tabRec->size;
968 // word align
969 offset = (offset + 3) & ~3;
970 }
971 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800972}
973
974/*
975 * Walk the compilation unit and assign offsets to instructions
976 * and literals and compute the total size of the compiled unit.
977 */
978void oatAssignOffsets(CompilationUnit* cUnit)
979{
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800981
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 /* Const values have to be word aligned */
983 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800984
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 /* Set up offsets for literals */
986 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800987
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800989
Bill Buzbeea114add2012-05-03 15:00:40 -0700990 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800991
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800993
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800995}
996
997/*
998 * Go over each instruction in the list and calculate the offset from the top
999 * before sending them off to the assembler. If out-of-range branch distance is
1000 * seen rearrange the instructions a bit to correct it.
1001 */
1002void oatAssembleLIR(CompilationUnit* cUnit)
1003{
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 oatAssignOffsets(cUnit);
1005 /*
1006 * Assemble here. Note that we generate code with optimistic assumptions
1007 * and if found now to work, we'll have to redo the sequence and retry.
1008 */
buzbeee3acd072012-02-25 17:03:10 -08001009
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 while (true) {
1011 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
1012 if (res == kSuccess) {
1013 break;
1014 } else {
1015 cUnit->assemblerRetries++;
1016 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
1017 oatCodegenDump(cUnit);
1018 LOG(FATAL) << "Assembler error - too many retries";
1019 }
1020 // Redo offsets and try again
1021 oatAssignOffsets(cUnit);
1022 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -08001023 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 }
buzbeee3acd072012-02-25 17:03:10 -08001025
Bill Buzbeea114add2012-05-03 15:00:40 -07001026 // Install literals
1027 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001028
Bill Buzbeea114add2012-05-03 15:00:40 -07001029 // Install switch tables
1030 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001031
Bill Buzbeea114add2012-05-03 15:00:40 -07001032 // Install fill array data
1033 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001034
Ian Rogers0c7abda2012-09-19 13:33:42 -07001035 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -07001036 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -07001037
1038 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001039}
1040
buzbee31a4a6f2012-02-28 15:36:15 -08001041/*
1042 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
1043 * offset vaddr. This label will be used to fix up the case
1044 * branch table during the assembly phase. Be sure to set
1045 * all resource flags on this to prevent code motion across
1046 * target boundaries. KeyVal is just there for debugging.
1047 */
1048LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
1049{
Bill Buzbeea114add2012-05-03 15:00:40 -07001050 SafeMap<unsigned int, LIR*>::iterator it;
1051 it = cUnit->boundaryMap.find(vaddr);
1052 if (it == cUnit->boundaryMap.end()) {
1053 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
1054 }
1055 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
1056 newLabel->dalvikOffset = vaddr;
1057 newLabel->opcode = kPseudoCaseLabel;
1058 newLabel->operands[0] = keyVal;
1059 oatInsertLIRAfter(it->second, (LIR*)newLabel);
1060 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -08001061}
1062
1063void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
1064{
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 const u2* table = tabRec->table;
1066 int baseVaddr = tabRec->vaddr;
1067 int *targets = (int*)&table[4];
1068 int entries = table[1];
1069 int lowKey = s4FromSwitchData(&table[2]);
1070 for (int i = 0; i < entries; i++) {
1071 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
1072 i + lowKey);
1073 }
buzbee31a4a6f2012-02-28 15:36:15 -08001074}
1075
1076void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
1077{
Bill Buzbeea114add2012-05-03 15:00:40 -07001078 const u2* table = tabRec->table;
1079 int baseVaddr = tabRec->vaddr;
1080 int entries = table[1];
1081 int* keys = (int*)&table[2];
1082 int* targets = &keys[entries];
1083 for (int i = 0; i < entries; i++) {
1084 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
1085 keys[i]);
1086 }
buzbee31a4a6f2012-02-28 15:36:15 -08001087}
1088
1089void oatProcessSwitchTables(CompilationUnit* cUnit)
1090{
Bill Buzbeea114add2012-05-03 15:00:40 -07001091 GrowableListIterator iterator;
1092 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
1093 while (true) {
1094 SwitchTable *tabRec =
1095 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
1096 if (tabRec == NULL) break;
1097 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
1098 markPackedCaseLabels(cUnit, tabRec);
1099 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
1100 markSparseCaseLabels(cUnit, tabRec);
1101 } else {
1102 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -08001103 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 }
buzbee31a4a6f2012-02-28 15:36:15 -08001105}
1106
1107//FIXME: Do we have endian issues here?
1108
1109void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001110 /*
1111 * Sparse switch data format:
1112 * ushort ident = 0x0200 magic value
1113 * ushort size number of entries in the table; > 0
1114 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1115 * int targets[size] branch targets, relative to switch opcode
1116 *
1117 * Total size is (2+size*4) 16-bit code units.
1118 */
buzbee31a4a6f2012-02-28 15:36:15 -08001119{
Bill Buzbeea114add2012-05-03 15:00:40 -07001120 u2 ident = table[0];
1121 int entries = table[1];
1122 int* keys = (int*)&table[2];
1123 int* targets = &keys[entries];
1124 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1125 << ", entries: " << std::dec << entries;
1126 for (int i = 0; i < entries; i++) {
1127 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1128 }
buzbee31a4a6f2012-02-28 15:36:15 -08001129}
1130
1131void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001132 /*
1133 * Packed switch data format:
1134 * ushort ident = 0x0100 magic value
1135 * ushort size number of entries in the table
1136 * int first_key first (and lowest) switch case value
1137 * int targets[size] branch targets, relative to switch opcode
1138 *
1139 * Total size is (4+size*2) 16-bit code units.
1140 */
buzbee31a4a6f2012-02-28 15:36:15 -08001141{
Bill Buzbeea114add2012-05-03 15:00:40 -07001142 u2 ident = table[0];
1143 int* targets = (int*)&table[4];
1144 int entries = table[1];
1145 int lowKey = s4FromSwitchData(&table[2]);
1146 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1147 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1148 for (int i = 0; i < entries; i++) {
1149 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1150 << targets[i];
1151 }
buzbee31a4a6f2012-02-28 15:36:15 -08001152}
buzbeee3acd072012-02-25 17:03:10 -08001153
buzbeed1643e42012-09-05 14:06:51 -07001154/*
1155 * Set up special LIR to mark a Dalvik byte-code instruction start and
1156 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1157 * which we split a single Dalvik instruction, only the first MIR op
1158 * associated with a Dalvik PC should be entered into the map.
1159 */
1160LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1161{
1162 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1163 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1164 cUnit->boundaryMap.Put(offset, res);
1165 }
1166 return res;
1167}
buzbeee3acd072012-02-25 17:03:10 -08001168
buzbeed1643e42012-09-05 14:06:51 -07001169}
1170 // namespace art