10c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/* 20c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Copyright (C) 2012 The Android Open Source Project 30c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 40c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Licensed under the Apache License, Version 2.0 (the "License"); 50c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * you may not use this file except in compliance with the License. 60c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * You may obtain a copy of the License at 70c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 80c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * http://www.apache.org/licenses/LICENSE-2.0 90c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Unless required by applicable law or agreed to in writing, software 110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * distributed under the License is distributed on an "AS IS" BASIS, 120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * See the License for the specific language governing permissions and 140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * limitations under the License. 150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen */ 160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! \file LowerReturn.cpp 190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen \brief This file lowers the following bytecodes: RETURN 200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexOpcodes.h" 230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexFile.h" 240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "mterp/Mterp.h" 250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "Lower.h" 260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "enc_wrapper.h" 270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "NcgHelper.h" 280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//4 GPRs and scratch registers used in get_self_pointer, set_glue_method and set_glue_dvmdex 300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//will jump to "gotoBail" if caller method is NULL or if debugger is active 310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//what is %edx for each case? for the latter case, it is 1 320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_ECX //must be ecx 330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_EBX 340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_SCRATCH_1 PhysicalReg_EDX 350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_OLD_FP PhysicalReg_EAX 360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief common section to return from a method 380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the helper switch is on, this will generate a helper function 400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_returnFromMethod() { 420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#if defined(ENABLE_TRACING) && !defined(TRACING_OPTION2) 430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertMapWorklist(offsetPC, mapFromBCtoNCG[offsetPC], 1); //check when helper switch is on 440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_7; 470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(2, false); 480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //update rFP to caller stack frame 500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_FP, true, 10, false); 510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_prevFrame, PhysicalReg_FP, true, PhysicalReg_FP, true); //update rFP 520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get caller method by accessing the stack save area 530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_method, PhysicalReg_FP, true, 6, false); 540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, 6, false); 550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, "common_gotoBail_0", false); 560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(3, false); 570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //update glue->method 580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 6, false, offsetof(Thread, interpSave.method), 2, false); 590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get clazz of caller method 600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offMethod_clazz, 6, false, 14, false); 610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //update self->frame 620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_FP, true, offThread_curFrame, 3, false); 630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get method->clazz->pDvmDex 640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offClassObject_pDvmDex, 14, false, 7, false); 650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 7, false, offsetof(Thread, interpSave.methodClassDex), 2, false); 660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_mem(OpndSize_32, 0, offsetof(Thread, suspendCount), 2, false); /* suspendCount */ 680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_returnAddr, 10, false, PhysicalReg_EBX, true); 690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, 17, false); 700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* if suspendCount is not zero, clear the chaining cell address */ 710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_move_reg_to_reg(OpndSize_32, Condition_NZ, 17, false/*src*/, PhysicalReg_EBX, true/*dst*/); 720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_savedPc, 10, false, PhysicalReg_EAX, true); 730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if returnAddr is not NULL, the thread is still in code cache 740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EBX, true, offThread_inJitCodeCache, 3, false); 750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".LreturnToInterp", true); //local label 770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move rPC by 6 (3 bytecode units for INVOKE) 780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen alu_binary_imm_reg(OpndSize_32, add_opc, 6, PhysicalReg_EAX, true); 790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //returnAddr in %ebx, if not zero, jump to returnAddr 810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EBX, true); 820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".LcontinueToInterp", true); 830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_CALL_STACK3 840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_EBX, true, PhysicalReg_ESI, true); 850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0xaabb, PhysicalReg_EBX, true); 860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_EAX; 870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_debug_dumpSwitch(); //%ebx, %eax, %edx 880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_ESI, true, PhysicalReg_EBX, true); 890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_debug_dumpSwitch(); 900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_ESI, true, PhysicalReg_EBX, true); 910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_reg(PhysicalReg_EBX, true); 930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".LcontinueToInterp", true); 940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_4; 950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen typedef void (*vmHelper)(int); 960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen vmHelper funcPtr = dvmJitToInterpNoChainNoProfile; //%eax is the input 970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); 9819eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#if defined(WITH_JIT_TUNING) 9919eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji /* Return address not in code cache. Indicate that continuing with interpreter. 10019eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji */ 10119eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji move_imm_to_mem(OpndSize_32, kCallsiteInterpreted, 0, PhysicalReg_ESP, true); 10219eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#endif 1030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); 1040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen touchEax(); 1050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 1080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 1090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_SCRATCH_1 1100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode RETURN_VOID 1120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It seems that shared code cache does not support helper switch 1140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_return_void() { 1150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int retval; 1160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen retval = common_returnFromMethod(); 1170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 1180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return retval; 1190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode RETURN 1220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It seems that shared code cache does not support helper switch 1240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! The return value is stored to glue->retval first 1250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_return() { 1260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 1270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 22, false); 1290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 1300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_return_value(OpndSize_32, 22, false); 1310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_returnFromMethod(); 1330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 1340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode RETURN_WIDE 1380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It seems that shared code cache does not support helper switch 1400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! The return value is stored to glue->retval first 1410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_return_wide() { 1420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 1430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_64, 1, false); 1440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_10; scratchRegs[1] = PhysicalReg_Null; 1450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 1460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_return_value(OpndSize_64, 1, false); 1470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_returnFromMethod(); 1490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 1500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 152