call_arm.cc revision 2ce745c06271d5223d57dbf08117b20d5b60694a
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2011 The Android Open Source Project 3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License. 6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at 7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * http://www.apache.org/licenses/LICENSE-2.0 9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software 11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS, 12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and 14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License. 15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 17efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* This file contains codegen for the Thumb2 ISA. */ 18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 191bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h" 2002031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h" 217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 22641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "oat/runtime/oat_support_entrypoints.h" 23efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 24efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 25efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 27efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Return the position of an ssa name within the argument list */ 282ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint ArmMir2Lir::InPosition(int s_reg) { 291fd3346740dfb7f47be9922312b68a4227fada96buzbee int v_reg = mir_graph_->SRegToVReg(s_reg); 301fd3346740dfb7f47be9922312b68a4227fada96buzbee return v_reg - cu_->num_regs; 31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Describe an argument. If it's already in an arg register, just leave it 35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * there. NOTE: all live arg registers must be locked prior to this call 36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * to avoid having them allocated as a temp by downstream utilities. 37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 382ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation ArmMir2Lir::ArgLoc(RegLocation loc) { 391fd3346740dfb7f47be9922312b68a4227fada96buzbee int arg_num = InPosition(loc.s_reg_low); 40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (loc.wide) { 41fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (arg_num == 2) { 42efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Bad case - half in register, half in frame. Just punt 43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocInvalid; 44fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee } else if (arg_num < 2) { 45fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee loc.low_reg = rARM_ARG1 + arg_num; 46fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee loc.high_reg = loc.low_reg + 1; 47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocPhysReg; 48efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 49efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocDalvikFrame; 50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 51efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 52fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (arg_num < 3) { 53fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee loc.low_reg = rARM_ARG1 + arg_num; 54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocPhysReg; 55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 56efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocDalvikFrame; 57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return loc; 60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Load an argument. If already in a register, just return. If in 6452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee * the frame, we can't use the normal LoadValue() because it assumed 65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * a proper frame - and we're frameless. 66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 672ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation ArmMir2Lir::LoadArg(RegLocation loc) { 68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (loc.location == kLocDalvikFrame) { 691fd3346740dfb7f47be9922312b68a4227fada96buzbee int start = (InPosition(loc.s_reg_low) + 1) * sizeof(uint32_t); 701fd3346740dfb7f47be9922312b68a4227fada96buzbee loc.low_reg = AllocTemp(); 711fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SP, start, loc.low_reg); 72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (loc.wide) { 731fd3346740dfb7f47be9922312b68a4227fada96buzbee loc.high_reg = AllocTemp(); 741fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SP, start + sizeof(uint32_t), loc.high_reg); 75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loc.location = kLocPhysReg; 77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return loc; 79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Lock any referenced arguments that arrive in registers */ 822ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::LockLiveArgs(MIR* mir) { 831fd3346740dfb7f47be9922312b68a4227fada96buzbee int first_in = cu_->num_regs; 84fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee const int num_arg_regs = 3; // TODO: generalize & move to RegUtil.cc 85fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee for (int i = 0; i < mir->ssa_rep->num_uses; i++) { 861fd3346740dfb7f47be9922312b68a4227fada96buzbee int v_reg = mir_graph_->SRegToVReg(mir->ssa_rep->uses[i]); 87fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int InPosition = v_reg - first_in; 88fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (InPosition < num_arg_regs) { 891fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(rARM_ARG1 + InPosition); 90efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 91efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 92efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 93efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 94efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Find the next MIR, which may be in a following basic block */ 951fd3346740dfb7f47be9922312b68a4227fada96buzbee// TODO: should this be a utility in mir_graph? 962ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromMIR* ArmMir2Lir::GetNextMir(BasicBlock** p_bb, MIR* mir) { 97fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee BasicBlock* bb = *p_bb; 98fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee MIR* orig_mir = mir; 99efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (bb != NULL) { 100efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mir != NULL) { 101efc6369224b036a1fb77849f7ae65b3492c832c0buzbee mir = mir->next; 102efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 103efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mir != NULL) { 104efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return mir; 105efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 106fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bb = bb->fall_through; 107fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee *p_bb = bb; 108efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (bb) { 109fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee mir = bb->first_mir_insn; 110efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mir != NULL) { 111efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return mir; 112efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 113efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 114efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 115efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 116fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee return orig_mir; 117efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 118efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 119fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee/* Used for the "verbose" listing */ 12002031b185b4653e6c72e21f7a51238b903f6d638buzbee//TODO: move to common code 1212ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenPrintLabel(MIR* mir) { 122efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Mark the beginning of a Dalvik instruction for line tracking */ 1231fd3346740dfb7f47be9922312b68a4227fada96buzbee char* inst_str = cu_->verbose ? 1241fd3346740dfb7f47be9922312b68a4227fada96buzbee mir_graph_->GetDalvikDisassembly(mir) : NULL; 1251fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkBoundary(mir->offset, inst_str); 126efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 127efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1281fd3346740dfb7f47be9922312b68a4227fada96buzbeeMIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, 1292ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom OpSize size, bool long_or_double, bool is_object) { 130fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int field_offset; 131fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool is_volatile; 132fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t field_idx = mir->dalvikInsn.vC; 1331fd3346740dfb7f47be9922312b68a4227fada96buzbee bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false); 134fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) { 135efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return NULL; 136efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 1371fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_obj = mir_graph_->GetSrc(mir, 0); 1381fd3346740dfb7f47be9922312b68a4227fada96buzbee LockLiveArgs(mir); 1391fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = ArmMir2Lir::ArgLoc(rl_obj); 140fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_dest; 141fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (long_or_double) { 1421fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_dest = GetReturnWide(false); 143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 1441fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_dest = GetReturn(false); 145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 146efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Point of no return - no aborts after this 1471fd3346740dfb7f47be9922312b68a4227fada96buzbee ArmMir2Lir::GenPrintLabel(mir); 1481fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = LoadArg(rl_obj); 1491fd3346740dfb7f47be9922312b68a4227fada96buzbee GenIGet(field_idx, mir->optimization_flags, size, rl_dest, rl_obj, long_or_double, is_object); 1501fd3346740dfb7f47be9922312b68a4227fada96buzbee return GetNextMir(bb, mir); 151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1531fd3346740dfb7f47be9922312b68a4227fada96buzbeeMIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, 1542ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom OpSize size, bool long_or_double, bool is_object) { 155fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int field_offset; 156fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool is_volatile; 157fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t field_idx = mir->dalvikInsn.vC; 1581fd3346740dfb7f47be9922312b68a4227fada96buzbee bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false); 159fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) { 160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return NULL; 161efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 162fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src; 163fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_obj; 1641fd3346740dfb7f47be9922312b68a4227fada96buzbee LockLiveArgs(mir); 165fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (long_or_double) { 1661fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = mir_graph_->GetSrcWide(mir, 0); 1671fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = mir_graph_->GetSrc(mir, 2); 168efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 1691fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = mir_graph_->GetSrc(mir, 0); 1701fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = mir_graph_->GetSrc(mir, 1); 171efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 1721fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = ArmMir2Lir::ArgLoc(rl_src); 1731fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = ArmMir2Lir::ArgLoc(rl_obj); 174efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Reject if source is split across registers & frame 175fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_obj.location == kLocInvalid) { 1761fd3346740dfb7f47be9922312b68a4227fada96buzbee ResetRegPool(); 177efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return NULL; 178efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Point of no return - no aborts after this 1801fd3346740dfb7f47be9922312b68a4227fada96buzbee ArmMir2Lir::GenPrintLabel(mir); 1811fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_obj = LoadArg(rl_obj); 1821fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadArg(rl_src); 1831fd3346740dfb7f47be9922312b68a4227fada96buzbee GenIPut(field_idx, mir->optimization_flags, size, rl_src, rl_obj, long_or_double, is_object); 1841fd3346740dfb7f47be9922312b68a4227fada96buzbee return GetNextMir(bb, mir); 185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1872ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromMIR* ArmMir2Lir::SpecialIdentity(MIR* mir) { 188fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_src; 189fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee RegLocation rl_dest; 190fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee bool wide = (mir->ssa_rep->num_uses == 2); 191efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (wide) { 1921fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = mir_graph_->GetSrcWide(mir, 0); 1931fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_dest = GetReturnWide(false); 194efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 1951fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = mir_graph_->GetSrc(mir, 0); 1961fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_dest = GetReturn(false); 197efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 1981fd3346740dfb7f47be9922312b68a4227fada96buzbee LockLiveArgs(mir); 1991fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = ArmMir2Lir::ArgLoc(rl_src); 200fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (rl_src.location == kLocInvalid) { 2011fd3346740dfb7f47be9922312b68a4227fada96buzbee ResetRegPool(); 202efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return NULL; 203efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Point of no return - no aborts after this 2051fd3346740dfb7f47be9922312b68a4227fada96buzbee ArmMir2Lir::GenPrintLabel(mir); 2061fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadArg(rl_src); 207efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (wide) { 2081fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValueWide(rl_dest, rl_src); 209efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 2101fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_src); 211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return mir; 213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 214efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 215efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Special-case code genration for simple non-throwing leaf methods. 217efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 2181fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, 2192ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom SpecialCaseHandler special_case) { 2201fd3346740dfb7f47be9922312b68a4227fada96buzbee current_dalvik_offset_ = mir->offset; 221fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee MIR* next_mir = NULL; 222fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee switch (special_case) { 223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kNullMethod: 224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID); 225fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee next_mir = mir; 226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kConstFunction: 2281fd3346740dfb7f47be9922312b68a4227fada96buzbee ArmMir2Lir::GenPrintLabel(mir); 2291fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadConstant(rARM_RET0, mir->dalvikInsn.vB); 2301fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = GetNextMir(&bb, mir); 231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 232efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGet: 2331fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kWord, false, false); 234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetBoolean: 236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetByte: 2371fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kUnsignedByte, false, false); 238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetObject: 2401fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kWord, false, true); 241efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetChar: 2431fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kUnsignedHalf, false, false); 244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetShort: 2461fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kSignedHalf, false, false); 247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIGetWide: 2491fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIGet(&bb, mir, kLong, true, false); 250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPut: 2521fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kWord, false, false); 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutBoolean: 255efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutByte: 2561fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kUnsignedByte, false, false); 257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutObject: 2591fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kWord, false, true); 260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutChar: 2621fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kUnsignedHalf, false, false); 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutShort: 2651fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kSignedHalf, false, false); 266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIPutWide: 2681fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIPut(&bb, mir, kLong, true, false); 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kIdentity: 2711fd3346740dfb7f47be9922312b68a4227fada96buzbee next_mir = SpecialIdentity(mir); 272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 276fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (next_mir != NULL) { 2771fd3346740dfb7f47be9922312b68a4227fada96buzbee current_dalvik_offset_ = next_mir->offset; 278fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (special_case != kIdentity) { 2791fd3346740dfb7f47be9922312b68a4227fada96buzbee ArmMir2Lir::GenPrintLabel(next_mir); 280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 2811fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumbBx, rARM_LR); 2821fd3346740dfb7f47be9922312b68a4227fada96buzbee core_spill_mask_ = 0; 2831fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_ = 0; 2841fd3346740dfb7f47be9922312b68a4227fada96buzbee fp_spill_mask_ = 0; 2851fd3346740dfb7f47be9922312b68a4227fada96buzbee num_fp_spills_ = 0; 2861fd3346740dfb7f47be9922312b68a4227fada96buzbee frame_size_ = 0; 2871fd3346740dfb7f47be9922312b68a4227fada96buzbee core_vmap_table_.clear(); 2881fd3346740dfb7f47be9922312b68a4227fada96buzbee fp_vmap_table_.clear(); 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * The sparse table in the literal pool is an array of <key,displacement> 294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * pairs. For each set, we'll load them as a pair using ldmia. 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * This means that the register number of the temp we use for the key 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * must be lower than the reg for the displacement. 297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * The test loop will look something like: 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * adr rBase, <table> 301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * ldr r_val, [rARM_SP, v_reg_off] 302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov r_idx, #table_size 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * lp: 304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * ldmia rBase!, {r_key, r_disp} 305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * sub r_idx, #1 306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * cmp r_val, r_key 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ifeq 308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * add rARM_PC, r_disp ; This is the branch from which we compute displacement 309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * cbnz r_idx, lp 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3111fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenSparseSwitch(MIR* mir, uint32_t table_offset, 3122ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom RegLocation rl_src) { 3131fd3346740dfb7f47be9922312b68a4227fada96buzbee const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; 3141fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 31552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee DumpSparseSwitchTable(table); 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Add the table to the list - we'll process it later 318fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SwitchTable *tab_rec = 319862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee static_cast<SwitchTable*>(arena_->NewMem(sizeof(SwitchTable), true, 320862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator::kAllocData)); 321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->table = table; 3221fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->vaddr = current_dalvik_offset_; 323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int size = table[1]; 324862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee tab_rec->targets = static_cast<LIR**>(arena_->NewMem(size * sizeof(LIR*), true, 325862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator::kAllocLIR)); 326862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee switch_tables_.Insert(tab_rec); 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Get the switch value 3291fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 3301fd3346740dfb7f47be9922312b68a4227fada96buzbee int rBase = AllocTemp(); 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Allocate key and disp temps */ 3321fd3346740dfb7f47be9922312b68a4227fada96buzbee int r_key = AllocTemp(); 3331fd3346740dfb7f47be9922312b68a4227fada96buzbee int r_disp = AllocTemp(); 334fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee // Make sure r_key's register number is less than r_disp's number for ldmia 335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (r_key > r_disp) { 336fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int tmp = r_disp; 337fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee r_disp = r_key; 338fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee r_key = tmp; 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Materialize a pointer to the switch table 3411fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Adr, rBase, 0, reinterpret_cast<uintptr_t>(tab_rec)); 342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee // Set up r_idx 3431fd3346740dfb7f47be9922312b68a4227fada96buzbee int r_idx = AllocTemp(); 3441fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadConstant(r_idx, size); 345efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Establish loop branch target 3461fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* target = NewLIR0(kPseudoTargetLabel); 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Load next key/disp 3481fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR2(kThumb2LdmiaWB, rBase, (1 << r_key) | (1 << r_disp)); 3491fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegReg(kOpCmp, r_key, rl_src.low_reg); 350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Go if match. NOTE: No instruction set switch here - must stay Thumb2 3511fd3346740dfb7f47be9922312b68a4227fada96buzbee OpIT(kCondEq, ""); 3521fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* switch_branch = NewLIR1(kThumb2AddPCR, r_disp); 353fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->anchor = switch_branch; 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Needs to use setflags encoding here 3551fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2SubsRRI12, r_idx, r_idx, 1); 3561fd3346740dfb7f47be9922312b68a4227fada96buzbee OpCondBranch(kCondNe, target); 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3601fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset, 3612ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom RegLocation rl_src) { 3621fd3346740dfb7f47be9922312b68a4227fada96buzbee const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; 3631fd3346740dfb7f47be9922312b68a4227fada96buzbee if (cu_->verbose) { 36452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee DumpPackedSwitchTable(table); 365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Add the table to the list - we'll process it later 367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee SwitchTable *tab_rec = 368862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee static_cast<SwitchTable*>(arena_->NewMem(sizeof(SwitchTable), true, 369862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator::kAllocData)); 370fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->table = table; 3711fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->vaddr = current_dalvik_offset_; 372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int size = table[1]; 373862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee tab_rec->targets = 374862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee static_cast<LIR**>(arena_->NewMem(size * sizeof(LIR*), true, ArenaAllocator::kAllocLIR)); 375862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee switch_tables_.Insert(tab_rec); 376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Get the switch value 3781fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 3791fd3346740dfb7f47be9922312b68a4227fada96buzbee int table_base = AllocTemp(); 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Materialize a pointer to the switch table 3811fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Adr, table_base, 0, reinterpret_cast<uintptr_t>(tab_rec)); 382fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int keyReg; 384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Remove the bias, if necessary 385fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (low_key == 0) { 386fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee keyReg = rl_src.low_reg; 387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 3881fd3346740dfb7f47be9922312b68a4227fada96buzbee keyReg = AllocTemp(); 3891fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegRegImm(kOpSub, keyReg, rl_src.low_reg, low_key); 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Bounds check - if < 0 or >= size continue following switch 3921fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpCmp, keyReg, size-1); 3931fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_over = OpCondBranch(kCondHi, NULL); 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Load the displacement from the switch table 3961fd3346740dfb7f47be9922312b68a4227fada96buzbee int disp_reg = AllocTemp(); 3971fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadBaseIndexed(table_base, keyReg, disp_reg, 2, kWord); 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // ..and go! NOTE: No instruction set switch here - must stay Thumb2 4001fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* switch_branch = NewLIR1(kThumb2AddPCR, disp_reg); 401fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->anchor = switch_branch; 402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee /* branch_over target here */ 4041fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* target = NewLIR0(kPseudoTargetLabel); 405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch_over->target = target; 406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Array data table format: 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ushort ident = 0x0300 magic value 411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ushort width width of each element in the table 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * uint size number of elements in the table 413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ubyte data[size*width] table of data values (may contain a single-byte 414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * padding at the end) 415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Total size is 4+(width * size + 1)/2 16-bit code units. 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 4182ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src) { 4191fd3346740dfb7f47be9922312b68a4227fada96buzbee const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset; 420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Add the table to the list - we'll process it later 421fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee FillArrayData *tab_rec = 422862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee static_cast<FillArrayData*>(arena_->NewMem(sizeof(FillArrayData), true, 423862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator::kAllocData)); 424fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->table = table; 4251fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->vaddr = current_dalvik_offset_; 426fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint16_t width = tab_rec->table[1]; 427fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16); 428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->size = (size * width) + 8; 429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 430862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee fill_array_data_.Insert(tab_rec); 431efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Making a call - use explicit registers 4331fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushAllRegs(); /* Everything to home location */ 4341fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadValueDirectFixed(rl_src, r0); 4351fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), 436efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rARM_LR); 437efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Materialize a pointer to the fill data image 4381fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Adr, r1, 0, reinterpret_cast<uintptr_t>(tab_rec)); 4391fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberCalleeSave(); 4401fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* call_inst = OpReg(kOpBlx, rARM_LR); 4411fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkSafepointPC(call_inst); 442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Handle simple case (thin lock) inline. If it's complicated, bail 446efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * out to the heavyweight lock/unlock routines. We'll use dedicated 447efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * registers here in order to be in the right position in case we 448eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee * to bail to oat[Lock/Unlock]Object(self, object) 449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 450eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee * r0 -> self pointer [arg0 for oat[Lock/Unlock]Object 451eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee * r1 -> object [arg1 for oat[Lock/Unlock]Object 452efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * r2 -> intial contents of object->lock, later result of strex 453fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * r3 -> self->thread_id 454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * r12 -> allow to be used by utilities as general temp 455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 456efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * The result of the strex is 0 if we acquire the lock. 457efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 4589e1448a9c316baf44afac10208eaee32a163f914Sebastien Hertz * See comments in monitor.cc for the layout of the lock word. 459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Of particular interest to this code is the test for the 460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * simple case - which we handle inline. For monitor enter, the 461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * simple case is thin lock, held by no-one. For monitor exit, 462efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * the simple case is thin lock, held by the unlocking thread with 463efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * a recurse count of 0. 464efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A minor complication is that there is a field in the lock word 466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * unrelated to locking: the hash state. This field must be ignored, but 467efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * preserved. 468efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 469efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 4702ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) { 4711fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushAllRegs(); 472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(LW_SHAPE_THIN, 0); 4731fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadValueDirectFixed(rl_src, r0); // Get obj 4741fd3346740dfb7f47be9922312b68a4227fada96buzbee LockCallTemps(); // Prepare for explicit register usage 4751fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNullCheck(rl_src.s_reg_low, r0, opt_flags); 4761fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); 4771fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Ldrex, r1, r0, 4782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object::MonitorOffset().Int32Value() >> 2); // Get object->lock 479efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Align owner 4801fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT); 481fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee // Is lock unheld on lock or held by us (==thread_id) on unlock? 4821fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR4(kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1); 4831fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); 4841fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpCmp, r1, 0); 4851fd3346740dfb7f47be9922312b68a4227fada96buzbee OpIT(kCondEq, ""); 4861fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR4(kThumb2Strex, r1, r2, r0, 4872dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object::MonitorOffset().Int32Value() >> 2); 4881fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpCmp, r1, 0); 4891fd3346740dfb7f47be9922312b68a4227fada96buzbee OpIT(kCondNe, "T"); 490efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Go expensive route - artLockObjectFromCode(self, obj); 4911fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rARM_LR); 4921fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberCalleeSave(); 4931fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* call_inst = OpReg(kOpBlx, rARM_LR); 4941fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkSafepointPC(call_inst); 4951fd3346740dfb7f47be9922312b68a4227fada96buzbee GenMemBarrier(kLoadLoad); 496efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 497efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 498efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * For monitor unlock, we don't have to use ldrex/strex. Once 500efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * we've determined that the lock is thin and that we own it with 501efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * a zero recursion count, it's safe to punch it back to the 502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * initial, unlock thin state with a store word. 503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5042ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) { 505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(LW_SHAPE_THIN, 0); 5061fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushAllRegs(); 5071fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadValueDirectFixed(rl_src, r0); // Get obj 5081fd3346740dfb7f47be9922312b68a4227fada96buzbee LockCallTemps(); // Prepare for explicit register usage 5091fd3346740dfb7f47be9922312b68a4227fada96buzbee GenNullCheck(rl_src.s_reg_low, r0, opt_flags); 5101fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r1); // Get lock 5111fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2); 512fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee // Is lock unheld on lock or held by us (==thread_id) on unlock? 5131fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegRegImm(kOpAnd, r3, r1, 514efc6369224b036a1fb77849f7ae65b3492c832c0buzbee (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); 515efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Align owner 5161fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT); 5171fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); 5181fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegReg(kOpSub, r1, r2); 5191fd3346740dfb7f47be9922312b68a4227fada96buzbee OpIT(kCondEq, "EE"); 5201fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r3); 521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Go expensive route - UnlockObjectFromCode(obj); 5221fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR); 5231fd3346740dfb7f47be9922312b68a4227fada96buzbee ClobberCalleeSave(); 5241fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* call_inst = OpReg(kOpBlx, rARM_LR); 5251fd3346740dfb7f47be9922312b68a4227fada96buzbee MarkSafepointPC(call_inst); 5261fd3346740dfb7f47be9922312b68a4227fada96buzbee GenMemBarrier(kStoreLoad); 527efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5292ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenMoveException(RegLocation rl_dest) { 5301eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao int ex_offset = Thread::ExceptionOffset().Int32Value(); 5311fd3346740dfb7f47be9922312b68a4227fada96buzbee RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 5321fd3346740dfb7f47be9922312b68a4227fada96buzbee int reset_reg = AllocTemp(); 5331fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, ex_offset, rl_result.low_reg); 5341fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadConstant(reset_reg, 0); 5351fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreWordDisp(rARM_SELF, ex_offset, reset_reg); 5361fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(reset_reg); 5371fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 5381eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao} 5391eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao 540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Mark garbage collection card. Skip if the value we're storing is null. 542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5432ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) { 5441fd3346740dfb7f47be9922312b68a4227fada96buzbee int reg_card_base = AllocTemp(); 5451fd3346740dfb7f47be9922312b68a4227fada96buzbee int reg_card_no = AllocTemp(); 5461fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL); 5471fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base); 5481d54e73444e017d3a65234e0f193846f3e27472bIan Rogers OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift); 5491fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, 550efc6369224b036a1fb77849f7ae65b3492c832c0buzbee kUnsignedByte); 5511fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* target = NewLIR0(kPseudoTargetLabel); 552fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch_over->target = target; 5531fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(reg_card_base); 5541fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(reg_card_no); 555efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 556efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5572ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { 5581fd3346740dfb7f47be9922312b68a4227fada96buzbee int spill_count = num_core_spills_ + num_fp_spills_; 559efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 560efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * On entry, r0, r1, r2 & r3 are live. Let the register allocation 561efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * mechanism know so it doesn't try to use any of them when 562efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * expanding the frame or flushing. This leaves the utility 563efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * code with a single temp: r12. This should be enough. 564efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5651fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r0); 5661fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r1); 5671fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r2); 5681fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r3); 569efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 570efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 571efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * We can safely skip the stack overflow check if we're 572efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * a leaf *and* our frame size < fudge factor. 573efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5741fd3346740dfb7f47be9922312b68a4227fada96buzbee bool skip_overflow_check = (mir_graph_->MethodIsLeaf() && 5751fd3346740dfb7f47be9922312b68a4227fada96buzbee (static_cast<size_t>(frame_size_) < 576efc6369224b036a1fb77849f7ae65b3492c832c0buzbee Thread::kStackOverflowReservedBytes)); 5771fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kPseudoMethodEntry); 578fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!skip_overflow_check) { 579efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Load stack limit */ 5801fd3346740dfb7f47be9922312b68a4227fada96buzbee LoadWordDisp(rARM_SELF, Thread::StackEndOffset().Int32Value(), r12); 581efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 582efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Spill core callee saves */ 5831fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumb2Push, core_spill_mask_); 584efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Need to spill any FP regs? */ 5851fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_fp_spills_) { 586efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 587efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * NOTE: fp spills are a little different from core spills in that 588efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * they are pushed as a contiguous block. When promoting from 589efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * the fp set, we must allocate all singles from s16..highest-promoted 590efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5911fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumb2VPushCS, num_fp_spills_); 592efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 593fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!skip_overflow_check) { 5941fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegRegImm(kOpSub, rARM_LR, rARM_SP, frame_size_ - (spill_count * 4)); 5951fd3346740dfb7f47be9922312b68a4227fada96buzbee GenRegRegCheck(kCondCc, rARM_LR, r12, kThrowStackOverflow); 5961fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegCopy(rARM_SP, rARM_LR); // Establish stack 597efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 5981fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpSub, rARM_SP, frame_size_ - (spill_count * 4)); 599efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 600efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6011fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushIns(ArgLocs, rl_method); 602efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6031fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r0); 6041fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r1); 6051fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r2); 6061fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(r3); 607efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 608efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6092ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenExitSequence() { 6101fd3346740dfb7f47be9922312b68a4227fada96buzbee int spill_count = num_core_spills_ + num_fp_spills_; 611efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 612efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * In the exit path, r0/r1 are live - make sure they aren't 613efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * allocated by the register utilities as temps. 614efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 6151fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r0); 6161fd3346740dfb7f47be9922312b68a4227fada96buzbee LockTemp(r1); 617efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6181fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kPseudoMethodExit); 6191fd3346740dfb7f47be9922312b68a4227fada96buzbee OpRegImm(kOpAdd, rARM_SP, frame_size_ - (spill_count * 4)); 620efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Need to restore any FP callee saves? */ 6211fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_fp_spills_) { 6221fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumb2VPopCS, num_fp_spills_); 623efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 6241fd3346740dfb7f47be9922312b68a4227fada96buzbee if (core_spill_mask_ & (1 << rARM_LR)) { 625efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Unspill rARM_LR to rARM_PC */ 6261fd3346740dfb7f47be9922312b68a4227fada96buzbee core_spill_mask_ &= ~(1 << rARM_LR); 6271fd3346740dfb7f47be9922312b68a4227fada96buzbee core_spill_mask_ |= (1 << rARM_PC); 628efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 6291fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumb2Pop, core_spill_mask_); 6301fd3346740dfb7f47be9922312b68a4227fada96buzbee if (!(core_spill_mask_ & (1 << rARM_PC))) { 631efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* We didn't pop to rARM_PC, so must do a bv rARM_LR */ 6321fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR1(kThumbBx, rARM_LR); 633efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 634efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 635efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 636efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} // namespace art 637