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