codegen_util.cc revision 7934ac288acfb2552bb0b06ec1f61e5820d924a4
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 177940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h" 184f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h" 208d3a117b374352a1853fae9b7306afeaaa9e3b91Ian Rogers#include "mir_to_lir-inl.h" 210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h" 220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h" 230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 24e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art { 25e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 262ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src) { 274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee bool res = false; 284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.is_const) { 294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.wide) { 304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.fp) { 311fd3346740dfb7f47be9922312b68a4227fada96buzbee res = InexpensiveConstantDouble(mir_graph_->ConstantValueWide(rl_src)); 324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 331fd3346740dfb7f47be9922312b68a4227fada96buzbee res = InexpensiveConstantLong(mir_graph_->ConstantValueWide(rl_src)); 344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.fp) { 371fd3346740dfb7f47be9922312b68a4227fada96buzbee res = InexpensiveConstantFloat(mir_graph_->ConstantValue(rl_src)); 384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 391fd3346740dfb7f47be9922312b68a4227fada96buzbee res = InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src)); 404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return res; 444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 462ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkSafepointPC(LIR* inst) { 4702031b185b4653e6c72e21f7a51238b903f6d638buzbee inst->def_mask = ENCODE_ALL; 481fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* safepoint_pc = NewLIR0(kPseudoSafepointPC); 4902031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL); 5002031b185b4653e6c72e21f7a51238b903f6d638buzbee} 5102031b185b4653e6c72e21f7a51238b903f6d638buzbee 522ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put) { 531fd3346740dfb7f47be9922312b68a4227fada96buzbee return cu_->compiler_driver->ComputeInstanceFieldInfo( 541fd3346740dfb7f47be9922312b68a4227fada96buzbee field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put); 5502031b185b4653e6c72e21f7a51238b903f6d638buzbee} 5602031b185b4653e6c72e21f7a51238b903f6d638buzbee 57cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */ 58df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstromvoid Mir2Lir::NopLIR(LIR* lir) { 59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->flags.is_nop = true; 60cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee} 61cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee 622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::SetMemRefType(LIR* lir, bool is_load, int mem_type) { 63fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint64_t *mask_ptr; 64f69863b3039fc621ff4250e262d2a024d5e79ec8Brian Carlstrom uint64_t mask = ENCODE_MEM; 651fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE)); 66fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_load) { 67fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee mask_ptr = &lir->use_mask; 68a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee mask_ptr = &lir->def_mask; 70a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 71a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Clear out the memref flags */ 72fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr &= ~mask; 73a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* ..and then add back the one we need */ 74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee switch (mem_type) { 75a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kLiteral: 76fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(is_load); 77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_LITERAL; 78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kDalvikReg: 80fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_DALVIK_REG; 81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kHeapRef: 83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_HEAP_REF; 84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kMustNotAlias: 86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Currently only loads can be marked as kMustNotAlias */ 871fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE)); 88fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_MUST_NOT_ALIAS; 89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(FATAL) << "Oat: invalid memref kind - " << mem_type; 92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 9331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 9431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 9531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack. 9731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 981fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, 992ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom bool is64bit) { 1001fd3346740dfb7f47be9922312b68a4227fada96buzbee SetMemRefType(lir, is_load, kDalvikReg); 10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 102a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 103fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit 104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * access. 105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 106fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit); 10731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 10831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 10931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 1105de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros 1115de3494e4297c0d480409da3fecee39173f1d4e1buzbee */ 1125de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X) 1135de3494e4297c0d480409da3fecee39173f1d4e1buzbee 1145de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */ 1152ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr) { 116a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int offset = lir->offset; 117a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest = lir->operands[0]; 1181fd3346740dfb7f47be9922312b68a4227fada96buzbee const bool dump_nop = (cu_->enable_debug & (1 << kDebugShowNops)); 119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 120a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Handle pseudo-ops individually, and all regular insns as a group */ 121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee switch (lir->opcode) { 122a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodEntry: 123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- method entry " 1241fd3346740dfb7f47be9922312b68a4227fada96buzbee << PrettyMethod(cu_->method_idx, *cu_->dex_file); 125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodExit: 127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- Method_Exit"; 128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoBarrier: 130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- BARRIER"; 131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEntryBlock: 133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; 134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoDalvikByteCodeBoundary: 1364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (lir->operands[0] == 0) { 1374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string"); 1384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- dalvik offset: 0x" << std::hex 140fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]); 141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoExitBlock: 143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; 144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoPseudoAlign4: 146fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex 147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << offset << "): .align4"; 148a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEHBlockLabel: 150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Exception_Handling:"; 151a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoTargetLabel: 153a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoNormalBlockLabel: 154cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":"; 155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoThrowTarget: 157cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":"; 158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 159a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoIntrinsicRetry: 160cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":"; 161a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoSuspendTarget: 163cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":"; 164a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 1658320f3867c02bae9bef6cdab267820cb7b412781buzbee case kPseudoSafepointPC: 166fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":"; 1678320f3867c02bae9bef6cdab267820cb7b412781buzbee break; 168a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee case kPseudoExportedPC: 169fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":"; 170a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee break; 171a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoCaseLabel: 172cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x" 173a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << lir->operands[0] << "|" << std::dec << 174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->operands[0]; 175a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 177fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->flags.is_nop && !dump_nop) { 178a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 1801fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode), 18102031b185b4653e6c72e21f7a51238b903f6d638buzbee lir, base_addr)); 1821fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode), 18302031b185b4653e6c72e21f7a51238b903f6d638buzbee lir, base_addr)); 184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("%05x: %-9s%s%s", 185fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee reinterpret_cast<unsigned int>(base_addr + offset), 186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op_name.c_str(), op_operands.c_str(), 187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->flags.is_nop ? "(nop)" : ""); 188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 190a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 191a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 192fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) { 1932d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom DUMP_RESOURCE_MASK(DumpResourceMask(lir, lir->use_mask, "use")); 194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 195fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) { 1962d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom DUMP_RESOURCE_MASK(DumpResourceMask(lir, lir->def_mask, "def")); 197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 1985de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 1995de3494e4297c0d480409da3fecee39173f1d4e1buzbee 2002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpPromotionMap() { 2011fd3346740dfb7f47be9922312b68a4227fada96buzbee int num_regs = cu_->num_dalvik_registers + cu_->num_compiler_temps + 1; 202fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int i = 0; i < num_regs; i++) { 2031fd3346740dfb7f47be9922312b68a4227fada96buzbee PromotionMap v_reg_map = promotion_map_[i]; 204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf; 205fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (v_reg_map.fp_location == kLocPhysReg) { 2061fd3346740dfb7f47be9922312b68a4227fada96buzbee StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask()); 207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2089c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee 209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf3; 2101fd3346740dfb7f47be9922312b68a4227fada96buzbee if (i < cu_->num_dalvik_registers) { 211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee StringAppendF(&buf3, "%02d", i); 2121fd3346740dfb7f47be9922312b68a4227fada96buzbee } else if (i == mir_graph_->GetMethodSReg()) { 213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf3 = "Method*"; 214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 2151fd3346740dfb7f47be9922312b68a4227fada96buzbee StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers); 2165de3494e4297c0d480409da3fecee39173f1d4e1buzbee } 217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(), 219fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee v_reg_map.core_location == kLocPhysReg ? 220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee "r" : "SP+", v_reg_map.core_location == kLocPhysReg ? 2211fd3346740dfb7f47be9922312b68a4227fada96buzbee v_reg_map.core_reg : SRegOffset(i), 222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.c_str()); 223a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2245de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 2255de3494e4297c0d480409da3fecee39173f1d4e1buzbee 226a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */ 2271fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor, 2281fd3346740dfb7f47be9922312b68a4227fada96buzbee const std::string& name, const std::string& signature, 2291fd3346740dfb7f47be9922312b68a4227fada96buzbee const std::vector<uint32_t>& v) { 230a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if (v.size() > 0) { 231a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name, 232a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee descriptor.c_str(), name.c_str(), signature.c_str(), v.size())); 233a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::replace(line.begin(), line.end(), ';', '_'); 234a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 235a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee for (uint32_t i = 0; i < v.size(); i+=2) { 236a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]); 237a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 238a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 239a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) <<" };\n\n"; 240a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 241a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee} 242a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee 2435de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */ 2442ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::CodegenDump() { 245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Dumping LIR insns for " 2461fd3346740dfb7f47be9922312b68a4227fada96buzbee << PrettyMethod(cu_->method_idx, *cu_->dex_file); 247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* lir_insn; 2481fd3346740dfb7f47be9922312b68a4227fada96buzbee int insns_size = cu_->code_item->insns_size_in_code_units_; 2491fd3346740dfb7f47be9922312b68a4227fada96buzbee 2501fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs; 2511fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Ins : " << cu_->num_ins; 2521fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Outs : " << cu_->num_outs; 2531fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "CoreSpills : " << num_core_spills_; 2541fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "FPSpills : " << num_fp_spills_; 2551fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "CompilerTemps : " << cu_->num_compiler_temps; 2561fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Frame size : " << frame_size_; 2571fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "code size is " << total_size_ << 258fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee " bytes, Dalvik size is " << insns_size * 2; 259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "expansion factor: " 2601fd3346740dfb7f47be9922312b68a4227fada96buzbee << static_cast<float>(total_size_) / static_cast<float>(insns_size * 2); 2611fd3346740dfb7f47be9922312b68a4227fada96buzbee DumpPromotionMap(); 2621fd3346740dfb7f47be9922312b68a4227fada96buzbee for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) { 2631fd3346740dfb7f47be9922312b68a4227fada96buzbee DumpLIRInsn(lir_insn, 0); 264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2651fd3346740dfb7f47be9922312b68a4227fada96buzbee for (lir_insn = literal_list_; lir_insn != NULL; lir_insn = lir_insn->next) { 266fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset, 267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir_insn->operands[0]); 268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee const DexFile::MethodId& method_id = 2711fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->dex_file->GetMethodId(cu_->method_idx); 2721fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string signature(cu_->dex_file->GetMethodSignature(method_id)); 2731fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string name(cu_->dex_file->GetMethodName(method_id)); 2741fd3346740dfb7f47be9922312b68a4227fada96buzbee std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id)); 275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 276a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee // Dump mapping tables 2771fd3346740dfb7f47be9922312b68a4227fada96buzbee DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_); 2781fd3346740dfb7f47be9922312b68a4227fada96buzbee DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_); 2795de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 2805de3494e4297c0d480409da3fecee39173f1d4e1buzbee 28131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 28231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match 28331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0). 28431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 2852ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::ScanLiteralPool(LIR* data_target, int value, unsigned int delta) { 286fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_target) { 287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta) 288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return data_target; 289fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_target = data_target->next; 290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 291a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 29231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 29331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 29431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */ 2952ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) { 296fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool lo_match = false; 297fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* lo_target = NULL; 298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_target) { 299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lo_match && (data_target->operands[0] == val_hi)) { 3004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee // Record high word in case we need to expand this later. 3014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee lo_target->operands[1] = val_hi; 302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return lo_target; 30331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_match = false; 305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (data_target->operands[0] == val_lo) { 306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_match = true; 307fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_target = data_target; 308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_target = data_target->next; 310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 31231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 31331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 31431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 31531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or 31631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams. 31731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 31831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 3194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/* Add a 32-bit constant to the constant pool */ 3202ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::AddWordData(LIR* *constant_list_p, int value) { 321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Add the constant to the literal pool */ 322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (constant_list_p) { 323862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee LIR* new_value = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocData)); 324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_value->operands[0] = value; 325fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_value->next = *constant_list_p; 326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *constant_list_p = new_value; 327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return new_value; 328a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 329a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 33031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 33131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 33231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */ 3332ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi) { 3341fd3346740dfb7f47be9922312b68a4227fada96buzbee AddWordData(constant_list_p, val_hi); 3351fd3346740dfb7f47be9922312b68a4227fada96buzbee return AddWordData(constant_list_p, val_lo); 33631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 33731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 338aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void PushWord(std::vector<uint8_t>&buf, int data) { 339df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom buf.push_back(data & 0xff); 340df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom buf.push_back((data >> 8) & 0xff); 341df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom buf.push_back((data >> 16) & 0xff); 342df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom buf.push_back((data >> 24) & 0xff); 343e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 344e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 345aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) { 346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (buf.size() < offset) { 347a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back(0); 348a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 349e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 350e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 351e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */ 3522ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallLiteralPools() { 3531fd3346740dfb7f47be9922312b68a4227fada96buzbee AlignBuffer(code_buffer_, data_offset_); 3541fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* data_lir = literal_list_; 355fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 3561fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, data_lir->operands[0]); 357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 358a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Push code and method literals, record offsets for the compiler to patch. 3601fd3346740dfb7f47be9922312b68a4227fada96buzbee data_lir = code_literal_list_; 361fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t target = data_lir->operands[0]; 3631fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->compiler_driver->AddCodePatch(cu_->dex_file, 3641fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->method_idx, 3651fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->invoke_type, 3661212a022fa5f8ef9585d765b1809521812af882cIan Rogers target, 3671212a022fa5f8ef9585d765b1809521812af882cIan Rogers static_cast<InvokeType>(data_lir->operands[1]), 3681fd3346740dfb7f47be9922312b68a4227fada96buzbee code_buffer_.size()); 3691fd3346740dfb7f47be9922312b68a4227fada96buzbee const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target); 370137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 371137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 3721fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, unique_patch_value); 373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 374137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers } 3751fd3346740dfb7f47be9922312b68a4227fada96buzbee data_lir = method_literal_list_; 376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 377fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t target = data_lir->operands[0]; 3781fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->compiler_driver->AddMethodPatch(cu_->dex_file, 3791fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->method_idx, 3801fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->invoke_type, 3811212a022fa5f8ef9585d765b1809521812af882cIan Rogers target, 3821212a022fa5f8ef9585d765b1809521812af882cIan Rogers static_cast<InvokeType>(data_lir->operands[1]), 3831fd3346740dfb7f47be9922312b68a4227fada96buzbee code_buffer_.size()); 3841fd3346740dfb7f47be9922312b68a4227fada96buzbee const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target); 385137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 386137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 3871fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, unique_patch_value); 388fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 390e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 391e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 392e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */ 3932ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallSwitchTables() { 394862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_); 395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 396862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee Mir2Lir::SwitchTable* tab_rec = iterator.Next(); 397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 3981fd3346740dfb7f47be9922312b68a4227fada96buzbee AlignBuffer(code_buffer_, tab_rec->offset); 399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 400a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * For Arm, our reference point is the address of the bx 401a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * instruction that does the launch, so we have to subtract 402a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * the auto pc-advance. For other targets the reference point 403a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * is a label, so we can use the offset as-is. 404a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int bx_offset = INVALID_OFFSET; 4061fd3346740dfb7f47be9922312b68a4227fada96buzbee switch (cu_->instruction_set) { 407b046e16d8b8da318d6055f9308950131f1255e08buzbee case kThumb2: 408fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = tab_rec->anchor->offset + 4; 409b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 410b046e16d8b8da318d6055f9308950131f1255e08buzbee case kX86: 411fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = 0; 412b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 413b046e16d8b8da318d6055f9308950131f1255e08buzbee case kMips: 414fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = tab_rec->anchor->offset; 415b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 4161fd3346740dfb7f47be9922312b68a4227fada96buzbee default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set; 417b046e16d8b8da318d6055f9308950131f1255e08buzbee } 4181fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 419fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset; 420a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 421fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2])); 423fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int elems = 0; elems < tab_rec->table[1]; elems++) { 424fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int disp = tab_rec->targets[elems]->offset - bx_offset; 4251fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 426a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] key: 0x" 427a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << keys[elems] << ", disp: 0x" 428a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 429e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 4301fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, keys[elems]); 4311fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, 432fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->targets[elems]->offset - bx_offset); 433a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 434a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK_EQ(static_cast<int>(tab_rec->table[0]), 436a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 437fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int elems = 0; elems < tab_rec->table[1]; elems++) { 438fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int disp = tab_rec->targets[elems]->offset - bx_offset; 4391fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 440a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] disp: 0x" 441a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 442e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 4431fd3346740dfb7f47be9922312b68a4227fada96buzbee PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset); 444a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 445e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 446a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 447e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 448e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 449e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */ 4502ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallFillArrayData() { 451862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_); 452a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 453862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee Mir2Lir::FillArrayData *tab_rec = iterator.Next(); 454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 4551fd3346740dfb7f47be9922312b68a4227fada96buzbee AlignBuffer(code_buffer_, tab_rec->offset); 456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int i = 0; i < (tab_rec->size + 1) / 2; i++) { 457df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom code_buffer_.push_back(tab_rec->table[i] & 0xFF); 458df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom code_buffer_.push_back((tab_rec->table[i] >> 8) & 0xFF); 459e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 460a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 461e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 462e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 4632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstatic int AssignLiteralOffsetCommon(LIR* lir, int offset) { 46402c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom for (; lir != NULL; lir = lir->next) { 465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->offset = offset; 466a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += 4; 467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 468a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 469e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 470e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 4716459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry 4722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::VerifyCatchEntries() { 4736459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool success = true; 4741fd3346740dfb7f47be9922312b68a4227fada96buzbee for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin(); 4751fd3346740dfb7f47be9922312b68a4227fada96buzbee it != mir_graph_->catches_.end(); ++it) { 476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t dex_pc = *it; 4776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool found = false; 4781fd3346740dfb7f47be9922312b68a4227fada96buzbee for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) { 4791fd3346740dfb7f47be9922312b68a4227fada96buzbee if (dex_pc == dex2pc_mapping_table_[i+1]) { 4806459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee found = true; 4816459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee break; 4826459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4836459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4846459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!found) { 485fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc; 4866459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 4876459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4886459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4896459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee // Now, try in the other direction 4901fd3346740dfb7f47be9922312b68a4227fada96buzbee for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) { 4911fd3346740dfb7f47be9922312b68a4227fada96buzbee uint32_t dex_pc = dex2pc_mapping_table_[i+1]; 4921fd3346740dfb7f47be9922312b68a4227fada96buzbee if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) { 493fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc; 4946459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 4956459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4966459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 4976459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!success) { 4981fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file); 4991fd3346740dfb7f47be9922312b68a4227fada96buzbee LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: " 5001fd3346740dfb7f47be9922312b68a4227fada96buzbee << dex2pc_mapping_table_.size()/2; 5016459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 5026459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee return success; 5036459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee} 5046459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee 505311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 5062ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::CreateMappingTables() { 5071fd3346740dfb7f47be9922312b68a4227fada96buzbee for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) { 508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) { 5091fd3346740dfb7f47be9922312b68a4227fada96buzbee pc2dex_mapping_table_.push_back(tgt_lir->offset); 5101fd3346740dfb7f47be9922312b68a4227fada96buzbee pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset); 511a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 512fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) { 5131fd3346740dfb7f47be9922312b68a4227fada96buzbee dex2pc_mapping_table_.push_back(tgt_lir->offset); 5141fd3346740dfb7f47be9922312b68a4227fada96buzbee dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset); 515e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 516a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 517311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (kIsDebugBuild) { 5181fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(VerifyCatchEntries()); 519311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 5201fd3346740dfb7f47be9922312b68a4227fada96buzbee combined_mapping_table_.push_back(pc2dex_mapping_table_.size() + 5211fd3346740dfb7f47be9922312b68a4227fada96buzbee dex2pc_mapping_table_.size()); 5221fd3346740dfb7f47be9922312b68a4227fada96buzbee combined_mapping_table_.push_back(pc2dex_mapping_table_.size()); 5231fd3346740dfb7f47be9922312b68a4227fada96buzbee combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(), 5241fd3346740dfb7f47be9922312b68a4227fada96buzbee pc2dex_mapping_table_.end()); 5251fd3346740dfb7f47be9922312b68a4227fada96buzbee combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(), 5261fd3346740dfb7f47be9922312b68a4227fada96buzbee dex2pc_mapping_table_.end()); 527e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 528e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 5290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder { 5300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public: 5310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers NativePcToReferenceMapBuilder(std::vector<uint8_t>* table, 5320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t entries, uint32_t max_native_offset, 5330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t references_width) : entries_(entries), 5340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers references_width_(references_width), in_use_(entries), 5350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_(table) { 5360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute width in bytes needed to hold max_native_offset. 5370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_ = 0; 5380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (max_native_offset != 0) { 5390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_++; 5400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset >>= 8; 5410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Resize table and set up header. 5430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table->resize((EntryWidth() * entries) + sizeof(uint32_t)); 544000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(native_offset_width_, 1U << 3); 545000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] = native_offset_width_ & 7; 546000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(references_width_, 1U << 13); 547000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] |= (references_width_ << 3) & 0xFF; 548000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[1] = (references_width_ >> 5) & 0xFF; 5490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers CHECK_LT(entries, 1U << 16); 5500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[2] = entries & 0xFF; 5510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[3] = (entries >> 8) & 0xFF; 5520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5540c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void AddEntry(uint32_t native_offset, const uint8_t* references) { 5550c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_index = TableIndex(native_offset); 5560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (in_use_[table_index]) { 5570c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_index = (table_index + 1) % entries_; 5580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers in_use_[table_index] = true; 5600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetNativeOffset(table_index, native_offset); 5610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers DCHECK_EQ(native_offset, GetNativeOffset(table_index)); 5620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetReferences(table_index, references); 5630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private: 5660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t TableIndex(uint32_t native_offset) { 5670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_; 5680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t GetNativeOffset(size_t table_index) { 5710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = 0; 5720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 5730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 5740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset |= (*table_)[table_offset + i] << (i * 8); 5750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset; 5770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetNativeOffset(size_t table_index, uint32_t native_offset) { 5800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 5810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 5820c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF; 5830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetReferences(size_t table_index, const uint8_t* references) { 5870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 5880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_); 5890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t EntryWidth() const { 5920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset_width_ + references_width_; 5930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 5940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 5950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of entries in the table. 5960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t entries_; 5970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode the reference bitmap. 5980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t references_width_; 5990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode a native offset. 6000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t native_offset_width_; 6010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Entries that are in use. 6020c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<bool> in_use_; 6030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // The table we're building. 6040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<uint8_t>* const table_; 6050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}; 6060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 6071fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::CreateNativeGcMap() { 6081fd3346740dfb7f47be9922312b68a4227fada96buzbee const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_; 6090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t max_native_offset = 0; 6100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 6110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 6120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers if (native_offset > max_native_offset) { 6130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset = native_offset; 6140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 6150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 61651c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom MethodReference method_ref(cu_->dex_file, cu_->method_idx); 6170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref); 6180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4); 6190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute native offset to references size. 6201fd3346740dfb7f47be9922312b68a4227fada96buzbee NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_, 6210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers mapping_table.size() / 2, max_native_offset, 6220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers dex_gc_map.RegWidth()); 6230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 6240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 6250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 6260c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t dex_pc = mapping_table[i + 1]; 6270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false); 628a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc; 629a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee native_gc_map_builder.AddEntry(native_offset, references); 6300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 6310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers} 6320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 633e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */ 6342ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignLiteralOffset(int offset) { 6351fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignLiteralOffsetCommon(literal_list_, offset); 6361fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignLiteralOffsetCommon(code_literal_list_, offset); 6371fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignLiteralOffsetCommon(method_literal_list_, offset); 638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 639e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 640e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 6412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignSwitchTablesOffset(int offset) { 642862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_); 643a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 644862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee Mir2Lir::SwitchTable *tab_rec = iterator.Next(); 645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 646fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->offset = offset; 647fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 648fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->table[1] * (sizeof(int) * 2); 649a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 650fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK_EQ(static_cast<int>(tab_rec->table[0]), 651a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 652fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->table[1] * sizeof(int); 653e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 654a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 655a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 656e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 657e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 6582ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignFillArrayDataOffset(int offset) { 659862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_); 660a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 661862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee Mir2Lir::FillArrayData *tab_rec = iterator.Next(); 662fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 663fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->offset = offset; 664fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->size; 665a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // word align 666a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 667a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 668a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 669e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 670e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 671a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee// LIR offset assignment. 6722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignInsnOffsets() { 673a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee LIR* lir; 674a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee int offset = 0; 675a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 6761fd3346740dfb7f47be9922312b68a4227fada96buzbee for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) { 677a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->offset = offset; 678a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (lir->opcode >= 0) { 679a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (!lir->flags.is_nop) { 680a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee offset += lir->flags.size; 681a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 682a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } else if (lir->opcode == kPseudoPseudoAlign4) { 683a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (offset & 0x2) { 684a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee offset += 2; 685a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->operands[0] = 1; 686a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } else { 687a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->operands[0] = 0; 688a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 689a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 690a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee /* Pseudo opcodes don't consume space */ 691a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 692a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 693a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee return offset; 694a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee} 695a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 696e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 697e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions 698e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit. 699e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 7002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AssignOffsets() { 7011fd3346740dfb7f47be9922312b68a4227fada96buzbee int offset = AssignInsnOffsets(); 702e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 703a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Const values have to be word aligned */ 704a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 705e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 706a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Set up offsets for literals */ 7071fd3346740dfb7f47be9922312b68a4227fada96buzbee data_offset_ = offset; 708e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7091fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignLiteralOffset(offset); 710e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7111fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignSwitchTablesOffset(offset); 712e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7131fd3346740dfb7f47be9922312b68a4227fada96buzbee offset = AssignFillArrayDataOffset(offset); 714e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7151fd3346740dfb7f47be9922312b68a4227fada96buzbee total_size_ = offset; 716e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 717e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 718e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 719e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top 720e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is 721e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it. 722e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 7232ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AssembleLIR() { 7241fd3346740dfb7f47be9922312b68a4227fada96buzbee AssignOffsets(); 725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int assembler_retries = 0; 726a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 727a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Assemble here. Note that we generate code with optimistic assumptions 728a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * and if found now to work, we'll have to redo the sequence and retry. 729a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 730e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 731a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 7321fd3346740dfb7f47be9922312b68a4227fada96buzbee AssemblerStatus res = AssembleInstructions(0); 733a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (res == kSuccess) { 734a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 735a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 736311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee assembler_retries++; 737311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (assembler_retries > MAX_ASSEMBLER_RETRIES) { 7381fd3346740dfb7f47be9922312b68a4227fada96buzbee CodegenDump(); 739a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Assembler error - too many retries"; 740a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 741a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Redo offsets and try again 7421fd3346740dfb7f47be9922312b68a4227fada96buzbee AssignOffsets(); 7431fd3346740dfb7f47be9922312b68a4227fada96buzbee code_buffer_.clear(); 744e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 745a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 746e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 747a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install literals 7481fd3346740dfb7f47be9922312b68a4227fada96buzbee InstallLiteralPools(); 749e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 750a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install switch tables 7511fd3346740dfb7f47be9922312b68a4227fada96buzbee InstallSwitchTables(); 752e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 753a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install fill array data 7541fd3346740dfb7f47be9922312b68a4227fada96buzbee InstallFillArrayData(); 755e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Create the mapping table and native offset to reference map. 7571fd3346740dfb7f47be9922312b68a4227fada96buzbee CreateMappingTables(); 7580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7591fd3346740dfb7f47be9922312b68a4227fada96buzbee CreateNativeGcMap(); 760e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 761e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 76231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 76331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik 76431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr. This label will be used to fix up the case 76531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase. Be sure to set 76631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across 76731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries. KeyVal is just there for debugging. 76831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 7692ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal) { 770a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee SafeMap<unsigned int, LIR*>::iterator it; 7711fd3346740dfb7f47be9922312b68a4227fada96buzbee it = boundary_map_.find(vaddr); 7721fd3346740dfb7f47be9922312b68a4227fada96buzbee if (it == boundary_map_.end()) { 773a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; 774a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 775862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee LIR* new_label = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocLIR)); 776fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->dalvik_offset = vaddr; 777fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->opcode = kPseudoCaseLabel; 778fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->operands[0] = keyVal; 779fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee InsertLIRAfter(it->second, new_label); 780fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return new_label; 78131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 78231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 7832ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec) { 784fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const uint16_t* table = tab_rec->table; 785fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int base_vaddr = tab_rec->vaddr; 786cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int *targets = reinterpret_cast<const int*>(&table[4]); 787a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 788fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 789a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 7901fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key); 791a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 79231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 79331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 7942ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec) { 795fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const uint16_t* table = tab_rec->table; 796fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int base_vaddr = tab_rec->vaddr; 797a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 798cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 799cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 800a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 8011fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]); 802a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 80331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 80431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 8052ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::ProcessSwitchTables() { 806862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_); 807a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 808862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee Mir2Lir::SwitchTable *tab_rec = iterator.Next(); 809fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 810fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) { 8111fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkPackedCaseLabels(tab_rec); 812fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 8131fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkSparseCaseLabels(tab_rec); 814a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 815a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Invalid switch table"; 81631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 817a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 81831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 81931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 8202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpSparseSwitchTable(const uint16_t* table) { 821a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 822a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Sparse switch data format: 823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0200 magic value 824a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table; > 0 825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int keys[size] keys, sorted low-to-high; 32-bit aligned 826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 827a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 828a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (2+size*4) 16-bit code units. 829a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 830eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 832cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 833cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 834a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident 835a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << ", entries: " << std::dec << entries; 836a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i]; 838a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 83931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 84031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 8412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpPackedSwitchTable(const uint16_t* table) { 842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 843a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Packed switch data format: 844a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0100 magic value 845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table 846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int first_key first (and lowest) switch case value 847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (4+size*2) 16-bit code units. 850a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 851eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 852cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = reinterpret_cast<const int*>(&table[4]); 853a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 854fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 855a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident 856fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << ", entries: " << std::dec << entries << ", low_key: " << low_key; 857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 858fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << " Key[" << (i + low_key) << "] -> 0x" << std::hex 859a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << targets[i]; 860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 86131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 862e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 863d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/* 864d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and 865fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * record it in the boundary_map. NOTE: in cases such as kMirOpCheck in 866d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op 867d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map. 868d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */ 8692ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str) { 8701fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str)); 8711fd3346740dfb7f47be9922312b68a4227fada96buzbee if (boundary_map_.find(offset) == boundary_map_.end()) { 8721fd3346740dfb7f47be9922312b68a4227fada96buzbee boundary_map_.Put(offset, res); 873d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee } 874d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee return res; 875d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee} 876e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 8772ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) { 878e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee bool is_taken; 879e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee switch (opcode) { 880e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_EQ: is_taken = (src1 == src2); break; 881e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_NE: is_taken = (src1 != src2); break; 882e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LT: is_taken = (src1 < src2); break; 883e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GE: is_taken = (src1 >= src2); break; 884e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GT: is_taken = (src1 > src2); break; 885e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LE: is_taken = (src1 <= src2); break; 886e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_EQZ: is_taken = (src1 == 0); break; 887e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_NEZ: is_taken = (src1 != 0); break; 888e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LTZ: is_taken = (src1 < 0); break; 889e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GEZ: is_taken = (src1 >= 0); break; 890e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GTZ: is_taken = (src1 > 0); break; 891e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LEZ: is_taken = (src1 <= 0); break; 892e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee default: 893e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee LOG(FATAL) << "Unexpected opcode " << opcode; 894e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee is_taken = false; 895e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee } 896e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee return is_taken; 897e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee} 898e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee 8994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee// Convert relation of src1/src2 to src2/src1 9001fd3346740dfb7f47be9922312b68a4227fada96buzbeeConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) { 9014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee ConditionCode res; 9024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee switch (before) { 9034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondEq: res = kCondEq; break; 9044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondNe: res = kCondNe; break; 9054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondLt: res = kCondGt; break; 9064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondGt: res = kCondLt; break; 9074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondLe: res = kCondGe; break; 9084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondGe: res = kCondLe; break; 9094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee default: 9104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee res = static_cast<ConditionCode>(0); 9114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee LOG(FATAL) << "Unexpected ccode " << before; 9124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 9134ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return res; 9144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 9154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 916862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee// TODO: move to mir_to_lir.cc 917862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 9186282dc12440a2072dc06a616160027ff21bd895eIan Rogers : Backend(arena), 9196282dc12440a2072dc06a616160027ff21bd895eIan Rogers literal_list_(NULL), 9201fd3346740dfb7f47be9922312b68a4227fada96buzbee method_literal_list_(NULL), 9211fd3346740dfb7f47be9922312b68a4227fada96buzbee code_literal_list_(NULL), 9221fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_(cu), 9231fd3346740dfb7f47be9922312b68a4227fada96buzbee mir_graph_(mir_graph), 924862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee switch_tables_(arena, 4, kGrowableArraySwitchTables), 925862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee fill_array_data_(arena, 4, kGrowableArrayFillArrayData), 926862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee throw_launchpads_(arena, 2048, kGrowableArrayThrowLaunchPads), 927862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee suspend_launchpads_(arena, 4, kGrowableArraySuspendLaunchPads), 928862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee intrinsic_launchpads_(arena, 2048, kGrowableArrayMisc), 9291fd3346740dfb7f47be9922312b68a4227fada96buzbee data_offset_(0), 9301fd3346740dfb7f47be9922312b68a4227fada96buzbee total_size_(0), 9311fd3346740dfb7f47be9922312b68a4227fada96buzbee block_label_list_(NULL), 932862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee current_dalvik_offset_(0), 933862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee reg_pool_(NULL), 9341fd3346740dfb7f47be9922312b68a4227fada96buzbee live_sreg_(0), 9351fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_(0), 9361fd3346740dfb7f47be9922312b68a4227fada96buzbee num_fp_spills_(0), 9371fd3346740dfb7f47be9922312b68a4227fada96buzbee frame_size_(0), 9381fd3346740dfb7f47be9922312b68a4227fada96buzbee core_spill_mask_(0), 9391fd3346740dfb7f47be9922312b68a4227fada96buzbee fp_spill_mask_(0), 9401fd3346740dfb7f47be9922312b68a4227fada96buzbee first_lir_insn_(NULL), 9412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom last_lir_insn_(NULL) { 9421fd3346740dfb7f47be9922312b68a4227fada96buzbee promotion_map_ = static_cast<PromotionMap*> 943862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee (arena_->NewMem((cu_->num_dalvik_registers + cu_->num_compiler_temps + 1) * 944862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee sizeof(promotion_map_[0]), true, ArenaAllocator::kAllocRegAlloc)); 9451fd3346740dfb7f47be9922312b68a4227fada96buzbee} 9461fd3346740dfb7f47be9922312b68a4227fada96buzbee 9471fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::Materialize() { 9481fd3346740dfb7f47be9922312b68a4227fada96buzbee CompilerInitializeRegAlloc(); // Needs to happen after SSA naming 9491fd3346740dfb7f47be9922312b68a4227fada96buzbee 9501fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Allocate Registers using simple local allocation scheme */ 9511fd3346740dfb7f47be9922312b68a4227fada96buzbee SimpleRegAlloc(); 9521fd3346740dfb7f47be9922312b68a4227fada96buzbee 953479f83c196d5a95e36196eac548dc6019e70a5bebuzbee if (mir_graph_->IsSpecialCase()) { 9541fd3346740dfb7f47be9922312b68a4227fada96buzbee /* 9551fd3346740dfb7f47be9922312b68a4227fada96buzbee * Custom codegen for special cases. If for any reason the 9561fd3346740dfb7f47be9922312b68a4227fada96buzbee * special codegen doesn't succeed, first_lir_insn_ will 9571fd3346740dfb7f47be9922312b68a4227fada96buzbee * set to NULL; 9581fd3346740dfb7f47be9922312b68a4227fada96buzbee */ 959479f83c196d5a95e36196eac548dc6019e70a5bebuzbee SpecialMIR2LIR(mir_graph_->GetSpecialCase()); 9601fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9611fd3346740dfb7f47be9922312b68a4227fada96buzbee 9621fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Convert MIR to LIR, etc. */ 9631fd3346740dfb7f47be9922312b68a4227fada96buzbee if (first_lir_insn_ == NULL) { 9641fd3346740dfb7f47be9922312b68a4227fada96buzbee MethodMIR2LIR(); 9651fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9661fd3346740dfb7f47be9922312b68a4227fada96buzbee 9671fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Method is not empty */ 9681fd3346740dfb7f47be9922312b68a4227fada96buzbee if (first_lir_insn_) { 9691fd3346740dfb7f47be9922312b68a4227fada96buzbee // mark the targets of switch statement case labels 9701fd3346740dfb7f47be9922312b68a4227fada96buzbee ProcessSwitchTables(); 9711fd3346740dfb7f47be9922312b68a4227fada96buzbee 9721fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Convert LIR into machine code. */ 9731fd3346740dfb7f47be9922312b68a4227fada96buzbee AssembleLIR(); 9741fd3346740dfb7f47be9922312b68a4227fada96buzbee 9751fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 9761fd3346740dfb7f47be9922312b68a4227fada96buzbee CodegenDump(); 9771fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9781fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9791fd3346740dfb7f47be9922312b68a4227fada96buzbee} 9801fd3346740dfb7f47be9922312b68a4227fada96buzbee 9811fd3346740dfb7f47be9922312b68a4227fada96buzbeeCompiledMethod* Mir2Lir::GetCompiledMethod() { 9821fd3346740dfb7f47be9922312b68a4227fada96buzbee // Combine vmap tables - core regs, then fp regs - into vmap_table 9831fd3346740dfb7f47be9922312b68a4227fada96buzbee std::vector<uint16_t> vmap_table; 9841fd3346740dfb7f47be9922312b68a4227fada96buzbee // Core regs may have been inserted out of order - sort first 9851fd3346740dfb7f47be9922312b68a4227fada96buzbee std::sort(core_vmap_table_.begin(), core_vmap_table_.end()); 9861fd3346740dfb7f47be9922312b68a4227fada96buzbee for (size_t i = 0 ; i < core_vmap_table_.size(); i++) { 9871fd3346740dfb7f47be9922312b68a4227fada96buzbee // Copy, stripping out the phys register sort key 9881fd3346740dfb7f47be9922312b68a4227fada96buzbee vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]); 9891fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9901fd3346740dfb7f47be9922312b68a4227fada96buzbee // If we have a frame, push a marker to take place of lr 9911fd3346740dfb7f47be9922312b68a4227fada96buzbee if (frame_size_ > 0) { 9921fd3346740dfb7f47be9922312b68a4227fada96buzbee vmap_table.push_back(INVALID_VREG); 9931fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 9941fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0); 9951fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0); 9961fd3346740dfb7f47be9922312b68a4227fada96buzbee } 9971fd3346740dfb7f47be9922312b68a4227fada96buzbee // Combine vmap tables - core regs, then fp regs. fp regs already sorted 9981fd3346740dfb7f47be9922312b68a4227fada96buzbee for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) { 9991fd3346740dfb7f47be9922312b68a4227fada96buzbee vmap_table.push_back(fp_vmap_table_[i]); 10001fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10011fd3346740dfb7f47be9922312b68a4227fada96buzbee CompiledMethod* result = 10021fd3346740dfb7f47be9922312b68a4227fada96buzbee new CompiledMethod(cu_->instruction_set, code_buffer_, 10031fd3346740dfb7f47be9922312b68a4227fada96buzbee frame_size_, core_spill_mask_, fp_spill_mask_, 10041fd3346740dfb7f47be9922312b68a4227fada96buzbee combined_mapping_table_, vmap_table, native_gc_map_); 10051fd3346740dfb7f47be9922312b68a4227fada96buzbee return result; 10061fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10071fd3346740dfb7f47be9922312b68a4227fada96buzbee 10081fd3346740dfb7f47be9922312b68a4227fada96buzbeeint Mir2Lir::ComputeFrameSize() { 10091fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Figure out the frame size */ 10101fd3346740dfb7f47be9922312b68a4227fada96buzbee static const uint32_t kAlignMask = kStackAlignment - 1; 10111fd3346740dfb7f47be9922312b68a4227fada96buzbee uint32_t size = (num_core_spills_ + num_fp_spills_ + 10121fd3346740dfb7f47be9922312b68a4227fada96buzbee 1 /* filler word */ + cu_->num_regs + cu_->num_outs + 10131fd3346740dfb7f47be9922312b68a4227fada96buzbee cu_->num_compiler_temps + 1 /* cur_method* */) 10141fd3346740dfb7f47be9922312b68a4227fada96buzbee * sizeof(uint32_t); 10151fd3346740dfb7f47be9922312b68a4227fada96buzbee /* Align and set */ 10161fd3346740dfb7f47be9922312b68a4227fada96buzbee return (size + kAlignMask) & ~(kAlignMask); 10171fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10181fd3346740dfb7f47be9922312b68a4227fada96buzbee 10191fd3346740dfb7f47be9922312b68a4227fada96buzbee/* 10201fd3346740dfb7f47be9922312b68a4227fada96buzbee * Append an LIR instruction to the LIR list maintained by a compilation 10211fd3346740dfb7f47be9922312b68a4227fada96buzbee * unit 10221fd3346740dfb7f47be9922312b68a4227fada96buzbee */ 10232ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AppendLIR(LIR* lir) { 10241fd3346740dfb7f47be9922312b68a4227fada96buzbee if (first_lir_insn_ == NULL) { 10251fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(last_lir_insn_ == NULL); 10261fd3346740dfb7f47be9922312b68a4227fada96buzbee last_lir_insn_ = first_lir_insn_ = lir; 10271fd3346740dfb7f47be9922312b68a4227fada96buzbee lir->prev = lir->next = NULL; 10281fd3346740dfb7f47be9922312b68a4227fada96buzbee } else { 10291fd3346740dfb7f47be9922312b68a4227fada96buzbee last_lir_insn_->next = lir; 10301fd3346740dfb7f47be9922312b68a4227fada96buzbee lir->prev = last_lir_insn_; 10311fd3346740dfb7f47be9922312b68a4227fada96buzbee lir->next = NULL; 10321fd3346740dfb7f47be9922312b68a4227fada96buzbee last_lir_insn_ = lir; 10331fd3346740dfb7f47be9922312b68a4227fada96buzbee } 10341fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10351fd3346740dfb7f47be9922312b68a4227fada96buzbee 10361fd3346740dfb7f47be9922312b68a4227fada96buzbee/* 10371fd3346740dfb7f47be9922312b68a4227fada96buzbee * Insert an LIR instruction before the current instruction, which cannot be the 10381fd3346740dfb7f47be9922312b68a4227fada96buzbee * first instruction. 10391fd3346740dfb7f47be9922312b68a4227fada96buzbee * 10401fd3346740dfb7f47be9922312b68a4227fada96buzbee * prev_lir <-> new_lir <-> current_lir 10411fd3346740dfb7f47be9922312b68a4227fada96buzbee */ 10422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir) { 10431fd3346740dfb7f47be9922312b68a4227fada96buzbee DCHECK(current_lir->prev != NULL); 10441fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR *prev_lir = current_lir->prev; 10451fd3346740dfb7f47be9922312b68a4227fada96buzbee 10461fd3346740dfb7f47be9922312b68a4227fada96buzbee prev_lir->next = new_lir; 10471fd3346740dfb7f47be9922312b68a4227fada96buzbee new_lir->prev = prev_lir; 10481fd3346740dfb7f47be9922312b68a4227fada96buzbee new_lir->next = current_lir; 10491fd3346740dfb7f47be9922312b68a4227fada96buzbee current_lir->prev = new_lir; 10501fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10511fd3346740dfb7f47be9922312b68a4227fada96buzbee 10521fd3346740dfb7f47be9922312b68a4227fada96buzbee/* 10531fd3346740dfb7f47be9922312b68a4227fada96buzbee * Insert an LIR instruction after the current instruction, which cannot be the 10541fd3346740dfb7f47be9922312b68a4227fada96buzbee * first instruction. 10551fd3346740dfb7f47be9922312b68a4227fada96buzbee * 10561fd3346740dfb7f47be9922312b68a4227fada96buzbee * current_lir -> new_lir -> old_next 10571fd3346740dfb7f47be9922312b68a4227fada96buzbee */ 10582ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir) { 10591fd3346740dfb7f47be9922312b68a4227fada96buzbee new_lir->prev = current_lir; 10601fd3346740dfb7f47be9922312b68a4227fada96buzbee new_lir->next = current_lir->next; 10611fd3346740dfb7f47be9922312b68a4227fada96buzbee current_lir->next = new_lir; 10621fd3346740dfb7f47be9922312b68a4227fada96buzbee new_lir->next->prev = new_lir; 10631fd3346740dfb7f47be9922312b68a4227fada96buzbee} 10641fd3346740dfb7f47be9922312b68a4227fada96buzbee 10651fd3346740dfb7f47be9922312b68a4227fada96buzbee 10667934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 1067