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/*! \file LowerObject.cpp 180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen \brief This file lowers the following bytecodes: CHECK_CAST, 190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexOpcodes.h" 210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexFile.h" 220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "Lower.h" 230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "NcgAot.h" 240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "enc_wrapper.h" 250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenextern void markCard_filled(int tgtAddrReg, bool isTgtPhysical, int scratchReg, bool isScratchPhysical); 270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_ESI 310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode CHECK_CAST and INSTANCE_OF 320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! CALL class_resolve (%ebx is live across the call) 330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! dvmInstanceofNonTrivial 340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! NO register is live through function check_cast_helper 350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint check_cast_nohelper(u2 vA, u4 tmp, bool instance, u2 vDest) { 360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); //object 370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* for trace-based JIT, it is likely that the class is already resolved */ 390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool needToResolve = true; 400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ClassObject *classPtr = 410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen (currentMethod->clazz->pDvmDex->pResClasses[tmp]); 420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGV("in check_cast, class is resolved to %p", classPtr); 430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(classPtr != NULL) { 440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen needToResolve = false; 450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGV("check_cast class %s", classPtr->descriptor); 460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(needToResolve) { 480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get_res_classes is moved here for NCG O1 to improve performance of GLUE optimization 490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; scratchRegs[1] = PhysicalReg_SCRATCH_2; 500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_res_classes(4, false); 510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, 1, false); 530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(1); 550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //for private code cache, previously it jumped to .instance_of_okay_1 560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if object reference is null, jump to the handler for this special case 570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".instance_of_null", true); 590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".check_cast_null", true); 620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check whether the class is already resolved 640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if yes, jump to check_cast_resolved 650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if not, call class_resolve 660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(needToResolve) { 670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, tmp*4, 4, false, PhysicalReg_EAX, true); 680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) 700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".instance_of_resolved", true); 710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else 720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".check_cast_resolved", true); 730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //try to resolve the class 740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(2); 750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, tmp, PhysicalReg_EAX, true); 760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); //trying to resolve the class 770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_helper_API(".class_resolve"); 780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen transferToState(2); 790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } //needToResolve 800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* the class is already resolved and is constant */ 820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, (int)classPtr, PhysicalReg_EAX, true); 830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //class is resolved, and it is in %eax 850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!instance) { 860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".check_cast_resolved", true); 870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else insertLabel(".instance_of_resolved", true); 890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offObject_clazz, 1, false, 6, false); //object->clazz 910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //%eax: resolved class 930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //compare resolved class and object->clazz 940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if the same, jump to the handler for this special case 950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_reg_reg(PhysicalReg_EAX, true, 6, false); 960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(3); 970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".instance_of_equal", true); 990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 1000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".check_cast_equal", true); 1010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmInstanceofNonTrivial 1040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //INPUT: the resolved class & object reference 1050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 1060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 6, false, 0, PhysicalReg_ESP, true); 1070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EAX, true, 4, PhysicalReg_ESP, true); //resolved class 1080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_3; 1090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 2); //next version has 2 refs 1100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmInstanceofNonTrivial(); 1110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 1120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // 1130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 1140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move return value to P_GPR_2 1150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_EAX, true, 3, false); 1160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(4); 1170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump(".instance_of_okay", true); 1180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 1190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if return value of dvmInstanceofNonTrivial is zero, throw exception 1200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 1210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(4); 1220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".check_cast_okay", true); 1230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //two inputs for common_throw_message: object reference in eax, exception pointer in ecx 1240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 1); //next version has 1 ref 1250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, 1, false, PhysicalReg_EAX, true); 1260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_imm_global_data_API("strClassCastExceptionPtr", OpndSize_32, PhysicalReg_ECX, true); 1280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 ref count 1300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 1310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_global_API("common_throw_message", false); 1330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //handler for speical case where object reference is null 1350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) 1360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".instance_of_null", true); 1370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else insertLabel(".check_cast_null", true); 1380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen goToState(1); 1390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 1400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, 3, false); 1410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen transferToState(4); 1430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) 1440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump(".instance_of_okay", true); 1450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else 1460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump(".check_cast_okay", true); 1470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //handler for special case where class of object is the same as the resolved class 1490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) 1500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".instance_of_equal", true); 1510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else insertLabel(".check_cast_equal", true); 1520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen goToState(3); 1530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 1540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 1, 3, false); 1550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen transferToState(4); 1570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) 1580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".instance_of_okay", true); 1590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else insertLabel(".check_cast_okay", true); 1600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //all cases merge here and the value is put to virtual register 1610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(instance) { 1620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_virtual_reg(vDest, OpndSize_32, 3, false); 1630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! common code to lower CHECK_CAST & INSTANCE_OF 1670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 1690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_check_cast_instance_of(u2 vA, u4 tmp, bool instance, u2 vDest) { 1700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return check_cast_nohelper(vA, tmp, instance, vDest); 1710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 1730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 1740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 1750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode CHECK_CAST 1770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 1790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_check_cast() { 1800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 1810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 1820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_check_cast_instance_of(vA, tmp, false, 0); 1830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 1840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!LOWER bytecode INSTANCE_OF 1870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 1890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_instance_of() { 1900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 1910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 1920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 1930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_check_cast_instance_of(vB, tmp, true, vA); 1940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 1950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 1990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 2000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode MONITOR_ENTER without usage of helper function 2010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! CALL dvmLockObject 2030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint monitor_enter_nohelper(u2 vA) { 2040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 2050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen requestVRFreeDelay(vA,VRDELAY_NULLCHECK); // Request VR delay before transfer to temporary 2080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get_self_pointer is separated 2090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 2100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //to optimize redundant null check, NCG O1 wraps up null check in a function: nullCheck 2110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(3, false); 2120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nullCheck(1, false, 1, vA); //maybe optimized away 2130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen cancelVRFreeDelayRequest(vA,VRDELAY_NULLCHECK); 2140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ///////////////////////////// 2160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmLockObject, inputs: object reference and self 2170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // TODO: Should reset inJitCodeCache before calling dvmLockObject 2180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // so that code cache can be reset if needed when locking object 2190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // taking a long time. Not resetting inJitCodeCache may delay 2200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // code cache reset when code cache is full, preventing traces from 2210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // JIT compilation. This has performance implication. 2220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // However, after resetting inJitCodeCache, the code should be 2230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // wrapped in a helper instead of directly inlined in code cache. 2240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // If the code after dvmLockObject call is in code cache and the code 2250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // cache is reset during dvmLockObject call, execution after 2260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // dvmLockObject will return to a cleared code cache region, 2270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // resulting in seg fault. 2280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 1, false, 4, PhysicalReg_ESP, true); 2300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 3, false, 0, PhysicalReg_ESP, true); 2310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 2320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmLockObject(); 2330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ///////////////////////////// 2350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode MONITOR_ENTER 2380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It will use helper function if switch is on 2400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_monitor_enter() { 2410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 2420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 2430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen monitor_enter_nohelper(vA); 2440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 2450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 2480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 2490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 2510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 2520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode MONITOR_EXIT 2530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It will use helper function if switch is on 2550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_monitor_exit() { 2560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 2570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //////////////////// 2580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //LOWER bytecode MONITOR_EXIT without helper function 2590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // CALL dvmUnlockObject 2600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; scratchRegs[1] = PhysicalReg_SCRATCH_2; 2610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen requestVRFreeDelay(vA,VRDELAY_NULLCHECK); // Request VR delay before transfer to temporary 2630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 2640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nullCheck(1, false, 1, vA); //maybe optimized away 2650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen cancelVRFreeDelayRequest(vA,VRDELAY_NULLCHECK); 2660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ///////////////////////////// 2680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmUnlockObject, inputs: object reference and self 2690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen push_reg_to_stack(OpndSize_32, 1, false); 2700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen push_mem_to_stack(OpndSize_32, offEBP_self, PhysicalReg_EBP, true); 2710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 2720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmUnlockObject(); 2730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 2740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".unlock_object_done", true); 2770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //jump to dvmJitToExceptionThrown 2780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_3; 2790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToExceptionThrown(2/*exception number*/); 2800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".unlock_object_done", true); 2810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /////////////////////////// 2820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 2830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 2860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 2870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 2890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 2900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_EDX /*vA*/ 2910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode ARRAY_LENGTH 2920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It will use helper function if switch is on 2940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_array_length() { 2950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 2960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 2970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //////////////////// 2980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //no usage of helper function 2990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen requestVRFreeDelay(vB,VRDELAY_NULLCHECK); // Request VR delay before transfer to temporary 3000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vB, OpndSize_32, 1, false); 3010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nullCheck(1, false, 1, vB); //maybe optimized away 3020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen cancelVRFreeDelayRequest(vB,VRDELAY_NULLCHECK); 3030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offArrayObject_length, 1, false, 2, false); 3050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_virtual_reg(vA, OpndSize_32, 2, false); 3060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /////////////////////// 3070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 3080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 3090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 3110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 3120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 3130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 3150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 3160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_ESI 3170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode NEW_INSTANCE 3180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It will use helper function if switch is on 3200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_new_instance() { 3210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 3220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 3230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 3240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* for trace-based JIT, class is already resolved */ 3250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ClassObject *classPtr = 3260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen (currentMethod->clazz->pDvmDex->pResClasses[tmp]); 3270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(classPtr != NULL); 3280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(classPtr->status & CLASS_INITIALIZED); 3290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* 3300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * If it is going to throw, it should not make to the trace to begin 3310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * with. However, Alloc might throw, so we need to genExportPC() 3320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen */ 3330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0); 3340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmAllocObject, inputs: resolved class & flag ALLOC_DONT_TRACK 3350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 3360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* 1st argument to dvmAllocObject at -8(%esp) */ 3370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)classPtr, 0, PhysicalReg_ESP, true); 3380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, ALLOC_DONT_TRACK, 4, PhysicalReg_ESP, true); 3390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_3; 3400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 3); //next version has 3 refs 3410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmAllocObject(); 3420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 3430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //return value of dvmAllocObject is in %eax 3440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if return value is null, throw exception 3450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 3460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".new_instance_done", true); 3470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //jump to dvmJitToExceptionThrown 3480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_4; 3490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToExceptionThrown(3/*exception number*/); 3500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".new_instance_done", true); 3510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true); 3520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 3530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 3540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! function to initialize a class 3570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!INPUT: %eax (class object) %eax is recovered before return 3590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!OUTPUT: none 3600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!CALL: dvmInitClass 3610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!%eax, %esi, %ebx are live through function new_instance_needinit 3620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint new_instance_needinit() { 3630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".new_instance_needinit", false); 3640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 3650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EAX, true, 0, PhysicalReg_ESP, true); 3660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EAX, true, 4, PhysicalReg_ESP, true); 3670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_ECX; 3680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmInitClass(); 3690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if return value of dvmInitClass is zero, throw exception 3700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 3710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //recover EAX with the class object 3720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, 4, PhysicalReg_ESP, true, PhysicalReg_EAX, true); 3730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 3740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, "common_exceptionThrown", false); 3750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 3760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 3770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 3790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 3800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 3810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX //live through C function, must in callee-saved reg 3830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 3840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_EDX 3850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode NEW_ARRAY 3860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! It will use helper function if switch is on 3880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_new_array() { 3890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 3900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); //destination 3910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); //length 3920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ///////////////////////// 3930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // REGS used: %esi, %eax, P_GPR_1, P_GPR_2 3940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // CALL class_resolve, dvmAllocArrayByClass 3950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); //use %edx 3960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check size of the array, if negative, throw exception 3970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vB, OpndSize_32, 5, false); 3980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, 5, false); 3990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen handlePotentialException(Condition_S, Condition_NS, 4000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1, "common_errNegArraySize"); 4010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen void *classPtr = (void*) 4020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen (currentMethod->clazz->pDvmDex->pResClasses[tmp]); 4030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(classPtr != NULL); 4040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //here, class is already resolved, the class object is in %eax 4050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmAllocArrayByClass with inputs: resolved class, array length, flag ALLOC_DONT_TRACK 4060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".new_array_resolved", true); 4070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 4080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* 1st argument to dvmAllocArrayByClass at 0(%esp) */ 4090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)classPtr, 0, PhysicalReg_ESP, true); 4100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 5, false, 4, PhysicalReg_ESP, true); 4110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, ALLOC_DONT_TRACK, 8, PhysicalReg_ESP, true); 4120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_3; 4130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 3); //next version has 3 refs 4140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmAllocArrayByClass(); 4150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 4160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //the allocated object is in %eax 4180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check whether it is null, throw exception if null 4190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 4200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".new_array_done", true); 4210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //jump to dvmJitToExceptionThrown 4220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_4; 4230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToExceptionThrown(2/*exception number*/); 4240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".new_array_done", true); 4250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true); 4260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ////////////////////////////////////// 4270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 4280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 4290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 4300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 4310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 4320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 4330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 4350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_ECX 4360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_ESI 4370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! common code to lower FILLED_NEW_ARRAY 4380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! call: class_resolve call_dvmAllocPrimitiveArray 4400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! exception: filled_new_array_notimpl common_exceptionThrown 4410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_filled_new_array(u2 length, u4 tmp, bool hasRange) { 4420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ClassObject *classPtr = 4430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen (currentMethod->clazz->pDvmDex->pResClasses[tmp]); 4440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(classPtr != NULL) ALOGI("FILLED_NEW_ARRAY class %s", classPtr->descriptor); 4450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check whether class is resolved, if yes, jump to resolved 4460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if not, call class_resolve 4470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; scratchRegs[1] = PhysicalReg_SCRATCH_2; 4480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 4490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_res_classes(3, false); 4500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, tmp*4, 3, false, PhysicalReg_EAX, true); 4510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 4520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); //resolved class 4530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".filled_new_array_resolved", true); 4540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(1); 4550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, tmp, PhysicalReg_EAX, true); 4560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_helper_API(".class_resolve"); 4570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen transferToState(1); 4580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //here, class is already resolved 4590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".filled_new_array_resolved", true); 4600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check descriptor of the class object, if not implemented, throws exception 4610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, 24, PhysicalReg_EAX, true, 5, false); 4620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //load a single byte of the descriptor 4630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movez_mem_to_reg(OpndSize_8, 1, 5, false, 6, false); 4640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 'I', 6, false); 4650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".filled_new_array_impl", true); 4660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 'L', 6, false); 4670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".filled_new_array_impl", true); 4680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, '[', 6, false); 4690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".filled_new_array_notimpl", false); 4700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".filled_new_array_impl", true); 4720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmAllocArrayByClass with inputs: classObject, length, flag ALLOC_DONT_TRACK 4730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 4740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)classPtr, 0, PhysicalReg_ESP, true); 4750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, length, 4, PhysicalReg_ESP, true); 4760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, ALLOC_DONT_TRACK, 8, PhysicalReg_ESP, true); 4770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_3; scratchRegs[1] = PhysicalReg_Null; 4780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(hasRange) { 4790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 5+(length >= 1 ? LOOP_COUNT : 0)); //next version 4800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 4820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EAX, 5+length); //next version 4830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmAllocArrayByClass(); 4850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 4860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //return value of dvmAllocPrimitiveArray is in %eax 4870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if the return value is null, throw exception 4880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 4890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen handlePotentialException( 4900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Condition_E, Condition_NE, 4910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3, "common_exceptionThrown"); 4920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* we need to mark the card of the new array, if it's not an int */ 4940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 'I', 6, false); 4950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, ".dont_mark_filled_new_array", true); 4960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // Need to make copy of EAX, because it's used later in op_filled_new_array() 4980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_EAX, true, 6, false); 4990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen markCard_filled(6, false, PhysicalReg_SCRATCH_4, false); 5010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".dont_mark_filled_new_array", true); 5030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //return value of bytecode FILLED_NEW_ARRAY is in GLUE structure 5050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_4; scratchRegs[1] = PhysicalReg_Null; 5060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_return_value(OpndSize_32, PhysicalReg_EAX, true); 5070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 5080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode FILLED_NEW_ARRAY 5100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 5120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_filled_new_array() { 5130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 length = INST_B(inst); 5140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 5150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 v5 = INST_A(inst); 5160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vv = FETCH(2); 5170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 v1 = vv & 0xf; 5180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 v2 = (vv >> 4) & 0xf; 5190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 v3 = (vv >> 8) & 0xf; 5200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 v4 = (vv >> 12) & 0xf; 5210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_filled_new_array(length, tmp, false); 5220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 1) { 5230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move from virtual register to contents of array object 5240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(v1, OpndSize_32, 7, false); 5250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 7, false, offArrayObject_contents, PhysicalReg_EAX, true); 5260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 2) { 5280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move from virtual register to contents of array object 5290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(v2, OpndSize_32, 8, false); 5300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 8, false, offArrayObject_contents+4, PhysicalReg_EAX, true); 5310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 3) { 5330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move from virtual register to contents of array object 5340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(v3, OpndSize_32, 9, false); 5350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 9, false, offArrayObject_contents+8, PhysicalReg_EAX, true); 5360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 4) { 5380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move from virtual register to contents of array object 5390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(v4, OpndSize_32, 10, false); 5400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 10, false, offArrayObject_contents+12, PhysicalReg_EAX, true); 5410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 5) { 5430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //move from virtual register to contents of array object 5440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(v5, OpndSize_32, 11, false); 5450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 11, false, offArrayObject_contents+16, PhysicalReg_EAX, true); 5460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 5480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 5490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! function to handle the error of array not implemented 5510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 5530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint filled_new_array_notimpl() { 5540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //two inputs for common_throw: 5550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".filled_new_array_notimpl", false); 5560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrFilledNewArrayNotImpl, PhysicalReg_EAX, true); 5570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, (int) gDvm.exInternalError, PhysicalReg_ECX, true); 5580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 5590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 5600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_SCRATCH_1 PhysicalReg_EDX 5630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode FILLED_NEW_ARRAY_RANGE 5640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 5660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_filled_new_array_range() { 5670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 length = INST_AA(inst); 5680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 5690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 vC = (u4)FETCH(2); 5700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_filled_new_array(length, tmp, true/*hasRange*/); 5710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //here, %eax points to the array object 5720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(length >= 1) { 5730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //dump all virtual registers used by this bytecode to stack, for NCG O1 5740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int k; 5750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen for(k = 0; k < length; k++) { 5760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen spillVirtualReg(vC+k, LowOpndRegType_gp, true); //will update refCount 5770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //address of the first virtual register that will be moved to the array object 5790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(vC*4, PhysicalReg_FP, true, 7, false); //addr 5800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //start address for contents of the array object 5810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(offArrayObject_contents, PhysicalReg_EAX, true, 8, false); //addr 5820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //loop counter 5830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, length-1, 9, false); //counter 5840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //start of the loop 5850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".filled_new_array_range_loop1", true); 5860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rememberState(1); 5870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, 0, 7, false, 10, false); 5880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, 7, false, 7, false); 5890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 10, false, 0, 8, false); 5900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, 8, false, 8, false); 5910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen alu_binary_imm_reg(OpndSize_32, sub_opc, 1, 9, false); 5920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen transferToState(1); 5930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //jump back to the loop start 5940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NS, ".filled_new_array_range_loop1", true); 5950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 5970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 5980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 6000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 6010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 6020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_SCRATCH_1 6030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 6050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode FILL_ARRAY_DATA 6060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!use 1 GPR and scratch regs (export_pc dvmInterpHandleFillArrayData) 6080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//!CALL: dvmInterpHandleFillArrayData 6090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_fill_array_data() { 6100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 6110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 6120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen tmp |= (u4)FETCH(2) << 16; 6130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 6140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[1] = PhysicalReg_Null; 6150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 6160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 6170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //prepare to call dvmInterpHandleFillArrayData, input: array object, address of the data 6180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 6190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 1, false, 0, PhysicalReg_ESP, true); 6200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* 2nd argument to dvmInterpHandleFillArrayData at 4(%esp) */ 6210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)(rPC+tmp), 4, PhysicalReg_ESP, true); 6220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmInterpHandleFillArrayData(); 6230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 6240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //check return value of dvmInterpHandleFillArrayData, if zero, throw exception 6260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 6270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, ".fill_array_data_done", true); 6280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //jump to dvmJitToExceptionThrown 6290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 6300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToExceptionThrown(2/*exception number*/); 6310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel(".fill_array_data_done", true); 6320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 6330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 6340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 6360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 6380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode THROW 6390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 6410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_throw() { 6420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 6430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 6440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 6450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //null check 6460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, 1, false); 6470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_E, "common_errNullObject", false); 6480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //set glue->exception & throw exception 6490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 6500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; scratchRegs[1] = PhysicalReg_SCRATCH_2; 6510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_exception(1, false); 6520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_exceptionThrown", false); 6530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 6540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 6550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 6570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 6580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! LOWER bytecode THROW_VERIFICATION_ERROR 6590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! op AA, ref@BBBB 6610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_throw_verification_error() { 6620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA, vB; 6630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen vA = INST_AA(inst); 6640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen vB = FETCH(1); 6650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen export_pc(); 6670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 6680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_glue_method(1, false); 6690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 6710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, vB, 8, PhysicalReg_ESP, true); 6720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, vA, 4, PhysicalReg_ESP, true); 6730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 1, false, 0, PhysicalReg_ESP, true); 6740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 6750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmThrowVerificationError(); 6760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 6770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_exceptionThrown", false); 6790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 6800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 6810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 683