codegen_util.cc revision 311ca169f4727d46a55bdc8dfa0059719fa72b65
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 17395116cae130c983498c0a2f42b89e42f75bb9d0buzbee#include "compiler/dex/compiler_internals.h" 184f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h" 200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h" 210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h" 221bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "ralloc_util.h" 23eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee#include "codegen_util.h" 240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 25e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art { 26e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbeebool IsInexpensiveConstant(CompilationUnit* cu, RegLocation rl_src) 284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee{ 294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee bool res = false; 304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.is_const) { 314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.wide) { 324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.fp) { 33311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee res = cu->cg->InexpensiveConstantDouble(cu->mir_graph->ConstantValueWide(rl_src)); 344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 35311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee res = cu->cg->InexpensiveConstantLong(cu->mir_graph->ConstantValueWide(rl_src)); 364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (rl_src.fp) { 39311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee res = cu->cg->InexpensiveConstantFloat(cu->mir_graph->ConstantValue(rl_src)); 404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } else { 41311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee res = cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src)); 424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return res; 464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 4802031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid MarkSafepointPC(CompilationUnit* cu, LIR* inst) 4902031b185b4653e6c72e21f7a51238b903f6d638buzbee{ 5002031b185b4653e6c72e21f7a51238b903f6d638buzbee inst->def_mask = ENCODE_ALL; 5102031b185b4653e6c72e21f7a51238b903f6d638buzbee LIR* safepoint_pc = NewLIR0(cu, kPseudoSafepointPC); 5202031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL); 5302031b185b4653e6c72e21f7a51238b903f6d638buzbee} 5402031b185b4653e6c72e21f7a51238b903f6d638buzbee 5502031b185b4653e6c72e21f7a51238b903f6d638buzbeebool FastInstance(CompilationUnit* cu, uint32_t field_idx, 5602031b185b4653e6c72e21f7a51238b903f6d638buzbee int& field_offset, bool& is_volatile, bool is_put) 5702031b185b4653e6c72e21f7a51238b903f6d638buzbee{ 58311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee return cu->compiler_driver->ComputeInstanceFieldInfo( 59311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee field_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put); 6002031b185b4653e6c72e21f7a51238b903f6d638buzbee} 6102031b185b4653e6c72e21f7a51238b903f6d638buzbee 62cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */ 6352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid NopLIR( LIR* lir) 64cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee{ 65fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->flags.is_nop = true; 66cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee} 67cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee 6802031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type) 6931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 70fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint64_t *mask_ptr; 71eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint64_t mask = ENCODE_MEM;; 7202031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 7302031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(cg->GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE)); 74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (is_load) { 75fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee mask_ptr = &lir->use_mask; 76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee mask_ptr = &lir->def_mask; 78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Clear out the memref flags */ 80fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr &= ~mask; 81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* ..and then add back the one we need */ 82fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee switch (mem_type) { 83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kLiteral: 84fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK(is_load); 85fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_LITERAL; 86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kDalvikReg: 88fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_DALVIK_REG; 89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kHeapRef: 91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_HEAP_REF; 92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kMustNotAlias: 94a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Currently only loads can be marked as kMustNotAlias */ 9502031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(!(cg->GetTargetInstFlags(lir->opcode) & IS_STORE)); 96fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *mask_ptr |= ENCODE_MUST_NOT_ALIAS; 97a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 98a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 99fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(FATAL) << "Oat: invalid memref kind - " << mem_type; 100a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 10231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 10331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 104b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack. 10531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 10602031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid AnnotateDalvikRegAccess(CompilationUnit* cu, LIR* lir, int reg_id, bool is_load, bool is64bit) 10731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 10802031b185b4653e6c72e21f7a51238b903f6d638buzbee SetMemRefType(cu, lir, is_load, kDalvikReg); 10931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 110a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit 112a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * access. 113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 114fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit); 11531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 11631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 11731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 11831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s). 11931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupRegMask(CompilationUnit* cu, uint64_t* mask, int reg) 12131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 12202031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 12302031b185b4653e6c72e21f7a51238b903f6d638buzbee *mask |= cg->GetRegMaskCommon(cu, reg); 12431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 12531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 12631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 12731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask 12831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 129fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupResourceMasks(CompilationUnit* cu, LIR* lir) 13031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int opcode = lir->opcode; 13202031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 13331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (opcode <= 0) { 135fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->use_mask = lir->def_mask = 0; 136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return; 137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 13831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 13902031b185b4653e6c72e21f7a51238b903f6d638buzbee uint64_t flags = cg->GetTargetInstFlags(opcode); 14031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & NEEDS_FIXUP) { 142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->flags.pcRelFixup = true; 143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 14431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Get the starting size of the instruction's template */ 14602031b185b4653e6c72e21f7a51238b903f6d638buzbee lir->flags.size = cg->GetInsnSize(lir); 147e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee 148a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Set up the mask for resources that are updated */ 149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (IS_LOAD | IS_STORE)) { 150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Default to heap - will catch specialized classes later */ 15102031b185b4653e6c72e21f7a51238b903f6d638buzbee SetMemRefType(cu, lir, flags & IS_LOAD, kHeapRef); 152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Conservatively assume the branch here will call out a function that in 156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * turn will trash everything. 157a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & IS_BRANCH) { 159fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->def_mask = lir->use_mask = ENCODE_ALL; 160a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return; 161a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 16231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 163a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & REG_DEF0) { 164fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SetupRegMask(cu, &lir->def_mask, lir->operands[0]); 165a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 16631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 167a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & REG_DEF1) { 168fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SetupRegMask(cu, &lir->def_mask, lir->operands[1]); 169a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 17031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 17131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 172a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & SETS_CCODES) { 173fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->def_mask |= ENCODE_CCODE; 174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 17531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) { 177a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int i; 17831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (i = 0; i < 4; i++) { 180a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & (1 << (kRegUse0 + i))) { 181fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SetupRegMask(cu, &lir->use_mask, lir->operands[i]); 182a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 18331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 18531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (flags & USES_CCODES) { 187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->use_mask |= ENCODE_CCODE; 188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 18931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 190b046e16d8b8da318d6055f9308950131f1255e08buzbee // Handle target-specific actions 19102031b185b4653e6c72e21f7a51238b903f6d638buzbee cg->SetupTargetResourceMasks(cu, lir); 19231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 19331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 19431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 1955de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros 1965de3494e4297c0d480409da3fecee39173f1d4e1buzbee */ 1975de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X) 1985de3494e4297c0d480409da3fecee39173f1d4e1buzbee 1995de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */ 200fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr) 2015de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int offset = lir->offset; 203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest = lir->operands[0]; 204fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const bool dump_nop = (cu->enable_debug & (1 << kDebugShowNops)); 20502031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 206a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Handle pseudo-ops individually, and all regular insns as a group */ 208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee switch (lir->opcode) { 209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodEntry: 210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- method entry " 211fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file); 212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoMethodExit: 214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- Method_Exit"; 215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoBarrier: 217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- BARRIER"; 218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEntryBlock: 220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; 221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoDalvikByteCodeBoundary: 2234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee if (lir->operands[0] == 0) { 2244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string"); 2254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 226a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- dalvik offset: 0x" << std::hex 227fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]); 228a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 229a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoExitBlock: 230a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; 231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 232a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoPseudoAlign4: 233fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex 234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << offset << "): .align4"; 235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoEHBlockLabel: 237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Exception_Handling:"; 238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoTargetLabel: 240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoNormalBlockLabel: 241cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":"; 242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoThrowTarget: 244cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":"; 245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoIntrinsicRetry: 247cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":"; 248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoSuspendTarget: 250cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":"; 251a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 2528320f3867c02bae9bef6cdab267820cb7b412781buzbee case kPseudoSafepointPC: 253fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":"; 2548320f3867c02bae9bef6cdab267820cb7b412781buzbee break; 255a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee case kPseudoExportedPC: 256fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":"; 257a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee break; 258a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee case kPseudoCaseLabel: 259cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x" 260a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << lir->operands[0] << "|" << std::dec << 261a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->operands[0]; 262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee default: 264fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->flags.is_nop && !dump_nop) { 265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 26702031b185b4653e6c72e21f7a51238b903f6d638buzbee std::string op_name(cg->BuildInsnString(cg->GetTargetInstName(lir->opcode), 26802031b185b4653e6c72e21f7a51238b903f6d638buzbee lir, base_addr)); 26902031b185b4653e6c72e21f7a51238b903f6d638buzbee std::string op_operands(cg->BuildInsnString(cg->GetTargetInstFmt(lir->opcode), 27002031b185b4653e6c72e21f7a51238b903f6d638buzbee lir, base_addr)); 271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("%05x: %-9s%s%s", 272fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee reinterpret_cast<unsigned int>(base_addr + offset), 273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee op_name.c_str(), op_operands.c_str(), 274fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir->flags.is_nop ? "(nop)" : ""); 275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) { 280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->use_mask, "use")); 281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 282fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) { 283fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->def_mask, "def")); 284a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2855de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 2865de3494e4297c0d480409da3fecee39173f1d4e1buzbee 287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpPromotionMap(CompilationUnit *cu) 2885de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 28902031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 290fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int num_regs = cu->num_dalvik_registers + cu->num_compiler_temps + 1; 291fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int i = 0; i < num_regs; i++) { 292fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PromotionMap v_reg_map = cu->promotion_map[i]; 293a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf; 294fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (v_reg_map.fp_location == kLocPhysReg) { 29502031b185b4653e6c72e21f7a51238b903f6d638buzbee StringAppendF(&buf, " : s%d", v_reg_map.FpReg & cg->FpRegMask()); 296a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 2979c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee 298a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee std::string buf3; 299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (i < cu->num_dalvik_registers) { 300a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee StringAppendF(&buf3, "%02d", i); 301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (i == cu->method_sreg) { 302a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf3 = "Method*"; 303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee StringAppendF(&buf3, "ct%d", i - cu->num_dalvik_registers); 3055de3494e4297c0d480409da3fecee39173f1d4e1buzbee } 306a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(), 308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee v_reg_map.core_location == kLocPhysReg ? 309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee "r" : "SP+", v_reg_map.core_location == kLocPhysReg ? 310fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee v_reg_map.core_reg : SRegOffset(cu, i), 311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.c_str()); 312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 3135de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 3145de3494e4297c0d480409da3fecee39173f1d4e1buzbee 315a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */ 316aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void DumpMappingTable(const char* table_name, const std::string& descriptor, 317aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee const std::string& name, const std::string& signature, 318aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee const std::vector<uint32_t>& v) { 319a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if (v.size() > 0) { 320a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name, 321a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee descriptor.c_str(), name.c_str(), signature.c_str(), v.size())); 322a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee std::replace(line.begin(), line.end(), ';', '_'); 323a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 324a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee for (uint32_t i = 0; i < v.size(); i+=2) { 325a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]); 326a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) << line; 327a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 328a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee LOG(INFO) <<" };\n\n"; 329a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 330a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee} 331a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee 3325de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */ 333fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid CodegenDump(CompilationUnit* cu) 3345de3494e4297c0d480409da3fecee39173f1d4e1buzbee{ 335a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Dumping LIR insns for " 336fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file); 337fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* lir_insn; 338311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int insns_size = cu->code_item->insns_size_in_code_units_; 339fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee 340fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Regs (excluding ins) : " << cu->num_regs; 341fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Ins : " << cu->num_ins; 342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Outs : " << cu->num_outs; 343fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "CoreSpills : " << cu->num_core_spills; 344fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "FPSpills : " << cu->num_fp_spills; 345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "CompilerTemps : " << cu->num_compiler_temps; 346fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Frame size : " << cu->frame_size; 347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "code size is " << cu->total_size << 348fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee " bytes, Dalvik size is " << insns_size * 2; 349a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "expansion factor: " 350fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << static_cast<float>(cu->total_size) / static_cast<float>(insns_size * 2); 351fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DumpPromotionMap(cu); 35228c9a83398a6e48eefb9b79a390920629bbb8519buzbee for (lir_insn = cu->first_lir_insn; lir_insn != NULL; lir_insn = lir_insn->next) { 353fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DumpLIRInsn(cu, lir_insn, 0); 354a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 35528c9a83398a6e48eefb9b79a390920629bbb8519buzbee for (lir_insn = cu->literal_list; lir_insn != NULL; lir_insn = lir_insn->next) { 356fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset, 357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lir_insn->operands[0]); 358a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 360a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee const DexFile::MethodId& method_id = 361fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex_file->GetMethodId(cu->method_idx); 362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee std::string signature(cu->dex_file->GetMethodSignature(method_id)); 363fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee std::string name(cu->dex_file->GetMethodName(method_id)); 364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee std::string descriptor(cu->dex_file->GetMethodDeclaringClassDescriptor(method_id)); 365a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee 366a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee // Dump mapping tables 367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cu->pc2dexMappingTable); 368fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cu->dex2pcMappingTable); 3695de3494e4297c0d480409da3fecee39173f1d4e1buzbee} 3705de3494e4297c0d480409da3fecee39173f1d4e1buzbee 371a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee 372fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0, 373a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int op1, int op2, int op3, int op4, LIR* target) 374a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 375fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); 376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee insn->dalvik_offset = dalvik_offset; 377a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->opcode = opcode; 378a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[0] = op0; 379a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[1] = op1; 380a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[2] = op2; 381a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[3] = op3; 382a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->operands[4] = op4; 383a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee insn->target = target; 384fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SetupResourceMasks(cu, insn); 385a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || 386a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee (opcode == kPseudoExportedPC)) { 387a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Always make labels scheduling barriers 388fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee insn->use_mask = insn->def_mask = ENCODE_ALL; 389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 390a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 391a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee} 392a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee 393a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/* 394a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4 395a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands. 396a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */ 397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR0(CompilationUnit* cu, int opcode) 398a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{ 39902031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 40002031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & NO_OPERAND)) 40102031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 402fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 404fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode); 405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 406a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 40731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 40831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 409fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR1(CompilationUnit* cu, int opcode, 410a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest) 41131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 41202031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 41302031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_UNARY_OP)) 41402031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 415fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 416fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 417fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest); 418fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 419a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 42031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 42131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR2(CompilationUnit* cu, int opcode, 423a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1) 42431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 42502031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 42602031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_BINARY_OP)) 42702031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 429fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 430fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1); 431fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 432a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 43331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 43431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR3(CompilationUnit* cu, int opcode, 436a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2) 43731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 43802031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 43902031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_TERTIARY_OP)) 44002031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 441fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 443fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2); 444fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 445a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 44631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 44731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR4(CompilationUnit* cu, int opcode, 449a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2, int info) 45031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 45102031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 45202031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUAD_OP)) 45302031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 455fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info); 457fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 45931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 46031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 461fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR5(CompilationUnit* cu, int opcode, 462a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int dest, int src1, int src2, int info1, int info2) 463b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{ 46402031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 46502031b185b4653e6c72e21f7a51238b903f6d638buzbee DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUIN_OP)) 46602031b185b4653e6c72e21f7a51238b903f6d638buzbee << cg->GetTargetInstName(opcode) << " " << opcode << " " 467fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << PrettyMethod(cu->method_idx, *cu->dex_file) << " " 468fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->current_dalvik_offset; 469fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info1, info2); 470fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AppendLIR(cu, insn); 471a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return insn; 472b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers} 473b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 47431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 47531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match 47631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0). 47731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 478fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta) 47931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 480fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_target) { 481fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta) 482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return data_target; 483fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_target = data_target->next; 484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 485a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 48631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 48731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 48831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */ 489fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) 49031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 491fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool lo_match = false; 492fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* lo_target = NULL; 493fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_target) { 494fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (lo_match && (data_target->operands[0] == val_hi)) { 4954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee // Record high word in case we need to expand this later. 4964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee lo_target->operands[1] = val_hi; 497fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return lo_target; 49831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 499fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_match = false; 500fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (data_target->operands[0] == val_lo) { 501fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_match = true; 502fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee lo_target = data_target; 503a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 504fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_target = data_target->next; 505a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 506a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 50731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 50831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 50931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 51031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or 51131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams. 51231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 51331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 5144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/* Add a 32-bit constant to the constant pool */ 515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value) 51631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 517a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Add the constant to the literal pool */ 518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (constant_list_p) { 519fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* new_value = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocData)); 520fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_value->operands[0] = value; 521fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_value->next = *constant_list_p; 522fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *constant_list_p = new_value; 523fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return new_value; 524a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 525a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return NULL; 52631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 52731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 52831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */ 529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWideData(CompilationUnit* cu, LIR* *constant_list_p, 530fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int val_lo, int val_hi) 53131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 532fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AddWordData(cu, constant_list_p, val_hi); 533fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return AddWordData(cu, constant_list_p, val_lo); 53431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 53531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 536aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void PushWord(std::vector<uint8_t>&buf, int data) { 537a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( data & 0xff); 538a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 8) & 0xff); 539a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 16) & 0xff); 540a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back( (data >> 24) & 0xff); 541e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 542e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 543aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) { 544a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (buf.size() < offset) { 545a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee buf.push_back(0); 546a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 547e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 548e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 549e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */ 550fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallLiteralPools(CompilationUnit* cu) 551e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 552fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AlignBuffer(cu->code_buffer, cu->data_offset); 553fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* data_lir = cu->literal_list; 554fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 555fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, data_lir->operands[0]); 556fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 558a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Push code and method literals, record offsets for the compiler to patch. 559fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = cu->code_literal_list; 560fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 561fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t target = data_lir->operands[0]; 5621212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->compiler_driver->AddCodePatch(cu->dex_file, 5631212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->method_idx, 5641212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->invoke_type, 5651212a022fa5f8ef9585d765b1809521812af882cIan Rogers target, 5661212a022fa5f8ef9585d765b1809521812af882cIan Rogers static_cast<InvokeType>(data_lir->operands[1]), 5671212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->code_buffer.size()); 568fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const DexFile::MethodId& id = cu->dex_file->GetMethodId(target); 569137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 570137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 571fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, unique_patch_value); 572fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 573137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers } 574fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = cu->method_literal_list; 575fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee while (data_lir != NULL) { 576fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t target = data_lir->operands[0]; 5771212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->compiler_driver->AddMethodPatch(cu->dex_file, 5781212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->method_idx, 5791212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->invoke_type, 5801212a022fa5f8ef9585d765b1809521812af882cIan Rogers target, 5811212a022fa5f8ef9585d765b1809521812af882cIan Rogers static_cast<InvokeType>(data_lir->operands[1]), 5821212a022fa5f8ef9585d765b1809521812af882cIan Rogers cu->code_buffer.size()); 583fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const DexFile::MethodId& id = cu->dex_file->GetMethodId(target); 584137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers // unique based on target to ensure code deduplication works 585137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id); 586fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, unique_patch_value); 587fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee data_lir = NEXT_LIR(data_lir); 588a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 589e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 590e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 591e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */ 592fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallSwitchTables(CompilationUnit* cu) 593e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 594a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 595fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee GrowableListIteratorInit(&cu->switch_tables, &iterator); 596a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 597311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Codegen::SwitchTable* tab_rec = 598311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext( &iterator)); 599fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 600fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AlignBuffer(cu->code_buffer, tab_rec->offset); 601a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 602a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * For Arm, our reference point is the address of the bx 603a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * instruction that does the launch, so we have to subtract 604a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * the auto pc-advance. For other targets the reference point 605a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * is a label, so we can use the offset as-is. 606a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 607fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int bx_offset = INVALID_OFFSET; 608fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee switch (cu->instruction_set) { 609b046e16d8b8da318d6055f9308950131f1255e08buzbee case kThumb2: 610fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = tab_rec->anchor->offset + 4; 611b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 612b046e16d8b8da318d6055f9308950131f1255e08buzbee case kX86: 613fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = 0; 614b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 615b046e16d8b8da318d6055f9308950131f1255e08buzbee case kMips: 616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bx_offset = tab_rec->anchor->offset; 617b046e16d8b8da318d6055f9308950131f1255e08buzbee break; 618fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set; 619b046e16d8b8da318d6055f9308950131f1255e08buzbee } 620fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (cu->verbose) { 621fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset; 622a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 623fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 624fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2])); 625fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int elems = 0; elems < tab_rec->table[1]; elems++) { 626fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int disp = tab_rec->targets[elems]->offset - bx_offset; 627fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (cu->verbose) { 628a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] key: 0x" 629a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << keys[elems] << ", disp: 0x" 630a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 631e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 632fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, keys[elems]); 633fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, 634fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->targets[elems]->offset - bx_offset); 635a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 636a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 637fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK_EQ(static_cast<int>(tab_rec->table[0]), 638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 639fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int elems = 0; elems < tab_rec->table[1]; elems++) { 640fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int disp = tab_rec->targets[elems]->offset - bx_offset; 641fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (cu->verbose) { 642a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Case[" << elems << "] disp: 0x" 643a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << std::hex << disp; 644e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee PushWord(cu->code_buffer, tab_rec->targets[elems]->offset - bx_offset); 646a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 647e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 648a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 649e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 650e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 651e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */ 652fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallFillArrayData(CompilationUnit* cu) 653e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 654a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 655fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee GrowableListIteratorInit(&cu->fill_array_data, &iterator); 656a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 657311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Codegen::FillArrayData *tab_rec = 658311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext( &iterator)); 659fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 660fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AlignBuffer(cu->code_buffer, tab_rec->offset); 661fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int i = 0; i < (tab_rec->size + 1) / 2; i++) { 662fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->code_buffer.push_back( tab_rec->table[i] & 0xFF); 663fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->code_buffer.push_back( (tab_rec->table[i] >> 8) & 0xFF); 664e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 665a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 666e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 667e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 668aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic int AssignLiteralOffsetCommon(LIR* lir, int offset) 669e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 670a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (;lir != NULL; lir = lir->next) { 671a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee lir->offset = offset; 672a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset += 4; 673a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 674a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 675e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 676e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 6776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry 678fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic bool VerifyCatchEntries(CompilationUnit* cu) 6796459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee{ 6806459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool success = true; 681311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee for (std::set<uint32_t>::const_iterator it = cu->mir_graph->catches_.begin(); 682311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee it != cu->mir_graph->catches_.end(); ++it) { 683fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t dex_pc = *it; 6846459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee bool found = false; 685fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) { 686fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (dex_pc == cu->dex2pcMappingTable[i+1]) { 6876459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee found = true; 6886459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee break; 6896459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6906459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6916459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!found) { 692fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc; 6936459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 6946459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6956459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 6966459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee // Now, try in the other direction 697fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) { 698fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t dex_pc = cu->dex2pcMappingTable[i+1]; 699311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (cu->mir_graph->catches_.find(dex_pc) == cu->mir_graph->catches_.end()) { 700fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc; 7016459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee success = false; 7026459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 7036459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 7046459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee if (!success) { 705fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu->method_idx, *cu->dex_file); 706311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee LOG(INFO) << "Entries @ decode: " << cu->mir_graph->catches_.size() << ", Entries in table: " 707fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << cu->dex2pcMappingTable.size()/2; 7086459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee } 7096459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee return success; 7106459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee} 7116459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee 712311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee 713fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateMappingTables(CompilationUnit* cu) 714e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 715fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (LIR* tgt_lir = cu->first_lir_insn; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) { 716fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) { 717fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->pc2dexMappingTable.push_back(tgt_lir->offset); 718fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->pc2dexMappingTable.push_back(tgt_lir->dalvik_offset); 719a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee } 720fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) { 721fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex2pcMappingTable.push_back(tgt_lir->offset); 722fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex2pcMappingTable.push_back(tgt_lir->dalvik_offset); 723e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 724a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (kIsDebugBuild) { 726311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee DCHECK(VerifyCatchEntries(cu)); 727311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee } 728fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size() + 729fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex2pcMappingTable.size()); 730fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size()); 731fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->combined_mapping_table.insert(cu->combined_mapping_table.end(), 732fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->pc2dexMappingTable.begin(), 733fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->pc2dexMappingTable.end()); 734fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->combined_mapping_table.insert(cu->combined_mapping_table.end(), 735fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex2pcMappingTable.begin(), 736fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->dex2pcMappingTable.end()); 737e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 738e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 7390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder { 7400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public: 7410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers NativePcToReferenceMapBuilder(std::vector<uint8_t>* table, 7420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t entries, uint32_t max_native_offset, 7430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t references_width) : entries_(entries), 7440c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers references_width_(references_width), in_use_(entries), 7450c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_(table) { 7460c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute width in bytes needed to hold max_native_offset. 7470c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_ = 0; 7480c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (max_native_offset != 0) { 7490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset_width_++; 7500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset >>= 8; 7510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Resize table and set up header. 7530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table->resize((EntryWidth() * entries) + sizeof(uint32_t)); 754000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(native_offset_width_, 1U << 3); 755000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] = native_offset_width_ & 7; 756000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers CHECK_LT(references_width_, 1U << 13); 757000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[0] |= (references_width_ << 3) & 0xFF; 758000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers (*table)[1] = (references_width_ >> 5) & 0xFF; 7590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers CHECK_LT(entries, 1U << 16); 7600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[2] = entries & 0xFF; 7610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table)[3] = (entries >> 8) & 0xFF; 7620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void AddEntry(uint32_t native_offset, const uint8_t* references) { 7650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_index = TableIndex(native_offset); 7660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers while (in_use_[table_index]) { 7670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers table_index = (table_index + 1) % entries_; 7680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers in_use_[table_index] = true; 7700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetNativeOffset(table_index, native_offset); 7710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers DCHECK_EQ(native_offset, GetNativeOffset(table_index)); 7720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers SetReferences(table_index, references); 7730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private: 7760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t TableIndex(uint32_t native_offset) { 7770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_; 7780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t GetNativeOffset(size_t table_index) { 7810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = 0; 7820c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 7840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers native_offset |= (*table_)[table_offset + i] << (i * 8); 7850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset; 7870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetNativeOffset(size_t table_index, uint32_t native_offset) { 7900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < native_offset_width_; i++) { 7920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF; 7930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 7950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 7960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers void SetReferences(size_t table_index, const uint8_t* references) { 7970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); 7980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_); 7990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 8010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t EntryWidth() const { 8020c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers return native_offset_width_ + references_width_; 8030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 8050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of entries in the table. 8060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t entries_; 8070c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode the reference bitmap. 8080c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const size_t references_width_; 8090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Number of bytes used to encode a native offset. 8100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers size_t native_offset_width_; 8110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Entries that are in use. 8120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<bool> in_use_; 8130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // The table we're building. 8140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers std::vector<uint8_t>* const table_; 8150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}; 8160c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 817fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateNativeGcMap(CompilationUnit* cu) { 818fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const std::vector<uint32_t>& mapping_table = cu->pc2dexMappingTable; 8190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t max_native_offset = 0; 8200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 8210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 8220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers if (native_offset > max_native_offset) { 8230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers max_native_offset = native_offset; 8240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8261212a022fa5f8ef9585d765b1809521812af882cIan Rogers CompilerDriver::MethodReference method_ref(cu->dex_file, cu->method_idx); 8270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref); 8280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4); 8290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Compute native offset to references size. 830fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee NativePcToReferenceMapBuilder native_gc_map_builder(&cu->native_gc_map, 8310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers mapping_table.size() / 2, max_native_offset, 8320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers dex_gc_map.RegWidth()); 8330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 8340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers for (size_t i = 0; i < mapping_table.size(); i += 2) { 8350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t native_offset = mapping_table[i + 0]; 8360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers uint32_t dex_pc = mapping_table[i + 1]; 8370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false); 838a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc; 839a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee native_gc_map_builder.AddEntry(native_offset, references); 8400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers } 8410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers} 8420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 843e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */ 844fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignLiteralOffset(CompilationUnit* cu, int offset) 845e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 846fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignLiteralOffsetCommon(cu->literal_list, offset); 847fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignLiteralOffsetCommon(cu->code_literal_list, offset); 848fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignLiteralOffsetCommon(cu->method_literal_list, offset); 849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 850e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 851e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 852fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignSwitchTablesOffset(CompilationUnit* cu, int offset) 853e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 854a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 855fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee GrowableListIteratorInit(&cu->switch_tables, &iterator); 856a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 857311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Codegen::SwitchTable *tab_rec = 858311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator)); 859fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 860fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->offset = offset; 861fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 862fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->table[1] * (sizeof(int) * 2); 863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 864fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee DCHECK_EQ(static_cast<int>(tab_rec->table[0]), 865a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee static_cast<int>(Instruction::kPackedSwitchSignature)); 866fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->table[1] * sizeof(int); 867e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 868a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 870e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 871e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 872fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignFillArrayDataOffset(CompilationUnit* cu, int offset) 873e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 874a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 875fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee GrowableListIteratorInit(&cu->fill_array_data, &iterator); 876a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 877311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Codegen::FillArrayData *tab_rec = 878311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext(&iterator)); 879fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 880fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->offset = offset; 881fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset += tab_rec->size; 882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // word align 883a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 884a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 885a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee return offset; 886e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 887e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 888a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee// LIR offset assignment. 889a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbeestatic int AssignInsnOffsets(CompilationUnit* cu) 890a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee{ 891a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee LIR* lir; 892a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee int offset = 0; 893a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 894a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) { 895a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->offset = offset; 896a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (lir->opcode >= 0) { 897a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (!lir->flags.is_nop) { 898a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee offset += lir->flags.size; 899a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 900a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } else if (lir->opcode == kPseudoPseudoAlign4) { 901a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee if (offset & 0x2) { 902a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee offset += 2; 903a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->operands[0] = 1; 904a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } else { 905a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee lir->operands[0] = 0; 906a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 907a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 908a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee /* Pseudo opcodes don't consume space */ 909a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee } 910a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 911a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee return offset; 912a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee} 913a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee 914e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 915e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions 916e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit. 917e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 918fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void AssignOffsets(CompilationUnit* cu) 919e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 920a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee int offset = AssignInsnOffsets(cu); 921e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 922a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Const values have to be word aligned */ 923a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee offset = (offset + 3) & ~3; 924e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 925a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* Set up offsets for literals */ 926fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->data_offset = offset; 927e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 928fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignLiteralOffset(cu, offset); 929e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 930fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignSwitchTablesOffset(cu, offset); 931e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 932fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee offset = AssignFillArrayDataOffset(cu, offset); 933e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 934fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->total_size = offset; 935e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 936e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 937e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* 938e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top 939e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is 940e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it. 941e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */ 942fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid AssembleLIR(CompilationUnit* cu) 943e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{ 94402031b185b4653e6c72e21f7a51238b903f6d638buzbee Codegen* cg = cu->cg.get(); 945fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AssignOffsets(cu); 946311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee int assembler_retries = 0; 947a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 948a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Assemble here. Note that we generate code with optimistic assumptions 949a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * and if found now to work, we'll have to redo the sequence and retry. 950a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 951e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 952a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 95302031b185b4653e6c72e21f7a51238b903f6d638buzbee AssemblerStatus res = cg->AssembleInstructions(cu, 0); 954a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee if (res == kSuccess) { 955a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee break; 956a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 957311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee assembler_retries++; 958311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee if (assembler_retries > MAX_ASSEMBLER_RETRIES) { 959fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee CodegenDump(cu); 960a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Assembler error - too many retries"; 961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 962a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Redo offsets and try again 963fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee AssignOffsets(cu); 964fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->code_buffer.clear(); 965e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee } 966a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 967e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install literals 969fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee InstallLiteralPools(cu); 970e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install switch tables 972fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee InstallSwitchTables(cu); 973e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee // Install fill array data 975fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee InstallFillArrayData(cu); 976e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 9770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers // Create the mapping table and native offset to reference map. 978fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee CreateMappingTables(cu); 9790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers 980fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee CreateNativeGcMap(cu); 981e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee} 982e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 98331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* 98431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik 98531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr. This label will be used to fix up the case 98631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase. Be sure to set 98731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across 98831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries. KeyVal is just there for debugging. 98931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */ 990fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic LIR* InsertCaseLabel(CompilationUnit* cu, int vaddr, int keyVal) 99131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 992a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee SafeMap<unsigned int, LIR*>::iterator it; 993fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee it = cu->boundary_map.find(vaddr); 994fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (it == cu->boundary_map.end()) { 995a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; 996a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 997fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* new_label = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR)); 998fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->dalvik_offset = vaddr; 999fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->opcode = kPseudoCaseLabel; 1000fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee new_label->operands[0] = keyVal; 1001fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee InsertLIRAfter(it->second, new_label); 1002fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return new_label; 100331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 100431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 1005311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeestatic void MarkPackedCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec) 100631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 1007fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const uint16_t* table = tab_rec->table; 1008fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int base_vaddr = tab_rec->vaddr; 1009cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int *targets = reinterpret_cast<const int*>(&table[4]); 1010a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 1011fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 1012a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1013fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], i + low_key); 1014a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 101531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 101631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 1017311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeestatic void MarkSparseCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec) 101831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 1019fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const uint16_t* table = tab_rec->table; 1020fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int base_vaddr = tab_rec->vaddr; 1021a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 1022cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 1023cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 1024a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1025fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], keys[i]); 1026a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 102731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 102831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 1029fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid ProcessSwitchTables(CompilationUnit* cu) 103031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{ 1031a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee GrowableListIterator iterator; 1032fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee GrowableListIteratorInit(&cu->switch_tables, &iterator); 1033a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee while (true) { 1034311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee Codegen::SwitchTable *tab_rec = 1035311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator)); 1036fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec == NULL) break; 1037fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) { 1038fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee MarkPackedCaseLabels(cu, tab_rec); 1039fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) { 1040fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee MarkSparseCaseLabels(cu, tab_rec); 1041a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } else { 1042a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(FATAL) << "Invalid switch table"; 104331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee } 1044a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 104531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 104631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 104752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpSparseSwitchTable(const uint16_t* table) 1048a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 1049a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Sparse switch data format: 1050a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0200 magic value 1051a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table; > 0 1052a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int keys[size] keys, sorted low-to-high; 32-bit aligned 1053a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 1054a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 1055a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (2+size*4) 16-bit code units. 1056a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 1057a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 1058eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 1059a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 1060cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* keys = reinterpret_cast<const int*>(&table[2]); 1061cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = &keys[entries]; 1062a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident 1063a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << ", entries: " << std::dec << entries; 1064a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1065a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i]; 1066a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 106731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 106831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee 106952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpPackedSwitchTable(const uint16_t* table) 1070a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee /* 1071a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Packed switch data format: 1072a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort ident = 0x0100 magic value 1073a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * ushort size number of entries in the table 1074a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int first_key first (and lowest) switch case value 1075a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * int targets[size] branch targets, relative to switch opcode 1076a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * 1077a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee * Total size is (4+size*2) 16-bit code units. 1078a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee */ 1079a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{ 1080eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint16_t ident = table[0]; 1081cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee const int* targets = reinterpret_cast<const int*>(&table[4]); 1082a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee int entries = table[1]; 1083fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 1084a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident 1085fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee << ", entries: " << std::dec << entries << ", low_key: " << low_key; 1086a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee for (int i = 0; i < entries; i++) { 1087fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LOG(INFO) << " Key[" << (i + low_key) << "] -> 0x" << std::hex 1088a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee << targets[i]; 1089a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee } 109031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee} 1091e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 1092d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/* 1093d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and 1094fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * record it in the boundary_map. NOTE: in cases such as kMirOpCheck in 1095d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op 1096d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map. 1097d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */ 1098fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str) 1099d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee{ 1100fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee LIR* res = NewLIR1(cu, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str)); 1101fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (cu->boundary_map.find(offset) == cu->boundary_map.end()) { 1102fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee cu->boundary_map.Put(offset, res); 1103d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee } 1104d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee return res; 1105d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee} 1106e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee 1107e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbeebool EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) 1108e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee{ 1109e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee bool is_taken; 1110e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee switch (opcode) { 1111e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_EQ: is_taken = (src1 == src2); break; 1112e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_NE: is_taken = (src1 != src2); break; 1113e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LT: is_taken = (src1 < src2); break; 1114e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GE: is_taken = (src1 >= src2); break; 1115e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GT: is_taken = (src1 > src2); break; 1116e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LE: is_taken = (src1 <= src2); break; 1117e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_EQZ: is_taken = (src1 == 0); break; 1118e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_NEZ: is_taken = (src1 != 0); break; 1119e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LTZ: is_taken = (src1 < 0); break; 1120e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GEZ: is_taken = (src1 >= 0); break; 1121e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_GTZ: is_taken = (src1 > 0); break; 1122e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee case Instruction::IF_LEZ: is_taken = (src1 <= 0); break; 1123e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee default: 1124e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee LOG(FATAL) << "Unexpected opcode " << opcode; 1125e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee is_taken = false; 1126e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee } 1127e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee return is_taken; 1128e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee} 1129e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee 11304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee// Convert relation of src1/src2 to src2/src1 11314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbeeConditionCode FlipComparisonOrder(ConditionCode before) { 11324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee ConditionCode res; 11334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee switch (before) { 11344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondEq: res = kCondEq; break; 11354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondNe: res = kCondNe; break; 11364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondLt: res = kCondGt; break; 11374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondGt: res = kCondLt; break; 11384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondLe: res = kCondGe; break; 11394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee case kCondGe: res = kCondLe; break; 11404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee default: 11414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee res = static_cast<ConditionCode>(0); 11424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee LOG(FATAL) << "Unexpected ccode " << before; 11434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee } 11444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee return res; 11454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee} 11464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee 1147a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee} // namespace art 1148