call_x86.cc revision 72f53af0307b9109a1cfc0671675ce5d45c66d3a
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2012 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 X86 ISA */ 18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1902031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 200b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe 210b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h" 227940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 230b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "driver/compiler_driver.h" 24576ca0cd692c0b6ae70e776de91015b8ff000a08Ian Rogers#include "gc/accounting/card_table.h" 25f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko#include "mirror/art_method.h" 26f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko#include "mirror/object_array-inl.h" 27641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 281bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 29efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 30efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * The sparse table in the literal pool is an array of <key,displacement> 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * pairs. 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3548971b3242e5126bcd800cc9c68df64596b43d13Andreas Gampevoid X86Mir2Lir::GenLargeSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { 36da96aeda912ff317de2c41e5a49bd244427238acChao-ying Fu GenSmallSparseSwitch(mir, table_offset, rl_src); 37da96aeda912ff317de2c41e5a49bd244427238acChao-ying Fu} 38da96aeda912ff317de2c41e5a49bd244427238acChao-ying Fu 39da96aeda912ff317de2c41e5a49bd244427238acChao-ying Fu/* 40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Code pattern will look something like: 41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 42fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov r_val, .. 43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * call 0 44fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * pop r_start_of_method 45fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * sub r_start_of_method, .. 46fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov r_key_reg, r_val 47fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * sub r_key_reg, low_key 48fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * cmp r_key_reg, size-1 ; bound check 49efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ja done 50fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov r_disp, [r_start_of_method + r_key_reg * 4 + table_offset] 51fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * add r_start_of_method, r_disp 52fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * jmp r_start_of_method 53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done: 54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 5548971b3242e5126bcd800cc9c68df64596b43d13Andreas Gampevoid X86Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) { 5672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu const uint16_t* table = mir_graph_->GetTable(mir, table_offset); 57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Add the table to the list - we'll process it later 580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee SwitchTable* tab_rec = 5983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable), kArenaAllocData)); 6072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu tab_rec->switch_mir = mir; 61fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee tab_rec->table = table; 621fd3346740dfb7f47be9922312b68a4227fada96buzbee tab_rec->vaddr = current_dalvik_offset_; 63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int size = table[1]; 64e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko switch_tables_.push_back(tab_rec); 65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Get the switch value 671fd3346740dfb7f47be9922312b68a4227fada96buzbee rl_src = LoadValue(rl_src, kCoreReg); 6827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int low_key = s4FromSwitchData(&table[2]); 702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage keyReg; 71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Remove the bias, if necessary 72fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (low_key == 0) { 732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee keyReg = rl_src.reg; 74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 751fd3346740dfb7f47be9922312b68a4227fada96buzbee keyReg = AllocTemp(); 762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegRegImm(kOpSub, keyReg, rl_src.reg, low_key); 77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 7827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Bounds check - if < 0 or >= size continue following switch 80407a9d2847161b843966a443b71760b1280bd396Serguei Katkov OpRegImm(kOpCmp, keyReg, size - 1); 811fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* branch_over = OpCondBranch(kCondHi, NULL); 82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 8327dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell RegStorage addr_for_jump; 8427dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell if (cu_->target64) { 8527dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell RegStorage table_base = AllocTempWide(); 8627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Load the address of the table into table_base. 8727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell LIR* lea = RawLIR(current_dalvik_offset_, kX86Lea64RM, table_base.GetReg(), kRIPReg, 8827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 256, 0, WrapPointer(tab_rec)); 8927dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell lea->flags.fixup = kFixupSwitchTable; 9027dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell AppendLIR(lea); 9127dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 9227dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Load the offset from the table out of the table. 9327dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell addr_for_jump = AllocTempWide(); 9427dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell NewLIR5(kX86MovsxdRA, addr_for_jump.GetReg(), table_base.GetReg(), keyReg.GetReg(), 2, 0); 9527dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 9627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Add the offset from the table to the table base. 9727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell OpRegReg(kOpAdd, addr_for_jump, table_base); 9827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } else { 9927dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Materialize a pointer to the switch table. 10027dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell RegStorage start_of_method_reg; 10127dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell if (base_of_code_ != nullptr) { 10227dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // We can use the saved value. 10327dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 10427dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell rl_method = LoadValue(rl_method, kCoreReg); 10527dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell start_of_method_reg = rl_method.reg; 10627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell store_method_addr_used_ = true; 10727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } else { 10827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell start_of_method_reg = AllocTempRef(); 10927dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell NewLIR1(kX86StartOfMethod, start_of_method_reg.GetReg()); 11027dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } 11127dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Load the displacement from the switch table. 11227dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell addr_for_jump = AllocTemp(); 11327dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell NewLIR5(kX86PcRelLoadRA, addr_for_jump.GetReg(), start_of_method_reg.GetReg(), keyReg.GetReg(), 11427dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 2, WrapPointer(tab_rec)); 11527dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell // Add displacement to start of method. 11627dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell OpRegReg(kOpAdd, addr_for_jump, start_of_method_reg); 11727dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell } 11827dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell 119efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // ..and go! 12027dee8bcd7b4a53840b60818da8d2c819ef199bdMark Mendell tab_rec->anchor = NewLIR1(kX86JmpR, addr_for_jump.GetReg()); 121efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 122fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee /* branch_over target here */ 1231fd3346740dfb7f47be9922312b68a4227fada96buzbee LIR* target = NewLIR0(kPseudoTargetLabel); 124fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee branch_over->target = target; 125efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 126efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1272ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenMoveException(RegLocation rl_dest) { 12833ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee int ex_offset = cu_->target64 ? 1292f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe Thread::ExceptionOffset<8>().Int32Value() : 1302f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe Thread::ExceptionOffset<4>().Int32Value(); 131a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); 132407a9d2847161b843966a443b71760b1280bd396Serguei Katkov NewLIR2(cu_->target64 ? kX86Mov64RT : kX86Mov32RT, rl_result.reg.GetReg(), ex_offset); 133407a9d2847161b843966a443b71760b1280bd396Serguei Katkov NewLIR2(cu_->target64 ? kX86Mov64TI : kX86Mov32TI, ex_offset, 0); 1341fd3346740dfb7f47be9922312b68a4227fada96buzbee StoreValue(rl_dest, rl_result); 1351eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao} 1361eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao 137bf535be514570fc33fc0a6347a87dcd9097d9bfdVladimir Markovoid X86Mir2Lir::UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) { 138407a9d2847161b843966a443b71760b1280bd396Serguei Katkov DCHECK_EQ(tgt_addr_reg.Is64Bit(), cu_->target64); 139407a9d2847161b843966a443b71760b1280bd396Serguei Katkov RegStorage reg_card_base = AllocTempRef(); 140407a9d2847161b843966a443b71760b1280bd396Serguei Katkov RegStorage reg_card_no = AllocTempRef(); 14133ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee int ct_offset = cu_->target64 ? 1422f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe Thread::CardTableOffset<8>().Int32Value() : 1432f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe Thread::CardTableOffset<4>().Int32Value(); 144407a9d2847161b843966a443b71760b1280bd396Serguei Katkov NewLIR2(cu_->target64 ? kX86Mov64RT : kX86Mov32RT, reg_card_base.GetReg(), ct_offset); 1451d54e73444e017d3a65234e0f193846f3e27472bIan Rogers OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift); 1462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0, kUnsignedByte); 1471fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(reg_card_base); 1481fd3346740dfb7f47be9922312b68a4227fada96buzbee FreeTemp(reg_card_no); 149efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 150efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1512ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { 152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 153efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * On entry, rX86_ARG0, rX86_ARG1, rX86_ARG2 are live. Let the register 154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * allocation mechanism know so it doesn't try to use any of them when 155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * expanding the frame or flushing. This leaves the utility 156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * code with no spare temps. 157efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 158b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage arg0 = TargetReg32(kArg0); 159b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage arg1 = TargetReg32(kArg1); 160b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage arg2 = TargetReg32(kArg2); 161b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(arg0); 162b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(arg1); 163b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(arg2); 164efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 165efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 166efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * We can safely skip the stack overflow check if we're 167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * a leaf *and* our frame size < fudge factor. 168efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 169b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const InstructionSet isa = cu_->target64 ? kX86_64 : kX86; 170648d7112609dd19c38131b3e71c37bcbbd19d11eDave Allison bool skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_, isa); 171b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 17269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 17369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // If we doing an implicit stack overflow check, perform the load immediately 17469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // before the stack pointer is decremented and anything is saved. 17569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!skip_overflow_check && 17669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison cu_->compiler_driver->GetCompilerOptions().GetImplicitStackOverflowChecks()) { 17769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Implicit stack overflow check. 17869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // test eax,[esp + -overflow] 17969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison int overflow = GetStackOverflowReservedBytes(isa); 180b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers NewLIR3(kX86Test32RM, rs_rAX.GetReg(), rs_rSP.GetReg(), -overflow); 18169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison MarkPossibleStackOverflowException(); 18269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison } 18369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 18469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison /* Build frame, return address already on stack */ 185b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers stack_decrement_ = OpRegImm(kOpSub, rs_rSP, frame_size_ - 18669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison GetInstructionSetPointerSize(cu_->instruction_set)); 18769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 1881fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kPseudoMethodEntry); 189efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Spill core callee saves */ 1901fd3346740dfb7f47be9922312b68a4227fada96buzbee SpillCoreRegs(); 191c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov SpillFPRegs(); 192fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (!skip_overflow_check) { 1930d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier class StackOverflowSlowPath : public LIRSlowPath { 1940d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier public: 1950d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier StackOverflowSlowPath(Mir2Lir* m2l, LIR* branch, size_t sp_displace) 1960d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch, nullptr), sp_displace_(sp_displace) { 1970d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier } 1980d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier void Compile() OVERRIDE { 1990d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier m2l_->ResetRegPool(); 2000d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier m2l_->ResetDefTracking(); 2016ffcfa04ebb2660e238742a6000f5ccebdd5df15Mingyao Yang GenerateTargetLabel(kPseudoThrowTarget); 202b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage local_rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 203b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers m2l_->OpRegImm(kOpAdd, local_rs_rSP, sp_displace_); 2040d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier m2l_->ClobberCallerSave(); 2050d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier // Assumes codegen and target are in thumb2 mode. 206984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe m2l_->CallHelper(RegStorage::InvalidReg(), kQuickThrowStackOverflow, 207984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe false /* MarkSafepointPC */, false /* UseLink */); 2080d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier } 2090d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier 2100d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier private: 2110d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier const size_t sp_displace_; 2120d507d1e0441e6bd6f3affca3a60774ea920f317Mathieu Chartier }; 21369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitStackOverflowChecks()) { 21469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // TODO: for large frames we should do something like: 21569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // spill ebp 21669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // lea ebp, [esp + frame_size] 21769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // cmp ebp, fs:[stack_end_] 21869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // jcc stack_overflow_exception 21969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // mov esp, ebp 22069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // in case a signal comes in that's not using an alternate signal stack and the large frame 22169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // may have moved us outside of the reserved area at the end of the stack. 22269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // cmp rs_rX86_SP, fs:[stack_end_]; jcc throw_slowpath 22369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (cu_->target64) { 224b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers OpRegThreadMem(kOpCmp, rs_rX86_SP_64, Thread::StackEndOffset<8>()); 22569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison } else { 226b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers OpRegThreadMem(kOpCmp, rs_rX86_SP_32, Thread::StackEndOffset<4>()); 22769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison } 22869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison LIR* branch = OpCondBranch(kCondUlt, nullptr); 22969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison AddSlowPath( 230e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu new(arena_)StackOverflowSlowPath(this, branch, 231e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu frame_size_ - 232e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu GetInstructionSetPointerSize(cu_->instruction_set))); 23369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison } 234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2361fd3346740dfb7f47be9922312b68a4227fada96buzbee FlushIns(ArgLocs, rl_method); 237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 23867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell if (base_of_code_ != nullptr) { 239a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu RegStorage method_start = TargetPtrReg(kArg0); 24067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // We have been asked to save the address of the method start for later use. 241a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu setup_method_address_[0] = NewLIR1(kX86StartOfMethod, method_start.GetReg()); 24267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell int displacement = SRegOffset(base_of_code_->s_reg_low); 243695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee // Native pointer - must be natural word size. 244b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers setup_method_address_[1] = StoreBaseDisp(rs_rSP, displacement, method_start, 245dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina cu_->target64 ? k64 : k32, kNotVolatile); 24667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell } 24767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 248b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(arg0); 249b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(arg1); 250b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(arg2); 251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2531fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenExitSequence() { 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 255efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * In the exit path, rX86_RET0/rX86_RET1 are live - make sure they aren't 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * allocated by the register utilities as temps. 257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_RET0); 259091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_RET1); 260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2611fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kPseudoMethodExit); 2621fd3346740dfb7f47be9922312b68a4227fada96buzbee UnSpillCoreRegs(); 263c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov UnSpillFPRegs(); 264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Remove frame except for return address */ 265b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 266b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers stack_increment_ = OpRegImm(kOpAdd, rs_rSP, 267b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers frame_size_ - GetInstructionSetPointerSize(cu_->instruction_set)); 2681fd3346740dfb7f47be9922312b68a4227fada96buzbee NewLIR0(kX86Ret); 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2713bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoruvoid X86Mir2Lir::GenSpecialExitSequence() { 2723bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru NewLIR0(kX86Ret); 2733bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru} 2743bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru 27569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allisonvoid X86Mir2Lir::GenImplicitNullCheck(RegStorage reg, int opt_flags) { 27669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) { 27769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison return; 27869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison } 27969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Implicit null pointer check. 28069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // test eax,[arg1+0] 28169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison NewLIR3(kX86Test32RM, rs_rAX.GetReg(), reg.GetReg(), 0); 28269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison MarkPossibleNullPointerException(opt_flags); 28369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison} 28469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 285f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko/* 286f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko * Bit of a hack here - in the absence of a real scheduling pass, 287f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko * emit the next instruction in static & direct invoke sequences. 288f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko */ 289f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markostatic int X86NextSDCallInsn(CompilationUnit* cu, CallInfo* info, 290f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko int state, const MethodReference& target_method, 2916a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers uint32_t, 292f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko uintptr_t direct_code, uintptr_t direct_method, 293f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko InvokeType type) { 2946a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(info, direct_code); 295f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); 296f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (direct_method != 0) { 297f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko switch (state) { 298f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case 0: // Get the current Method* [sets kArg0] 299f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (direct_method != static_cast<uintptr_t>(-1)) { 300f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko cg->LoadConstant(cg->TargetReg(kArg0, kRef), direct_method); 301f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 302f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko cg->LoadMethodAddress(target_method, type, kArg0); 303f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 304f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 305f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko default: 306f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return -1; 307f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 308f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 309f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko RegStorage arg0_ref = cg->TargetReg(kArg0, kRef); 310f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko switch (state) { 311f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case 0: // Get the current Method* [sets kArg0] 312f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // TUNING: we can save a reg copy if Method* has been promoted. 313f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko cg->LoadCurrMethodDirect(arg0_ref); 314f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 315f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case 1: // Get method->dex_cache_resolved_methods_ 316f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko cg->LoadRefDisp(arg0_ref, 317f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(), 318f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko arg0_ref, 319f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko kNotVolatile); 320f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 321f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case 2: // Grab target method* 322f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko CHECK_EQ(cu->dex_file, target_method.dex_file); 323f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko cg->LoadRefDisp(arg0_ref, 324f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko mirror::ObjectArray<mirror::Object>::OffsetOfElement( 325f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko target_method.dex_method_index).Int32Value(), 326f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko arg0_ref, 327f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko kNotVolatile); 328f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 329f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko default: 330f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return -1; 331f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 332f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 333f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return state + 1; 334f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 335f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 336f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir MarkoNextCallInsn X86Mir2Lir::GetNextSDCallInsn() { 337f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return X86NextSDCallInsn; 338f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 339f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} // namespace art 341