codegen_util.cc revision cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8
1e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 2e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Copyright (C) 2011 The Android Open Source Project 3e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * 4e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * you may not use this file except in compliance with the License. 6e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * You may obtain a copy of the License at 7e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * 8e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * http://www.apache.org/licenses/LICENSE-2.0 9e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * 10e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Unless required by applicable law or agreed to in writing, software 11e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * distributed under the License is distributed on an "AS IS" BASIS, 12e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * See the License for the specific language governing permissions and 14e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * limitations under the License. 15e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 16e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h" 180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h" 190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h" 20eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee#include "codegen_util.h" 210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 22e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art { 23e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 24cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */ 25cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbeevoid oatNopLIR( LIR* lir) 26cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee{ 27cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee lir->flags.isNop = true; 28cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee} 29cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee 3031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid setMemRefType(LIR* lir, bool isLoad, int memType) 3131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 32eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint64_t *maskPtr; 33eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint64_t mask = ENCODE_MEM;; 34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE)); 35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (isLoad) { 36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee maskPtr = &lir->useMask; 37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee maskPtr = &lir->defMask; 39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Clear out the memref flags */ 41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee *maskPtr &= ~mask; 42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* ..and then add back the one we need */ 43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee switch (memType) { 44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kLiteral: 45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isLoad); 46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee *maskPtr |= ENCODE_LITERAL; 47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kDalvikReg: 49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee *maskPtr |= ENCODE_DALVIK_REG; 50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 51a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kHeapRef: 52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee *maskPtr |= ENCODE_HEAP_REF; 53a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 54a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kMustNotAlias: 55a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Currently only loads can be marked as kMustNotAlias */ 56a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE)); 57a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee *maskPtr |= ENCODE_MUST_NOT_ALIAS; 58a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 59a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 60a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Oat: invalid memref kind - " << memType; 61a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 6231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 6331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 6431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 65b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack. 6631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 67b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersvoid annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit) 6831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 69a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee setMemRefType(lir, isLoad, kDalvikReg); 7031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 71a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 72a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit 73a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * access. 74a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 75ec13743da80a80c1817cf6660c28917fc28846bcbuzbee lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit); 7631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 7731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 78eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeeuint64_t oatGetRegMaskCommon(CompilationUnit* cUnit, int reg) 79b046e16d8b8da318d6055f9308950131f1255e08buzbee{ 80b046e16d8b8da318d6055f9308950131f1255e08buzbee return getRegMaskCommon(cUnit, reg); 81b046e16d8b8da318d6055f9308950131f1255e08buzbee} 82b046e16d8b8da318d6055f9308950131f1255e08buzbee 8331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 8431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s). 8531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 86eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeeinline void setupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg) 87b046e16d8b8da318d6055f9308950131f1255e08buzbee{ 88b046e16d8b8da318d6055f9308950131f1255e08buzbee *mask |= getRegMaskCommon(cUnit, reg); 89b046e16d8b8da318d6055f9308950131f1255e08buzbee} 90b046e16d8b8da318d6055f9308950131f1255e08buzbee 91b046e16d8b8da318d6055f9308950131f1255e08buzbee/* Exported version of setupRegMask */ 92eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid oatSetupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg) 9331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 94b046e16d8b8da318d6055f9308950131f1255e08buzbee setupRegMask(cUnit, mask, reg); 9531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 9631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 9731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 9831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask 9931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 100b046e16d8b8da318d6055f9308950131f1255e08buzbeevoid setupResourceMasks(CompilationUnit* cUnit, LIR* lir) 10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 102a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int opcode = lir->opcode; 10331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (opcode <= 0) { 105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->useMask = lir->defMask = 0; 106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return; 107a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 10831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 109ec13743da80a80c1817cf6660c28917fc28846bcbuzbee uint64_t flags = EncodingMap[opcode].flags; 11031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 111a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & NEEDS_FIXUP) { 112a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->flags.pcRelFixup = true; 113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 11431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 115a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Get the starting size of the instruction's template */ 116a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->flags.size = oatGetInsnSize(lir); 117e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 118a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Set up the mask for resources that are updated */ 119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (IS_LOAD | IS_STORE)) { 120a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Default to heap - will catch specialized classes later */ 121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee setMemRefType(lir, flags & IS_LOAD, kHeapRef); 122a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 12331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Conservatively assume the branch here will call out a function that in 126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * turn will trash everything. 127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & IS_BRANCH) { 129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->defMask = lir->useMask = ENCODE_ALL; 130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return; 131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 13231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & REG_DEF0) { 134b046e16d8b8da318d6055f9308950131f1255e08buzbee setupRegMask(cUnit, &lir->defMask, lir->operands[0]); 135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 13631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & REG_DEF1) { 138b046e16d8b8da318d6055f9308950131f1255e08buzbee setupRegMask(cUnit, &lir->defMask, lir->operands[1]); 139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 14031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 14131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & SETS_CCODES) { 143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->defMask |= ENCODE_CCODE; 144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 14531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 146a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) { 147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int i; 14831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (i = 0; i < 4; i++) { 150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (1 << (kRegUse0 + i))) { 151b046e16d8b8da318d6055f9308950131f1255e08buzbee setupRegMask(cUnit, &lir->useMask, lir->operands[i]); 152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 15531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & USES_CCODES) { 157a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->useMask |= ENCODE_CCODE; 158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 15931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 160b046e16d8b8da318d6055f9308950131f1255e08buzbee // Handle target-specific actions 161b046e16d8b8da318d6055f9308950131f1255e08buzbee setupTargetResourceMasks(cUnit, lir); 16231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 16331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 16431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 1655de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros 1665de3494e4297c0d480409da3fecee39173f1d4e1buzbee */ 1675de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X) 1685de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_SSA_REP(X) 1695de3494e4297c0d480409da3fecee39173f1d4e1buzbee 1705de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */ 171cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbeevoid oatDumpLIRInsn(CompilationUnit* cUnit, LIR* lir, unsigned char* baseAddr) 1725de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 173a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int offset = lir->offset; 174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest = lir->operands[0]; 175a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops)); 176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 177a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Handle pseudo-ops individually, and all regular insns as a group */ 178a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee switch (lir->opcode) { 179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodEntry: 180a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- method entry " 181a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); 182a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 183a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodExit: 184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- Method_Exit"; 185a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoBarrier: 187a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- BARRIER"; 188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoExtended: 190cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "-------- " << reinterpret_cast<char*>(dest); 191a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoSSARep: 193cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << reinterpret_cast<char*>(dest)); 194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEntryBlock: 196a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; 197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 198a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoDalvikByteCodeBoundary: 199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- dalvik offset: 0x" << std::hex 200cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << lir->dalvikOffset << " @ " << reinterpret_cast<char*>(lir->operands[0]); 201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoExitBlock: 203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; 204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 205a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoPseudoAlign4: 206cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << reinterpret_cast<uintptr_t>(baseAddr) + offset << " (0x" << std::hex 207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << offset << "): .align4"; 208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEHBlockLabel: 210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Exception_Handling:"; 211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoTargetLabel: 213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoNormalBlockLabel: 214cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":"; 215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoThrowTarget: 217cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":"; 218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoIntrinsicRetry: 220cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":"; 221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoSuspendTarget: 223cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":"; 224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 2258320f3867c02bae9bef6cdab267820cb7b412781buzbee case kPseudoSafepointPC: 2268320f3867c02bae9bef6cdab267820cb7b412781buzbee LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":"; 2278320f3867c02bae9bef6cdab267820cb7b412781buzbee break; 228a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee case kPseudoExportedPC: 229a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":"; 230a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee break; 231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoCaseLabel: 232cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x" 233a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << lir->operands[0] << "|" << std::dec << 234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->operands[0]; 235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (lir->flags.isNop && !dumpNop) { 238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, 241a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir, baseAddr)); 242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt 243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee , lir, baseAddr)); 244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("%05x: %-9s%s%s", 245cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee reinterpret_cast<unsigned int>(baseAddr + offset), 246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op_name.c_str(), op_operands.c_str(), 247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->flags.isNop ? "(nop)" : ""); 248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 251a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (lir->useMask && (!lir->flags.isNop || dumpNop)) { 253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use")); 254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 255a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (lir->defMask && (!lir->flags.isNop || dumpNop)) { 256a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def")); 257a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2585de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 2595de3494e4297c0d480409da3fecee39173f1d4e1buzbee 2605de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatDumpPromotionMap(CompilationUnit *cUnit) 2615de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1; 263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < numRegs; i++) { 264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee PromotionMap vRegMap = cUnit->promotionMap[i]; 265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf; 266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (vRegMap.fpLocation == kLocPhysReg) { 267f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask()); 268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2699c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee 270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf3; 271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (i < cUnit->numDalvikRegisters) { 272a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee StringAppendF(&buf3, "%02d", i); 273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else if (i == cUnit->methodSReg) { 274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf3 = "Method*"; 275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters); 2775de3494e4297c0d480409da3fecee39173f1d4e1buzbee } 278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 279a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(), 280a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee vRegMap.coreLocation == kLocPhysReg ? 281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ? 282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee vRegMap.coreReg : oatSRegOffset(cUnit, i), 283a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.c_str()); 284a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2855de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 2865de3494e4297c0d480409da3fecee39173f1d4e1buzbee 287a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */ 288a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbeevoid dumpMappingTable(const char* table_name, const std::string& descriptor, 289a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee const std::string& name, const std::string& signature, 290a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee const std::vector<uint32_t>& v) { 291a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if (v.size() > 0) { 292a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name, 293a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee descriptor.c_str(), name.c_str(), signature.c_str(), v.size())); 294a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::replace(line.begin(), line.end(), ';', '_'); 295a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 296a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee for (uint32_t i = 0; i < v.size(); i+=2) { 297a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]); 298a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 299a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 300a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) <<" };\n\n"; 301a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 302a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee} 303a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee 3045de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */ 3055de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatCodegenDump(CompilationUnit* cUnit) 3065de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Dumping LIR insns for " 308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); 309a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* lirInsn; 310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int insnsSize = cUnit->insnsSize; 311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs; 313a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Ins : " << cUnit->numIns; 314a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Outs : " << cUnit->numOuts; 315a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills; 316a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "FPSpills : " << cUnit->numFPSpills; 317a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps; 318a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Frame size : " << cUnit->frameSize; 319a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "code size is " << cUnit->totalSize << 320a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee " bytes, Dalvik size is " << insnsSize * 2; 321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "expansion factor: " 322cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << static_cast<float>(cUnit->totalSize) / static_cast<float>(insnsSize * 2); 323a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatDumpPromotionMap(cUnit); 324a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { 325a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatDumpLIRInsn(cUnit, lirInsn, 0); 326a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 327a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { 328cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lirInsn->offset, lirInsn->offset, 329cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee lirInsn->operands[0]); 330a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 331a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 332a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee const DexFile::MethodId& method_id = 333a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->dex_file->GetMethodId(cUnit->method_idx); 334a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string signature(cUnit->dex_file->GetMethodSignature(method_id)); 335a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string name(cUnit->dex_file->GetMethodName(method_id)); 336a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id)); 337a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 338a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee // Dump mapping tables 339a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable); 340a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable); 3415de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 3425de3494e4297c0d480409da3fecee39173f1d4e1buzbee 343a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee 344a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0, 345a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int op1, int op2, int op3, int op4, LIR* target) 346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 347cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* insn = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR)); 348a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->dalvikOffset = dalvikOffset; 349a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->opcode = opcode; 350a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[0] = op0; 351a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[1] = op1; 352a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[2] = op2; 353a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[3] = op3; 354a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[4] = op4; 355a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->target = target; 356b046e16d8b8da318d6055f9308950131f1255e08buzbee oatSetupResourceMasks(cUnit, insn); 357a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || 358a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee (opcode == kPseudoExportedPC)) { 359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Always make labels scheduling barriers 3608320f3867c02bae9bef6cdab267820cb7b412781buzbee insn->useMask = insn->defMask = ENCODE_ALL; 361a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 362a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 363a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee} 364a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee 365a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/* 366a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4 367a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands. 368a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */ 369a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* newLIR0(CompilationUnit* cUnit, int opcode) 370a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{ 371a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)) 372cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 373a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 374a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 375a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode); 376cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 377a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 37831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 37931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 3805de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR1(CompilationUnit* cUnit, int opcode, 381a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest) 38231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 383a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP)) 384cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 385a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 386a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 387a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest); 388cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 39031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 39131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 3925de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR2(CompilationUnit* cUnit, int opcode, 393a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1) 39431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP)) 396cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 397a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 398a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1); 400cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 401a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 40231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 40331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 4045de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR3(CompilationUnit* cUnit, int opcode, 405a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2) 40631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 407a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP)) 408cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 409a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 410a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 411cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2); 412cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 413a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 41431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 41531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 4165de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR4(CompilationUnit* cUnit, int opcode, 417a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2, int info) 41831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 419a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP)) 420cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 421a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 422a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 423cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info); 424cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 425a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 42631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 42731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 428b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian RogersLIR* newLIR5(CompilationUnit* cUnit, int opcode, 429a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2, int info1, int info2) 430b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{ 431a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP)) 432cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee << EncodingMap[opcode].name << " " << opcode << " " 433a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " 434a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << cUnit->currentDalvikOffset; 435cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info1, info2); 436cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, insn); 437a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 438b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers} 439b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 44031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 44131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match 44231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0). 44331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 44431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta) 44531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 446a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (dataTarget) { 447cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee if ((static_cast<unsigned>(value - dataTarget->operands[0])) <= delta) 448cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return dataTarget; 449a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee dataTarget = dataTarget->next; 450a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 451a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 45231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 45331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 45431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */ 45531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi) 45631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 457a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee bool loMatch = false; 458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* loTarget = NULL; 459a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (dataTarget) { 460cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee if (loMatch && (dataTarget->operands[0] == valHi)) { 461cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return loTarget; 46231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 463a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee loMatch = false; 464cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee if (dataTarget->operands[0] == valLo) { 465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee loMatch = true; 466a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee loTarget = dataTarget; 467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 468a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee dataTarget = dataTarget->next; 469a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 470a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 47131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 47231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 47331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 47431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or 47531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams. 47631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 47731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 4785de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Add a 32-bit constant either in the constant pool */ 4793fa13791c51985d9956d01bc465de6d36c3390d3Ian RogersLIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value) 48031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 481a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Add the constant to the literal pool */ 482a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (constantListP) { 483cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* newValue = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocData)); 484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee newValue->operands[0] = value; 485a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee newValue->next = *constantListP; 486cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee *constantListP = newValue; 487a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return newValue; 488a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 489a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 49031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 49131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 49231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */ 49331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP, 494a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int valLo, int valHi) 49531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 496a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee addWordData(cUnit, constantListP, valHi); 497a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return addWordData(cUnit, constantListP, valLo); 49831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 49931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 500ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid pushWord(std::vector<uint8_t>&buf, int data) { 501a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( data & 0xff); 502a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 8) & 0xff); 503a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 16) & 0xff); 504a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 24) & 0xff); 505e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 506e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 507ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid alignBuffer(std::vector<uint8_t>&buf, size_t offset) { 508a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (buf.size() < offset) { 509a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back(0); 510a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 511e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 512e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 513f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrombool IsDirect(int invokeType) { 514f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom InvokeType type = static_cast<InvokeType>(invokeType); 515f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom return type == kStatic || type == kDirect; 516f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 517f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 518e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */ 51931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installLiteralPools(CompilationUnit* cUnit) 520e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 521a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee alignBuffer(cUnit->codeBuffer, cUnit->dataOffset); 522a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LIR* dataLIR = cUnit->literalList; 523a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (dataLIR != NULL) { 524a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee pushWord(cUnit->codeBuffer, dataLIR->operands[0]); 525a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee dataLIR = NEXT_LIR(dataLIR); 526a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 527a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Push code and method literals, record offsets for the compiler to patch. 528a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee dataLIR = cUnit->codeLiteralList; 529137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers while (dataLIR != NULL) { 530137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t target = dataLIR->operands[0]; 531137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers cUnit->compiler->AddCodePatch(cUnit->dex_file, 532137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers cUnit->method_idx, 533137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers cUnit->invoke_type, 534137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers target, 535137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers static_cast<InvokeType>(dataLIR->operands[1]), 536137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers cUnit->codeBuffer.size()); 537137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target); 538137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 539137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 540137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers pushWord(cUnit->codeBuffer, unique_patch_value); 541137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers dataLIR = NEXT_LIR(dataLIR); 542137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers } 543137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers dataLIR = cUnit->methodLiteralList; 544137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers while (dataLIR != NULL) { 545137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t target = dataLIR->operands[0]; 546137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers cUnit->compiler->AddMethodPatch(cUnit->dex_file, 547a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->method_idx, 54808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers cUnit->invoke_type, 549a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee target, 55008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers static_cast<InvokeType>(dataLIR->operands[1]), 551a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->codeBuffer.size()); 552137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target); 553137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 554137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 555137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers pushWord(cUnit->codeBuffer, unique_patch_value); 556137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers dataLIR = NEXT_LIR(dataLIR); 557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 558e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 559e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 560e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */ 56131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installSwitchTables(CompilationUnit* cUnit) 562e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 563a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 564a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatGrowableListIteratorInit(&cUnit->switchTables, &iterator); 565a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 566cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee SwitchTable* tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext( &iterator)); 567a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec == NULL) break; 568a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee alignBuffer(cUnit->codeBuffer, tabRec->offset); 569a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 570a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * For Arm, our reference point is the address of the bx 571a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * instruction that does the launch, so we have to subtract 572a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * the auto pc-advance. For other targets the reference point 573a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * is a label, so we can use the offset as-is. 574a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 575b046e16d8b8da318d6055f9308950131f1255e08buzbee int bxOffset = INVALID_OFFSET; 576b046e16d8b8da318d6055f9308950131f1255e08buzbee switch (cUnit->instructionSet) { 577b046e16d8b8da318d6055f9308950131f1255e08buzbee case kThumb2: 578b046e16d8b8da318d6055f9308950131f1255e08buzbee bxOffset = tabRec->anchor->offset + 4; 579b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 580b046e16d8b8da318d6055f9308950131f1255e08buzbee case kX86: 581b046e16d8b8da318d6055f9308950131f1255e08buzbee bxOffset = 0; 582b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 583b046e16d8b8da318d6055f9308950131f1255e08buzbee case kMips: 584b046e16d8b8da318d6055f9308950131f1255e08buzbee bxOffset = tabRec->anchor->offset; 585b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 586b046e16d8b8da318d6055f9308950131f1255e08buzbee default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet; 587b046e16d8b8da318d6055f9308950131f1255e08buzbee } 588a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (cUnit->printMe) { 589a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset; 590a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 591a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec->table[0] == Instruction::kSparseSwitchSignature) { 592cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&(tabRec->table[2])); 593a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int elems = 0; elems < tabRec->table[1]; elems++) { 594a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int disp = tabRec->targets[elems]->offset - bxOffset; 595e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee if (cUnit->printMe) { 596a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] key: 0x" 597a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << keys[elems] << ", disp: 0x" 598a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 599e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 600a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee pushWord(cUnit->codeBuffer, keys[elems]); 601a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee pushWord(cUnit->codeBuffer, 602a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee tabRec->targets[elems]->offset - bxOffset); 603a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 604a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 605a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK_EQ(static_cast<int>(tabRec->table[0]), 606a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 607a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int elems = 0; elems < tabRec->table[1]; elems++) { 608a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int disp = tabRec->targets[elems]->offset - bxOffset; 609a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (cUnit->printMe) { 610a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] disp: 0x" 611a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 612e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 613a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset); 614a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 615e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 616a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 617e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 618e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 619e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */ 62031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installFillArrayData(CompilationUnit* cUnit) 621e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 622a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 623a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator); 624a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 625cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee FillArrayData *tabRec = 626cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext( &iterator)); 627a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec == NULL) break; 628a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee alignBuffer(cUnit->codeBuffer, tabRec->offset); 629a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < (tabRec->size + 1) / 2; i++) { 630a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF); 631a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF); 632e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 633a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 634e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 635e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 63631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffsetCommon(LIR* lir, int offset) 637e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (;lir != NULL; lir = lir->next) { 639a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->offset = offset; 640a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += 4; 641a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 642a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 643e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 644e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 6456459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry 6466459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbeebool verifyCatchEntries(CompilationUnit* cUnit) 6476459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee{ 6486459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool success = true; 6496459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) { 6506459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee uint32_t dexPc = *it; 6516459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool found = false; 6526459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) { 6536459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (dexPc == cUnit->dex2pcMappingTable[i+1]) { 6546459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee found = true; 6556459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee break; 6566459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6576459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6586459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!found) { 6596459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc; 6606459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 6616459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6626459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6636459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee // Now, try in the other direction 6646459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) { 6656459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee uint32_t dexPc = cUnit->dex2pcMappingTable[i+1]; 6666459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (cUnit->catches.find(dexPc) == cUnit->catches.end()) { 6676459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc; 6686459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 6696459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6706459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6716459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!success) { 6726459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); 6736459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: " 6746459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee << cUnit->dex2pcMappingTable.size()/2; 6756459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6766459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee return success; 6776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee} 6786459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee 679a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbeevoid createMappingTables(CompilationUnit* cUnit) 680e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 681cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee for (LIR* tgtLIR = cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) { 6828320f3867c02bae9bef6cdab267820cb7b412781buzbee if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) { 683a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->pc2dexMappingTable.push_back(tgtLIR->offset); 684a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset); 685a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 686a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) { 687a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->dex2pcMappingTable.push_back(tgtLIR->offset); 688a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset); 689e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 690a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 6916459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee DCHECK(verifyCatchEntries(cUnit)); 692a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() + 693a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->dex2pcMappingTable.size()); 694a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size()); 695a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(), 696a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->pc2dexMappingTable.begin(), 697a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->pc2dexMappingTable.end()); 698a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(), 699a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->dex2pcMappingTable.begin(), 700a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee cUnit->dex2pcMappingTable.end()); 701e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 702e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder { 7040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public: 7050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers NativePcToReferenceMapBuilder(std::vector<uint8_t>* table, 7060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t entries, uint32_t max_native_offset, 7070c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t references_width) : entries_(entries), 7080c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers references_width_(references_width), in_use_(entries), 7090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_(table) { 7100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute width in bytes needed to hold max_native_offset. 7110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_ = 0; 7120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (max_native_offset != 0) { 7130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_++; 7140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset >>= 8; 7150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7160c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Resize table and set up header. 7170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table->resize((EntryWidth() * entries) + sizeof(uint32_t)); 718000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(native_offset_width_, 1U << 3); 719000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] = native_offset_width_ & 7; 720000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(references_width_, 1U << 13); 721000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] |= (references_width_ << 3) & 0xFF; 722000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[1] = (references_width_ >> 5) & 0xFF; 7230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers CHECK_LT(entries, 1U << 16); 7240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[2] = entries & 0xFF; 7250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[3] = (entries >> 8) & 0xFF; 7260c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void AddEntry(uint32_t native_offset, const uint8_t* references) { 7290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_index = TableIndex(native_offset); 7300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (in_use_[table_index]) { 7310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_index = (table_index + 1) % entries_; 7320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers in_use_[table_index] = true; 7340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetNativeOffset(table_index, native_offset); 7350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers DCHECK_EQ(native_offset, GetNativeOffset(table_index)); 7360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetReferences(table_index, references); 7370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private: 7400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t TableIndex(uint32_t native_offset) { 7410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_; 7420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7440c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t GetNativeOffset(size_t table_index) { 7450c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = 0; 7460c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7470c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 7480c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset |= (*table_)[table_offset + i] << (i * 8); 7490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset; 7510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetNativeOffset(size_t table_index, uint32_t native_offset) { 7540c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7550c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 7560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF; 7570c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetReferences(size_t table_index, const uint8_t* references) { 7610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_); 7630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t EntryWidth() const { 7660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset_width_ + references_width_; 7670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of entries in the table. 7700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t entries_; 7710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode the reference bitmap. 7720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t references_width_; 7730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode a native offset. 7740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t native_offset_width_; 7750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Entries that are in use. 7760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<bool> in_use_; 7770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // The table we're building. 7780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<uint8_t>* const table_; 7790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}; 7800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersstatic void createNativeGcMap(CompilationUnit* cUnit) { 782a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable; 7830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t max_native_offset = 0; 7840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 7850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 7860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers if (native_offset > max_native_offset) { 7870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset = native_offset; 7880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx); 7910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref); 7920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4); 7930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute native offset to references size. 7940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap, 7950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers mapping_table.size() / 2, max_native_offset, 7960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers dex_gc_map.RegWidth()); 7970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 7990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 8000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t dex_pc = mapping_table[i + 1]; 8010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false); 802a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc; 803a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee native_gc_map_builder.AddEntry(native_offset, references); 8040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers} 8060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 807e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */ 80831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffset(CompilationUnit* cUnit, int offset) 809e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 810a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignLiteralOffsetCommon(cUnit->literalList, offset); 811a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset); 812a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset); 813a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 814e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 815e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 81631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignSwitchTablesOffset(CompilationUnit* cUnit, int offset) 817e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 818a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 819a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatGrowableListIteratorInit(&cUnit->switchTables, &iterator); 820a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 821cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee SwitchTable *tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator)); 822a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec == NULL) break; 823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee tabRec->offset = offset; 824a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec->table[0] == Instruction::kSparseSwitchSignature) { 825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += tabRec->table[1] * (sizeof(int) * 2); 826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 827a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee DCHECK_EQ(static_cast<int>(tabRec->table[0]), 828a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 829a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += tabRec->table[1] * sizeof(int); 830e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 832a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 833e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 834e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 83531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignFillArrayDataOffset(CompilationUnit* cUnit, int offset) 836e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 838a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator); 839a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 840cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee FillArrayData *tabRec = 841cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext(&iterator)); 842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec == NULL) break; 843a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee tabRec->offset = offset; 844a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += tabRec->size; 845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // word align 846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 849e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 850e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 851e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 852e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions 853e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit. 854e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 855e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssignOffsets(CompilationUnit* cUnit) 856e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int offset = oatAssignInsnOffsets(cUnit); 858e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 859a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Const values have to be word aligned */ 860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 861e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 862a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Set up offsets for literals */ 863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->dataOffset = offset; 864e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 865a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignLiteralOffset(cUnit, offset); 866e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 867a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignSwitchTablesOffset(cUnit, offset); 868e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = assignFillArrayDataOffset(cUnit, offset); 870e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 871a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->totalSize = offset; 872e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 873e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 874e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 875e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top 876e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is 877e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it. 878e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 879e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssembleLIR(CompilationUnit* cUnit) 880e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 881a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatAssignOffsets(cUnit); 882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 883a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Assemble here. Note that we generate code with optimistic assumptions 884a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * and if found now to work, we'll have to redo the sequence and retry. 885a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 886e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 887a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 888a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee AssemblerStatus res = oatAssembleInstructions(cUnit, 0); 889a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (res == kSuccess) { 890a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 891a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 892a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->assemblerRetries++; 893a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) { 894a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatCodegenDump(cUnit); 895a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Assembler error - too many retries"; 896a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 897a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Redo offsets and try again 898a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatAssignOffsets(cUnit); 899a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee cUnit->codeBuffer.clear(); 900e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 901a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 902e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 903a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install literals 904a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee installLiteralPools(cUnit); 905e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 906a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install switch tables 907a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee installSwitchTables(cUnit); 908e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 909a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install fill array data 910a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee installFillArrayData(cUnit); 911e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 9120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Create the mapping table and native offset to reference map. 913a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee createMappingTables(cUnit); 9140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 9150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers createNativeGcMap(cUnit); 916e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 917e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 91831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 91931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik 92031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr. This label will be used to fix up the case 92131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase. Be sure to set 92231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across 92331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries. KeyVal is just there for debugging. 92431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 92531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal) 92631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 927a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee SafeMap<unsigned int, LIR*>::iterator it; 928a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee it = cUnit->boundaryMap.find(vaddr); 929a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (it == cUnit->boundaryMap.end()) { 930a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; 931a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 932cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* newLabel = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR)); 933a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee newLabel->dalvikOffset = vaddr; 934a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee newLabel->opcode = kPseudoCaseLabel; 935a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee newLabel->operands[0] = keyVal; 936cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatInsertLIRAfter(it->second, newLabel); 937a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return newLabel; 93831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 93931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 94031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec) 94131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 942eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee const uint16_t* table = tabRec->table; 943a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int baseVaddr = tabRec->vaddr; 944cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int *targets = reinterpret_cast<const int*>(&table[4]); 945a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 946a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int lowKey = s4FromSwitchData(&table[2]); 947a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 948cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], i + lowKey); 949a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 95031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 95131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 95231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec) 95331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 954eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee const uint16_t* table = tabRec->table; 955a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int baseVaddr = tabRec->vaddr; 956a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 957cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 958cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 959a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 960cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], keys[i]); 961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 96231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 96331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 96431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid oatProcessSwitchTables(CompilationUnit* cUnit) 96531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 966a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 967a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee oatGrowableListIteratorInit(&cUnit->switchTables, &iterator); 968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 969a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee SwitchTable *tabRec = 970cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator)); 971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec == NULL) break; 972a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (tabRec->table[0] == Instruction::kPackedSwitchSignature) { 973a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee markPackedCaseLabels(cUnit, tabRec); 974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) { 975a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee markSparseCaseLabels(cUnit, tabRec); 976a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 977a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Invalid switch table"; 97831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 979a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 98031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 98131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 982eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid dumpSparseSwitchTable(const uint16_t* table) 983a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 984a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Sparse switch data format: 985a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0200 magic value 986a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table; > 0 987a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int keys[size] keys, sorted low-to-high; 32-bit aligned 988a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 989a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 990a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (2+size*4) 16-bit code units. 991a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 992a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 993eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 994a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 995cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 996cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 997a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident 998a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << ", entries: " << std::dec << entries; 999a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1000a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i]; 1001a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 100231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 100331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 1004eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid dumpPackedSwitchTable(const uint16_t* table) 1005a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 1006a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Packed switch data format: 1007a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0100 magic value 1008a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table 1009a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int first_key first (and lowest) switch case value 1010a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 1011a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 1012a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (4+size*2) 16-bit code units. 1013a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 1014a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 1015eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 1016cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = reinterpret_cast<const int*>(&table[4]); 1017a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 1018a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int lowKey = s4FromSwitchData(&table[2]); 1019a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident 1020a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << ", entries: " << std::dec << entries << ", lowKey: " << lowKey; 1021a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1022a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex 1023a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << targets[i]; 1024a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 102531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 1026e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 1027d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/* 1028d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and 1029d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in 1030d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op 1031d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map. 1032d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */ 1033d1643e41ef242ae656f667bf3c8b0324635cefd3buzbeeLIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr) 1034d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee{ 1035cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(instStr)); 1036d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) { 1037d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee cUnit->boundaryMap.Put(offset, res); 1038d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee } 1039d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee return res; 1040d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee} 1041e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 1042d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee} 1043d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee // namespace art 1044