Home | History | Annotate | Download | only in x86
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 /*! \file AnalysisO1.cpp
     19   \brief This file implements register allocator, constant folding
     20 */
     21 #include "libdex/DexOpcodes.h"
     22 #include "libdex/DexFile.h"
     23 #include "Lower.h"
     24 #include "interp/InterpState.h"
     25 #include "interp/InterpDefs.h"
     26 #include "libdex/Leb128.h"
     27 
     28 /* compilation flags to turn on debug printout */
     29 //#define DEBUG_COMPILE_TABLE
     30 //#define DEBUG_ALLOC_CONSTRAINT
     31 //#define DEBUG_REGALLOC
     32 //#define DEBUG_REG_USED
     33 //#define DEBUG_REFCOUNT
     34 //#define DEBUG_REACHING_DEF2
     35 //#define DEBUG_REACHING_DEF
     36 //#define DEBUG_LIVE_RANGE
     37 //#define DEBUG_MOVE_OPT
     38 //#define DEBUG_SPILL
     39 //#define DEBUG_ENDOFBB
     40 //#define DEBUG_CONST
     41 /*
     42   #define DEBUG_XFER_POINTS
     43   #define DEBUG_DSE
     44   #define DEBUG_CFG
     45   #define DEBUG_GLOBALTYPE
     46   #define DEBUG_STATE
     47   #define DEBUG_COMPILE_TABLE
     48   #define DEBUG_VIRTUAL_INFO
     49   #define DEBUG_MOVE_OPT
     50   #define DEBUG_MERGE_ENTRY
     51   #define DEBUG_INVALIDATE
     52 */
     53 #include "AnalysisO1.h"
     54 
     55 void dumpCompileTable();
     56 
     57 /* There are 3 kinds of variables that are handled in this file:
     58    1> virtual register (isVirtualReg())
     59    2> temporary (!isVirtualReg() && regNum < PhysicalReg_GLUE_DVMDEX)
     60    3> glue variables: regNum >= PhysicalReg_GLUE_DVMDEX
     61 */
     62 /** check whether a variable is a virtual register
     63  */
     64 bool isVirtualReg(int type) {
     65     if((type & LowOpndRegType_virtual) != 0) return true;
     66     return false;
     67 }
     68 bool isTemporary(int type, int regNum) {
     69     if(!isVirtualReg(type) && regNum < PhysicalReg_GLUE_DVMDEX) return true;
     70     return false;
     71 }
     72 
     73 /** convert type defined in lowering module to type defined in register allocator
     74     in lowering module <type, isPhysical>
     75     in register allocator: LowOpndRegType_hard LowOpndRegType_virtual LowOpndRegType_scratch
     76 */
     77 int convertType(int type, int reg, bool isPhysical) {
     78     int newType = type;
     79     if(isPhysical) newType |= LowOpndRegType_hard;
     80     if(isVirtualReg(type)) newType |= LowOpndRegType_virtual;
     81     else {
     82         /* reg number for a VR can exceed PhysicalReg_SCRATCH_1 */
     83         if(reg >= PhysicalReg_SCRATCH_1 && reg < PhysicalReg_GLUE_DVMDEX)
     84             newType |= LowOpndRegType_scratch;
     85     }
     86     return newType;
     87 }
     88 
     89 /** return the size of a variable
     90  */
     91 OpndSize getRegSize(int type) {
     92     if((type & MASK_FOR_TYPE) == LowOpndRegType_xmm) return OpndSize_64;
     93     if((type & MASK_FOR_TYPE) == LowOpndRegType_fs) return OpndSize_64;
     94     /* for type _gp, _fs_s, _ss */
     95     return OpndSize_32;
     96 }
     97 
     98 /*
     99    Overlapping cases between two variables A and B
    100    layout for A,B   isAPartiallyOverlapB  isBPartiallyOverlapA
    101    1> |__|  |____|         OVERLAP_ALIGN        OVERLAP_B_COVER_A
    102       |__|  |____|
    103    2> |____|           OVERLAP_B_IS_LOW_OF_A    OVERLAP_B_COVER_LOW_OF_A
    104         |__|
    105    3> |____|           OVERLAP_B_IS_HIGH_OF_A   OVERLAP_B_COVER_HIGH_OF_A
    106       |__|
    107    4> |____|      OVERLAP_LOW_OF_A_IS_HIGH_OF_B OVERLAP_B_COVER_LOW_OF_A
    108          |____|
    109    5>    |____|   OVERLAP_HIGH_OF_A_IS_LOW_OF_B OVERLAP_B_COVER_HIGH_OF_A
    110       |____|
    111    6>   |__|           OVERLAP_A_IS_LOW_OF_B    OVERLAP_B_COVER_A
    112       |____|
    113    7> |__|             OVERLAP_A_IS_HIGH_OF_B   OVERLAP_B_COVER_A
    114       |____|
    115 */
    116 /** determine the overlapping between variable B and A
    117 */
    118 OverlapCase getBPartiallyOverlapA(int regB, LowOpndRegType tB, int regA, LowOpndRegType tA) {
    119     if(getRegSize(tA) == getRegSize(tB) && regA == regB) return OVERLAP_B_COVER_A;
    120     if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regA == regB) return OVERLAP_B_COVER_LOW_OF_A;
    121     if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regB == regA + 1) return OVERLAP_B_COVER_HIGH_OF_A;
    122     if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && (regA == regB || regA == regB+1)) return OVERLAP_B_COVER_A;
    123     if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regA == regB+1) return OVERLAP_B_COVER_LOW_OF_A;
    124     if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regB == regA+1) return OVERLAP_B_COVER_HIGH_OF_A;
    125     return OVERLAP_NO;
    126 }
    127 
    128 /** determine overlapping between variable A and B
    129 */
    130 OverlapCase getAPartiallyOverlapB(int regA, LowOpndRegType tA, int regB, LowOpndRegType tB) {
    131     if(getRegSize(tA) == getRegSize(tB) && regA == regB) return OVERLAP_ALIGN;
    132     if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regA == regB)
    133         return OVERLAP_B_IS_LOW_OF_A;
    134     if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regB == regA+1)
    135         return OVERLAP_B_IS_HIGH_OF_A;
    136     if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regA == regB+1)
    137         return OVERLAP_LOW_OF_A_IS_HIGH_OF_B;
    138     if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regB == regA+1)
    139         return OVERLAP_HIGH_OF_A_IS_LOW_OF_B;
    140     if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && regA == regB)
    141         return OVERLAP_A_IS_LOW_OF_B;
    142     if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && regA == regB+1)
    143         return OVERLAP_A_IS_HIGH_OF_B;
    144     return OVERLAP_NO;
    145 }
    146 
    147 /** determine whether variable A fully covers B
    148  */
    149 bool isAFullyCoverB(int regA, LowOpndRegType tA, int regB, LowOpndRegType tB) {
    150     if(getRegSize(tB) == OpndSize_32) return true;
    151     if(getRegSize(tA) == getRegSize(tB) && regA == regB) return true;
    152     return false;
    153 }
    154 
    155 /*
    156    RegAccessType accessType
    157    1> DefOrUse.accessType
    158       can only be D(VR), L(low part of VR), H(high part of VR), N(none)
    159       for def, it means which part of the VR is live
    160       for use, it means which part of the VR comes from the def
    161    2> VirtualRegInfo.accessType
    162       for currentInfo, it can only be a combination of U & D
    163       for entries in infoBasicBlock, it can be a combination of U & D|L|H
    164 */
    165 
    166 /*
    167    Key data structures used:
    168    1> BasicBlock_O1
    169       VirtualRegInfo infoBasicBlock[]
    170       DefUsePair* defUseTable
    171       XferPoint xferPoints[]
    172    2> MemoryVRInfo memVRTable[]
    173       LiveRange* ranges
    174    3> compileTableEntry compileTable[]
    175    4> VirtualRegInfo
    176       DefOrUse reachingDefs[3]
    177    5> DefUsePair, LiveRange
    178 */
    179 
    180 //! one entry for each variable used
    181 
    182 //! a variable can be virtual register, or a temporary (can be hard-coded)
    183 compileTableEntry compileTable[COMPILE_TABLE_SIZE];
    184 int num_compile_entries;
    185 //! tables to save the states of register allocation
    186 regAllocStateEntry1 stateTable1_1[COMPILE_TABLE_SIZE];
    187 regAllocStateEntry1 stateTable1_2[COMPILE_TABLE_SIZE];
    188 regAllocStateEntry1 stateTable1_3[COMPILE_TABLE_SIZE];
    189 regAllocStateEntry1 stateTable1_4[COMPILE_TABLE_SIZE];
    190 regAllocStateEntry2 stateTable2_1[COMPILE_TABLE_SIZE];
    191 regAllocStateEntry2 stateTable2_2[COMPILE_TABLE_SIZE];
    192 regAllocStateEntry2 stateTable2_3[COMPILE_TABLE_SIZE];
    193 regAllocStateEntry2 stateTable2_4[COMPILE_TABLE_SIZE];
    194 
    195 //! array of VirtualRegInfo to store VRs accessed by a single bytecode
    196 VirtualRegInfo infoByteCode[MAX_REG_PER_BYTECODE];
    197 int num_regs_per_bytecode;
    198 //! array of TempRegInfo to store temporaries accessed by a single bytecode
    199 TempRegInfo infoByteCodeTemp[MAX_TEMP_REG_PER_BYTECODE];
    200 int num_temp_regs_per_bytecode;
    201 //! array of MemoryVRInfo to store whether a VR is in memory
    202 #define NUM_MEM_VR_ENTRY 140
    203 MemoryVRInfo memVRTable[NUM_MEM_VR_ENTRY];
    204 int num_memory_vr;
    205 
    206 CompilationUnit* currentUnit = NULL;
    207 
    208 //! the current basic block
    209 BasicBlock_O1* currentBB = NULL;
    210 //! array of RegisterInfo for all the physical registers
    211 RegisterInfo allRegs[PhysicalReg_GLUE+1]; //initialized in codeGen
    212 
    213 VirtualRegInfo currentInfo;
    214 VirtualRegInfo tmpInfo;
    215 
    216 //! this array says whether a spill location is used (0 means not used, 1 means used)
    217 int spillIndexUsed[MAX_SPILL_JIT_IA];
    218 int indexForGlue = -1;
    219 
    220 int num_bbs_for_method;
    221 //! array of basic blocks in a method in program order
    222 BasicBlock_O1* method_bbs_sorted[MAX_NUM_BBS_PER_METHOD];
    223 //! the entry basic block
    224 BasicBlock_O1* bb_entry;
    225 int pc_start = -1;
    226 int pc_end = -1;
    227 
    228 //!array of PCs for exception handlers
    229 int exceptionHandlers[10];
    230 int num_exception_handlers;
    231 
    232 bool canSpillReg[PhysicalReg_Null]; //physical registers that should not be spilled
    233 int inGetVR_num = -1;
    234 int inGetVR_type;
    235 
    236 ///////////////////////////////////////////////////////////////////////////////
    237 // FORWARD FUNCTION DECLARATION
    238 void addExceptionHandler(s4 tmp);
    239 
    240 int createCFG(Method* method);
    241 int collectInfoOfBasicBlock(Method* method, BasicBlock_O1* bb);
    242 void dumpVirtualInfoOfBasicBlock(BasicBlock_O1* bb);
    243 void setTypeOfVR();
    244 void insertGlueReg();
    245 void dumpVirtualInfoOfMethod();
    246 int codeGenBasicBlock(const Method* method, BasicBlock_O1* bb);
    247 
    248 //used in collectInfoOfBasicBlock: getVirtualRegInfo
    249 int mergeEntry2(BasicBlock_O1* bb);
    250 int sortAllocConstraint(RegAllocConstraint* allocConstraints,
    251                         RegAllocConstraint* allocConstraintsSorted, bool fromHighToLow);
    252 
    253 //used in codeGenBasicBlock
    254 void insertFromVirtualInfo(BasicBlock_O1* bb, int k); //update compileTable
    255 void insertFromTempInfo(int k); //update compileTable
    256 int updateXferPoints();
    257 void updateLiveTable();
    258 void printDefUseTable();
    259 bool isFirstOfHandler(BasicBlock_O1* bb);
    260 
    261 //used in mergeEntry2
    262 //following functions will not update global data structure
    263 RegAccessType mergeAccess2(RegAccessType A, RegAccessType B, OverlapCase isBPartiallyOverlapA);
    264 RegAccessType updateAccess1(RegAccessType A, OverlapCase isAPartiallyOverlapB); //will not update global data structure
    265 RegAccessType updateAccess2(RegAccessType C1, RegAccessType C2);
    266 RegAccessType updateAccess3(RegAccessType C, RegAccessType B);
    267 
    268 void updateDefUseTable();
    269 void updateReachingDefA(int indexToA, OverlapCase isBPartiallyOverlapA);
    270 void updateReachingDefB1(int indexToA);
    271 void updateReachingDefB2();
    272 void updateReachingDefB3();
    273 
    274 RegAccessType insertAUse(DefUsePair* ptr, int offsetPC, int regNum, LowOpndRegType physicalType);
    275 DefUsePair* insertADef(int offsetPC, int regNum, LowOpndRegType pType, RegAccessType rType);
    276 RegAccessType insertDefUsePair(int reachingDefIndex);
    277 
    278 //used in updateXferPoints
    279 int fakeUsageAtEndOfBB(BasicBlock_O1* bb);
    280 void insertLoadXfer(int offset, int regNum, LowOpndRegType pType);
    281 int searchMemTable(int regNum);
    282 void mergeLiveRange(int tableIndex, int rangeStart, int rangeEnd);
    283 //used in updateLiveTable
    284 RegAccessType setAccessTypeOfUse(OverlapCase isDefPartiallyOverlapUse, RegAccessType reachingDefLive);
    285 DefUsePair* searchDefUseTable(int offsetPC, int regNum, LowOpndRegType pType);
    286 void insertAccess(int tableIndex, LiveRange* startP, int rangeStart);
    287 
    288 //register allocation
    289 int spillLogicalReg(int spill_index, bool updateTable);
    290 
    291 /** check whether the current bytecode is IF or GOTO or SWITCH
    292  */
    293 bool isCurrentByteCodeJump() {
    294     u2 inst_op = INST_INST(inst);
    295     if(inst_op == OP_IF_EQ || inst_op == OP_IF_NE || inst_op == OP_IF_LT ||
    296        inst_op == OP_IF_GE || inst_op == OP_IF_GT || inst_op == OP_IF_LE) return true;
    297     if(inst_op == OP_IF_EQZ || inst_op == OP_IF_NEZ || inst_op == OP_IF_LTZ ||
    298        inst_op == OP_IF_GEZ || inst_op == OP_IF_GTZ || inst_op == OP_IF_LEZ) return true;
    299     if(inst_op == OP_GOTO || inst_op == OP_GOTO_16 || inst_op == OP_GOTO_32) return true;
    300     if(inst_op == OP_PACKED_SWITCH || inst_op == OP_SPARSE_SWITCH) return true;
    301     return false;
    302 }
    303 
    304 /* this function is called before code generation of basic blocks
    305    initialize data structure allRegs, which stores information for each physical register,
    306    whether it is used, when it was last freed, whether it is callee-saved */
    307 void initializeAllRegs() {
    308     int k;
    309     for(k = PhysicalReg_EAX; k <= PhysicalReg_EBP; k++) {
    310         allRegs[k].physicalReg = (PhysicalReg) k;
    311         if(k == PhysicalReg_EDI || k == PhysicalReg_ESP || k == PhysicalReg_EBP)
    312             allRegs[k].isUsed = true;
    313         else {
    314             allRegs[k].isUsed = false;
    315             allRegs[k].freeTimeStamp = -1;
    316         }
    317         if(k == PhysicalReg_EBX || k == PhysicalReg_EBP || k == PhysicalReg_ESI || k == PhysicalReg_EDI)
    318             allRegs[k].isCalleeSaved = true;
    319         else
    320             allRegs[k].isCalleeSaved = false;
    321     }
    322     for(k = PhysicalReg_XMM0; k <= PhysicalReg_XMM7; k++) {
    323         allRegs[k].physicalReg = (PhysicalReg) k;
    324         allRegs[k].isUsed = false;
    325         allRegs[k].freeTimeStamp = -1;
    326         allRegs[k].isCalleeSaved = false;
    327     }
    328 }
    329 
    330 /** sync up allRegs (isUsed & freeTimeStamp) with compileTable
    331     global data: RegisterInfo allRegs[PhysicalReg_Null]
    332     update allRegs[EAX to XMM7] except EDI,ESP,EBP
    333     update RegisterInfo.isUsed & RegisterInfo.freeTimeStamp
    334         if the physical register was used and is not used now
    335 */
    336 void syncAllRegs() {
    337     int k, k2;
    338     for(k = PhysicalReg_EAX; k <= PhysicalReg_XMM7; k++) {
    339         if(k == PhysicalReg_EDI || k == PhysicalReg_ESP || k == PhysicalReg_EBP)
    340             continue;
    341         //check whether the physical register is used by any logical register
    342         bool stillUsed = false;
    343         for(k2 = 0; k2 < num_compile_entries; k2++) {
    344             if(compileTable[k2].physicalReg == k) {
    345                 stillUsed = true;
    346                 break;
    347             }
    348         }
    349         if(stillUsed && !allRegs[k].isUsed) {
    350             allRegs[k].isUsed = true;
    351         }
    352         if(!stillUsed && allRegs[k].isUsed) {
    353             allRegs[k].isUsed = false;
    354             allRegs[k].freeTimeStamp = lowOpTimeStamp;
    355         }
    356     }
    357     return;
    358 }
    359 
    360 //!sync up spillIndexUsed with compileTable
    361 
    362 //!
    363 void updateSpillIndexUsed() {
    364     int k;
    365     for(k = 0; k <= MAX_SPILL_JIT_IA-1; k++) spillIndexUsed[k] = 0;
    366     for(k = 0; k < num_compile_entries; k++) {
    367         if(isVirtualReg(compileTable[k].physicalType)) continue;
    368         if(compileTable[k].spill_loc_index >= 0) {
    369             if(compileTable[k].spill_loc_index > 4*(MAX_SPILL_JIT_IA-1))
    370                 ALOGE("spill_loc_index is wrong for entry %d: %d",
    371                       k, compileTable[k].spill_loc_index);
    372             spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 1;
    373         }
    374     }
    375 }
    376 
    377 /* free memory used in all basic blocks */
    378 void freeCFG() {
    379     int k;
    380     for(k = 0; k < num_bbs_for_method; k++) {
    381         /* free defUseTable for method_bbs_sorted[k] */
    382         DefUsePair* ptr = method_bbs_sorted[k]->defUseTable;
    383         while(ptr != NULL) {
    384             DefUsePair* tmp = ptr->next;
    385             /* free ptr->uses */
    386             DefOrUseLink* ptrUse = ptr->uses;
    387             while(ptrUse != NULL) {
    388                 DefOrUseLink* tmp2 = ptrUse->next;
    389                 free(ptrUse);
    390                 ptrUse = tmp2;
    391             }
    392             free(ptr);
    393             ptr = tmp;
    394         }
    395         free(method_bbs_sorted[k]);
    396     }
    397 }
    398 
    399 /* update compileTable.physicalReg, compileTable.spill_loc_index & allRegs.isUsed
    400    for glue-related variables, they do not exist
    401        not in a physical register (physicalReg is Null)
    402        not in a spilled memory location (spill_loc_index is -1)
    403 */
    404 void initializeRegStateOfBB(BasicBlock_O1* bb) {
    405     //for GLUE variables, do not exist
    406     int k;
    407     for(k = 0; k < num_compile_entries; k++) {
    408         /* trace-based JIT: there is no VR with GG type */
    409         if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType == GLOBALTYPE_GG) {
    410             if(bb->bb_index > 0) { //non-entry block
    411                 if(isFirstOfHandler(bb)) {
    412                     /* at the beginning of an exception handler, GG VR is in the interpreted stack */
    413                     compileTable[k].physicalReg = PhysicalReg_Null;
    414 #ifdef DEBUG_COMPILE_TABLE
    415                     ALOGI("at the first basic block of an exception handler, GG VR %d type %d is in memory",
    416                           compileTable[k].regNum, compileTable[k].physicalType);
    417 #endif
    418                 } else {
    419                     if(compileTable[k].physicalReg == PhysicalReg_Null) {
    420                         /* GG VR is in a specific physical register */
    421                         compileTable[k].physicalReg = compileTable[k].physicalReg_prev;
    422                     }
    423                     int tReg = compileTable[k].physicalReg;
    424                     allRegs[tReg].isUsed = true;
    425 #ifdef DEBUG_REG_USED
    426                     ALOGI("REGALLOC: physical reg %d is used by a GG VR %d %d at beginning of BB", tReg, compileTable[k].regNum, compileTable[k].physicalType);
    427 #endif
    428                 }
    429             } //non-entry block
    430         } //if GG VR
    431         if(compileTable[k].regNum != PhysicalReg_GLUE &&
    432            compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX) {
    433             /* glue related registers */
    434             compileTable[k].physicalReg = PhysicalReg_Null;
    435             compileTable[k].spill_loc_index = -1;
    436         }
    437     }
    438 }
    439 
    440 /* update memVRTable[].nullCheckDone */
    441 void initializeNullCheck(int indexToMemVR) {
    442     bool found = false;
    443 #ifdef GLOBAL_NULLCHECK_OPT
    444     /* search nullCheck_inB of the current Basic Block */
    445     for(k = 0; k < nullCheck_inSize[currentBB->bb_index2]; k++) {
    446         if(nullCheck_inB[currentBB->bb_index2][k] == memVRTable[indexToMemVR].regNum) {
    447             found = true;
    448             break;
    449         }
    450     }
    451 #endif
    452     memVRTable[indexToMemVR].nullCheckDone = found;
    453 }
    454 
    455 /* initialize memVRTable */
    456 void initializeMemVRTable() {
    457     num_memory_vr = 0;
    458     int k;
    459     for(k = 0; k < num_compile_entries; k++) {
    460         if(!isVirtualReg(compileTable[k].physicalType)) continue;
    461         /* VRs in compileTable */
    462         bool setToInMemory = (compileTable[k].physicalReg == PhysicalReg_Null);
    463         int regNum = compileTable[k].regNum;
    464         OpndSize sizeVR = getRegSize(compileTable[k].physicalType);
    465         /* search memVRTable for the VR in compileTable */
    466         int kk;
    467         int indexL = -1;
    468         int indexH = -1;
    469         for(kk = 0; kk < num_memory_vr; kk++) {
    470             if(memVRTable[kk].regNum == regNum) {
    471                 indexL = kk;
    472                 continue;
    473             }
    474             if(memVRTable[kk].regNum == regNum+1 && sizeVR == OpndSize_64) {
    475                 indexH = kk;
    476                 continue;
    477             }
    478         }
    479         if(indexL < 0) {
    480             /* the low half of VR is not in memVRTable
    481                add an entry for the low half in memVRTable */
    482             if(num_memory_vr >= NUM_MEM_VR_ENTRY) {
    483                 ALOGE("exceeds size of memVRTable");
    484                 dvmAbort();
    485             }
    486             memVRTable[num_memory_vr].regNum = regNum;
    487             memVRTable[num_memory_vr].inMemory = setToInMemory;
    488             initializeNullCheck(num_memory_vr); //set nullCheckDone
    489             memVRTable[num_memory_vr].boundCheck.checkDone = false;
    490             memVRTable[num_memory_vr].num_ranges = 0;
    491             memVRTable[num_memory_vr].ranges = NULL;
    492             memVRTable[num_memory_vr].delayFreeFlags = VRDELAY_NONE;
    493             num_memory_vr++;
    494         }
    495         if(sizeVR == OpndSize_64 && indexH < 0) {
    496             /* the high half of VR is not in memVRTable
    497                add an entry for the high half in memVRTable */
    498             if(num_memory_vr >= NUM_MEM_VR_ENTRY) {
    499                 ALOGE("exceeds size of memVRTable");
    500                 dvmAbort();
    501             }
    502             memVRTable[num_memory_vr].regNum = regNum+1;
    503             memVRTable[num_memory_vr].inMemory = setToInMemory;
    504             initializeNullCheck(num_memory_vr);
    505             memVRTable[num_memory_vr].boundCheck.checkDone = false;
    506             memVRTable[num_memory_vr].num_ranges = 0;
    507             memVRTable[num_memory_vr].ranges = NULL;
    508             memVRTable[num_memory_vr].delayFreeFlags = VRDELAY_NONE;
    509             num_memory_vr++;
    510         }
    511     }
    512 }
    513 
    514 /* create a O1 basic block from basic block constructed in JIT MIR */
    515 BasicBlock_O1* createBasicBlockO1(BasicBlock* bb) {
    516     BasicBlock_O1* bb1 = createBasicBlock(0, -1);
    517     bb1->jitBasicBlock = bb;
    518     return bb1;
    519 }
    520 
    521 /* a basic block in JIT MIR can contain bytecodes that are not in program order
    522    for example, a "goto" bytecode will be followed by the goto target */
    523 void preprocessingBB(BasicBlock* bb) {
    524     currentBB = createBasicBlockO1(bb);
    525     /* initialize currentBB->allocConstraints */
    526     int ii;
    527     for(ii = 0; ii < 8; ii++) {
    528         currentBB->allocConstraints[ii].physicalReg = (PhysicalReg)ii;
    529         currentBB->allocConstraints[ii].count = 0;
    530     }
    531     collectInfoOfBasicBlock(currentMethod, currentBB);
    532 #ifdef DEBUG_COMPILE_TABLE
    533     dumpVirtualInfoOfBasicBlock(currentBB);
    534 #endif
    535     currentBB = NULL;
    536 }
    537 
    538 void preprocessingTrace() {
    539     int k, k2, k3, jj;
    540     /* this is a simplified verson of setTypeOfVR()
    541         all VRs are assumed to be GL, no VR will be GG
    542     */
    543     for(k = 0; k < num_bbs_for_method; k++)
    544         for(jj = 0; jj < method_bbs_sorted[k]->num_regs; jj++)
    545             method_bbs_sorted[k]->infoBasicBlock[jj].gType = GLOBALTYPE_GL;
    546 
    547     /* insert a glue-related register GLUE_DVMDEX to compileTable */
    548     insertGlueReg();
    549 
    550     int compile_entries_old = num_compile_entries;
    551     for(k2 = 0; k2 < num_bbs_for_method; k2++) {
    552         currentBB = method_bbs_sorted[k2];
    553         /* update compileTable with virtual register from currentBB */
    554         for(k3 = 0; k3 < currentBB->num_regs; k3++) {
    555             insertFromVirtualInfo(currentBB, k3);
    556         }
    557 
    558         /* for each GL|GG type VR, insert fake usage at end of basic block to keep it live */
    559         int offsetPC_back = offsetPC;
    560         offsetPC = PC_FOR_END_OF_BB;
    561         for(k = 0; k < num_compile_entries; k++) {
    562             currentInfo.regNum = compileTable[k].regNum;
    563             currentInfo.physicalType = (LowOpndRegType)compileTable[k].physicalType;
    564             if(isVirtualReg(compileTable[k].physicalType) &&
    565                compileTable[k].gType == GLOBALTYPE_GL) {
    566                 /* update defUseTable by assuming a fake usage at END of a basic block for variable @ currentInfo */
    567                 fakeUsageAtEndOfBB(currentBB);
    568             }
    569             if(isVirtualReg(compileTable[k].physicalType) &&
    570                compileTable[k].gType == GLOBALTYPE_GG) {
    571                 fakeUsageAtEndOfBB(currentBB);
    572             }
    573         }
    574         offsetPC = offsetPC_back;
    575         num_compile_entries = compile_entries_old;
    576     }
    577     /* initialize data structure allRegs */
    578     initializeAllRegs();
    579 #ifdef DEBUG_COMPILE_TABLE
    580     dumpCompileTable();
    581 #endif
    582     currentBB = NULL;
    583 }
    584 
    585 void printJitTraceInfoAtRunTime(const Method* method, int offset) {
    586     ALOGI("execute trace for %s%s at offset %x", method->clazz->descriptor, method->name, offset);
    587 }
    588 
    589 void startOfTraceO1(const Method* method, LowOpBlockLabel* labelList, int exceptionBlockId, CompilationUnit *cUnit) {
    590     num_exception_handlers = 0;
    591     num_compile_entries = 0;
    592     currentBB = NULL;
    593     pc_start = -1;
    594     bb_entry = NULL;
    595     num_bbs_for_method = 0;
    596     currentUnit = cUnit;
    597     lowOpTimeStamp = 0;
    598 
    599 // dumpDebuggingInfo is gone in CompilationUnit struct
    600 #if 0
    601     /* add code to dump debugging information */
    602     if(cUnit->dumpDebuggingInfo) {
    603         move_imm_to_mem(OpndSize_32, cUnit->startOffset, -4, PhysicalReg_ESP, true); //2nd argument: offset
    604         move_imm_to_mem(OpndSize_32, (int)currentMethod, -8, PhysicalReg_ESP, true); //1st argument: method
    605         load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
    606 
    607         typedef void (*vmHelper)(const Method*, int);
    608         vmHelper funcPtr = printJitTraceInfoAtRunTime;
    609         move_imm_to_reg(OpndSize_32, (int)funcPtr, PhysicalReg_ECX, true);
    610         call_reg(PhysicalReg_ECX, true);
    611 
    612         load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
    613     }
    614 #endif
    615 }
    616 
    617 
    618 /* Code generation for a basic block defined for JIT
    619    We have two data structures for a basic block:
    620        BasicBlock defined in vm/compiler by JIT
    621        BasicBlock_O1 defined in o1 */
    622 int codeGenBasicBlockJit(const Method* method, BasicBlock* bb) {
    623     /* search method_bbs_sorted to find the O1 basic block corresponding to bb */
    624     int k;
    625     for(k = 0; k < num_bbs_for_method; k++) {
    626         if(method_bbs_sorted[k]->jitBasicBlock == bb) {
    627             lowOpTimeStamp = 0; //reset time stamp at start of a basic block
    628             currentBB = method_bbs_sorted[k];
    629             int cg_ret = codeGenBasicBlock(method, currentBB);
    630             currentBB = NULL;
    631             return cg_ret;
    632         }
    633     }
    634     ALOGE("can't find the corresponding O1 basic block for id %d type %d",
    635          bb->id, bb->blockType);
    636     return -1;
    637 }
    638 void endOfBasicBlock(BasicBlock* bb) {
    639     isScratchPhysical = true;
    640     currentBB = NULL;
    641 }
    642 void endOfTraceO1() {
    643      freeCFG();
    644 }
    645 
    646 /** entry point to collect information about virtual registers used in a basic block
    647     Initialize data structure BasicBlock_O1
    648     The usage information of virtual registers is stoerd in bb->infoBasicBlock
    649 
    650     Global variables accessed: offsetPC, rPC
    651 */
    652 int collectInfoOfBasicBlock(Method* method, BasicBlock_O1* bb) {
    653     bb->num_regs = 0;
    654     bb->num_defs = 0;
    655     bb->defUseTable = NULL;
    656     bb->defUseTail = NULL;
    657     u2* rPC_start = (u2*)method->insns;
    658     int kk;
    659     bb->endsWithReturn = false;
    660     bb->hasAccessToGlue = false;
    661 
    662     MIR* mir;
    663     int seqNum = 0;
    664     /* traverse the MIR in basic block
    665        sequence number is used to make sure next bytecode will have a larger sequence number */
    666     for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
    667         offsetPC = seqNum;
    668         mir->seqNum = seqNum++;
    669         rPC = rPC_start + mir->offset;
    670 #ifdef WITH_JIT_INLINING
    671         if(mir->dalvikInsn.opcode >= kMirOpFirst &&
    672            mir->dalvikInsn.opcode != kMirOpCheckInlinePrediction) continue;
    673         if(ir->dalvikInsn.opcode == kMirOpCheckInlinePrediction) { //TODO
    674         }
    675 #else
    676         if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) continue;
    677 #endif
    678         inst = FETCH(0);
    679         u2 inst_op = INST_INST(inst);
    680         /* update bb->hasAccessToGlue */
    681         if((inst_op >= OP_MOVE_RESULT && inst_op <= OP_RETURN_OBJECT) ||
    682            (inst_op >= OP_MONITOR_ENTER && inst_op <= OP_INSTANCE_OF) ||
    683            (inst_op == OP_FILLED_NEW_ARRAY) ||
    684            (inst_op == OP_FILLED_NEW_ARRAY_RANGE) ||
    685            (inst_op == OP_THROW) ||
    686            (inst_op >= OP_INVOKE_VIRTUAL && inst_op <= OP_INVOKE_INTERFACE_RANGE) ||
    687            (inst_op >= OP_THROW_VERIFICATION_ERROR &&
    688             inst_op <= OP_EXECUTE_INLINE_RANGE) ||
    689            (inst_op >= OP_INVOKE_VIRTUAL_QUICK && inst_op <= OP_INVOKE_SUPER_QUICK_RANGE))
    690             bb->hasAccessToGlue = true;
    691         /* update bb->endsWithReturn */
    692         if(inst_op == OP_RETURN_VOID || inst_op == OP_RETURN || inst_op == OP_RETURN_VOID_BARRIER ||
    693            inst_op == OP_RETURN_OBJECT || inst_op == OP_RETURN_WIDE)
    694             bb->endsWithReturn = true;
    695 
    696         /* get virtual register usage in current bytecode */
    697         getVirtualRegInfo(infoByteCode);
    698         int num_regs = num_regs_per_bytecode;
    699         for(kk = 0; kk < num_regs; kk++) {
    700             currentInfo = infoByteCode[kk];
    701 #ifdef DEBUG_MERGE_ENTRY
    702             ALOGI("call mergeEntry2 at offsetPC %x kk %d VR %d %d", offsetPC, kk,
    703                   currentInfo.regNum, currentInfo.physicalType);
    704 #endif
    705             mergeEntry2(bb); //update defUseTable of the basic block
    706         }
    707 
    708         //dumpVirtualInfoOfBasicBlock(bb);
    709     }//for each bytecode
    710 
    711     bb->pc_end = seqNum;
    712 
    713     //sort allocConstraints of each basic block
    714     for(kk = 0; kk < bb->num_regs; kk++) {
    715 #ifdef DEBUG_ALLOC_CONSTRAINT
    716         ALOGI("sort virtual reg %d type %d -------", bb->infoBasicBlock[kk].regNum,
    717               bb->infoBasicBlock[kk].physicalType);
    718 #endif
    719         sortAllocConstraint(bb->infoBasicBlock[kk].allocConstraints,
    720                             bb->infoBasicBlock[kk].allocConstraintsSorted, true);
    721     }
    722 #ifdef DEBUG_ALLOC_CONSTRAINT
    723     ALOGI("sort constraints for BB %d --------", bb->bb_index);
    724 #endif
    725     sortAllocConstraint(bb->allocConstraints, bb->allocConstraintsSorted, false);
    726     return 0;
    727 }
    728 
    729 /** entry point to generate native code for a O1 basic block
    730     There are 3 kinds of virtual registers in a O1 basic block:
    731     1> L VR: local within the basic block
    732     2> GG VR: is live in other basic blocks,
    733               its content is in a pre-defined GPR at the beginning of a basic block
    734     3> GL VR: is live in other basic blocks,
    735               its content is in the interpreted stack at the beginning of a basic block
    736     compileTable is updated with infoBasicBlock at the start of the basic block;
    737     Before lowering each bytecode, compileTable is updated with infoByteCodeTemp;
    738     At end of the basic block, right before the jump instruction, handles constant VRs and GG VRs
    739 */
    740 int codeGenBasicBlock(const Method* method, BasicBlock_O1* bb) {
    741     /* we assume at the beginning of each basic block,
    742        all GL VRs reside in memory and all GG VRs reside in predefined physical registers,
    743        so at the end of a basic block, recover a spilled GG VR, store a GL VR to memory */
    744     /* update compileTable with entries in bb->infoBasicBlock */
    745     int k;
    746     for(k = 0; k < bb->num_regs; k++) {
    747         insertFromVirtualInfo(bb, k);
    748     }
    749     updateXferPoints(); //call fakeUsageAtEndOfBB
    750 #ifdef DEBUG_REACHING_DEF
    751     printDefUseTable();
    752 #endif
    753 #ifdef DSE_OPT
    754     removeDeadDefs();
    755     printDefUseTable();
    756 #endif
    757     //clear const section of compileTable
    758     for(k = 0; k < num_compile_entries; k++) compileTable[k].isConst = false;
    759     num_const_vr = 0;
    760 #ifdef DEBUG_COMPILE_TABLE
    761     ALOGI("At start of basic block %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
    762     dumpCompileTable();
    763 #endif
    764     initializeRegStateOfBB(bb);
    765     initializeMemVRTable();
    766     updateLiveTable();
    767     freeReg(true);  //before code gen of a basic block, also called at end of a basic block?
    768 #ifdef DEBUG_COMPILE_TABLE
    769     ALOGI("At start of basic block %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
    770 #endif
    771 
    772     u2* rPC_start = (u2*)method->insns;
    773     bool lastByteCodeIsJump = false;
    774     MIR* mir;
    775     for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
    776         offsetPC = mir->seqNum;
    777         rPC = rPC_start + mir->offset;
    778 #ifdef WITH_JIT_INLINING
    779         if(mir->dalvikInsn.opcode >= kMirOpFirst &&
    780            mir->dalvikInsn.opcode != kMirOpCheckInlinePrediction) {
    781 #else
    782         if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) {
    783 #endif
    784             handleExtendedMIR(currentUnit, mir);
    785             continue;
    786         }
    787 
    788         inst = FETCH(0);
    789         //before handling a bytecode, import info of temporary registers to compileTable including refCount
    790         num_temp_regs_per_bytecode = getTempRegInfo(infoByteCodeTemp);
    791         for(k = 0; k < num_temp_regs_per_bytecode; k++) {
    792             if(infoByteCodeTemp[k].versionNum > 0) continue;
    793             insertFromTempInfo(k);
    794         }
    795         startNativeCode(-1, -1);
    796         for(k = 0; k <= MAX_SPILL_JIT_IA-1; k++) spillIndexUsed[k] = 0;
    797         //update spillIndexUsed if a glue variable was spilled
    798         for(k = 0; k < num_compile_entries; k++) {
    799             if(compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX) {
    800                 if(compileTable[k].spill_loc_index >= 0)
    801                     spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 1;
    802             }
    803         }
    804 #ifdef DEBUG_COMPILE_TABLE
    805         ALOGI("compile table size after importing temporary info %d", num_compile_entries);
    806         ALOGI("before one bytecode %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
    807 #endif
    808         //set isConst to true for CONST & MOVE MOVE_OBJ?
    809         //clear isConst to true for MOVE, MOVE_OBJ, MOVE_RESULT, MOVE_EXCEPTION ...
    810         bool isConst = getConstInfo(bb); //will reset isConst if a VR is updated by the bytecode
    811         bool isDeadStmt = false;
    812 #ifdef DSE_OPT
    813         for(k = 0; k < num_dead_pc; k++) {
    814             if(deadPCs[k] == offsetPC) {
    815                 isDeadStmt = true;
    816                 break;
    817             }
    818         }
    819 #endif
    820         getVirtualRegInfo(infoByteCode);
    821         //call something similar to mergeEntry2, but only update refCount
    822         //clear refCount
    823         for(k = 0; k < num_regs_per_bytecode; k++) {
    824             int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
    825                                             infoByteCode[k].regNum);
    826             if(indexT >= 0)
    827                 compileTable[indexT].refCount = 0;
    828         }
    829         for(k = 0; k < num_regs_per_bytecode; k++) {
    830             int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
    831                                             infoByteCode[k].regNum);
    832             if(indexT >= 0)
    833                 compileTable[indexT].refCount += infoByteCode[k].refCount;
    834         } //for k
    835 #ifdef DSE_OPT
    836         if(isDeadStmt) { //search compileTable
    837             getVirtualRegInfo(infoByteCode);
    838 #ifdef DEBUG_DSE
    839             ALOGI("DSE: stmt at offsetPC %d is dead", offsetPC);
    840 #endif
    841             for(k = 0; k < num_regs_per_bytecode; k++) {
    842                 int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
    843                                                 infoByteCode[k].regNum);
    844                 if(indexT >= 0)
    845                     compileTable[indexT].refCount -= infoByteCode[k].refCount;
    846             }
    847         }
    848 #endif
    849         lastByteCodeIsJump = false;
    850         if(!isConst && !isDeadStmt)  //isDeadStmt is false when DSE_OPT is not enabled
    851         {
    852 #ifdef DEBUG_COMPILE_TABLE
    853             dumpCompileTable();
    854 #endif
    855             globalShortMap = NULL;
    856             if(isCurrentByteCodeJump()) lastByteCodeIsJump = true;
    857             //lowerByteCode will call globalVREndOfBB if it is jump
    858             int retCode = lowerByteCodeJit(method, rPC, mir);
    859             if(gDvmJit.codeCacheByteUsed + (stream - streamStart) +
    860                  CODE_CACHE_PADDING > gDvmJit.codeCacheSize) {
    861                  ALOGE("JIT code cache full");
    862                  gDvmJit.codeCacheFull = true;
    863                  return -1;
    864             }
    865 
    866             if (retCode == 1) {
    867                 ALOGE("JIT couldn't compile %s%s dex_pc=%d", method->clazz->descriptor, method->name, offsetPC);
    868                 return -1;
    869             }
    870             updateConstInfo(bb);
    871             freeShortMap();
    872             if(retCode < 0) {
    873                 ALOGE("error in lowering the bytecode");
    874                 return retCode;
    875             }
    876             freeReg(true); //may dump GL VR to memory (this is necessary)
    877             //after each bytecode, make sure non-VRs have refCount of zero
    878             for(k = 0; k < num_compile_entries; k++) {
    879                 if(isTemporary(compileTable[k].physicalType, compileTable[k].regNum)) {
    880 #ifdef PRINT_WARNING
    881                     if(compileTable[k].refCount > 0) {
    882                         ALOGW("refCount for a temporary reg %d %d is %d after a bytecode", compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
    883                     }
    884 #endif
    885                     compileTable[k].refCount = 0;
    886                 }
    887             }
    888         } else { //isConst || isDeadStmt
    889             //if this bytecode is the target of a jump, the mapFromBCtoNCG should be updated
    890             offsetNCG = stream - streamMethodStart;
    891             mapFromBCtoNCG[offsetPC] = offsetNCG;
    892 #ifdef DEBUG_COMPILE_TABLE
    893             ALOGI("this bytecode generates a constant and has no side effect");
    894 #endif
    895             freeReg(true); //may dump GL VR to memory (this is necessary)
    896         }
    897 #ifdef DEBUG_COMPILE_TABLE
    898         ALOGI("after one bytecode BB %d (num of VRs %d)", bb->bb_index, bb->num_regs);
    899 #endif
    900     }//for each bytecode
    901 #ifdef DEBUG_COMPILE_TABLE
    902     dumpCompileTable();
    903 #endif
    904     if(!lastByteCodeIsJump) constVREndOfBB();
    905     //at end of a basic block, get spilled GG VR & dump GL VR
    906     if(!lastByteCodeIsJump) globalVREndOfBB(method);
    907     //remove entries for temporary registers, L VR and GL VR
    908     int jj;
    909     for(k = 0; k < num_compile_entries; ) {
    910         bool removeEntry = false;
    911         if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType != GLOBALTYPE_GG) {
    912             removeEntry = true;
    913         }
    914         if(isTemporary(compileTable[k].physicalType, compileTable[k].regNum))
    915             removeEntry = true;
    916         if(removeEntry) {
    917 #ifdef PRINT_WARNING
    918             if(compileTable[k].refCount > 0)
    919                 ALOGW("refCount for REG %d %d is %d at end of a basic block", compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
    920 #endif
    921             compileTable[k].refCount = 0;
    922             for(jj = k+1; jj < num_compile_entries; jj++) {
    923                 compileTable[jj-1] = compileTable[jj];
    924             }
    925             num_compile_entries--;
    926         } else {
    927             k++;
    928         }
    929     }
    930     freeReg(true);
    931     //free LIVE TABLE
    932     for(k = 0; k < num_memory_vr; k++) {
    933         LiveRange* ptr2 = memVRTable[k].ranges;
    934         while(ptr2 != NULL) {
    935             LiveRange* tmpP = ptr2->next;
    936             free(ptr2->accessPC);
    937             free(ptr2);
    938             ptr2 = tmpP;
    939         }
    940     }
    941 #ifdef DEBUG_COMPILE_TABLE
    942     ALOGI("At end of basic block -------");
    943     dumpCompileTable();
    944 #endif
    945     return 0;
    946 }
    947 
    948 /** update infoBasicBlock & defUseTable
    949     input: currentInfo
    950     side effect: update currentInfo.reachingDefs
    951 
    952     update entries in infoBasicBlock by calling updateReachingDefA
    953     if there is no entry in infoBasicBlock for B, an entry will be created and inserted to infoBasicBlock
    954 
    955     defUseTable is updated to account for the access at currentInfo
    956     if accessType of B is U or UD, we call updateReachingDefB to update currentInfo.reachingDefs
    957         in order to correctly insert the usage to defUseTable
    958 */
    959 int mergeEntry2(BasicBlock_O1* bb) {
    960     LowOpndRegType typeB = currentInfo.physicalType;
    961     int regB = currentInfo.regNum;
    962     int jj, k;
    963     int jjend = bb->num_regs;
    964     bool isMerged = false;
    965     bool hasAlias = false;
    966     OverlapCase isBPartiallyOverlapA, isAPartiallyOverlapB;
    967     RegAccessType tmpType = REGACCESS_N;
    968     currentInfo.num_reaching_defs = 0;
    969 
    970     /* traverse variable A in infoBasicBlock */
    971     for(jj = 0; jj < jjend; jj++) {
    972         int regA = bb->infoBasicBlock[jj].regNum;
    973         LowOpndRegType typeA = bb->infoBasicBlock[jj].physicalType;
    974         isBPartiallyOverlapA = getBPartiallyOverlapA(regB, typeB, regA, typeA);
    975         isAPartiallyOverlapB = getAPartiallyOverlapB(regA, typeA, regB, typeB);
    976         if(regA == regB && typeA == typeB) {
    977             /* variable A and B are aligned */
    978             bb->infoBasicBlock[jj].accessType = mergeAccess2(bb->infoBasicBlock[jj].accessType, currentInfo.accessType,
    979                                                              OVERLAP_B_COVER_A);
    980             bb->infoBasicBlock[jj].refCount += currentInfo.refCount;
    981             /* copy reaching defs of variable B from variable A */
    982             currentInfo.num_reaching_defs = bb->infoBasicBlock[jj].num_reaching_defs;
    983             for(k = 0; k < currentInfo.num_reaching_defs; k++)
    984                 currentInfo.reachingDefs[k] = bb->infoBasicBlock[jj].reachingDefs[k];
    985             updateDefUseTable(); //use currentInfo to update defUseTable
    986             updateReachingDefA(jj, OVERLAP_B_COVER_A); //update reachingDefs of A
    987             isMerged = true;
    988             hasAlias = true;
    989             if(typeB == LowOpndRegType_gp) {
    990                 //merge allocConstraints
    991                 for(k = 0; k < 8; k++) {
    992                     bb->infoBasicBlock[jj].allocConstraints[k].count += currentInfo.allocConstraints[k].count;
    993                 }
    994             }
    995         }
    996         else if(isBPartiallyOverlapA != OVERLAP_NO) {
    997             tmpType = updateAccess2(tmpType, updateAccess1(bb->infoBasicBlock[jj].accessType, isAPartiallyOverlapB));
    998             bb->infoBasicBlock[jj].accessType = mergeAccess2(bb->infoBasicBlock[jj].accessType, currentInfo.accessType,
    999                                                              isBPartiallyOverlapA);
   1000 #ifdef DEBUG_MERGE_ENTRY
   1001             ALOGI("update accessType in case 2: VR %d %d accessType %d", regA, typeA, bb->infoBasicBlock[jj].accessType);
   1002 #endif
   1003             hasAlias = true;
   1004             if(currentInfo.accessType == REGACCESS_U || currentInfo.accessType == REGACCESS_UD) {
   1005                 /* update currentInfo.reachingDefs */
   1006                 updateReachingDefB1(jj);
   1007                 updateReachingDefB2();
   1008             }
   1009             updateReachingDefA(jj, isBPartiallyOverlapA);
   1010         }
   1011         else {
   1012             //even if B does not overlap with A, B can affect the reaching defs of A
   1013             //for example, B is a def of "v0", A is "v1"
   1014             //  B can kill some reaching defs of A or affect the accessType of a reaching def
   1015             updateReachingDefA(jj, OVERLAP_NO); //update reachingDefs of A
   1016         }
   1017     }//for each variable A in infoBasicBlock
   1018     if(!isMerged) {
   1019         /* create a new entry in infoBasicBlock */
   1020         bb->infoBasicBlock[bb->num_regs].refCount = currentInfo.refCount;
   1021         bb->infoBasicBlock[bb->num_regs].physicalType = typeB;
   1022         if(hasAlias)
   1023             bb->infoBasicBlock[bb->num_regs].accessType = updateAccess3(tmpType, currentInfo.accessType);
   1024         else
   1025             bb->infoBasicBlock[bb->num_regs].accessType = currentInfo.accessType;
   1026 #ifdef DEBUG_MERGE_ENTRY
   1027         ALOGI("update accessType in case 3: VR %d %d accessType %d", regB, typeB, bb->infoBasicBlock[bb->num_regs].accessType);
   1028 #endif
   1029         bb->infoBasicBlock[bb->num_regs].regNum = regB;
   1030         for(k = 0; k < 8; k++)
   1031             bb->infoBasicBlock[bb->num_regs].allocConstraints[k] = currentInfo.allocConstraints[k];
   1032 #ifdef DEBUG_MERGE_ENTRY
   1033         ALOGI("isMerged is false, call updateDefUseTable");
   1034 #endif
   1035         updateDefUseTable(); //use currentInfo to update defUseTable
   1036         updateReachingDefB3(); //update currentInfo.reachingDefs if currentInfo defines variable B
   1037 
   1038         //copy from currentInfo.reachingDefs to bb->infoBasicBlock[bb->num_regs]
   1039         bb->infoBasicBlock[bb->num_regs].num_reaching_defs = currentInfo.num_reaching_defs;
   1040         for(k = 0; k < currentInfo.num_reaching_defs; k++)
   1041             bb->infoBasicBlock[bb->num_regs].reachingDefs[k] = currentInfo.reachingDefs[k];
   1042 #ifdef DEBUG_MERGE_ENTRY
   1043         ALOGI("try to update reaching defs for VR %d %d", regB, typeB);
   1044         for(k = 0; k < bb->infoBasicBlock[bb->num_regs].num_reaching_defs; k++)
   1045             ALOGI("reaching def %d @ %d for VR %d %d access %d", k, currentInfo.reachingDefs[k].offsetPC,
   1046                   currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType,
   1047                   currentInfo.reachingDefs[k].accessType);
   1048 #endif
   1049         bb->num_regs++;
   1050         if(bb->num_regs >= MAX_REG_PER_BASICBLOCK) {
   1051             ALOGE("too many VRs in a basic block");
   1052             dvmAbort();
   1053         }
   1054         return -1;
   1055     }
   1056     return 0;
   1057 }
   1058 
   1059 //!update reaching defs for infoBasicBlock[indexToA]
   1060 
   1061 //!use currentInfo.reachingDefs to update reaching defs for variable A
   1062 void updateReachingDefA(int indexToA, OverlapCase isBPartiallyOverlapA) {
   1063     if(indexToA < 0) return;
   1064     int k, k2;
   1065     OverlapCase isBPartiallyOverlapDef;
   1066     if(currentInfo.accessType == REGACCESS_U) {
   1067         return; //no update to reachingDefs of the VR
   1068     }
   1069     /* access in currentInfo is DU, D, or UD */
   1070     if(isBPartiallyOverlapA == OVERLAP_B_COVER_A) {
   1071         /* from this point on, the reachingDefs for variable A is a single def to currentInfo at offsetPC */
   1072         currentBB->infoBasicBlock[indexToA].num_reaching_defs = 1;
   1073         currentBB->infoBasicBlock[indexToA].reachingDefs[0].offsetPC = offsetPC;
   1074         currentBB->infoBasicBlock[indexToA].reachingDefs[0].regNum = currentInfo.regNum;
   1075         currentBB->infoBasicBlock[indexToA].reachingDefs[0].physicalType = currentInfo.physicalType;
   1076         currentBB->infoBasicBlock[indexToA].reachingDefs[0].accessType = REGACCESS_D;
   1077 #ifdef DEBUG_REACHING_DEF
   1078         ALOGI("single reaching def @ %d for VR %d %d", offsetPC, currentInfo.regNum, currentInfo.physicalType);
   1079 #endif
   1080         return;
   1081     }
   1082     /* update reachingDefs for variable A to get rid of dead defs */
   1083     /* Bug fix: it is possible that more than one reaching defs need to be removed
   1084                 after one reaching def is removed, num_reaching_defs--, but k should not change
   1085     */
   1086     for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; ) {
   1087         /* remove one reaching def in one interation of the loop */
   1088         //check overlapping between def & B
   1089         isBPartiallyOverlapDef = getBPartiallyOverlapA(currentInfo.regNum, currentInfo.physicalType,
   1090                                                        currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
   1091                                                        currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType);
   1092 #ifdef DEBUG_REACHING_DEF
   1093         ALOGI("DEBUG B %d %d def %d %d %d", currentInfo.regNum, currentInfo.physicalType,
   1094               currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
   1095               currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
   1096               currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType);
   1097 #endif
   1098         /* cases where one def nees to be removed:
   1099            if B fully covers def, def is removed
   1100            if B overlaps high half of def & def's accessType is H, def is removed
   1101            if B overlaps low half of def & def's accessType is L, def is removed
   1102         */
   1103         if((isBPartiallyOverlapDef == OVERLAP_B_COVER_HIGH_OF_A &&
   1104             currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType == REGACCESS_H) ||
   1105            (isBPartiallyOverlapDef == OVERLAP_B_COVER_LOW_OF_A &&
   1106             currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType == REGACCESS_L) ||
   1107            isBPartiallyOverlapDef == OVERLAP_B_COVER_A
   1108            ) { //remove def
   1109             //shift from k+1 to end
   1110             for(k2 = k+1; k2 < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k2++)
   1111                 currentBB->infoBasicBlock[indexToA].reachingDefs[k2-1] = currentBB->infoBasicBlock[indexToA].reachingDefs[k2];
   1112             currentBB->infoBasicBlock[indexToA].num_reaching_defs--;
   1113         }
   1114         /*
   1115            if B overlaps high half of def & def's accessType is not H --> update accessType of def
   1116         */
   1117         else if(isBPartiallyOverlapDef == OVERLAP_B_COVER_HIGH_OF_A &&
   1118                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType != REGACCESS_H) {
   1119             //low half is still valid
   1120             if(getRegSize(currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType) == OpndSize_32)
   1121                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_D;
   1122             else
   1123                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_L;
   1124 #ifdef DEBUG_REACHING_DEF
   1125             ALOGI("DEBUG: set accessType of def to L");
   1126 #endif
   1127             k++;
   1128         }
   1129         /*
   1130            if B overlaps low half of def & def's accessType is not L --> update accessType of def
   1131         */
   1132         else if(isBPartiallyOverlapDef == OVERLAP_B_COVER_LOW_OF_A &&
   1133                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType != REGACCESS_L) {
   1134             //high half of def is still valid
   1135             currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_H;
   1136 #ifdef DEBUG_REACHING_DEF
   1137             ALOGI("DEBUG: set accessType of def to H");
   1138 #endif
   1139             k++;
   1140         }
   1141         else {
   1142             k++;
   1143         }
   1144     }//for k
   1145     if(isBPartiallyOverlapA != OVERLAP_NO) {
   1146         //insert the def to variable @ currentInfo
   1147         k = currentBB->infoBasicBlock[indexToA].num_reaching_defs;
   1148         if(k >= 3) {
   1149           ALOGE("more than 3 reaching defs");
   1150         }
   1151         currentBB->infoBasicBlock[indexToA].reachingDefs[k].offsetPC = offsetPC;
   1152         currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum = currentInfo.regNum;
   1153         currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType = currentInfo.physicalType;
   1154         currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_D;
   1155         currentBB->infoBasicBlock[indexToA].num_reaching_defs++;
   1156     }
   1157 #ifdef DEBUG_REACHING_DEF2
   1158     ALOGI("IN updateReachingDefA for VR %d %d", currentBB->infoBasicBlock[indexToA].regNum,
   1159           currentBB->infoBasicBlock[indexToA].physicalType);
   1160     for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k++)
   1161         ALOGI("reaching def %d @ %d for VR %d %d access %d", k,
   1162               currentBB->infoBasicBlock[indexToA].reachingDefs[k].offsetPC,
   1163               currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
   1164               currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
   1165               currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType);
   1166 #endif
   1167 }
   1168 
   1169 /** Given a variable B @currentInfo,
   1170     updates its reaching defs by checking reaching defs of variable A @currentBB->infoBasicBlock[indexToA]
   1171     The result is stored in tmpInfo.reachingDefs
   1172 */
   1173 void updateReachingDefB1(int indexToA) {
   1174     if(indexToA < 0) return;
   1175     int k;
   1176     tmpInfo.num_reaching_defs = 0;
   1177     for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k++) {
   1178         /* go through reachingDefs of variable A @currentBB->infoBasicBlock[indexToA]
   1179            for each def, check whether it overlaps with variable B @currentInfo
   1180                if the def overlaps with variable B, insert it to tmpInfo.reachingDefs
   1181         */
   1182         OverlapCase isDefPartiallyOverlapB = getAPartiallyOverlapB(
   1183                                                  currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
   1184                                                  currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
   1185                                                  currentInfo.regNum, currentInfo.physicalType
   1186                                                  );
   1187         bool insert1 = false; //whether to insert the def to tmpInfo.reachingDefs
   1188         if(isDefPartiallyOverlapB == OVERLAP_ALIGN ||
   1189            isDefPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B ||
   1190            isDefPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B) {
   1191             /* B aligns with def */
   1192             /* def is low half of B, def is high half of B
   1193                in these two cases, def is 32 bits */
   1194             insert1 = true;
   1195         }
   1196         RegAccessType deftype = currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType;
   1197         if(isDefPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A ||
   1198            isDefPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B) {
   1199             /* B is the low half of def */
   1200             /* the low half of def is the high half of B */
   1201             if(deftype != REGACCESS_H) insert1 = true;
   1202         }
   1203         if(isDefPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A ||
   1204            isDefPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B) {
   1205             /* B is the high half of def */
   1206             /* the high half of def is the low half of B */
   1207             if(deftype != REGACCESS_L) insert1 = true;
   1208         }
   1209         if(insert1) {
   1210             if(tmpInfo.num_reaching_defs >= 3) {
   1211                 ALOGE("more than 3 reaching defs for tmpInfo");
   1212             }
   1213             tmpInfo.reachingDefs[tmpInfo.num_reaching_defs] = currentBB->infoBasicBlock[indexToA].reachingDefs[k];
   1214             tmpInfo.num_reaching_defs++;
   1215 #ifdef DEBUG_REACHING_DEF2
   1216             ALOGI("insert from entry %d %d: index %d", currentBB->infoBasicBlock[indexToA].regNum,
   1217                   currentBB->infoBasicBlock[indexToA].physicalType, k);
   1218 #endif
   1219         }
   1220     }
   1221 }
   1222 
   1223 /** update currentInfo.reachingDefs by merging currentInfo.reachingDefs with tmpInfo.reachingDefs
   1224 */
   1225 void updateReachingDefB2() {
   1226     int k, k2;
   1227     for(k2 = 0; k2 < tmpInfo.num_reaching_defs; k2++ ) {
   1228         bool merged = false;
   1229         for(k = 0; k < currentInfo.num_reaching_defs; k++) {
   1230             /* check whether it is the same def, if yes, do nothing */
   1231             if(currentInfo.reachingDefs[k].regNum == tmpInfo.reachingDefs[k2].regNum &&
   1232                currentInfo.reachingDefs[k].physicalType == tmpInfo.reachingDefs[k2].physicalType) {
   1233                 merged = true;
   1234                 if(currentInfo.reachingDefs[k].offsetPC != tmpInfo.reachingDefs[k2].offsetPC) {
   1235                     ALOGE("defs on the same VR %d %d with different offsetPC %d vs %d",
   1236                           currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType,
   1237                           currentInfo.reachingDefs[k].offsetPC, tmpInfo.reachingDefs[k2].offsetPC);
   1238                 }
   1239                 if(currentInfo.reachingDefs[k].accessType != tmpInfo.reachingDefs[k2].accessType)
   1240                     ALOGE("defs on the same VR %d %d with different accessType",
   1241                           currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType);
   1242                 break;
   1243             }
   1244         }
   1245         if(!merged) {
   1246             if(currentInfo.num_reaching_defs >= 3) {
   1247                ALOGE("more than 3 reaching defs for currentInfo");
   1248             }
   1249             currentInfo.reachingDefs[currentInfo.num_reaching_defs] = tmpInfo.reachingDefs[k2];
   1250             currentInfo.num_reaching_defs++;
   1251         }
   1252     }
   1253 }
   1254 
   1255 //!update currentInfo.reachingDefs with currentInfo if variable is defined in currentInfo
   1256 
   1257 //!
   1258 void updateReachingDefB3() {
   1259     if(currentInfo.accessType == REGACCESS_U) {
   1260         return; //no need to update currentInfo.reachingDefs
   1261     }
   1262     currentInfo.num_reaching_defs = 1;
   1263     currentInfo.reachingDefs[0].regNum = currentInfo.regNum;
   1264     currentInfo.reachingDefs[0].physicalType = currentInfo.physicalType;
   1265     currentInfo.reachingDefs[0].offsetPC = offsetPC;
   1266     currentInfo.reachingDefs[0].accessType = REGACCESS_D;
   1267 }
   1268 
   1269 /** update defUseTable by checking currentInfo
   1270 */
   1271 void updateDefUseTable() {
   1272     /* no access */
   1273     if(currentInfo.accessType == REGACCESS_N) return;
   1274     /* define then use, or define only */
   1275     if(currentInfo.accessType == REGACCESS_DU || currentInfo.accessType == REGACCESS_D) {
   1276         /* insert a definition at offsetPC to variable @ currentInfo */
   1277         DefUsePair* ptr = insertADef(offsetPC, currentInfo.regNum, currentInfo.physicalType, REGACCESS_D);
   1278         if(currentInfo.accessType != REGACCESS_D) {
   1279              /* if access is define then use, insert a use at offsetPC */
   1280             insertAUse(ptr, offsetPC, currentInfo.regNum, currentInfo.physicalType);
   1281         }
   1282         return;
   1283     }
   1284     /* use only or use then define
   1285        check the reaching defs for the usage */
   1286     int k;
   1287     bool isLCovered = false, isHCovered = false, isDCovered = false;
   1288     for(k = 0; k < currentInfo.num_reaching_defs; k++) {
   1289         /* insert a def currentInfo.reachingDefs[k] and a use of variable at offsetPC */
   1290         RegAccessType useType = insertDefUsePair(k);
   1291         if(useType == REGACCESS_D) isDCovered = true;
   1292         if(useType == REGACCESS_L) isLCovered = true;
   1293         if(useType == REGACCESS_H) isHCovered = true;
   1294     }
   1295     OpndSize useSize = getRegSize(currentInfo.physicalType);
   1296     if((!isDCovered) && (!isLCovered)) {
   1297         /* the low half of variable is not defined in the basic block
   1298            so insert a def to the low half at START of the basic block */
   1299         insertDefUsePair(-1);
   1300     }
   1301     if(useSize == OpndSize_64 && (!isDCovered) && (!isHCovered)) {
   1302         /* the high half of variable is not defined in the basic block
   1303            so insert a def to the high half at START of the basic block */
   1304         insertDefUsePair(-2);
   1305     }
   1306     if(currentInfo.accessType == REGACCESS_UD) {
   1307         /* insert a def at offsetPC to variable @ currentInfo */
   1308         insertADef(offsetPC, currentInfo.regNum, currentInfo.physicalType, REGACCESS_D);
   1309         return;
   1310     }
   1311 }
   1312 
   1313 //! insert a use at offsetPC of given variable at end of DefUsePair
   1314 
   1315 //!
   1316 RegAccessType insertAUse(DefUsePair* ptr, int offsetPC, int regNum, LowOpndRegType physicalType) {
   1317     DefOrUseLink* tLink = (DefOrUseLink*)malloc(sizeof(DefOrUseLink));
   1318     if(tLink == NULL) {
   1319         ALOGE("Memory allocation failed");
   1320         return REGACCESS_UNKNOWN;
   1321     }
   1322     tLink->offsetPC = offsetPC;
   1323     tLink->regNum = regNum;
   1324     tLink->physicalType = physicalType;
   1325     tLink->next = NULL;
   1326     if(ptr->useTail != NULL)
   1327         ptr->useTail->next = tLink;
   1328     ptr->useTail = tLink;
   1329     if(ptr->uses == NULL)
   1330         ptr->uses = tLink;
   1331     ptr->num_uses++;
   1332 
   1333     //check whether the def is partially overlapping with the variable
   1334     OverlapCase isDefPartiallyOverlapB = getBPartiallyOverlapA(ptr->def.regNum,
   1335                                                        ptr->def.physicalType,
   1336                                                        regNum, physicalType);
   1337     RegAccessType useType = setAccessTypeOfUse(isDefPartiallyOverlapB, ptr->def.accessType);
   1338     tLink->accessType = useType;
   1339     return useType;
   1340 }
   1341 
   1342 //! insert a def to currentBB->defUseTable
   1343 
   1344 //! update currentBB->defUseTail if necessary
   1345 DefUsePair* insertADef(int offsetPC, int regNum, LowOpndRegType pType, RegAccessType rType) {
   1346     DefUsePair* ptr = (DefUsePair*)malloc(sizeof(DefUsePair));
   1347     if(ptr == NULL) {
   1348         ALOGE("Memory allocation failed");
   1349         return NULL;
   1350     }
   1351     ptr->next = NULL;
   1352     ptr->def.offsetPC = offsetPC;
   1353     ptr->def.regNum = regNum;
   1354     ptr->def.physicalType = pType;
   1355     ptr->def.accessType = rType;
   1356     ptr->num_uses = 0;
   1357     ptr->useTail = NULL;
   1358     ptr->uses = NULL;
   1359     if(currentBB->defUseTail != NULL) {
   1360         currentBB->defUseTail->next = ptr;
   1361     }
   1362     currentBB->defUseTail = ptr;
   1363     if(currentBB->defUseTable == NULL)
   1364         currentBB->defUseTable = ptr;
   1365     currentBB->num_defs++;
   1366 #ifdef DEBUG_REACHING_DEF
   1367     ALOGI("insert a def at %d to defUseTable for VR %d %d", offsetPC,
   1368           regNum, pType);
   1369 #endif
   1370     return ptr;
   1371 }
   1372 
   1373 /** insert a def to defUseTable, then insert a use of variable @ currentInfo
   1374     if reachingDefIndex >= 0, the def is currentInfo.reachingDefs[index]
   1375     if reachingDefIndex is -1, the low half is defined at START of the basic block
   1376     if reachingDefIndex is -2, the high half is defined at START of the basic block
   1377 */
   1378 RegAccessType insertDefUsePair(int reachingDefIndex) {
   1379     int k = reachingDefIndex;
   1380     DefUsePair* tableIndex = NULL;
   1381     DefOrUse theDef;
   1382     theDef.regNum = 0;
   1383     if(k < 0) {
   1384         /* def at start of the basic blcok */
   1385         theDef.offsetPC = PC_FOR_START_OF_BB;
   1386         theDef.accessType = REGACCESS_D;
   1387         if(k == -1) //low half of variable
   1388             theDef.regNum = currentInfo.regNum;
   1389         if(k == -2) //high half of variable
   1390             theDef.regNum = currentInfo.regNum+1;
   1391         theDef.physicalType = LowOpndRegType_gp;
   1392     }
   1393     else {
   1394         theDef = currentInfo.reachingDefs[k];
   1395     }
   1396     tableIndex = searchDefUseTable(theDef.offsetPC, theDef.regNum, theDef.physicalType);
   1397     if(tableIndex == NULL) //insert an entry
   1398         tableIndex = insertADef(theDef.offsetPC, theDef.regNum, theDef.physicalType, theDef.accessType);
   1399     else
   1400         tableIndex->def.accessType = theDef.accessType;
   1401     RegAccessType useType = insertAUse(tableIndex, offsetPC, currentInfo.regNum, currentInfo.physicalType);
   1402     return useType;
   1403 }
   1404 
   1405 //! insert a XFER_MEM_TO_XMM to currentBB->xferPoints
   1406 
   1407 //!
   1408 void insertLoadXfer(int offset, int regNum, LowOpndRegType pType) {
   1409     //check whether it is already in currentBB->xferPoints
   1410     int k;
   1411     for(k = 0; k < currentBB->num_xfer_points; k++) {
   1412         if(currentBB->xferPoints[k].xtype == XFER_MEM_TO_XMM &&
   1413            currentBB->xferPoints[k].offsetPC == offset &&
   1414            currentBB->xferPoints[k].regNum == regNum &&
   1415            currentBB->xferPoints[k].physicalType == pType)
   1416             return;
   1417     }
   1418     currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_MEM_TO_XMM;
   1419     currentBB->xferPoints[currentBB->num_xfer_points].regNum = regNum;
   1420     currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = offset;
   1421     currentBB->xferPoints[currentBB->num_xfer_points].physicalType = pType;
   1422 #ifdef DEBUG_XFER_POINTS
   1423     ALOGI("insert to xferPoints %d: XFER_MEM_TO_XMM of VR %d %d at %d", currentBB->num_xfer_points, regNum, pType, offset);
   1424 #endif
   1425     currentBB->num_xfer_points++;
   1426     if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
   1427         ALOGE("too many xfer points");
   1428         dvmAbort();
   1429     }
   1430 }
   1431 
   1432 /** update defUseTable by assuming a fake usage at END of a basic block for variable @ currentInfo
   1433     create a fake usage at end of a basic block for variable B (currentInfo.physicalType, currentInfo.regNum)
   1434     get reaching def info for variable B and store the info in currentInfo.reachingDefs
   1435         for each virtual register (variable A) accessed in the basic block
   1436             update reaching defs of B by checking reaching defs of variable A
   1437     update defUseTable
   1438 */
   1439 int fakeUsageAtEndOfBB(BasicBlock_O1* bb) {
   1440     currentInfo.accessType = REGACCESS_U;
   1441     LowOpndRegType typeB = currentInfo.physicalType;
   1442     int regB = currentInfo.regNum;
   1443     int jj, k;
   1444     currentInfo.num_reaching_defs = 0;
   1445     for(jj = 0; jj < bb->num_regs; jj++) {
   1446         int regA = bb->infoBasicBlock[jj].regNum;
   1447         LowOpndRegType typeA = bb->infoBasicBlock[jj].physicalType;
   1448         OverlapCase isBPartiallyOverlapA = getBPartiallyOverlapA(regB, typeB, regA, typeA);
   1449         if(regA == regB && typeA == typeB) {
   1450             /* copy reachingDefs from variable A */
   1451             currentInfo.num_reaching_defs = bb->infoBasicBlock[jj].num_reaching_defs;
   1452             for(k = 0; k < currentInfo.num_reaching_defs; k++)
   1453                 currentInfo.reachingDefs[k] = bb->infoBasicBlock[jj].reachingDefs[k];
   1454             break;
   1455         }
   1456         else if(isBPartiallyOverlapA != OVERLAP_NO) {
   1457             /* B overlaps with A */
   1458             /* update reaching defs of variable B by checking reaching defs of bb->infoBasicBlock[jj] */
   1459             updateReachingDefB1(jj);
   1460             updateReachingDefB2(); //merge currentInfo with tmpInfo
   1461         }
   1462     }
   1463     /* update defUseTable by checking currentInfo */
   1464     updateDefUseTable();
   1465     return 0;
   1466 }
   1467 
   1468 /** update xferPoints of currentBB
   1469     Traverse currentBB->defUseTable
   1470 */
   1471 int updateXferPoints() {
   1472     int k = 0;
   1473     currentBB->num_xfer_points = 0;
   1474     DefUsePair* ptr = currentBB->defUseTable;
   1475     DefOrUseLink* ptrUse = NULL;
   1476     /* traverse the def use chain of the basic block */
   1477     while(ptr != NULL) {
   1478         LowOpndRegType defType = ptr->def.physicalType;
   1479         //if definition is for a variable of 32 bits
   1480         if(getRegSize(defType) == OpndSize_32) {
   1481             /* check usages of the definition, whether it reaches a GPR, a XMM, a FS, or a SS */
   1482             bool hasGpUsage = false;
   1483             bool hasGpUsage2 = false; //not a fake usage
   1484             bool hasXmmUsage = false;
   1485             bool hasFSUsage = false;
   1486             bool hasSSUsage = false;
   1487             ptrUse = ptr->uses;
   1488             while(ptrUse != NULL) {
   1489                 if(ptrUse->physicalType == LowOpndRegType_gp) {
   1490                     hasGpUsage = true;
   1491                     if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
   1492                         hasGpUsage2 = true;
   1493                 }
   1494                 if(ptrUse->physicalType == LowOpndRegType_ss) hasSSUsage = true;
   1495                 if(ptrUse->physicalType == LowOpndRegType_fs ||
   1496                    ptrUse->physicalType == LowOpndRegType_fs_s)
   1497                     hasFSUsage = true;
   1498                 if(ptrUse->physicalType == LowOpndRegType_xmm) {
   1499                     hasXmmUsage = true;
   1500                 }
   1501                 if(ptrUse->physicalType == LowOpndRegType_xmm ||
   1502                    ptrUse->physicalType == LowOpndRegType_ss) {
   1503                     /* if a 32-bit definition reaches a xmm usage or a SS usage,
   1504                        insert a XFER_MEM_TO_XMM */
   1505                     insertLoadXfer(ptrUse->offsetPC,
   1506                                    ptrUse->regNum, LowOpndRegType_xmm);
   1507                 }
   1508                 ptrUse = ptrUse->next;
   1509             }
   1510             if(((hasXmmUsage || hasFSUsage || hasSSUsage) && defType == LowOpndRegType_gp) ||
   1511                (hasGpUsage && defType == LowOpndRegType_fs) ||
   1512                (defType == LowOpndRegType_ss && (hasGpUsage || hasXmmUsage || hasFSUsage))) {
   1513                 /* insert a transfer if def is on a GPR, usage is on a XMM, FS or SS
   1514                                      if def is on a FS, usage is on a GPR
   1515                                      if def is on a SS, usage is on a GPR, XMM or FS
   1516                    transfer type is XFER_DEF_TO_GP_MEM if a real GPR usage exisits
   1517                    transfer type is XFER_DEF_TO_GP otherwise*/
   1518                 currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = ptr->def.offsetPC;
   1519                 currentBB->xferPoints[currentBB->num_xfer_points].regNum = ptr->def.regNum;
   1520                 currentBB->xferPoints[currentBB->num_xfer_points].physicalType = ptr->def.physicalType;
   1521                 if(hasGpUsage2) { //create an entry XFER_DEF_TO_GP_MEM
   1522                     currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_TO_GP_MEM;
   1523                 }
   1524                 else { //create an entry XFER_DEF_TO_MEM
   1525                     currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_TO_MEM;
   1526                 }
   1527                 currentBB->xferPoints[currentBB->num_xfer_points].tableIndex = k;
   1528 #ifdef DEBUG_XFER_POINTS
   1529                 ALOGI("insert XFER %d at def %d: V%d %d", currentBB->num_xfer_points, ptr->def.offsetPC, ptr->def.regNum, defType);
   1530 #endif
   1531                 currentBB->num_xfer_points++;
   1532                 if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
   1533                     ALOGE("too many xfer points");
   1534                     dvmAbort();
   1535                 }
   1536             }
   1537         }
   1538         else { /* def is on 64 bits */
   1539             bool hasGpUsageOfL = false; //exist a GPR usage of the low half
   1540             bool hasGpUsageOfH = false; //exist a GPR usage of the high half
   1541             bool hasGpUsageOfL2 = false;
   1542             bool hasGpUsageOfH2 = false;
   1543             bool hasMisaligned = false;
   1544             bool hasAligned = false;
   1545             bool hasFSUsage = false;
   1546             bool hasSSUsage = false;
   1547             ptrUse = ptr->uses;
   1548             while(ptrUse != NULL) {
   1549                 if(ptrUse->physicalType == LowOpndRegType_gp &&
   1550                    ptrUse->regNum == ptr->def.regNum) {
   1551                     hasGpUsageOfL = true;
   1552                     if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
   1553                         hasGpUsageOfL2 = true;
   1554                 }
   1555                 if(ptrUse->physicalType == LowOpndRegType_gp &&
   1556                    ptrUse->regNum == ptr->def.regNum + 1) {
   1557                     hasGpUsageOfH = true;
   1558                     if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
   1559                         hasGpUsageOfH2 = true;
   1560                 }
   1561                 if(ptrUse->physicalType == LowOpndRegType_xmm &&
   1562                    ptrUse->regNum == ptr->def.regNum) {
   1563                     hasAligned = true;
   1564                     /* if def is on FS and use is on XMM, insert a XFER_MEM_TO_XMM */
   1565                     if(defType == LowOpndRegType_fs)
   1566                         insertLoadXfer(ptrUse->offsetPC,
   1567                                        ptrUse->regNum, LowOpndRegType_xmm);
   1568                 }
   1569                 if(ptrUse->physicalType == LowOpndRegType_fs ||
   1570                    ptrUse->physicalType == LowOpndRegType_fs_s)
   1571                     hasFSUsage = true;
   1572                 if(ptrUse->physicalType == LowOpndRegType_xmm &&
   1573                    ptrUse->regNum != ptr->def.regNum) {
   1574                     hasMisaligned = true;
   1575                     /* if use is on XMM and use and def are misaligned, insert a XFER_MEM_TO_XMM */
   1576                     insertLoadXfer(ptrUse->offsetPC,
   1577                                    ptrUse->regNum, LowOpndRegType_xmm);
   1578                 }
   1579                 if(ptrUse->physicalType == LowOpndRegType_ss) {
   1580                     hasSSUsage = true;
   1581                     /* if use is on SS, insert a XFER_MEM_TO_XMM */
   1582                     insertLoadXfer(ptrUse->offsetPC,
   1583                                    ptrUse->regNum, LowOpndRegType_ss);
   1584                 }
   1585                 ptrUse = ptrUse->next;
   1586             }
   1587             if(defType == LowOpndRegType_fs && !hasGpUsageOfL && !hasGpUsageOfH) {
   1588                 ptr = ptr->next;
   1589                 continue;
   1590             }
   1591             if(defType == LowOpndRegType_xmm && !hasFSUsage &&
   1592                !hasGpUsageOfL && !hasGpUsageOfH && !hasMisaligned && !hasSSUsage) {
   1593                 ptr = ptr->next;
   1594                 continue;
   1595             }
   1596             /* insert a XFER_DEF_IS_XMM */
   1597             currentBB->xferPoints[currentBB->num_xfer_points].regNum = ptr->def.regNum;
   1598             currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = ptr->def.offsetPC;
   1599             currentBB->xferPoints[currentBB->num_xfer_points].physicalType = ptr->def.physicalType;
   1600             currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_IS_XMM;
   1601             currentBB->xferPoints[currentBB->num_xfer_points].vr_gpl = -1;
   1602             currentBB->xferPoints[currentBB->num_xfer_points].vr_gph = -1;
   1603             if(hasGpUsageOfL2) currentBB->xferPoints[currentBB->num_xfer_points].vr_gpl = ptr->def.regNum;
   1604             if(hasGpUsageOfH2) currentBB->xferPoints[currentBB->num_xfer_points].vr_gph = ptr->def.regNum+1;
   1605             currentBB->xferPoints[currentBB->num_xfer_points].dumpToMem = true;
   1606             currentBB->xferPoints[currentBB->num_xfer_points].dumpToXmm = false; //not used in updateVirtualReg
   1607             if(hasAligned) currentBB->xferPoints[currentBB->num_xfer_points].dumpToXmm = true;
   1608             currentBB->xferPoints[currentBB->num_xfer_points].tableIndex = k;
   1609 #ifdef DEBUG_XFER_POINTS
   1610             ALOGI("insert XFER %d at def %d: V%d %d", currentBB->num_xfer_points, ptr->def.offsetPC, ptr->def.regNum, defType);
   1611 #endif
   1612             currentBB->num_xfer_points++;
   1613             if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
   1614                 ALOGE("too many xfer points");
   1615                 dvmAbort();
   1616             }
   1617         }
   1618         ptr = ptr->next;
   1619     } //while ptr
   1620 #ifdef DEBUG_XFER_POINTS
   1621     ALOGI("XFER points for current basic block ------");
   1622     for(k = 0; k < currentBB->num_xfer_points; k++) {
   1623         ALOGI("  at offset %x, VR %d %d: type %d, vr_gpl %d, vr_gph %d, dumpToMem %d, dumpToXmm %d",
   1624               currentBB->xferPoints[k].offsetPC, currentBB->xferPoints[k].regNum,
   1625               currentBB->xferPoints[k].physicalType, currentBB->xferPoints[k].xtype,
   1626               currentBB->xferPoints[k].vr_gpl, currentBB->xferPoints[k].vr_gph,
   1627               currentBB->xferPoints[k].dumpToMem, currentBB->xferPoints[k].dumpToXmm);
   1628     }
   1629 #endif
   1630     return -1;
   1631 }
   1632 
   1633 //! update memVRTable[].ranges by browsing the defUseTable
   1634 
   1635 //! each virtual register has a list of live ranges, and each live range has a list of PCs that access the VR
   1636 void updateLiveTable() {
   1637     DefUsePair* ptr = currentBB->defUseTable;
   1638     while(ptr != NULL) {
   1639         bool updateUse = false;
   1640         if(ptr->num_uses == 0) {
   1641             ptr->num_uses = 1;
   1642             ptr->uses = (DefOrUseLink*)malloc(sizeof(DefOrUseLink));
   1643             if(ptr->uses == NULL) {
   1644                 ALOGE("Memory allocation failed");
   1645                 return;
   1646             }
   1647             ptr->uses->accessType = REGACCESS_D;
   1648             ptr->uses->regNum = ptr->def.regNum;
   1649             ptr->uses->offsetPC = ptr->def.offsetPC;
   1650             ptr->uses->physicalType = ptr->def.physicalType;
   1651             ptr->uses->next = NULL;
   1652             ptr->useTail = ptr->uses;
   1653             updateUse = true;
   1654         }
   1655         DefOrUseLink* ptrUse = ptr->uses;
   1656         while(ptrUse != NULL) {
   1657             RegAccessType useType = ptrUse->accessType;
   1658             if(useType == REGACCESS_L || useType == REGACCESS_D) {
   1659                 int indexL = searchMemTable(ptrUse->regNum);
   1660                 if(indexL >= 0)
   1661                     mergeLiveRange(indexL, ptr->def.offsetPC,
   1662                                    ptrUse->offsetPC); //tableIndex, start PC, end PC
   1663             }
   1664             if(getRegSize(ptrUse->physicalType) == OpndSize_64 &&
   1665                (useType == REGACCESS_H || useType == REGACCESS_D)) {
   1666                 int indexH = searchMemTable(ptrUse->regNum+1);
   1667                 if(indexH >= 0)
   1668                     mergeLiveRange(indexH, ptr->def.offsetPC,
   1669                                    ptrUse->offsetPC);
   1670             }
   1671             ptrUse = ptrUse->next;
   1672         }//while ptrUse
   1673         if(updateUse) {
   1674             ptr->num_uses = 0;
   1675             free(ptr->uses);
   1676             ptr->uses = NULL;
   1677             ptr->useTail = NULL;
   1678         }
   1679         ptr = ptr->next;
   1680     }//while ptr
   1681 #ifdef DEBUG_LIVE_RANGE
   1682     ALOGI("LIVE TABLE");
   1683     for(int k = 0; k < num_memory_vr; k++) {
   1684         ALOGI("VR %d live ", memVRTable[k].regNum);
   1685         LiveRange* ptr = memVRTable[k].ranges;
   1686         while(ptr != NULL) {
   1687             ALOGI("[%x %x] (", ptr->start, ptr->end);
   1688             for(int k3 = 0; k3 < ptr->num_access; k3++)
   1689                 ALOGI("%x ", ptr->accessPC[k3]);
   1690             ALOGI(") ");
   1691             ptr = ptr->next;
   1692         }
   1693         ALOGI("");
   1694     }
   1695 #endif
   1696 }
   1697 
   1698 //!add a live range [rangeStart, rangeEnd] to ranges of memVRTable, merge to existing live ranges if necessary
   1699 
   1700 //!ranges are in increasing order of startPC
   1701 void mergeLiveRange(int tableIndex, int rangeStart, int rangeEnd) {
   1702     if(rangeStart == PC_FOR_START_OF_BB) rangeStart = currentBB->pc_start;
   1703     if(rangeEnd == PC_FOR_END_OF_BB) rangeEnd = currentBB->pc_end;
   1704 #ifdef DEBUG_LIVE_RANGE
   1705     ALOGI("LIVERANGE call mergeLiveRange on tableIndex %d with [%x %x]", tableIndex, rangeStart, rangeEnd);
   1706 #endif
   1707     int startIndex = -1, endIndex = -1;
   1708     bool startBeforeRange = false, endBeforeRange = false; //before the index or in the range
   1709     bool startDone = false, endDone = false;
   1710     LiveRange* ptr = memVRTable[tableIndex].ranges;
   1711     LiveRange* ptrStart = NULL;
   1712     LiveRange* ptrStart_prev = NULL;
   1713     LiveRange* ptrEnd = NULL;
   1714     LiveRange* ptrEnd_prev = NULL;
   1715     int k = 0;
   1716     while(ptr != NULL) {
   1717         if(!startDone) {
   1718             if(ptr->start <= rangeStart &&
   1719                ptr->end >= rangeStart) {
   1720                 startIndex = k;
   1721                 ptrStart = ptr;
   1722                 startBeforeRange = false;
   1723                 startDone = true;
   1724             }
   1725             else if(ptr->start > rangeStart) {
   1726                 startIndex = k;
   1727                 ptrStart = ptr;
   1728                 startBeforeRange = true;
   1729                 startDone = true;
   1730             }
   1731         }
   1732         if(!startDone) ptrStart_prev = ptr;
   1733         if(!endDone) {
   1734             if(ptr->start <= rangeEnd &&
   1735                ptr->end >= rangeEnd) {
   1736                 endIndex = k;
   1737                 ptrEnd = ptr;
   1738                 endBeforeRange = false;
   1739                 endDone = true;
   1740             }
   1741             else if(ptr->start > rangeEnd) {
   1742                 endIndex = k;
   1743                 ptrEnd = ptr;
   1744                 endBeforeRange = true;
   1745                 endDone = true;
   1746             }
   1747         }
   1748         if(!endDone) ptrEnd_prev = ptr;
   1749         ptr = ptr->next;
   1750         k++;
   1751     } //while
   1752     if(!startDone) { //both can be NULL
   1753         startIndex = memVRTable[tableIndex].num_ranges;
   1754         ptrStart = NULL; //ptrStart_prev should be the last live range
   1755         startBeforeRange = true;
   1756     }
   1757     //if endDone, ptrEnd is not NULL, ptrEnd_prev can be NULL
   1758     if(!endDone) { //both can be NULL
   1759         endIndex = memVRTable[tableIndex].num_ranges;
   1760         ptrEnd = NULL;
   1761         endBeforeRange = true;
   1762     }
   1763     if(startIndex == endIndex && startBeforeRange && endBeforeRange) { //insert at startIndex
   1764         //3 cases depending on BeforeRange when startIndex == endIndex
   1765         //insert only if both true
   1766         //merge otherwise
   1767         /////////// insert before ptrStart
   1768         LiveRange* currRange = (LiveRange *)malloc(sizeof(LiveRange));
   1769         if(ptrStart_prev == NULL) {
   1770             currRange->next = memVRTable[tableIndex].ranges;
   1771             memVRTable[tableIndex].ranges = currRange;
   1772         } else {
   1773             currRange->next = ptrStart_prev->next;
   1774             ptrStart_prev->next = currRange;
   1775         }
   1776         currRange->start = rangeStart;
   1777         currRange->end = rangeEnd;
   1778         currRange->accessPC = (int *)malloc(sizeof(int) * NUM_ACCESS_IN_LIVERANGE);
   1779         currRange->num_alloc = NUM_ACCESS_IN_LIVERANGE;
   1780         if(rangeStart != rangeEnd) {
   1781             currRange->num_access = 2;
   1782             currRange->accessPC[0] = rangeStart;
   1783             currRange->accessPC[1] = rangeEnd;
   1784         } else {
   1785             currRange->num_access = 1;
   1786             currRange->accessPC[0] = rangeStart;
   1787         }
   1788         memVRTable[tableIndex].num_ranges++;
   1789 #ifdef DEBUG_LIVE_RANGE
   1790         ALOGI("LIVERANGE insert one live range [%x %x] to tableIndex %d", rangeStart, rangeEnd, tableIndex);
   1791 #endif
   1792         return;
   1793     }
   1794     if(!endBeforeRange) { //here ptrEnd is not NULL
   1795         endIndex++; //next
   1796         ptrEnd_prev = ptrEnd; //ptrEnd_prev is not NULL
   1797         ptrEnd = ptrEnd->next; //ptrEnd can be NULL
   1798     }
   1799     if(endIndex < startIndex+1) ALOGE("mergeLiveRange endIndex %d startIndex %d", endIndex, startIndex);
   1800     ///////// use ptrStart & ptrEnd_prev
   1801     if(ptrStart == NULL || ptrEnd_prev == NULL) {
   1802         ALOGE("mergeLiveRange ptr is NULL");
   1803         return;
   1804     }
   1805     //endIndex > startIndex (merge the ranges between startIndex and endIndex-1)
   1806     //update ptrStart
   1807     if(ptrStart->start > rangeStart)
   1808         ptrStart->start = rangeStart; //min of old start & rangeStart
   1809     ptrStart->end = ptrEnd_prev->end; //max of old end & rangeEnd
   1810     if(rangeEnd > ptrStart->end)
   1811         ptrStart->end = rangeEnd;
   1812 #ifdef DEBUG_LIVE_RANGE
   1813     ALOGI("LIVERANGE merge entries for tableIndex %d from %d to %d", tableIndex, startIndex+1, endIndex-1);
   1814 #endif
   1815     if(ptrStart->num_access <= 0) ALOGE("mergeLiveRange number of access");
   1816 #ifdef DEBUG_LIVE_RANGE
   1817     ALOGI("LIVERANGE tableIndex %d startIndex %d num_access %d (", tableIndex, startIndex, ptrStart->num_access);
   1818     for(k = 0; k < ptrStart->num_access; k++)
   1819         ALOGI("%x ", ptrStart->accessPC[k]);
   1820     ALOGI(")");
   1821 #endif
   1822     ///// go through pointers from ptrStart->next to ptrEnd
   1823     //from startIndex+1 to endIndex-1
   1824     ptr = ptrStart->next;
   1825     while(ptr != NULL && ptr != ptrEnd) {
   1826         int k2;
   1827         for(k2 = 0; k2 < ptr->num_access; k2++) { //merge to startIndex
   1828             insertAccess(tableIndex, ptrStart, ptr->accessPC[k2]);
   1829         }//k2
   1830         ptr = ptr->next;
   1831     }
   1832     insertAccess(tableIndex, ptrStart, rangeStart);
   1833     insertAccess(tableIndex, ptrStart, rangeEnd);
   1834     //remove startIndex+1 to endIndex-1
   1835     if(startIndex+1 < endIndex) {
   1836         ptr = ptrStart->next;
   1837         while(ptr != NULL && ptr != ptrEnd) {
   1838             LiveRange* tmpP = ptr->next;
   1839             free(ptr->accessPC);
   1840             free(ptr);
   1841             ptr = tmpP;
   1842         }
   1843         ptrStart->next = ptrEnd;
   1844     }
   1845     memVRTable[tableIndex].num_ranges -= (endIndex - startIndex - 1);
   1846 #ifdef DEBUG_LIVE_RANGE
   1847     ALOGI("num_ranges for VR %d: %d", memVRTable[tableIndex].regNum, memVRTable[tableIndex].num_ranges);
   1848 #endif
   1849 }
   1850 //! insert an access to a given live range, in order
   1851 
   1852 //!
   1853 void insertAccess(int tableIndex, LiveRange* startP, int rangeStart) {
   1854     int k3, k4;
   1855 #ifdef DEBUG_LIVE_RANGE
   1856     ALOGI("LIVERANGE insertAccess %d %x", tableIndex, rangeStart);
   1857 #endif
   1858     int insertIndex = -1;
   1859     for(k3 = 0; k3 < startP->num_access; k3++) {
   1860         if(startP->accessPC[k3] == rangeStart) {
   1861             return;
   1862         }
   1863         if(startP->accessPC[k3] > rangeStart) {
   1864             insertIndex = k3;
   1865             break;
   1866         }
   1867     }
   1868 
   1869     //insert here
   1870     k3 = insertIndex;
   1871     if(insertIndex == -1) {
   1872         k3 = startP->num_access;
   1873     }
   1874     if(startP->num_access == startP->num_alloc) {
   1875         int currentAlloc = startP->num_alloc;
   1876         startP->num_alloc += NUM_ACCESS_IN_LIVERANGE;
   1877         int* tmpPtr = (int *)malloc(sizeof(int) * startP->num_alloc);
   1878         for(k4 = 0; k4 < currentAlloc; k4++)
   1879             tmpPtr[k4] = startP->accessPC[k4];
   1880         free(startP->accessPC);
   1881         startP->accessPC = tmpPtr;
   1882     }
   1883     //insert accessPC
   1884     for(k4 = startP->num_access-1; k4 >= k3; k4--)
   1885         startP->accessPC[k4+1] = startP->accessPC[k4];
   1886     startP->accessPC[k3] = rangeStart;
   1887 #ifdef DEBUG_LIVE_RANGE
   1888     ALOGI("LIVERANGE insert %x to tableIndex %d", rangeStart, tableIndex);
   1889 #endif
   1890     startP->num_access++;
   1891     return;
   1892 }
   1893 
   1894 /////////////////////////////////////////////////////////////////////
   1895 bool isInMemory(int regNum, OpndSize size);
   1896 void setVRToMemory(int regNum, OpndSize size);
   1897 bool isVRLive(int vA);
   1898 int getSpillIndex(bool isGLUE, OpndSize size);
   1899 void clearVRToMemory(int regNum, OpndSize size);
   1900 void clearVRNullCheck(int regNum, OpndSize size);
   1901 
   1902 inline int getSpillLocDisp(int offset) {
   1903 #ifdef SPILL_IN_THREAD
   1904     return offset+offsetof(Thread, spillRegion);;
   1905 #else
   1906     return offset+offEBP_spill;
   1907 #endif
   1908 }
   1909 #if 0
   1910 /* used if we keep self pointer in a physical register */
   1911 inline int getSpillLocReg(int offset) {
   1912     return PhysicalReg_Glue;
   1913 }
   1914 #endif
   1915 #ifdef SPILL_IN_THREAD
   1916 inline void loadFromSpillRegion_with_self(OpndSize size, int reg_self, bool selfPhysical, int reg, int offset) {
   1917     /* only 1 instruction is generated by move_mem_to_reg_noalloc */
   1918     move_mem_to_reg_noalloc(size,
   1919                             getSpillLocDisp(offset), reg_self, selfPhysical,
   1920                             MemoryAccess_SPILL, offset,
   1921                             reg, true);
   1922 }
   1923 inline void loadFromSpillRegion(OpndSize size, int reg, int offset) {
   1924     get_self_pointer(C_SCRATCH_1, isScratchPhysical);
   1925     int reg_self = registerAlloc(LowOpndRegType_scratch, C_SCRATCH_1, isScratchPhysical, false);
   1926     /* only 1 instruction is generated by move_mem_to_reg_noalloc */
   1927     move_mem_to_reg_noalloc(size,
   1928                             getSpillLocDisp(offset), reg_self, true,
   1929                             MemoryAccess_SPILL, offset,
   1930                             reg, true);
   1931 }
   1932 inline void saveToSpillRegion_with_self(OpndSize size, int selfReg, bool selfPhysical, int reg, int offset) {
   1933     move_reg_to_mem_noalloc(size,
   1934                             reg, true,
   1935                             getSpillLocDisp(offset), selfReg, selfPhysical,
   1936                             MemoryAccess_SPILL, offset);
   1937 }
   1938 inline void saveToSpillRegion(OpndSize size, int reg, int offset) {
   1939     get_self_pointer(C_SCRATCH_1, isScratchPhysical);
   1940     int reg_self = registerAlloc(LowOpndRegType_scratch, C_SCRATCH_1, isScratchPhysical, false);
   1941     move_reg_to_mem_noalloc(size,
   1942                             reg, true,
   1943                             getSpillLocDisp(offset), reg_self, true,
   1944                             MemoryAccess_SPILL, offset);
   1945 }
   1946 #else
   1947 inline void loadFromSpillRegion(OpndSize size, int reg, int offset) {
   1948     /* only 1 instruction is generated by move_mem_to_reg_noalloc */
   1949     move_mem_to_reg_noalloc(size,
   1950                             getSpillLocDisp(offset), PhysicalReg_EBP, true,
   1951                             MemoryAccess_SPILL, offset,
   1952                             reg, true);
   1953 }
   1954 inline void saveToSpillRegion(OpndSize size, int reg, int offset) {
   1955     move_reg_to_mem_noalloc(size,
   1956                             reg, true,
   1957                             getSpillLocDisp(offset), PhysicalReg_EBP, true,
   1958                             MemoryAccess_SPILL, offset);
   1959 }
   1960 #endif
   1961 
   1962 //! dump an immediate to memory, set inMemory to true
   1963 
   1964 //!
   1965 void dumpImmToMem(int vrNum, OpndSize size, int value) {
   1966     if(isInMemory(vrNum, size)) {
   1967 #ifdef DEBUG_SPILL
   1968         ALOGI("Skip dumpImmToMem vA %d size %d", vrNum, size);
   1969 #endif
   1970         return;
   1971     }
   1972     set_VR_to_imm_noalloc(vrNum, size, value);
   1973     setVRToMemory(vrNum, size);
   1974 }
   1975 //! dump content of a VR to memory, set inMemory to true
   1976 
   1977 //!
   1978 void dumpToMem(int vrNum, LowOpndRegType type, int regAll) { //ss,gp,xmm
   1979     if(isInMemory(vrNum, getRegSize(type))) {
   1980 #ifdef DEBUG_SPILL
   1981         ALOGI("Skip dumpToMem vA %d type %d", vrNum, type);
   1982 #endif
   1983         return;
   1984     }
   1985     if(type == LowOpndRegType_gp || type == LowOpndRegType_xmm)
   1986         set_virtual_reg_noalloc(vrNum, getRegSize(type), regAll, true);
   1987     if(type == LowOpndRegType_ss)
   1988         move_ss_reg_to_mem_noalloc(regAll, true,
   1989                                    4*vrNum, PhysicalReg_FP, true,
   1990                                    MemoryAccess_VR, vrNum);
   1991     setVRToMemory(vrNum, getRegSize(type));
   1992 }
   1993 //! dump part of a 64-bit VR to memory and update inMemory
   1994 
   1995 //! isLow tells whether low half or high half is dumped
   1996 void dumpPartToMem(int reg /*xmm physical reg*/, int vA, bool isLow) {
   1997     if(isLow) {
   1998         if(isInMemory(vA, OpndSize_32)) {
   1999 #ifdef DEBUG_SPILL
   2000             ALOGI("Skip dumpPartToMem isLow %d vA %d", isLow, vA);
   2001 #endif
   2002             return;
   2003         }
   2004     }
   2005     else {
   2006         if(isInMemory(vA+1, OpndSize_32)) {
   2007 #ifdef DEBUG_SPILL
   2008             ALOGI("Skip dumpPartToMem isLow %d vA %d", isLow, vA);
   2009 #endif
   2010             return;
   2011         }
   2012     }
   2013     if(isLow) {
   2014         if(!isVRLive(vA)) return;
   2015     }
   2016     else {
   2017         if(!isVRLive(vA+1)) return;
   2018     }
   2019     //move part to vA or vA+1
   2020     if(isLow) {
   2021         move_ss_reg_to_mem_noalloc(reg, true,
   2022                                    4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
   2023     } else {
   2024         int k = getSpillIndex(false, OpndSize_64);
   2025         //H, L in 4*k+4 & 4*k
   2026 #ifdef SPILL_IN_THREAD
   2027         get_self_pointer(PhysicalReg_SCRATCH_1, isScratchPhysical);
   2028         saveToSpillRegion_with_self(OpndSize_64, PhysicalReg_SCRATCH_1, isScratchPhysical, reg, 4*k);
   2029         //update low 32 bits of xmm reg from 4*k+4
   2030         move_ss_mem_to_reg(NULL,
   2031                                    getSpillLocDisp(4*k+4), PhysicalReg_SCRATCH_1, isScratchPhysical,
   2032                                    reg, true);
   2033 #else
   2034         saveToSpillRegion(OpndSize_64, reg, 4*k);
   2035         //update low 32 bits of xmm reg from 4*k+4
   2036         move_ss_mem_to_reg_noalloc(
   2037                                    getSpillLocDisp(4*k+4), PhysicalReg_EBP, true,
   2038                                    MemoryAccess_SPILL, 4*k+4,
   2039                                    reg, true);
   2040 #endif
   2041         //move low 32 bits of xmm reg to vA+1
   2042         move_ss_reg_to_mem_noalloc(reg, true, 4*(vA+1), PhysicalReg_FP, true, MemoryAccess_VR, vA+1);
   2043     }
   2044     if(isLow)
   2045         setVRToMemory(vA, OpndSize_32);
   2046     else
   2047         setVRToMemory(vA+1, OpndSize_32);
   2048 }
   2049 void clearVRBoundCheck(int regNum, OpndSize size);
   2050 //! the content of a VR is no longer in memory or in physical register if the latest content of a VR is constant
   2051 
   2052 //! clear nullCheckDone; if another VR is overlapped with the given VR, the content of that VR is no longer in physical register
   2053 void invalidateVRDueToConst(int reg, OpndSize size) {
   2054     clearVRToMemory(reg, size); //memory content is out-dated
   2055     clearVRNullCheck(reg, size);
   2056     clearVRBoundCheck(reg, size);
   2057     //check reg,gp reg,ss reg,xmm reg-1,xmm
   2058     //if size is 64: check reg+1,gp|ss reg+1,xmm
   2059     int index;
   2060     //if VR is xmm, check whether we need to dump part of VR to memory
   2061     index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg);
   2062     if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2063 #ifdef DEBUG_INVALIDATE
   2064         ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_xmm);
   2065 #endif
   2066         if(size == OpndSize_32)
   2067             dumpPartToMem(compileTable[index].physicalReg, reg, false); //dump high of xmm to memory
   2068         compileTable[index].physicalReg = PhysicalReg_Null;
   2069     }
   2070     index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg-1);
   2071     if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2072 #ifdef DEBUG_INVALIDATE
   2073         ALOGI("INVALIDATE virtual reg %d type %d", reg-1, LowOpndRegType_xmm);
   2074 #endif
   2075         dumpPartToMem(compileTable[index].physicalReg, reg-1, true); //dump low of xmm to memory
   2076         compileTable[index].physicalReg = PhysicalReg_Null;
   2077     }
   2078     index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg);
   2079     if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2080 #ifdef DEBUG_INVALIDATE
   2081         ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_gp);
   2082 #endif
   2083         compileTable[index].physicalReg = PhysicalReg_Null;
   2084     }
   2085     index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg);
   2086     if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2087 #ifdef DEBUG_INVALIDATE
   2088         ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_ss);
   2089 #endif
   2090         compileTable[index].physicalReg = PhysicalReg_Null;
   2091     }
   2092     if(size == OpndSize_64) {
   2093         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg+1);
   2094         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2095 #ifdef DEBUG_INVALIDATE
   2096             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_xmm);
   2097 #endif
   2098             dumpPartToMem(compileTable[index].physicalReg, reg+1, false); //dump high of xmm to memory
   2099             compileTable[index].physicalReg = PhysicalReg_Null;
   2100         }
   2101         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg+1);
   2102         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2103 #ifdef DEBUG_INVALIDATE
   2104             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_gp);
   2105 #endif
   2106             compileTable[index].physicalReg = PhysicalReg_Null;
   2107         }
   2108         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg+1);
   2109         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2110 #ifdef DEBUG_INVALIDATE
   2111             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_ss);
   2112 #endif
   2113             compileTable[index].physicalReg = PhysicalReg_Null;
   2114         }
   2115     }
   2116 }
   2117 //! check which physical registers hold out-dated content if there is a def
   2118 
   2119 //! if another VR is overlapped with the given VR, the content of that VR is no longer in physical register
   2120 //! should we update inMemory?
   2121 void invalidateVR(int reg, LowOpndRegType pType) {
   2122     //def at fs: content of xmm & gp & ss are out-dated (reg-1,xmm reg,xmm reg+1,xmm) (reg,gp|ss reg+1,gp|ss)
   2123     //def at xmm: content of misaligned xmm & gp are out-dated (reg-1,xmm reg+1,xmm) (reg,gp|ss reg+1,gp|ss)
   2124     //def at fs_s: content of xmm & gp are out-dated (reg-1,xmm reg,xmm) (reg,gp|ss)
   2125     //def at gp:   content of xmm is out-dated (reg-1,xmm reg,xmm) (reg,ss)
   2126     //def at ss:   content of xmm & gp are out-dated (reg-1,xmm reg,xmm) (reg,gp)
   2127     int index;
   2128     if(pType != LowOpndRegType_xmm) { //check xmm @reg
   2129         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg);
   2130         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2131 #ifdef DEBUG_INVALIDATE
   2132             ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_xmm);
   2133 #endif
   2134             if(getRegSize(pType) == OpndSize_32)
   2135                 dumpPartToMem(compileTable[index].physicalReg, reg, false); //dump high of xmm to memory
   2136             compileTable[index].physicalReg = PhysicalReg_Null;
   2137         }
   2138     }
   2139     //check misaligned xmm @ reg-1
   2140     index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg-1);
   2141     if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2142 #ifdef DEBUG_INVALIDATE
   2143         ALOGI("INVALIDATE virtual reg %d type %d", reg-1, LowOpndRegType_xmm);
   2144 #endif
   2145         dumpPartToMem(compileTable[index].physicalReg, reg-1, true); //dump low of xmm to memory
   2146         compileTable[index].physicalReg = PhysicalReg_Null;
   2147     }
   2148     //check misaligned xmm @ reg+1
   2149     if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
   2150         //check reg+1,xmm
   2151         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg+1);
   2152         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2153 #ifdef DEBUG_INVALIDATE
   2154             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_xmm);
   2155 #endif
   2156             dumpPartToMem(compileTable[index].physicalReg, reg+1, false); //dump high of xmm to memory
   2157             compileTable[index].physicalReg = PhysicalReg_Null;
   2158         }
   2159     }
   2160     if(pType != LowOpndRegType_gp) {
   2161         //check reg,gp
   2162         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg);
   2163         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2164 #ifdef DEBUG_INVALIDATE
   2165             ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_gp);
   2166 #endif
   2167             compileTable[index].physicalReg = PhysicalReg_Null;
   2168         }
   2169     }
   2170     if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
   2171         //check reg+1,gp
   2172         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg+1);
   2173         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2174 #ifdef DEBUG_INVALIDATE
   2175             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_gp);
   2176 #endif
   2177             compileTable[index].physicalReg = PhysicalReg_Null;
   2178         }
   2179     }
   2180     if(pType != LowOpndRegType_ss) {
   2181         //check reg,ss
   2182         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg);
   2183         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2184 #ifdef DEBUG_INVALIDATE
   2185             ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_ss);
   2186 #endif
   2187             compileTable[index].physicalReg = PhysicalReg_Null;
   2188         }
   2189     }
   2190     if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
   2191         //check reg+1,ss
   2192         index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg+1);
   2193         if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   2194 #ifdef DEBUG_INVALIDATE
   2195             ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_ss);
   2196 #endif
   2197             compileTable[index].physicalReg = PhysicalReg_Null;
   2198         }
   2199     }
   2200 }
   2201 //! bookkeeping when a VR is updated
   2202 
   2203 //! invalidate contents of some physical registers, clear nullCheckDone, and update inMemory;
   2204 //! check whether there exist tranfer points for this bytecode, if yes, perform the transfer
   2205 int updateVirtualReg(int reg, LowOpndRegType pType) {
   2206     int k;
   2207     OpndSize size = getRegSize(pType);
   2208     //WAS only invalidate xmm VRs for the following cases:
   2209     //if def reaches a use of vA,xmm and (the def is not xmm or is misaligned xmm)
   2210     //  invalidate "vA,xmm"
   2211     invalidateVR(reg, pType);
   2212     clearVRNullCheck(reg, size);
   2213     clearVRBoundCheck(reg, size);
   2214     if(pType == LowOpndRegType_fs || pType == LowOpndRegType_fs_s)
   2215         setVRToMemory(reg, size);
   2216     else {
   2217         clearVRToMemory(reg, size);
   2218     }
   2219     for(k = 0; k < currentBB->num_xfer_points; k++) {
   2220         if(currentBB->xferPoints[k].offsetPC == offsetPC &&
   2221            currentBB->xferPoints[k].regNum == reg &&
   2222            currentBB->xferPoints[k].physicalType == pType &&
   2223            currentBB->xferPoints[k].xtype != XFER_MEM_TO_XMM) {
   2224             //perform the corresponding action for the def
   2225             PhysicalReg regAll;
   2226             if(currentBB->xferPoints[k].xtype == XFER_DEF_IS_XMM) {
   2227                 //def at fs: content of xmm is out-dated
   2228                 //def at xmm: content of misaligned xmm is out-dated
   2229                 //invalidateXmmVR(currentBB->xferPoints[k].tableIndex);
   2230 #ifdef DEBUG_XFER_POINTS
   2231                 if(currentBB->xferPoints[k].dumpToXmm) ALOGI("XFER set_virtual_reg to xmm: xmm VR %d", reg);
   2232 #endif
   2233                 if(pType == LowOpndRegType_xmm)  {
   2234 #ifdef DEBUG_XFER_POINTS
   2235                     ALOGI("XFER set_virtual_reg to memory: xmm VR %d", reg);
   2236 #endif
   2237                     PhysicalReg regAll = (PhysicalReg)checkVirtualReg(reg, LowOpndRegType_xmm, 0 /* do not update*/);
   2238                     dumpToMem(reg, LowOpndRegType_xmm, regAll);
   2239                 }
   2240                 if(currentBB->xferPoints[k].vr_gpl >= 0) { //
   2241                 }
   2242                 if(currentBB->xferPoints[k].vr_gph >= 0) {
   2243                 }
   2244             }
   2245             if((pType == LowOpndRegType_gp || pType == LowOpndRegType_ss) &&
   2246                (currentBB->xferPoints[k].xtype == XFER_DEF_TO_MEM ||
   2247                 currentBB->xferPoints[k].xtype == XFER_DEF_TO_GP_MEM)) {
   2248                 //the defined gp VR already in register
   2249                 //invalidateXmmVR(currentBB->xferPoints[k].tableIndex);
   2250                 regAll = (PhysicalReg)checkVirtualReg(reg, pType, 0 /* do not update*/);
   2251                 dumpToMem(reg, pType, regAll);
   2252 #ifdef DEBUG_XFER_POINTS
   2253                 ALOGI("XFER set_virtual_reg to memory: gp VR %d", reg);
   2254 #endif
   2255             }
   2256             if((pType == LowOpndRegType_fs_s || pType == LowOpndRegType_ss) &&
   2257                currentBB->xferPoints[k].xtype == XFER_DEF_TO_GP_MEM) {
   2258             }
   2259         }
   2260     }
   2261     return -1;
   2262 }
   2263 ////////////////////////////////////////////////////////////////
   2264 //REGISTER ALLOCATION
   2265 int spillForHardReg(int regNum, int type);
   2266 void decreaseRefCount(int index);
   2267 int getFreeReg(int type, int reg, int indexToCompileTable);
   2268 PhysicalReg spillForLogicalReg(int type, int reg, int indexToCompileTable);
   2269 int unspillLogicalReg(int spill_index, int physicalReg);
   2270 int searchVirtualInfoOfBB(LowOpndRegType type, int regNum, BasicBlock_O1* bb);
   2271 bool isTemp8Bit(int type, int reg);
   2272 bool matchType(int typeA, int typeB);
   2273 int getNextAccess(int compileIndex);
   2274 void dumpCompileTable();
   2275 
   2276 //! allocate a register for a variable
   2277 
   2278 //!if no physical register is free, call spillForLogicalReg to free up a physical register;
   2279 //!if the variable is a temporary and it was spilled, call unspillLogicalReg to load from spill location to the allocated physical register;
   2280 //!if updateRefCount is true, reduce reference count of the variable by 1
   2281 int registerAlloc(int type, int reg, bool isPhysical, bool updateRefCount) {
   2282 #ifdef DEBUG_REGALLOC
   2283     ALOGI("%p: try to allocate register %d type %d isPhysical %d", currentBB, reg, type, isPhysical);
   2284 #endif
   2285     if(currentBB == NULL) {
   2286         if(type & LowOpndRegType_virtual) return PhysicalReg_Null;
   2287         if(isPhysical) return reg; //for helper functions
   2288         return PhysicalReg_Null;
   2289     }
   2290     //ignore EDI, ESP, EBP (glue)
   2291     if(isPhysical && (reg == PhysicalReg_EDI || reg == PhysicalReg_ESP ||
   2292                       reg == PhysicalReg_EBP || reg == PhysicalReg_Null))
   2293         return reg;
   2294 
   2295     int newType = convertType(type, reg, isPhysical);
   2296     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   2297     int tIndex = searchCompileTable(newType, reg);
   2298     if(tIndex < 0) {
   2299       ALOGE("reg %d type %d not found in registerAlloc", reg, newType);
   2300       return PhysicalReg_Null;
   2301     }
   2302 
   2303     //physical register
   2304     if(isPhysical) {
   2305         if(allRegs[reg].isUsed) { //if used by a non hard-coded register
   2306             spillForHardReg(reg, newType);
   2307         }
   2308         allRegs[reg].isUsed = true;
   2309 #ifdef DEBUG_REG_USED
   2310         ALOGI("REGALLOC: allocate a reg %d", reg);
   2311 #endif
   2312         compileTable[tIndex].physicalReg = reg;
   2313         if(updateRefCount)
   2314             decreaseRefCount(tIndex);
   2315 #ifdef DEBUG_REGALLOC
   2316         ALOGI("REGALLOC: allocate register %d for logical register %d %d",
   2317                compileTable[tIndex].physicalReg, reg, newType);
   2318 #endif
   2319         return reg;
   2320     }
   2321     //already allocated
   2322     if(compileTable[tIndex].physicalReg != PhysicalReg_Null) {
   2323 #ifdef DEBUG_REGALLOC
   2324         ALOGI("already allocated to physical register %d", compileTable[tIndex].physicalReg);
   2325 #endif
   2326         if(updateRefCount)
   2327             decreaseRefCount(tIndex);
   2328         return compileTable[tIndex].physicalReg;
   2329     }
   2330 
   2331     //at this point, the logical register is not hard-coded and is mapped to Reg_Null
   2332     //first check whether there is a free reg
   2333     //if not, call spillForLogicalReg
   2334     int index = getFreeReg(newType, reg, tIndex);
   2335     if(index >= 0 && index < PhysicalReg_Null) {
   2336         //update compileTable & allRegs
   2337         compileTable[tIndex].physicalReg = allRegs[index].physicalReg;
   2338         allRegs[index].isUsed = true;
   2339 #ifdef DEBUG_REG_USED
   2340         ALOGI("REGALLOC: register %d is free", allRegs[index].physicalReg);
   2341 #endif
   2342     } else {
   2343         PhysicalReg allocR = spillForLogicalReg(newType, reg, tIndex);
   2344         compileTable[tIndex].physicalReg = allocR;
   2345     }
   2346     if(compileTable[tIndex].spill_loc_index >= 0) {
   2347         unspillLogicalReg(tIndex, compileTable[tIndex].physicalReg);
   2348     }
   2349     if(updateRefCount)
   2350         decreaseRefCount(tIndex);
   2351 #ifdef DEBUG_REGALLOC
   2352     ALOGI("REGALLOC: allocate register %d for logical register %d %d",
   2353            compileTable[tIndex].physicalReg, reg, newType);
   2354 #endif
   2355     return compileTable[tIndex].physicalReg;
   2356 }
   2357 //!a variable will use a physical register allocated for another variable
   2358 
   2359 //!This is used when MOVE_OPT is on, it tries to alias a virtual register with a temporary to remove a move
   2360 int registerAllocMove(int reg, int type, bool isPhysical, int srcReg) {
   2361     if(srcReg == PhysicalReg_EDI || srcReg == PhysicalReg_ESP || srcReg == PhysicalReg_EBP)
   2362         ALOGE("can't move from srcReg EDI or ESP or EBP");
   2363 #ifdef DEBUG_REGALLOC
   2364     ALOGI("in registerAllocMove: reg %d type %d srcReg %d", reg, type, srcReg);
   2365 #endif
   2366     int newType = convertType(type, reg, isPhysical);
   2367     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   2368     int index = searchCompileTable(newType, reg);
   2369     if(index < 0) {
   2370         ALOGE("reg %d type %d not found in registerAllocMove", reg, newType);
   2371         return -1;
   2372     }
   2373 
   2374     decreaseRefCount(index);
   2375     compileTable[index].physicalReg = srcReg;
   2376 #ifdef DEBUG_REGALLOC
   2377     ALOGI("REGALLOC: registerAllocMove %d for logical register %d %d",
   2378            compileTable[index].physicalReg, reg, newType);
   2379 #endif
   2380     return srcReg;
   2381 }
   2382 
   2383 //! check whether a physical register is available to be used by a variable
   2384 
   2385 //! data structures accessed:
   2386 //! 1> currentBB->infoBasicBlock[index].allocConstraintsSorted
   2387 //!    sorted from high count to low count
   2388 //! 2> currentBB->allocConstraintsSorted
   2389 //!    sorted from low count to high count
   2390 //! 3> allRegs: whether a physical register is available, indexed by PhysicalReg
   2391 //! NOTE: if a temporary variable is 8-bit, only %eax, %ebx, %ecx, %edx can be used
   2392 int getFreeReg(int type, int reg, int indexToCompileTable) {
   2393     syncAllRegs();
   2394     /* handles requests for xmm or ss registers */
   2395     int k;
   2396     if(((type & MASK_FOR_TYPE) == LowOpndRegType_xmm) ||
   2397        ((type & MASK_FOR_TYPE) == LowOpndRegType_ss)) {
   2398         for(k = PhysicalReg_XMM0; k <= PhysicalReg_XMM7; k++) {
   2399             if(!allRegs[k].isUsed) return k;
   2400         }
   2401         return -1;
   2402     }
   2403 #ifdef DEBUG_REGALLOC
   2404     ALOGI("USED registers: ");
   2405     for(k = 0; k < 8; k++)
   2406         ALOGI("%d used: %d time freed: %d callee-saveld: %d", k, allRegs[k].isUsed,
   2407              allRegs[k].freeTimeStamp, allRegs[k].isCalleeSaved);
   2408     ALOGI("");
   2409 #endif
   2410 
   2411     /* a VR is requesting a physical register */
   2412     if(isVirtualReg(type)) { //find a callee-saved register
   2413         /* if VR is type GG, check the pre-allocated physical register first */
   2414         bool isGGVR = compileTable[indexToCompileTable].gType == GLOBALTYPE_GG;
   2415         if(isGGVR) {
   2416             int regCandidateT = compileTable[indexToCompileTable].physicalReg_prev;
   2417             if(!allRegs[regCandidateT].isUsed) return regCandidateT;
   2418         }
   2419 
   2420         int index = searchVirtualInfoOfBB((LowOpndRegType)(type&MASK_FOR_TYPE), reg, currentBB);
   2421         if(index < 0) {
   2422             ALOGE("VR %d %d not found in infoBasicBlock of currentBB %d (num of VRs %d)",
   2423                   reg, type, currentBB->bb_index, currentBB->num_regs);
   2424             dvmAbort();
   2425         }
   2426 
   2427         /* check allocConstraints for this VR,
   2428            return an available physical register with the highest constraint > 0 */
   2429         for(k = 0; k < 8; k++) {
   2430             if(currentBB->infoBasicBlock[index].allocConstraintsSorted[k].count == 0) break;
   2431             int regCandidateT = currentBB->infoBasicBlock[index].allocConstraintsSorted[k].physicalReg;
   2432             assert(regCandidateT < PhysicalReg_Null);
   2433             if(!allRegs[regCandidateT].isUsed) return regCandidateT;
   2434         }
   2435 
   2436         /* WAS: return an available physical register with the lowest constraint
   2437            NOW: consider a new factor (freeTime) when there is a tie
   2438                 if 2 available physical registers have the same number of constraints
   2439                 choose the one with smaller free time stamp */
   2440         int currentCount = -1;
   2441         int index1 = -1;
   2442         int smallestTime = -1;
   2443         for(k = 0; k < 8; k++) {
   2444             int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
   2445             assert(regCandidateT < PhysicalReg_Null);
   2446             if(index1 >= 0 && currentBB->allocConstraintsSorted[k].count > currentCount)
   2447                 break; //candidate has higher count than index1
   2448             if(!allRegs[regCandidateT].isUsed) {
   2449                 if(index1 < 0) {
   2450                     index1 = k;
   2451                     currentCount = currentBB->allocConstraintsSorted[k].count;
   2452                     smallestTime = allRegs[regCandidateT].freeTimeStamp;
   2453                 } else if(allRegs[regCandidateT].freeTimeStamp < smallestTime) {
   2454                     index1 = k;
   2455                     smallestTime = allRegs[regCandidateT].freeTimeStamp;
   2456                 }
   2457             }
   2458         }
   2459         if(index1 >= 0) return currentBB->allocConstraintsSorted[index1].physicalReg;
   2460         return -1;
   2461     }
   2462     /* handle request from a temporary variable or a glue variable */
   2463     else {
   2464         bool is8Bit = isTemp8Bit(type, reg);
   2465 
   2466         /* if the temporary variable is linked to a VR and
   2467               the VR is not yet allocated to any physical register */
   2468         int vr_num = compileTable[indexToCompileTable].linkageToVR;
   2469         if(vr_num >= 0) {
   2470             int index3 = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_virtual, vr_num);
   2471             if(index3 < 0) {
   2472                 ALOGE("2 in tracing linkage to VR %d", vr_num);
   2473                 dvmAbort();
   2474             }
   2475 
   2476             if(compileTable[index3].physicalReg == PhysicalReg_Null) {
   2477                 int index2 = searchVirtualInfoOfBB(LowOpndRegType_gp, vr_num, currentBB);
   2478                 if(index2 < 0) {
   2479                     ALOGE("1 in tracing linkage to VR %d", vr_num);
   2480                     dvmAbort();
   2481                 }
   2482 #ifdef DEBUG_REGALLOC
   2483                 ALOGI("in getFreeReg for temporary reg %d, trace the linkage to VR %d",
   2484                      reg, vr_num);
   2485 #endif
   2486 
   2487                 /* check allocConstraints on the VR
   2488                    return an available physical register with the highest constraint > 0
   2489                 */
   2490                 for(k = 0; k < 8; k++) {
   2491                     if(currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].count == 0) break;
   2492                     int regCandidateT = currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].physicalReg;
   2493 #ifdef DEBUG_REGALLOC
   2494                     ALOGI("check register %d with count %d", regCandidateT,
   2495                           currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].count);
   2496 #endif
   2497                     /* if the requesting variable is 8 bit */
   2498                     if(is8Bit && regCandidateT > PhysicalReg_EDX) continue;
   2499                     assert(regCandidateT < PhysicalReg_Null);
   2500                     if(!allRegs[regCandidateT].isUsed) return regCandidateT;
   2501                 }
   2502             }
   2503         }
   2504         /* check allocConstraints of the basic block
   2505            if 2 available physical registers have the same constraint count,
   2506               return the non callee-saved physical reg */
   2507         /* enhancement: record the time when a register is freed (freeTimeStamp)
   2508                         the purpose is to reduce false dependency
   2509            priority: constraint count, non callee-saved, time freed
   2510                let x be the lowest constraint count
   2511                set A be available callee-saved physical registers with count == x
   2512                set B be available non callee-saved physical registers with count == x
   2513                if set B is not null, return the one with smallest free time
   2514                otherwise, return the one in A with smallest free time
   2515            To ignore whether it is callee-saved, add all candidates to set A
   2516         */
   2517         int setAIndex[8];
   2518         int num_A = 0;
   2519         int setBIndex[8];
   2520         int num_B = 0;
   2521         int index1 = -1; //points to an available physical reg with lowest count
   2522         int currentCount = -1;
   2523         for(k = 0; k < 8; k++) {
   2524             int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
   2525             if(is8Bit && regCandidateT > PhysicalReg_EDX) continue;
   2526 
   2527             if(index1 >= 0 && currentBB->allocConstraintsSorted[k].count > currentCount)
   2528                 break; //candidate has higher count than index1
   2529             assert(regCandidateT < PhysicalReg_Null);
   2530             if(!allRegs[regCandidateT].isUsed) {
   2531                 /*To ignore whether it is callee-saved, add all candidates to set A */
   2532                 if(false) {//!allRegs[regCandidateT].isCalleeSaved) { //add to set B
   2533                     setBIndex[num_B++] = k;
   2534                 } else { //add to set A
   2535                     setAIndex[num_A++] = k;
   2536                 }
   2537                 if(index1 < 0) {
   2538                     /* index1 points to a physical reg with lowest count */
   2539                     index1 = k;
   2540                     currentCount = currentBB->allocConstraintsSorted[k].count;
   2541                 }
   2542             }
   2543         }
   2544 
   2545         int kk;
   2546         int smallestTime = -1;
   2547         index1 = -1;
   2548         for(kk = 0; kk < num_B; kk++) {
   2549             k = setBIndex[kk];
   2550             int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
   2551             assert(regCandidateT < PhysicalReg_Null);
   2552             if(kk == 0 || allRegs[regCandidateT].freeTimeStamp < smallestTime) {
   2553                 index1 = k;
   2554                 smallestTime = allRegs[regCandidateT].freeTimeStamp;
   2555             }
   2556         }
   2557         if(index1 >= 0)
   2558             return currentBB->allocConstraintsSorted[index1].physicalReg;
   2559         index1 = -1;
   2560         for(kk = 0; kk < num_A; kk++) {
   2561             k = setAIndex[kk];
   2562             int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
   2563             if(kk == 0 || allRegs[regCandidateT].freeTimeStamp < smallestTime) {
   2564                 index1 = k;
   2565                 smallestTime = allRegs[regCandidateT].freeTimeStamp;
   2566             }
   2567         }
   2568         if(index1 >= 0) return currentBB->allocConstraintsSorted[index1].physicalReg;
   2569         return -1;
   2570     }
   2571     return -1;
   2572 }
   2573 
   2574 //! find a candidate physical register for a variable and spill all variables that are mapped to the candidate
   2575 
   2576 //!
   2577 PhysicalReg spillForLogicalReg(int type, int reg, int indexToCompileTable) {
   2578     //choose a used register to spill
   2579     //when a GG virtual register is spilled, write it to interpretd stack, set physicalReg to Null
   2580     //  at end of the basic block, load spilled GG VR to physical reg
   2581     //when other types of VR is spilled, write it to interpreted stack, set physicalReg to Null
   2582     //when a temporary (non-virtual) register is spilled, write it to stack, set physicalReg to Null
   2583     //can we spill a hard-coded temporary register? YES
   2584     int k, k2;
   2585     PhysicalReg allocR;
   2586 
   2587     //do not try to free a physical reg that is used by more than one logical registers
   2588     //fix on sep 28, 2009
   2589     //do not try to spill a hard-coded logical register
   2590     //do not try to free a physical reg that is outside of the range for 8-bit logical reg
   2591     /* for each physical register,
   2592        collect number of non-hardcode entries that are mapped to the physical register */
   2593     int numOfUses[PhysicalReg_Null];
   2594     for(k = PhysicalReg_EAX; k < PhysicalReg_Null; k++)
   2595         numOfUses[k] = 0;
   2596     for(k = 0; k < num_compile_entries; k++) {
   2597         if((compileTable[k].physicalReg != PhysicalReg_Null) &&
   2598            matchType(type, compileTable[k].physicalType) &&
   2599            (compileTable[k].physicalType & LowOpndRegType_hard) == 0) {
   2600             numOfUses[compileTable[k].physicalReg]++;
   2601         }
   2602     }
   2603 
   2604     /* candidates: all non-hardcode entries that are mapped to
   2605            a physical register that is used by only one entry*/
   2606     bool is8Bit = isTemp8Bit(type, reg);
   2607     int candidates[COMPILE_TABLE_SIZE];
   2608     int num_cand = 0;
   2609     for(k = 0; k < num_compile_entries; k++) {
   2610         if(matchType(type, compileTable[k].physicalType) &&
   2611            compileTable[k].physicalReg != PhysicalReg_Null) {
   2612             if(is8Bit && compileTable[k].physicalReg > PhysicalReg_EDX) continue; //not a candidate
   2613             if(!canSpillReg[compileTable[k].physicalReg]) continue; //not a candidate
   2614             if((compileTable[k].physicalType & LowOpndRegType_hard) == 0 &&
   2615                numOfUses[compileTable[k].physicalReg] <= 1) {
   2616                 candidates[num_cand++] = k;
   2617             }
   2618         }
   2619     }
   2620 
   2621     /* go through all candidates:
   2622        first check GLUE-related entries */
   2623     int spill_index = -1;
   2624     for(k2 = 0; k2 < num_cand; k2++) {
   2625         k = candidates[k2];
   2626         if((compileTable[k].physicalReg != PhysicalReg_Null) &&
   2627            matchType(type, compileTable[k].physicalType) &&
   2628            (compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
   2629             compileTable[k].regNum != PhysicalReg_GLUE)) {
   2630             allocR = (PhysicalReg)spillLogicalReg(k, true);
   2631 #ifdef DEBUG_REGALLOC
   2632             ALOGI("SPILL register used by num %d type %d it is a GLUE register with refCount %d",
   2633                   compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
   2634 #endif
   2635             return allocR;
   2636         }
   2637     }
   2638 
   2639     /* out of the candates, find a VR that has the furthest next use */
   2640     int furthestUse = offsetPC;
   2641     for(k2 = 0; k2 < num_cand; k2++) {
   2642         k = candidates[k2];
   2643         if((compileTable[k].physicalReg != PhysicalReg_Null) &&
   2644            matchType(type, compileTable[k].physicalType) &&
   2645            isVirtualReg(compileTable[k].physicalType)) {
   2646             int nextUse = getNextAccess(k);
   2647             if(spill_index < 0 || nextUse > furthestUse) {
   2648                 spill_index = k;
   2649                 furthestUse = nextUse;
   2650             }
   2651         }
   2652     }
   2653 
   2654     /* spill the VR with the furthest next use */
   2655     if(spill_index >= 0) {
   2656         allocR = (PhysicalReg)spillLogicalReg(spill_index, true);
   2657         return allocR; //the register is still being used
   2658     }
   2659 
   2660     /* spill an entry with the smallest refCount */
   2661     int baseLeftOver = 0;
   2662     int index = -1;
   2663     for(k2 = 0; k2 < num_cand; k2++) {
   2664         k = candidates[k2];
   2665         if(k != indexForGlue &&
   2666            (compileTable[k].physicalReg != PhysicalReg_Null) &&
   2667            (compileTable[k].physicalType & LowOpndRegType_hard) == 0 && //not hard-coded
   2668            matchType(type, compileTable[k].physicalType)) {
   2669             if((index < 0) || (compileTable[k].refCount < baseLeftOver)) {
   2670                 baseLeftOver = compileTable[k].refCount;
   2671                 index = k;
   2672             }
   2673         }
   2674     }
   2675     if(index < 0) {
   2676         dumpCompileTable();
   2677         ALOGE("no register to spill for logical %d %d", reg, type);
   2678         dvmAbort();
   2679     }
   2680     allocR = (PhysicalReg)spillLogicalReg(index, true);
   2681 #ifdef DEBUG_REGALLOC
   2682     ALOGI("SPILL register used by num %d type %d it is a temporary register with refCount %d",
   2683            compileTable[index].regNum, compileTable[index].physicalType, compileTable[index].refCount);
   2684 #endif
   2685     return allocR;
   2686 }
   2687 //!spill a variable to memory, the variable is specified by an index to compileTable
   2688 
   2689 //!If the variable is a temporary, get a spill location that is not in use and spill the content to the spill location;
   2690 //!If updateTable is true, set physicalReg to Null;
   2691 //!Return the physical register that was allocated to the variable
   2692 int spillLogicalReg(int spill_index, bool updateTable) {
   2693     if((compileTable[spill_index].physicalType & LowOpndRegType_hard) != 0) {
   2694         ALOGE("can't spill a hard-coded register");
   2695         dvmAbort();
   2696     }
   2697     int physicalReg = compileTable[spill_index].physicalReg;
   2698     if(!canSpillReg[physicalReg]) {
   2699 #ifdef PRINT_WARNING
   2700         ALOGW("can't spill register %d", physicalReg);
   2701 #endif
   2702         //dvmAbort(); //this happens in get_virtual_reg where VR is allocated to the same reg as the hardcoded temporary
   2703     }
   2704     if(isVirtualReg(compileTable[spill_index].physicalType)) {
   2705         //spill back to memory
   2706         dumpToMem(compileTable[spill_index].regNum,
   2707                   (LowOpndRegType)(compileTable[spill_index].physicalType&MASK_FOR_TYPE),
   2708                   compileTable[spill_index].physicalReg);
   2709     }
   2710     else {
   2711         //update spill_loc_index
   2712         int k = getSpillIndex(spill_index == indexForGlue,
   2713                     getRegSize(compileTable[spill_index].physicalType));
   2714         compileTable[spill_index].spill_loc_index = 4*k;
   2715         if(k >= 0)
   2716             spillIndexUsed[k] = 1;
   2717         saveToSpillRegion(getRegSize(compileTable[spill_index].physicalType),
   2718                           compileTable[spill_index].physicalReg, 4*k);
   2719     }
   2720     //compileTable[spill_index].physicalReg_prev = compileTable[spill_index].physicalReg;
   2721 #ifdef DEBUG_REGALLOC
   2722     ALOGI("REGALLOC: SPILL logical reg %d %d with refCount %d allocated to %d",
   2723            compileTable[spill_index].regNum,
   2724            compileTable[spill_index].physicalType, compileTable[spill_index].refCount,
   2725            compileTable[spill_index].physicalReg);
   2726 #endif
   2727     if(!updateTable) return PhysicalReg_Null;
   2728 
   2729     int allocR = compileTable[spill_index].physicalReg;
   2730     compileTable[spill_index].physicalReg = PhysicalReg_Null;
   2731     return allocR;
   2732 }
   2733 //! load a varible from memory to physical register, the variable is specified with an index to compileTable
   2734 
   2735 //!If the variable is a temporary, load from spill location and set the flag for the spill location to not used
   2736 int unspillLogicalReg(int spill_index, int physicalReg) {
   2737     //can't un-spill to %eax in afterCall!!!
   2738     //what if GG VR is allocated to %eax!!!
   2739     if(isVirtualReg(compileTable[spill_index].physicalType)) {
   2740         get_virtual_reg_noalloc(compileTable[spill_index].regNum,
   2741                                 getRegSize(compileTable[spill_index].physicalType),
   2742                                 physicalReg, true);
   2743     }
   2744     else {
   2745         loadFromSpillRegion(getRegSize(compileTable[spill_index].physicalType),
   2746                             physicalReg, compileTable[spill_index].spill_loc_index);
   2747         spillIndexUsed[compileTable[spill_index].spill_loc_index >> 2] = 0;
   2748         compileTable[spill_index].spill_loc_index = -1;
   2749     }
   2750 #ifdef DEBUG_REGALLOC
   2751     ALOGI("REGALLOC: UNSPILL logical reg %d %d with refCount %d", compileTable[spill_index].regNum,
   2752            compileTable[spill_index].physicalType, compileTable[spill_index].refCount);
   2753 #endif
   2754     return PhysicalReg_Null;
   2755 }
   2756 
   2757 //!spill a virtual register to memory
   2758 
   2759 //!if the current value of a VR is constant, write immediate to memory;
   2760 //!if the current value of a VR is in a physical register, call spillLogicalReg to dump content of the physical register to memory;
   2761 //!ifupdateTable is true, set the physical register for VR to Null and decrease reference count of the virtual register
   2762 int spillVirtualReg(int vrNum, LowOpndRegType type, bool updateTable) {
   2763     int index = searchCompileTable(type | LowOpndRegType_virtual, vrNum);
   2764     if(index < 0) {
   2765         ALOGE("can't find VR %d %d in spillVirtualReg", vrNum, type);
   2766         return -1;
   2767     }
   2768     //check whether it is const
   2769     int value[2];
   2770     int isConst = isVirtualRegConstant(vrNum, type, value, false); //do not update refCount
   2771     if(isConst == 1 || isConst == 3) {
   2772         dumpImmToMem(vrNum, OpndSize_32, value[0]);
   2773     }
   2774     if(getRegSize(type) == OpndSize_64 && (isConst == 2 || isConst == 3)) {
   2775         dumpImmToMem(vrNum+1, OpndSize_32, value[1]);
   2776     }
   2777     if(isConst != 3 && compileTable[index].physicalReg != PhysicalReg_Null)
   2778         spillLogicalReg(index, updateTable);
   2779     if(updateTable) decreaseRefCount(index);
   2780     return -1;
   2781 }
   2782 
   2783 //! spill variables that are mapped to physical register (regNum)
   2784 
   2785 //!
   2786 int spillForHardReg(int regNum, int type) {
   2787     //find an entry that uses the physical register
   2788     int spill_index = -1;
   2789     int k;
   2790     for(k = 0; k < num_compile_entries; k++) {
   2791         if(k != indexForGlue &&
   2792            compileTable[k].physicalReg == regNum &&
   2793            matchType(type, compileTable[k].physicalType)) {
   2794             spill_index = k;
   2795             if(compileTable[k].regNum == regNum && compileTable[k].physicalType == type)
   2796                 continue;
   2797             if(inGetVR_num >= 0 && compileTable[k].regNum == inGetVR_num && compileTable[k].physicalType == (type | LowOpndRegType_virtual))
   2798                 continue;
   2799 #ifdef DEBUG_REGALLOC
   2800             ALOGI("SPILL logical reg %d %d to free hard-coded reg %d %d",
   2801                    compileTable[spill_index].regNum, compileTable[spill_index].physicalType,
   2802                    regNum, type);
   2803             if(compileTable[spill_index].physicalType & LowOpndRegType_hard) dumpCompileTable();
   2804 #endif
   2805             assert(spill_index < COMPILE_TABLE_SIZE);
   2806             spillLogicalReg(spill_index, true);
   2807         }
   2808     }
   2809     return regNum;
   2810 }
   2811 ////////////////////////////////////////////////////////////////
   2812 //! update allocConstraints of the current basic block
   2813 
   2814 //! allocConstraints specify how many times a hardcoded register is used in this basic block
   2815 void updateCurrentBBWithConstraints(PhysicalReg reg) {
   2816     if(reg > PhysicalReg_EBP) {
   2817         ALOGE("register %d out of range in updateCurrentBBWithConstraints", reg);
   2818     }
   2819     currentBB->allocConstraints[reg].count++;
   2820 }
   2821 //! sort allocConstraints and save the result in allocConstraintsSorted
   2822 
   2823 //! allocConstraints specify how many times a virtual register is linked to a hardcode register
   2824 //! it is updated in getVirtualRegInfo and merged by mergeEntry2
   2825 int sortAllocConstraint(RegAllocConstraint* allocConstraints,
   2826                         RegAllocConstraint* allocConstraintsSorted, bool fromHighToLow) {
   2827     int ii, jj;
   2828     int num_sorted = 0;
   2829     for(jj = 0; jj < 8; jj++) {
   2830         //figure out where to insert allocConstraints[jj]
   2831         int count = allocConstraints[jj].count;
   2832         int regT = allocConstraints[jj].physicalReg;
   2833         assert(regT < PhysicalReg_Null);
   2834         int insertIndex = -1;
   2835         for(ii = 0; ii < num_sorted; ii++) {
   2836             int regT2 = allocConstraintsSorted[ii].physicalReg;
   2837             assert(regT2 < PhysicalReg_Null);
   2838             if(allRegs[regT].isCalleeSaved &&
   2839                count == allocConstraintsSorted[ii].count) {
   2840                 insertIndex = ii;
   2841                 break;
   2842             }
   2843             if((!allRegs[regT].isCalleeSaved) &&
   2844                count == allocConstraintsSorted[ii].count &&
   2845                (!allRegs[regT2].isCalleeSaved)) { //skip until found one that is not callee-saved
   2846                 insertIndex = ii;
   2847                 break;
   2848             }
   2849             if((fromHighToLow && count > allocConstraintsSorted[ii].count) ||
   2850                ((!fromHighToLow) && count < allocConstraintsSorted[ii].count)) {
   2851                 insertIndex = ii;
   2852                 break;
   2853             }
   2854         }
   2855         if(insertIndex < 0) {
   2856             allocConstraintsSorted[num_sorted].physicalReg = (PhysicalReg)regT;
   2857             allocConstraintsSorted[num_sorted].count = count;
   2858             num_sorted++;
   2859         } else {
   2860             for(ii = num_sorted-1; ii >= insertIndex; ii--) {
   2861                 allocConstraintsSorted[ii+1] = allocConstraintsSorted[ii];
   2862             }
   2863             allocConstraintsSorted[insertIndex] = allocConstraints[jj];
   2864             num_sorted++;
   2865         }
   2866     } //for jj
   2867 #ifdef DEBUG_ALLOC_CONSTRAINT
   2868     for(jj = 0; jj < 8; jj++) {
   2869         if(allocConstraintsSorted[jj].count > 0)
   2870             ALOGI("%d: register %d has count %d", jj, allocConstraintsSorted[jj].physicalReg, allocConstraintsSorted[jj].count);
   2871     }
   2872 #endif
   2873     return 0;
   2874 }
   2875 //! find the entry for a given virtual register in compileTable
   2876 
   2877 //!
   2878 int findVirtualRegInTable(u2 vA, LowOpndRegType type, bool printError) {
   2879     int k = searchCompileTable(type | LowOpndRegType_virtual, vA);
   2880     if(k < 0 && printError) {
   2881         ALOGE("findVirtualRegInTable virtual register %d type %d", vA, type);
   2882         dvmAbort();
   2883     }
   2884     return k;
   2885 }
   2886 
   2887 //! check whether a virtual register is constant
   2888 
   2889 //! the value of the constant is stored in valuePtr; if updateRefCount is true & the VR is constant, reference count for the VR will be reduced by 1
   2890 int isVirtualRegConstant(int regNum, LowOpndRegType type, int* valuePtr, bool updateRefCount) {
   2891 
   2892     OpndSize size = getRegSize(type);
   2893     int k;
   2894     int indexL = -1;
   2895     int indexH = -1;
   2896     for(k = 0; k < num_const_vr; k++) {
   2897 #ifdef DEBUG_CONST
   2898         ALOGI("constVRTable VR %d isConst %d value %x", constVRTable[k].regNum, constVRTable[k].isConst, constVRTable[k].value);
   2899 #endif
   2900         if(constVRTable[k].regNum == regNum) {
   2901             indexL = k;
   2902             continue;
   2903         }
   2904         if(constVRTable[k].regNum == regNum + 1 && size == OpndSize_64) {
   2905             indexH = k;
   2906             continue;
   2907         }
   2908     }
   2909     bool isConstL = false;
   2910     bool isConstH = false;
   2911     if(indexL >= 0) {
   2912         isConstL = constVRTable[indexL].isConst;
   2913     }
   2914     if(size == OpndSize_64 && indexH >= 0) {
   2915         isConstH = constVRTable[indexH].isConst;
   2916     }
   2917 
   2918     if((isConstL || isConstH)) {
   2919         if(size == OpndSize_64 && isConstH)
   2920             valuePtr[1] = constVRTable[indexH].value;
   2921         if(isConstL)
   2922             *valuePtr = constVRTable[indexL].value;
   2923     }
   2924     if((isConstL && size == OpndSize_32) || (isConstL && isConstH)) {
   2925         if(updateRefCount) {
   2926             int indexOrig = searchCompileTable(type | LowOpndRegType_virtual, regNum);
   2927             if(indexOrig < 0) ALOGE("can't find VR in isVirtualRegConstant num %d type %d", regNum, type);
   2928             decreaseRefCount(indexOrig);
   2929         }
   2930 #ifdef DEBUG_CONST
   2931         ALOGI("VR %d %d is const case", regNum, type);
   2932 #endif
   2933         return 3;
   2934     }
   2935     if(size == OpndSize_32) return 0;
   2936     if(isConstL) return 1;
   2937     if(isConstH) return 2;
   2938     return 0;
   2939 }
   2940 
   2941 //!update RegAccessType of virtual register vB given RegAccessType of vA
   2942 
   2943 //!RegAccessType can be D, L, H
   2944 //!D means full definition, L means only lower-half is defined, H means only higher half is defined
   2945 //!we say a VR has no exposed usage in a basic block if the accessType is D or DU
   2946 //!we say a VR has exposed usage in a basic block if the accessType is not D nor DU
   2947 //!we say a VR has exposed usage in other basic blocks (hasOtherExposedUsage) if
   2948 //!  there exists another basic block where VR has exposed usage in that basic block
   2949 //!A can be U, D, L, H, UD, UL, UH, DU, LU, HU (merged result)
   2950 //!B can be U, D, UD, DU (an entry for the current bytecode)
   2951 //!input isAPartiallyOverlapB can be any value between -1 to 6
   2952 //!if A is xmm: gp B lower half of A, (isAPartiallyOverlapB is 1)
   2953 //!             gp B higher half of A, (isAPartiallyOverlapB is 2)
   2954 //!             lower half of A covers the higher half of xmm B  (isAPartiallyOverlapB is 4)
   2955 //!             higher half of A covers the lower half of xmm B   (isAPartiallyOverlapB is 3)
   2956 //!if A is gp:  A covers the lower half of xmm B, (isAPartiallyOverlapB is 5)
   2957 //!             A covers the higher half of xmm B (isAPartiallyOverlapB is 6)
   2958 RegAccessType updateAccess1(RegAccessType A, OverlapCase isAPartiallyOverlapB) {
   2959     if(A == REGACCESS_D || A == REGACCESS_DU || A == REGACCESS_UD) {
   2960         if(isAPartiallyOverlapB == OVERLAP_ALIGN) return REGACCESS_D;
   2961         if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A || isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A)
   2962             return REGACCESS_D;
   2963         if(isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
   2964             return REGACCESS_L;
   2965         return REGACCESS_H;
   2966     }
   2967     if(A == REGACCESS_L || A == REGACCESS_LU || A == REGACCESS_UL) {
   2968         if(isAPartiallyOverlapB == OVERLAP_ALIGN || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
   2969             return REGACCESS_L;
   2970         if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A) return REGACCESS_D;
   2971         if(isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A || isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B)
   2972             return REGACCESS_N;
   2973         if(isAPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B)
   2974             return REGACCESS_H;
   2975     }
   2976     if(A == REGACCESS_H || A == REGACCESS_HU || A == REGACCESS_UH) {
   2977         if(isAPartiallyOverlapB == OVERLAP_ALIGN || isAPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B)
   2978             return REGACCESS_H;
   2979         if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A || isAPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B)
   2980             return REGACCESS_N;
   2981         if(isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A) return REGACCESS_D;
   2982         if(isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
   2983             return REGACCESS_L;
   2984     }
   2985     return REGACCESS_N;
   2986 }
   2987 //! merge RegAccessType C1 with RegAccessType C2
   2988 
   2989 //!C can be N,L,H,D
   2990 RegAccessType updateAccess2(RegAccessType C1, RegAccessType C2) {
   2991     if(C1 == REGACCESS_D || C2 == REGACCESS_D) return REGACCESS_D;
   2992     if(C1 == REGACCESS_N) return C2;
   2993     if(C2 == REGACCESS_N) return C1;
   2994     if(C1 == REGACCESS_L && C2 == REGACCESS_H) return REGACCESS_D;
   2995     if(C1 == REGACCESS_H && C2 == REGACCESS_L) return REGACCESS_D;
   2996     return C1;
   2997 }
   2998 //! merge RegAccessType C with RegAccessType B
   2999 
   3000 //!C can be N,L,H,D
   3001 //!B can be U, D, UD, DU
   3002 RegAccessType updateAccess3(RegAccessType C, RegAccessType B) {
   3003     if(B == REGACCESS_D || B == REGACCESS_DU) return B; //no exposed usage
   3004     if(B == REGACCESS_U || B == REGACCESS_UD) {
   3005         if(C == REGACCESS_N) return B;
   3006         if(C == REGACCESS_L) return REGACCESS_LU;
   3007         if(C == REGACCESS_H) return REGACCESS_HU;
   3008         if(C == REGACCESS_D) return REGACCESS_DU;
   3009     }
   3010     return B;
   3011 }
   3012 //! merge RegAccessType A with RegAccessType B
   3013 
   3014 //!argument isBPartiallyOverlapA can be any value between -1 and 2
   3015 //!0 means fully overlapping, 1 means B is the lower half, 2 means B is the higher half
   3016 RegAccessType mergeAccess2(RegAccessType A, RegAccessType B, OverlapCase isBPartiallyOverlapA) {
   3017     if(A == REGACCESS_UD || A == REGACCESS_UL || A == REGACCESS_UH ||
   3018        A == REGACCESS_DU || A == REGACCESS_LU || A == REGACCESS_HU) return A;
   3019     if(A == REGACCESS_D) {
   3020         if(B == REGACCESS_D) return REGACCESS_D;
   3021         if(B == REGACCESS_U) return REGACCESS_DU;
   3022         if(B == REGACCESS_UD) return REGACCESS_DU;
   3023         if(B == REGACCESS_DU) return B;
   3024     }
   3025     if(A == REGACCESS_U) {
   3026         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
   3027         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
   3028         if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
   3029         if(B == REGACCESS_U) return A;
   3030         if(B == REGACCESS_UD && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
   3031         if(B == REGACCESS_UD && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
   3032         if(B == REGACCESS_UD && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
   3033         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
   3034         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
   3035         if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
   3036     }
   3037     if(A == REGACCESS_L) {
   3038         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_L;
   3039         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_D;
   3040         if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_D;
   3041         if(B == REGACCESS_U) return REGACCESS_LU;
   3042         if(B == REGACCESS_UD) return REGACCESS_LU;
   3043         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_LU;
   3044         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_DU;
   3045         if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_DU;
   3046     }
   3047     if(A == REGACCESS_H) {
   3048         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_D;
   3049         if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_H;
   3050         if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_D;
   3051         if(B == REGACCESS_U) return REGACCESS_HU;
   3052         if(B == REGACCESS_UD) return REGACCESS_HU;
   3053         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_DU;
   3054         if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_HU;
   3055         if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_DU;
   3056     }
   3057     return REGACCESS_N;
   3058 }
   3059 
   3060 //!determines which part of a use is from a given definition
   3061 
   3062 //!reachingDefLive tells us which part of the def is live at this point
   3063 //!isDefPartiallyOverlapUse can be any value between -1 and 2
   3064 RegAccessType setAccessTypeOfUse(OverlapCase isDefPartiallyOverlapUse, RegAccessType reachingDefLive) {
   3065     if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_A)
   3066         return reachingDefLive;
   3067     if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_LOW_OF_A) { //def covers the low half of use
   3068         return REGACCESS_L;
   3069     }
   3070     if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_HIGH_OF_A) {
   3071         return REGACCESS_H;
   3072     }
   3073     return REGACCESS_N;
   3074 }
   3075 
   3076 //! search currentBB->defUseTable to find a def for regNum at offsetPC
   3077 
   3078 //!
   3079 DefUsePair* searchDefUseTable(int offsetPC, int regNum, LowOpndRegType pType) {
   3080     DefUsePair* ptr = currentBB->defUseTable;
   3081     while(ptr != NULL) {
   3082         if(ptr->def.offsetPC == offsetPC &&
   3083            ptr->def.regNum == regNum &&
   3084            ptr->def.physicalType == pType) {
   3085             return ptr;
   3086         }
   3087         ptr = ptr->next;
   3088     }
   3089     return NULL;
   3090 }
   3091 void printDefUseTable() {
   3092     ALOGI("PRINT defUseTable --------");
   3093     DefUsePair* ptr = currentBB->defUseTable;
   3094     while(ptr != NULL) {
   3095         ALOGI("  def @ %x of VR %d %d has %d uses", ptr->def.offsetPC,
   3096               ptr->def.regNum, ptr->def.physicalType,
   3097               ptr->num_uses);
   3098         DefOrUseLink* ptr2 = ptr->uses;
   3099         while(ptr2 != NULL) {
   3100             ALOGI("    use @ %x of VR %d %d accessType %d", ptr2->offsetPC,
   3101                   ptr2->regNum,
   3102                   ptr2->physicalType,
   3103                   ptr2->accessType);
   3104             ptr2 = ptr2->next;
   3105         }
   3106         ptr = ptr->next;
   3107     }
   3108 }
   3109 //! when a VR is used, check whether a transfer from memory to XMM is necessary
   3110 
   3111 //!
   3112 int updateVRAtUse(int reg, LowOpndRegType pType, int regAll) {
   3113     int k;
   3114     for(k = 0; k < currentBB->num_xfer_points; k++) {
   3115         if(currentBB->xferPoints[k].offsetPC == offsetPC &&
   3116            currentBB->xferPoints[k].xtype == XFER_MEM_TO_XMM &&
   3117            currentBB->xferPoints[k].regNum == reg &&
   3118            currentBB->xferPoints[k].physicalType == pType) {
   3119 #ifdef DEBUG_XFER_POINTS
   3120             ALOGI("XFER from memory to xmm %d", reg);
   3121 #endif
   3122             move_mem_to_reg_noalloc(OpndSize_64,
   3123                                     4*currentBB->xferPoints[k].regNum, PhysicalReg_FP, true,
   3124                                     MemoryAccess_VR, currentBB->xferPoints[k].regNum,
   3125                                     regAll, true);
   3126         }
   3127     }
   3128     return 0;
   3129 }
   3130 ///////////////////////////////////////////////////////////////////////////////
   3131 // DEAD/USELESS STATEMENT ELMINATION
   3132 // bytecodes can be removed if a bytecode has no side effect and the defs are not used
   3133 // this optimization is guarded with DSE_OPT
   3134 // currently, this optimization is not on, since it does not provide observable performance improvement
   3135 //     and it increases compilation time
   3136 
   3137 /* we remove a maximal of 40 bytecodes within a single basic block */
   3138 #define MAX_NUM_DEAD_PC_IN_BB 40
   3139 int deadPCs[MAX_NUM_DEAD_PC_IN_BB];
   3140 int num_dead_pc = 0;
   3141 //! collect all PCs that can be removed
   3142 
   3143 //! traverse each byte code in the current basic block and check whether it can be removed, if yes, update deadPCs
   3144 void getDeadStmts() {
   3145     BasicBlock_O1* bb = currentBB;
   3146     int k;
   3147     num_dead_pc = 0;
   3148     //traverse each bytecode in the basic block
   3149     //update offsetPC, rPC & inst
   3150     u2* rPC_start = (u2*)currentMethod->insns;
   3151     MIR* mir;
   3152     for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
   3153         offsetPC = mir->seqNum;
   3154         rPC = rPC_start + mir->offset;
   3155         if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) continue;
   3156 #ifdef DEBUG_DSE
   3157         ALOGI("DSE: offsetPC %x", offsetPC);
   3158 #endif
   3159         inst = FETCH(0);
   3160         bool isDeadStmt = true;
   3161         getVirtualRegInfo(infoByteCode);
   3162         u2 inst_op = INST_INST(inst);
   3163 	//skip bytecodes with side effect
   3164         if(inst_op != OP_CONST_STRING && inst_op != OP_CONST_STRING_JUMBO &&
   3165            inst_op != OP_MOVE && inst_op != OP_MOVE_OBJECT &&
   3166            inst_op != OP_MOVE_FROM16 && inst_op != OP_MOVE_OBJECT_FROM16 &&
   3167            inst_op != OP_MOVE_16 && inst_op != OP_CONST_CLASS &&
   3168            inst_op != OP_MOVE_OBJECT_16 && inst_op != OP_MOVE_WIDE &&
   3169            inst_op != OP_MOVE_WIDE_FROM16 && inst_op != OP_MOVE_WIDE_16 &&
   3170            inst_op != OP_MOVE_RESULT && inst_op != OP_MOVE_RESULT_OBJECT) {
   3171             continue;
   3172         }
   3173         //some statements do not define any VR!!!
   3174         int num_defs = 0;
   3175         for(k = 0; k < num_regs_per_bytecode; k++) {
   3176             if(infoByteCode[k].accessType == REGACCESS_D ||
   3177                infoByteCode[k].accessType == REGACCESS_UD ||
   3178                infoByteCode[k].accessType == REGACCESS_DU) { //search defUseTable
   3179                 num_defs++;
   3180                 DefUsePair* indexT = searchDefUseTable(offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
   3181                 if(indexT == NULL) {
   3182                     ALOGE("def at %x of VR %d %d not in table",
   3183                            offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
   3184                     return;
   3185                 }
   3186                 if(indexT->num_uses > 0) {
   3187                     isDeadStmt = false;
   3188                     break;
   3189                 } else {
   3190 #ifdef DEBUG_DSE
   3191                     ALOGI("DSE: num_uses is %d for def at %d for VR %d %d", indexT->num_uses,
   3192                           offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
   3193 #endif
   3194                 }
   3195             }
   3196         } //for k
   3197         if(num_defs == 0) isDeadStmt = false;
   3198         if(isDeadStmt && num_dead_pc < MAX_NUM_DEAD_PC_IN_BB) {
   3199 #ifdef DEBUG_DSE
   3200             ALOGI("DSE: stmt at %x is dead", offsetPC);
   3201 #endif
   3202             deadPCs[num_dead_pc++] = offsetPC;
   3203         }
   3204     } //for offsetPC
   3205 #ifdef DEBUG_DSE
   3206     ALOGI("Dead Stmts: ");
   3207     for(k = 0; k < num_dead_pc; k++) ALOGI("%x ", deadPCs[k]);
   3208     ALOGI("");
   3209 #endif
   3210 }
   3211 //! entry point to remove dead statements
   3212 
   3213 //! recursively call getDeadStmts and remove uses in defUseTable that are from a dead PC
   3214 //! until there is no change to number of dead PCs
   3215 void removeDeadDefs() {
   3216     int k;
   3217     int deadPCs_2[MAX_NUM_DEAD_PC_IN_BB];
   3218     int num_dead_pc_2 = 0;
   3219     getDeadStmts();
   3220     if(num_dead_pc == 0) return;
   3221     DefUsePair* ptr = NULL;
   3222     DefOrUseLink* ptrUse = NULL;
   3223     DefOrUseLink* ptrUse_prev = NULL;
   3224     while(true) {
   3225         //check all the uses in defUseTable and remove any use that is from a dead PC
   3226         ptr = currentBB->defUseTable;
   3227         while(ptr != NULL) {
   3228             int k3;
   3229             ptrUse = ptr->uses;
   3230             ptrUse_prev = NULL;
   3231             while(ptrUse != NULL) {
   3232                 bool isIn = false;
   3233                 for(k3 = 0; k3 < num_dead_pc; k3++) {
   3234                     if(ptrUse->offsetPC == deadPCs[k3]) {
   3235                         isIn = true;
   3236                         break;
   3237                     }
   3238                 }//k3
   3239                 if(!isIn) {
   3240                     ptrUse_prev = ptrUse;
   3241                     ptrUse = ptrUse->next; //next use
   3242                 }
   3243                 else {
   3244                     //go to next use and remove ptrUse
   3245 #ifdef DEBUG_DSE
   3246                     ALOGI("DSE: remove usage at offsetPC %d reached by def at %d", ptrUse->offsetPC,
   3247                            ptr->def.offsetPC);
   3248 #endif
   3249                     DefOrUseLink* nextP = ptrUse->next;
   3250                     if(ptrUse == ptr->useTail) ptr->useTail = ptrUse_prev;
   3251                     free(ptrUse);
   3252                     if(ptrUse_prev == NULL) {
   3253                         ptr->uses = nextP;
   3254                     } else {
   3255                         ptrUse_prev->next = nextP;
   3256                     }
   3257                     ptrUse = nextP; //do not update ptrUse_prev
   3258                     ptr->num_uses--;
   3259                 }
   3260             }//while ptrUse
   3261             ptr = ptr->next;
   3262         }//while ptr
   3263 	//save deadPCs in deadPCs_2
   3264         num_dead_pc_2 = num_dead_pc;
   3265         for(k = 0; k < num_dead_pc_2; k++)
   3266             deadPCs_2[k] = deadPCs[k];
   3267 	//update deadPCs
   3268         getDeadStmts();
   3269 	//if no change to number of dead PCs, break out of the while loop
   3270         if(num_dead_pc_2 == num_dead_pc) break;
   3271     }//while
   3272 #ifdef DEBUG_DSE
   3273     ALOGI("DSE: DEAD STMTS: ");
   3274     for(k = 0; k < num_dead_pc; k++) {
   3275         ALOGI("%d ", deadPCs[k]);
   3276     }
   3277     ALOGI("");
   3278 #endif
   3279 }
   3280 /////////////////////////////////////////////////////////////
   3281 //!search memVRTable for a given virtual register
   3282 
   3283 //!
   3284 int searchMemTable(int regNum) {
   3285     int k;
   3286     for(k = 0; k < num_memory_vr; k++) {
   3287         if(memVRTable[k].regNum == regNum) {
   3288             return k;
   3289         }
   3290     }
   3291     ALOGW("in searchMemTable can't find VR %d num_memory_vr %d", regNum, num_memory_vr);
   3292     return -1;
   3293 }
   3294 /////////////////////////////////////////////////////////////////////////
   3295 // A VR is already in memory && NULL CHECK
   3296 //!check whether the latest content of a VR is in memory
   3297 
   3298 //!
   3299 bool isInMemory(int regNum, OpndSize size) {
   3300     int indexL = searchMemTable(regNum);
   3301     int indexH = -1;
   3302     if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
   3303     if(indexL < 0) return false;
   3304     if(size == OpndSize_64 && indexH < 0) return false;
   3305     if(!memVRTable[indexL].inMemory) return false;
   3306     if(size == OpndSize_64 && (!memVRTable[indexH].inMemory)) return false;
   3307     return true;
   3308 }
   3309 //!set field inMemory of memVRTable to true
   3310 
   3311 //!
   3312 void setVRToMemory(int regNum, OpndSize size) {
   3313     int indexL = searchMemTable(regNum);
   3314     int indexH = -1;
   3315     if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
   3316     if(indexL < 0) {
   3317         ALOGE("VR %d not in memVRTable", regNum);
   3318         return;
   3319     }
   3320     memVRTable[indexL].inMemory = true;
   3321     if(size == OpndSize_64) {
   3322         if(indexH < 0) {
   3323             ALOGE("VR %d not in memVRTable", regNum+1);
   3324             return;
   3325         }
   3326         memVRTable[indexH].inMemory = true;
   3327     }
   3328 }
   3329 //! check whether null check for a VR is performed previously
   3330 
   3331 //!
   3332 bool isVRNullCheck(int regNum, OpndSize size) {
   3333     if(size != OpndSize_32) {
   3334         ALOGE("isVRNullCheck size should be 32");
   3335         dvmAbort();
   3336     }
   3337     int indexL = searchMemTable(regNum);
   3338     if(indexL < 0) {
   3339         ALOGE("VR %d not in memVRTable", regNum);
   3340         return false;
   3341     }
   3342     return memVRTable[indexL].nullCheckDone;
   3343 }
   3344 bool isVRBoundCheck(int vr_array, int vr_index) {
   3345     int indexL = searchMemTable(vr_array);
   3346     if(indexL < 0) {
   3347         ALOGE("isVRBoundCheck: VR %d not in memVRTable", vr_array);
   3348         return false;
   3349     }
   3350     if(memVRTable[indexL].boundCheck.indexVR == vr_index)
   3351         return memVRTable[indexL].boundCheck.checkDone;
   3352     return false;
   3353 }
   3354 //! set nullCheckDone in memVRTable to true
   3355 
   3356 //!
   3357 void setVRNullCheck(int regNum, OpndSize size) {
   3358     if(size != OpndSize_32) {
   3359         ALOGE("setVRNullCheck size should be 32");
   3360         dvmAbort();
   3361     }
   3362     int indexL = searchMemTable(regNum);
   3363     if(indexL < 0) {
   3364         ALOGE("VR %d not in memVRTable", regNum);
   3365         return;
   3366     }
   3367     memVRTable[indexL].nullCheckDone = true;
   3368 }
   3369 void setVRBoundCheck(int vr_array, int vr_index) {
   3370     int indexL = searchMemTable(vr_array);
   3371     if(indexL < 0) {
   3372         ALOGE("setVRBoundCheck: VR %d not in memVRTable", vr_array);
   3373         return;
   3374     }
   3375     memVRTable[indexL].boundCheck.indexVR = vr_index;
   3376     memVRTable[indexL].boundCheck.checkDone = true;
   3377 }
   3378 void clearVRBoundCheck(int regNum, OpndSize size) {
   3379     int k;
   3380     for(k = 0; k < num_memory_vr; k++) {
   3381         if(memVRTable[k].regNum == regNum ||
   3382            (size == OpndSize_64 && memVRTable[k].regNum == regNum+1)) {
   3383             memVRTable[k].boundCheck.checkDone = false;
   3384         }
   3385         if(memVRTable[k].boundCheck.indexVR == regNum ||
   3386            (size == OpndSize_64 && memVRTable[k].boundCheck.indexVR == regNum+1)) {
   3387             memVRTable[k].boundCheck.checkDone = false;
   3388         }
   3389     }
   3390 }
   3391 //! set inMemory of memVRTable to false
   3392 
   3393 //!
   3394 void clearVRToMemory(int regNum, OpndSize size) {
   3395     int indexL = searchMemTable(regNum);
   3396     int indexH = -1;
   3397     if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
   3398     if(indexL >= 0) {
   3399         memVRTable[indexL].inMemory = false;
   3400     }
   3401     if(size == OpndSize_64 && indexH >= 0) {
   3402         memVRTable[indexH].inMemory = false;
   3403     }
   3404 }
   3405 //! set nullCheckDone of memVRTable to false
   3406 
   3407 //!
   3408 void clearVRNullCheck(int regNum, OpndSize size) {
   3409     int indexL = searchMemTable(regNum);
   3410     int indexH = -1;
   3411     if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
   3412     if(indexL >= 0) {
   3413         memVRTable[indexL].nullCheckDone = false;
   3414     }
   3415     if(size == OpndSize_64 && indexH >= 0) {
   3416         memVRTable[indexH].nullCheckDone = false;
   3417     }
   3418 }
   3419 
   3420 //! Extend Virtual Register life
   3421 
   3422 //! Requests that the life of a specific virtual register be extended. This ensures
   3423 //! that its mapping to a physical register won't be canceled while the extension
   3424 //! request is valid. NOTE: This does not support 64-bit values (when two adjacent
   3425 //! VRs are used)
   3426 //! @see cancelVRFreeDelayRequest
   3427 //! @see getVRFreeDelayRequested
   3428 //! @see VRFreeDelayFlags
   3429 //! @param regNum is the VR number
   3430 //! @param reason explains why freeing must be delayed. A single or combination
   3431 //! of VRFreeDelayFlags should be used.
   3432 //! @return negative value if request failed
   3433 int requestVRFreeDelay(int regNum, u4 reason) {
   3434     //TODO Add 64-bit operand support when needed
   3435     int indexL = searchMemTable(regNum);
   3436     if(indexL >= 0) {
   3437         memVRTable[indexL].delayFreeFlags |= reason;
   3438     } else {
   3439         ALOGE("requestVRFreeDelay: VR %d not in memVRTable", regNum);
   3440     }
   3441     return indexL;
   3442 }
   3443 
   3444 //! Cancel request for virtual register life extension
   3445 
   3446 //! Cancels any outstanding requests to extended liveness of VR. Additionally,
   3447 //! this ensures that if the VR is no longer life after this point, it will
   3448 //! no longer be associated with a physical register which can then be reused.
   3449 //! NOTE: This does not support 64-bit values (when two adjacent VRs are used)
   3450 //! @see requestVRFreeDelay
   3451 //! @see getVRFreeDelayRequested
   3452 //! @see VRFreeDelayFlags
   3453 //! @param regNum is the VR number
   3454 //! @param reason explains what freeing delay request should be canceled. A single
   3455 //! or combination of VRFreeDelayFlags should be used.
   3456 void cancelVRFreeDelayRequest(int regNum, u4 reason) {
   3457     //TODO Add 64-bit operand support when needed
   3458     bool needCallToFreeReg = false;
   3459     int indexL = searchMemTable(regNum);
   3460     if(indexL >= 0) {
   3461         if((memVRTable[indexL].delayFreeFlags & reason) != VRDELAY_NONE) { // don't cancel delay if it wasn't requested
   3462             memVRTable[indexL].delayFreeFlags ^= reason; // only cancel this particular reason, not all others
   3463             if(memVRTable[indexL].delayFreeFlags == VRDELAY_NONE)
   3464                 needCallToFreeReg = true; // freeReg might want to free this VR now if there is no longer a valid delay
   3465         }
   3466     }
   3467     if(needCallToFreeReg)
   3468         freeReg(true);
   3469 }
   3470 
   3471 //! Gets status of virtual register free delay request
   3472 
   3473 //! Finds out if there was a delay request for freeing this VR.
   3474 //! NOTE: This does not support 64-bit values (when two adjacent VRs are used)
   3475 //! @see requestVRFreeDelay
   3476 //! @see cancelVRFreeDelayRequest
   3477 //! @param regNum is the VR number
   3478 //! @return true if VR has an active delay request
   3479 bool getVRFreeDelayRequested(int regNum) {
   3480     //TODO Add 64-bit operand support when needed
   3481     int indexL = searchMemTable(regNum);
   3482     if(indexL >= 0) {
   3483         if(memVRTable[indexL].delayFreeFlags != VRDELAY_NONE)
   3484             return true;
   3485         return false;
   3486     }
   3487     return false;
   3488 }
   3489 
   3490 //! find the basic block that a bytecode is in
   3491 
   3492 //!
   3493 BasicBlock_O1* findForOffset(int offset) {
   3494     int k;
   3495     for(k = 0; k < num_bbs_for_method; k++) {
   3496         if(method_bbs_sorted[k]->pc_start <= offset && method_bbs_sorted[k]->pc_end > offset)
   3497             return method_bbs_sorted[k];
   3498     }
   3499     return NULL;
   3500 }
   3501 void dump_CFG(Method* method);
   3502 
   3503 int current_bc_size = -1;
   3504 
   3505 //! check whether a virtual register is used in a basic block
   3506 
   3507 //!
   3508 bool isUsedInBB(int regNum, int type, BasicBlock_O1* bb) {
   3509     int k;
   3510     for(k = 0; k < bb->num_regs; k++) {
   3511         if(bb->infoBasicBlock[k].physicalType == (type&MASK_FOR_TYPE) && bb->infoBasicBlock[k].regNum == regNum)
   3512             return true;
   3513     }
   3514     return false;
   3515 }
   3516 //! return the index to infoBasicBlock for a given virtual register
   3517 
   3518 //! return -1 if not found
   3519 int searchVirtualInfoOfBB(LowOpndRegType type, int regNum, BasicBlock_O1* bb) {
   3520     int k;
   3521     for(k = 0; k < bb->num_regs; k++) {
   3522         if(bb->infoBasicBlock[k].physicalType == type && bb->infoBasicBlock[k].regNum == regNum)
   3523             return k;
   3524     }
   3525     return -1;
   3526 }
   3527 //! return the index to compileTable for a given virtual register
   3528 
   3529 //! return -1 if not found
   3530 int searchCompileTable(int type, int regNum) { //returns the index
   3531     int k;
   3532     for(k = 0; k < num_compile_entries; k++) {
   3533         if(compileTable[k].physicalType == type && compileTable[k].regNum == regNum)
   3534             return k;
   3535     }
   3536     return -1;
   3537 }
   3538 //!check whether a physical register for a variable with typeA will work for another variable with typeB
   3539 
   3540 //!Type LowOpndRegType_ss is compatible with type LowOpndRegType_xmm
   3541 bool matchType(int typeA, int typeB) {
   3542     if((typeA & MASK_FOR_TYPE) == (typeB & MASK_FOR_TYPE)) return true;
   3543     if((typeA & MASK_FOR_TYPE) == LowOpndRegType_ss &&
   3544        (typeB & MASK_FOR_TYPE) == LowOpndRegType_xmm) return true;
   3545     if((typeA & MASK_FOR_TYPE) == LowOpndRegType_xmm &&
   3546        (typeB & MASK_FOR_TYPE) == LowOpndRegType_ss) return true;
   3547     return false;
   3548 }
   3549 //!check whether a virtual register is used in the current bytecode
   3550 
   3551 //!
   3552 bool isUsedInByteCode(int regNum, int type) {
   3553     getVirtualRegInfo(infoByteCode);
   3554     int k;
   3555     for(k = 0; k < num_regs_per_bytecode; k++) {
   3556         if(infoByteCode[k].physicalType == (type&MASK_FOR_TYPE) && infoByteCode[k].regNum == regNum)
   3557             return true;
   3558     }
   3559     return false;
   3560 }
   3561 //! obsolete
   3562 bool defineFirst(int atype) {
   3563     if(atype == REGACCESS_D || atype == REGACCESS_L || atype == REGACCESS_H || atype == REGACCESS_DU)
   3564         return true;
   3565     return false;
   3566 }
   3567 //!check whether a virtual register is updated in a basic block
   3568 
   3569 //!
   3570 bool notUpdated(RegAccessType atype) {
   3571     if(atype == REGACCESS_U) return true;
   3572     return false;
   3573 }
   3574 //!check whether a virtual register has exposed usage within a given basic block
   3575 
   3576 //!
   3577 bool hasExposedUsage2(BasicBlock_O1* bb, int index) {
   3578     RegAccessType atype = bb->infoBasicBlock[index].accessType;
   3579     if(atype == REGACCESS_D || atype == REGACCESS_L || atype == REGACCESS_H || atype == REGACCESS_DU)
   3580         return false;
   3581     return true;
   3582 }
   3583 //! return the spill location that is not used
   3584 
   3585 //!
   3586 int getSpillIndex(bool isGLUE, OpndSize size) {
   3587     if(isGLUE) return 0;
   3588     int k;
   3589     for(k = 1; k <= MAX_SPILL_JIT_IA-1; k++) {
   3590         if(size == OpndSize_64) {
   3591             if(k < MAX_SPILL_JIT_IA-1 && spillIndexUsed[k] == 0 && spillIndexUsed[k+1] == 0)
   3592                 return k;
   3593         }
   3594         else if(spillIndexUsed[k] == 0) {
   3595             return k;
   3596         }
   3597     }
   3598     ALOGE("can't find spill position in spillLogicalReg");
   3599     return -1;
   3600 }
   3601 //!this is called before generating a native code, it sets entries in array canSpillReg to true
   3602 
   3603 //!startNativeCode must be paired with endNativeCode
   3604 void startNativeCode(int vr_num, int vr_type) {
   3605     int k;
   3606     for(k = 0; k < PhysicalReg_Null; k++) {
   3607         canSpillReg[k] = true;
   3608     }
   3609     inGetVR_num = vr_num;
   3610     inGetVR_type = vr_type;
   3611 }
   3612 //! called right after generating a native code
   3613 
   3614 //!It sets entries in array canSpillReg to true and reset inGetVR_num to -1
   3615 void endNativeCode() {
   3616     int k;
   3617     for(k = 0; k < PhysicalReg_Null; k++) {
   3618         canSpillReg[k] = true;
   3619     }
   3620     inGetVR_num = -1;
   3621 }
   3622 //! set canSpillReg[physicalReg] to false
   3623 
   3624 //!
   3625 void donotSpillReg(int physicalReg) {
   3626     canSpillReg[physicalReg] = false;
   3627 }
   3628 //! set canSpillReg[physicalReg] to true
   3629 
   3630 //!
   3631 void doSpillReg(int physicalReg) {
   3632     canSpillReg[physicalReg] = true;
   3633 }
   3634 //! touch hardcoded register %ecx and reduce its reference count
   3635 
   3636 //!
   3637 int touchEcx() {
   3638     //registerAlloc will spill logical reg that is mapped to ecx
   3639     //registerAlloc will reduce refCount
   3640     registerAlloc(LowOpndRegType_gp, PhysicalReg_ECX, true, true);
   3641     return 0;
   3642 }
   3643 //! touch hardcoded register %eax and reduce its reference count
   3644 
   3645 //!
   3646 int touchEax() {
   3647     registerAlloc(LowOpndRegType_gp, PhysicalReg_EAX, true, true);
   3648     return 0;
   3649 }
   3650 int touchEsi() {
   3651     registerAlloc(LowOpndRegType_gp, PhysicalReg_ESI, true, true);
   3652     return 0;
   3653 }
   3654 int touchXmm1() {
   3655     registerAlloc(LowOpndRegType_xmm, XMM_1, true, true);
   3656     return 0;
   3657 }
   3658 int touchEbx() {
   3659     registerAlloc(LowOpndRegType_gp, PhysicalReg_EBX, true, true);
   3660     return 0;
   3661 }
   3662 
   3663 //! touch hardcoded register %edx and reduce its reference count
   3664 
   3665 //!
   3666 int touchEdx() {
   3667     registerAlloc(LowOpndRegType_gp, PhysicalReg_EDX, true, true);
   3668     return 0;
   3669 }
   3670 
   3671 #ifdef HACK_FOR_DEBUG
   3672 //for debugging purpose, instructions are added at a certain place
   3673 bool hacked = false;
   3674 void hackBug() {
   3675   if(!hacked && iget_obj_inst == 13) {
   3676 #if 0
   3677     move_reg_to_reg_noalloc(OpndSize_32, PhysicalReg_EBX, true, PhysicalReg_ECX, true);
   3678     //move from ebx to ecx & update compileTable for v3
   3679     int tIndex = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, 3);
   3680     if(tIndex < 0) ALOGE("hack can't find VR3");
   3681     compileTable[tIndex].physicalReg = PhysicalReg_ECX;
   3682 #else
   3683     move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBX, true, 12, PhysicalReg_FP, true);
   3684 #endif
   3685   }
   3686 }
   3687 void hackBug2() {
   3688   if(!hacked && iget_obj_inst == 13) {
   3689     dump_imm_mem_noalloc(Mnemonic_MOV, OpndSize_32, 0, 12, PhysicalReg_FP, true);
   3690     hacked = true;
   3691   }
   3692 }
   3693 #endif
   3694 
   3695 //! this function is called before calling a helper function or a vm function
   3696 int beforeCall(const char* target) { //spill all live registers
   3697     if(currentBB == NULL) return -1;
   3698 
   3699     /* special case for ncgGetEIP: this function only updates %edx */
   3700     if(!strcmp(target, "ncgGetEIP")) {
   3701         touchEdx();
   3702         return -1;
   3703     }
   3704 
   3705     /* these functions use %eax for the return value */
   3706     if((!strcmp(target, "dvmInstanceofNonTrivial")) ||
   3707        (!strcmp(target, "dvmUnlockObject")) ||
   3708        (!strcmp(target, "dvmAllocObject")) ||
   3709        (!strcmp(target, "dvmAllocArrayByClass")) ||
   3710        (!strcmp(target, "dvmAllocPrimitiveArray")) ||
   3711        (!strcmp(target, "dvmInterpHandleFillArrayData")) ||
   3712        (!strcmp(target, "dvmFindInterfaceMethodInCache2")) ||
   3713        (!strcmp(target, "dvmNcgHandlePackedSwitch")) ||
   3714        (!strcmp(target, "dvmNcgHandleSparseSwitch")) ||
   3715        (!strcmp(target, "dvmCanPutArrayElement")) ||
   3716        (!strcmp(target, "moddi3")) || (!strcmp(target, "divdi3")) ||
   3717        (!strcmp(target, "execute_inline"))
   3718        || (!strcmp(target, "dvmJitToPatchPredictedChain"))
   3719        || (!strcmp(target, "dvmJitHandlePackedSwitch"))
   3720        || (!strcmp(target, "dvmJitHandleSparseSwitch"))
   3721        ) {
   3722         touchEax();
   3723     }
   3724 
   3725     //these two functions also use %edx for the return value
   3726     if((!strcmp(target, "moddi3")) || (!strcmp(target, "divdi3"))) {
   3727         touchEdx();
   3728     }
   3729     if((!strcmp(target, ".new_instance_helper"))) {
   3730         touchEsi(); touchEax();
   3731     }
   3732 #if defined(ENABLE_TRACING)
   3733     if((!strcmp(target, "common_periodicChecks4"))) {
   3734         touchEdx();
   3735     }
   3736 #endif
   3737     if((!strcmp(target, ".const_string_helper"))) {
   3738         touchEcx(); touchEax();
   3739     }
   3740     if((!strcmp(target, ".check_cast_helper"))) {
   3741         touchEbx(); touchEsi();
   3742     }
   3743     if((!strcmp(target, ".instance_of_helper"))) {
   3744         touchEbx(); touchEsi(); touchEcx();
   3745     }
   3746     if((!strcmp(target, ".monitor_enter_helper"))) {
   3747         touchEbx();
   3748     }
   3749     if((!strcmp(target, ".monitor_exit_helper"))) {
   3750         touchEbx();
   3751     }
   3752     if((!strcmp(target, ".aget_wide_helper"))) {
   3753         touchEbx(); touchEcx(); touchXmm1();
   3754     }
   3755     if((!strcmp(target, ".aget_helper")) || (!strcmp(target, ".aget_char_helper")) ||
   3756        (!strcmp(target, ".aget_short_helper")) || (!strcmp(target, ".aget_bool_helper")) ||
   3757        (!strcmp(target, ".aget_byte_helper"))) {
   3758         touchEbx(); touchEcx(); touchEdx();
   3759     }
   3760     if((!strcmp(target, ".aput_helper")) || (!strcmp(target, ".aput_char_helper")) ||
   3761        (!strcmp(target, ".aput_short_helper")) || (!strcmp(target, ".aput_bool_helper")) ||
   3762        (!strcmp(target, ".aput_byte_helper")) || (!strcmp(target, ".aput_wide_helper"))) {
   3763         touchEbx(); touchEcx(); touchEdx();
   3764     }
   3765     if((!strcmp(target, ".sput_helper")) || (!strcmp(target, ".sput_wide_helper"))) {
   3766         touchEdx(); touchEax();
   3767     }
   3768     if((!strcmp(target, ".sget_helper"))) {
   3769         touchEdx(); touchEcx();
   3770     }
   3771     if((!strcmp(target, ".sget_wide_helper"))) {
   3772         touchEdx(); touchXmm1();
   3773     }
   3774     if((!strcmp(target, ".aput_obj_helper"))) {
   3775         touchEdx(); touchEcx(); touchEax();
   3776     }
   3777     if((!strcmp(target, ".iput_helper")) || (!strcmp(target, ".iput_wide_helper"))) {
   3778         touchEbx(); touchEcx(); touchEsi();
   3779     }
   3780     if((!strcmp(target, ".iget_helper"))) {
   3781         touchEbx(); touchEcx(); touchEdx();
   3782     }
   3783     if((!strcmp(target, ".iget_wide_helper"))) {
   3784         touchEbx(); touchEcx(); touchXmm1();
   3785     }
   3786     if((!strcmp(target, ".new_array_helper"))) {
   3787         touchEbx(); touchEdx(); touchEax();
   3788     }
   3789     if((!strcmp(target, ".invoke_virtual_helper"))) {
   3790         touchEbx(); touchEcx();
   3791     }
   3792     if((!strcmp(target, ".invoke_direct_helper"))) {
   3793         touchEsi(); touchEcx();
   3794     }
   3795     if((!strcmp(target, ".invoke_super_helper"))) {
   3796         touchEbx(); touchEcx();
   3797     }
   3798     if((!strcmp(target, ".invoke_interface_helper"))) {
   3799         touchEbx(); touchEcx();
   3800     }
   3801     if((!strcmp(target, ".invokeMethodNoRange_5_helper")) ||
   3802        (!strcmp(target, ".invokeMethodNoRange_4_helper"))) {
   3803         touchEbx(); touchEsi(); touchEax(); touchEdx();
   3804     }
   3805     if((!strcmp(target, ".invokeMethodNoRange_3_helper"))) {
   3806         touchEbx(); touchEsi(); touchEax();
   3807     }
   3808     if((!strcmp(target, ".invokeMethodNoRange_2_helper"))) {
   3809         touchEbx(); touchEsi();
   3810     }
   3811     if((!strcmp(target, ".invokeMethodNoRange_1_helper"))) {
   3812         touchEbx();
   3813     }
   3814     if((!strcmp(target, ".invokeMethodRange_helper"))) {
   3815         touchEdx(); touchEsi();
   3816     }
   3817 #ifdef DEBUG_REGALLOC
   3818     ALOGI("enter beforeCall");
   3819 #endif
   3820     if(!strncmp(target, ".invokeArgsDone", 15)) resetGlue(PhysicalReg_GLUE_DVMDEX);
   3821 
   3822     freeReg(true); //to avoid spilling dead logical registers
   3823     int k;
   3824     for(k = 0; k < num_compile_entries; k++) {
   3825         /* before throwing an exception, if GLUE is spilled, load to %ebp
   3826            this should happen at last */
   3827         if(k == indexForGlue) continue;
   3828         if(compileTable[k].physicalReg != PhysicalReg_Null &&
   3829            (compileTable[k].physicalType & LowOpndRegType_hard) == 0) {
   3830             /* handles non hardcoded variables that are in physical registers */
   3831             if(!strcmp(target, "exception")) {
   3832                 /* before throwing an exception
   3833                    update contents of all VRs in Java stack */
   3834                 if(!isVirtualReg(compileTable[k].physicalType)) continue;
   3835                 /* to have correct GC, we should update contents for L VRs as well */
   3836                 //if(compileTable[k].gType == GLOBALTYPE_L) continue;
   3837             }
   3838             if((!strcmp(target, ".const_string_resolve")) ||
   3839                (!strcmp(target, ".static_field_resolve")) ||
   3840                (!strcmp(target, ".inst_field_resolve")) ||
   3841                (!strcmp(target, ".class_resolve")) ||
   3842                (!strcmp(target, ".direct_method_resolve")) ||
   3843                (!strcmp(target, ".virtual_method_resolve")) ||
   3844                (!strcmp(target, ".static_method_resolve"))) {
   3845                /* physical register %ebx will keep its content
   3846                   but to have correct GC, we should dump content of a VR
   3847                      that is mapped to %ebx */
   3848                 if(compileTable[k].physicalReg == PhysicalReg_EBX &&
   3849                    (!isVirtualReg(compileTable[k].physicalType)))
   3850                     continue;
   3851             }
   3852             if((!strncmp(target, "dvm", 3)) || (!strcmp(target, "moddi3")) ||
   3853                (!strcmp(target, "divdi3")) ||
   3854                (!strcmp(target, "fmod")) || (!strcmp(target, "fmodf"))) {
   3855                 /* callee-saved registers (%ebx, %esi, %ebp, %edi) will keep the content
   3856                    but to have correct GC, we should dump content of a VR
   3857                       that is mapped to a callee-saved register */
   3858                 if((compileTable[k].physicalReg == PhysicalReg_EBX ||
   3859                     compileTable[k].physicalReg == PhysicalReg_ESI) &&
   3860                    (!isVirtualReg(compileTable[k].physicalType)))
   3861                     continue;
   3862             }
   3863 #ifdef DEBUG_REGALLOC
   3864             ALOGI("SPILL logical register %d %d in beforeCall",
   3865                   compileTable[k].regNum, compileTable[k].physicalType);
   3866 #endif
   3867             spillLogicalReg(k, true);
   3868         }
   3869     }
   3870     if(indexForGlue >= 0 && !strcmp(target, "exception") &&
   3871        compileTable[indexForGlue].physicalReg == PhysicalReg_Null) {
   3872         unspillLogicalReg(indexForGlue, PhysicalReg_EBP); //load %ebp
   3873     }
   3874 #ifdef DEBUG_REGALLOC
   3875     ALOGI("exit beforeCall");
   3876 #endif
   3877     return 0;
   3878 }
   3879 int getFreeReg(int type, int reg, int indexToCompileTable);
   3880 //! after calling a helper function or a VM function
   3881 
   3882 //!
   3883 int afterCall(const char* target) { //un-spill
   3884     if(currentBB == NULL) return -1;
   3885     if(!strcmp(target, "ncgGetEIP")) return -1;
   3886 
   3887     return 0;
   3888 }
   3889 //! check whether a temporary is 8-bit
   3890 
   3891 //!
   3892 bool isTemp8Bit(int type, int reg) {
   3893     if(currentBB == NULL) return false;
   3894     if(!isTemporary(type, reg)) return false;
   3895     int k;
   3896     for(k = 0; k < num_temp_regs_per_bytecode; k++) {
   3897         if(infoByteCodeTemp[k].physicalType == type &&
   3898            infoByteCodeTemp[k].regNum == reg) {
   3899             return infoByteCodeTemp[k].is8Bit;
   3900         }
   3901     }
   3902     ALOGE("isTemp8Bit %d %d", type, reg);
   3903     return false;
   3904 }
   3905 
   3906 /* functions to access live ranges of a VR
   3907    Live range info is stored in memVRTable[].ranges, which is a linked list
   3908 */
   3909 //! check whether a VR is live at the current bytecode
   3910 
   3911 //!
   3912 bool isVRLive(int vA) {
   3913     int index = searchMemTable(vA);
   3914     if(index < 0) {
   3915         ALOGE("couldn't find VR %d in memTable", vA);
   3916         return false;
   3917     }
   3918     LiveRange* ptr = memVRTable[index].ranges;
   3919     while(ptr != NULL) {
   3920         if(offsetPC >= ptr->start && offsetPC <= ptr->end) return true;
   3921         ptr = ptr->next;
   3922     }
   3923     return false;
   3924 }
   3925 
   3926 //! check whether the current bytecode is the last access to a VR within a live range
   3927 
   3928 //!for 64-bit VR, return true only when true for both low half and high half
   3929 bool isLastByteCodeOfLiveRange(int compileIndex) {
   3930     int k = compileIndex;
   3931     OpndSize tSize = getRegSize(compileTable[k].physicalType);
   3932     int index;
   3933     LiveRange* ptr = NULL;
   3934     if(tSize == OpndSize_32) {
   3935         /* check live ranges for the VR */
   3936         index = searchMemTable(compileTable[k].regNum);
   3937         if(index < 0) {
   3938             ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   3939             return false;
   3940         }
   3941         ptr = memVRTable[index].ranges;
   3942         while(ptr != NULL) {
   3943             if(offsetPC == ptr->end) return true;
   3944             ptr = ptr->next;
   3945         }
   3946         return false;
   3947     }
   3948     /* size of the VR is 64 */
   3949     /* check live ranges of the low half */
   3950     index = searchMemTable(compileTable[k].regNum);
   3951     bool tmpB = false;
   3952     if(index < 0) {
   3953         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   3954         return false;
   3955     }
   3956     ptr = memVRTable[index].ranges;
   3957     while(ptr != NULL) {
   3958         if(offsetPC == ptr->end) {
   3959             tmpB = true;
   3960             break;
   3961         }
   3962         ptr = ptr->next;
   3963     }
   3964     if(!tmpB) return false;
   3965     /* check live ranges of the high half */
   3966     index = searchMemTable(compileTable[k].regNum+1);
   3967     if(index < 0) {
   3968         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
   3969         return false;
   3970     }
   3971     ptr = memVRTable[index].ranges;
   3972     while(ptr != NULL) {
   3973         if(offsetPC == ptr->end) {
   3974             return true;
   3975         }
   3976         ptr = ptr->next;
   3977     }
   3978     return false;
   3979 }
   3980 
   3981 //! check whether the current bytecode is in a live range that extends to end of a basic block
   3982 
   3983 //!for 64 bit, return true if true for both low half and high half
   3984 bool reachEndOfBB(int compileIndex) {
   3985     int k = compileIndex;
   3986     OpndSize tSize = getRegSize(compileTable[k].physicalType);
   3987     int index;
   3988     bool retCode = false;
   3989     /* check live ranges of the low half */
   3990     index = searchMemTable(compileTable[k].regNum);
   3991     if(index < 0) {
   3992         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   3993         return false;
   3994     }
   3995     LiveRange* ptr = memVRTable[index].ranges;
   3996     while(ptr != NULL) {
   3997         if(offsetPC >= ptr->start &&
   3998            offsetPC <= ptr->end) {
   3999             if(ptr->end == currentBB->pc_end) {
   4000                 retCode = true;
   4001             }
   4002             break;
   4003         }
   4004         ptr = ptr->next;
   4005     }
   4006     if(!retCode) return false;
   4007     if(tSize == OpndSize_32) return true;
   4008     /* check live ranges of the high half */
   4009     index = searchMemTable(compileTable[k].regNum+1);
   4010     if(index < 0) {
   4011         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
   4012         return false;
   4013     }
   4014     ptr = memVRTable[index].ranges;
   4015     while(ptr != NULL) {
   4016         if(offsetPC >= ptr->start &&
   4017            offsetPC <= ptr->end) {
   4018             if(ptr->end == currentBB->pc_end) return true;
   4019             return false;
   4020         }
   4021         ptr = ptr->next;
   4022     }
   4023 #ifdef PRINT_WARNING
   4024     ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum+1);
   4025 #endif
   4026     return false;
   4027 }
   4028 
   4029 //!check whether the current bytecode is the next to last access to a VR within a live range
   4030 
   4031 //!for 64 bit, return true if true for both low half and high half
   4032 bool isNextToLastAccess(int compileIndex) {
   4033     int k = compileIndex;
   4034     OpndSize tSize = getRegSize(compileTable[k].physicalType);
   4035     int index;
   4036     /* check live ranges for the low half */
   4037     bool retCode = false;
   4038     index = searchMemTable(compileTable[k].regNum);
   4039     if(index < 0) {
   4040         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   4041         return false;
   4042     }
   4043     LiveRange* ptr = memVRTable[index].ranges;
   4044     while(ptr != NULL) {
   4045         int num_access = ptr->num_access;
   4046 
   4047         if(num_access < 2) {
   4048            ptr = ptr->next;
   4049            continue;
   4050         }
   4051 
   4052         if(offsetPC == ptr->accessPC[num_access-2]) {
   4053            retCode = true;
   4054            break;
   4055         }
   4056         ptr = ptr->next;
   4057     }
   4058     if(!retCode) return false;
   4059     if(tSize == OpndSize_32) return true;
   4060     /* check live ranges for the high half */
   4061     index = searchMemTable(compileTable[k].regNum+1);
   4062     if(index < 0) {
   4063         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
   4064         return false;
   4065     }
   4066     ptr = memVRTable[index].ranges;
   4067     while(ptr != NULL) {
   4068         int num_access = ptr->num_access;
   4069 
   4070         if(num_access < 2) {
   4071            ptr = ptr->next;
   4072            continue;
   4073         }
   4074 
   4075         if(offsetPC == ptr->accessPC[num_access-2]) return true;
   4076         ptr = ptr->next;
   4077     }
   4078     return false;
   4079 }
   4080 
   4081 /** return the start of the next live range
   4082     if there does not exist a next live range, return pc_end of the basic block
   4083     for 64 bits, return the larger one for low half and high half
   4084     Assume live ranges are sorted in order
   4085 */
   4086 int getNextLiveRange(int compileIndex) {
   4087     int k = compileIndex;
   4088     OpndSize tSize = getRegSize(compileTable[k].physicalType);
   4089     /* check live ranges of the low half */
   4090     int index;
   4091     index = searchMemTable(compileTable[k].regNum);
   4092     if(index < 0) {
   4093         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   4094         return offsetPC;
   4095     }
   4096     bool found = false;
   4097     int nextUse = offsetPC;
   4098     LiveRange* ptr = memVRTable[index].ranges;
   4099     while(ptr != NULL) {
   4100         if(ptr->start > offsetPC) {
   4101             nextUse = ptr->start;
   4102             found = true;
   4103             break;
   4104         }
   4105         ptr = ptr->next;
   4106     }
   4107     if(!found) return currentBB->pc_end;
   4108     if(tSize == OpndSize_32) return nextUse;
   4109 
   4110     /* check live ranges of the high half */
   4111     found = false;
   4112     index = searchMemTable(compileTable[k].regNum+1);
   4113     if(index < 0) {
   4114         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
   4115         return offsetPC;
   4116     }
   4117     int nextUse2 = offsetPC;
   4118     ptr = memVRTable[index].ranges;
   4119     while(ptr != NULL) {
   4120         if(ptr->start > offsetPC) {
   4121             nextUse2 = ptr->start;
   4122             found = true;
   4123             break;
   4124         }
   4125         ptr = ptr->next;
   4126     }
   4127     if(!found) return currentBB->pc_end;
   4128     /* return the larger one */
   4129     return (nextUse2 > nextUse ? nextUse2 : nextUse);
   4130 }
   4131 
   4132 /** return the next access to a variable
   4133     If variable is 64-bit, get the next access to the lower half and the high half
   4134         return the eariler one
   4135 */
   4136 int getNextAccess(int compileIndex) {
   4137     int k = compileIndex;
   4138     OpndSize tSize = getRegSize(compileTable[k].physicalType);
   4139     int index, k3;
   4140     /* check live ranges of the low half */
   4141     index = searchMemTable(compileTable[k].regNum);
   4142     if(index < 0) {
   4143         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
   4144         return offsetPC;
   4145     }
   4146     bool found = false;
   4147     int nextUse = offsetPC;
   4148     LiveRange* ptr = memVRTable[index].ranges;
   4149     while(ptr != NULL) {
   4150         if(offsetPC >= ptr->start &&
   4151            offsetPC <= ptr->end) {
   4152             /* offsetPC belongs to this live range */
   4153             for(k3 = 0; k3 < ptr->num_access; k3++) {
   4154                 if(ptr->accessPC[k3] > offsetPC) {
   4155                     nextUse = ptr->accessPC[k3];
   4156                     break;
   4157                 }
   4158             }
   4159             found = true;
   4160             break;
   4161         }
   4162         ptr = ptr->next;
   4163     }
   4164 #ifdef PRINT_WARNING
   4165     if(!found)
   4166         ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum);
   4167 #endif
   4168     if(tSize == OpndSize_32) return nextUse;
   4169 
   4170     /* check live ranges of the high half */
   4171     found = false;
   4172     index = searchMemTable(compileTable[k].regNum+1);
   4173     if(index < 0) {
   4174         ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
   4175         return offsetPC;
   4176     }
   4177     int nextUse2 = offsetPC;
   4178     ptr = memVRTable[index].ranges;
   4179     while(ptr != NULL) {
   4180         if(offsetPC >= ptr->start &&
   4181            offsetPC <= ptr->end) {
   4182             for(k3 = 0; k3 < ptr->num_access; k3++) {
   4183                 if(ptr->accessPC[k3] > offsetPC) {
   4184                     nextUse2 = ptr->accessPC[k3];
   4185                     break;
   4186                 }
   4187             }
   4188             found = true;
   4189             break;
   4190         }
   4191         ptr = ptr->next;
   4192     }
   4193 #ifdef PRINT_WARNING
   4194     if(!found) ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum+1);
   4195 #endif
   4196     /* return the earlier one */
   4197     if(nextUse2 < nextUse) return nextUse2;
   4198     return nextUse;
   4199 }
   4200 
   4201 /** free variables that are no longer in use
   4202     free a temporary with reference count of zero
   4203     will dump content of a GL VR to memory if necessary
   4204 */
   4205 int freeReg(bool spillGL) {
   4206     if(currentBB == NULL) return 0;
   4207     int k;
   4208     for(k = 0; k < num_compile_entries; k++) {
   4209         if(compileTable[k].refCount == 0 && compileTable[k].physicalReg != PhysicalReg_Null) {
   4210             /* check entries with reference count of zero and is mapped to a physical register */
   4211             bool typeA = !isVirtualReg(compileTable[k].physicalType);
   4212             bool freeCrit = true, delayFreeing = false;
   4213             bool typeC = false, typeB = false, reachEnd = false;
   4214             if(isVirtualReg(compileTable[k].physicalType)) {
   4215                 /* VRs in the compile table */
   4216 
   4217                 /* Check if delay for freeing was requested for this VR */
   4218                 delayFreeing = getVRFreeDelayRequested(compileTable[k].regNum);
   4219 
   4220                 freeCrit = isLastByteCodeOfLiveRange(k); /* last bytecode of a live range */
   4221                 reachEnd = reachEndOfBB(k); /* in a live range that extends to end of a basic block */
   4222 #ifdef DEBUG_LIVE_RANGE
   4223                 ALOGI("IN freeReg: VR %d offsetPC %x freecrit %d reachEnd %d nextToLast %d", compileTable[k].regNum, offsetPC, freeCrit, reachEnd, isNextToLastAccess(k));
   4224 #endif
   4225                 /* Bug: spilling of VRs after edi(rFP) is updated in RETURN bytecode
   4226                         will cause variables for callee to be spilled to the caller stack frame and
   4227                                                         to overwrite varaibles for caller
   4228                 */
   4229                 /* last bytecode of a live range reaching end of BB if not counting the fake usage at end */
   4230                 bool boolB = reachEnd && isNextToLastAccess(k);
   4231                 /* Bug: when a GG VR is checked at end of a basic block,
   4232                         freeCrit will be true and physicalReg will be set to Null
   4233                    Fix: change free condition from freeCrit to (freeCrit && offsetPC != currentBB->pc_end)
   4234                 */
   4235                 /* conditions to free a GG VR:
   4236                        last bytecode of a live range reaching end of BB if not counting the fake usage at end && endsWithReturn
   4237                        or
   4238                        last bytecode of a live range && offsetPC != currentBB->pc_end
   4239                            -> last bytecode of a live range not reaching end
   4240                 */
   4241                 typeC = ((freeCrit && offsetPC != currentBB->pc_end) ||
   4242                          (currentBB->endsWithReturn && boolB)) &&
   4243                         compileTable[k].gType == GLOBALTYPE_GG &&
   4244                         !delayFreeing;
   4245                 /* conditions to free a L|GL VR:
   4246                        last bytecode of a live range
   4247                        or
   4248                        last bytecode of a live range reaching end of BB if not counting the fake usage at end
   4249                 */
   4250                 typeB = (freeCrit || boolB) &&
   4251                         (compileTable[k].gType != GLOBALTYPE_GG) &&
   4252                         !delayFreeing;
   4253             }
   4254             if(typeA || typeB || typeC) {
   4255 #ifdef DEBUG_REGALLOC
   4256                 if(typeA)
   4257                     ALOGI("FREE TEMP %d with type %d allocated to %d",
   4258                            compileTable[k].regNum, compileTable[k].physicalType,
   4259                            compileTable[k].physicalReg);
   4260                 else if(typeB)
   4261                     ALOGI("FREE VR L|GL %d with type %d allocated to %d",
   4262                            compileTable[k].regNum, compileTable[k].physicalType,
   4263                            compileTable[k].physicalReg);
   4264                 else if(typeC)
   4265                     ALOGI("FREE VR GG %d with type %d allocated to %d",
   4266                            compileTable[k].regNum, compileTable[k].physicalType,
   4267                            compileTable[k].physicalReg);
   4268 #endif
   4269                 bool dumpGL = false;
   4270                 if(compileTable[k].gType == GLOBALTYPE_GL && !reachEnd) {
   4271                     /* if the live range does not reach end of basic block
   4272                        and there exists a try block from offsetPC to the next live range
   4273                            dump VR to interpreted stack */
   4274                     int tmpPC = getNextLiveRange(k);
   4275                     if(existATryBlock(currentMethod, offsetPC, tmpPC)) dumpGL = true;
   4276                 }
   4277                 /* if the live range reach end of basic block, dump VR to interpreted stack */
   4278                 if(compileTable[k].gType == GLOBALTYPE_GL && reachEnd) dumpGL = true;
   4279                 if(dumpGL) {
   4280                     if(spillGL) {
   4281 #ifdef DEBUG_REGALLOC
   4282                         ALOGI("SPILL VR GL %d %d", compileTable[k].regNum, compileTable[k].physicalType);
   4283 #endif
   4284                         spillLogicalReg(k, true); //will dump VR to memory & update physicalReg
   4285                     }
   4286                 }
   4287                 else
   4288                      compileTable[k].physicalReg = PhysicalReg_Null;
   4289             }
   4290             if(typeA) {
   4291                 if(compileTable[k].spill_loc_index >= 0) {
   4292                     /* update spill info for temporaries */
   4293                     spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 0;
   4294                     compileTable[k].spill_loc_index = -1;
   4295                     ALOGE("free a temporary register with TRSTATE_SPILLED");
   4296                 }
   4297             }
   4298         }
   4299     }
   4300     syncAllRegs(); //sync up allRegs (isUsed & freeTimeStamp) with compileTable
   4301     return 0;
   4302 }
   4303 
   4304 //! reduce the reference count by 1
   4305 
   4306 //! input: index to compileTable
   4307 void decreaseRefCount(int index) {
   4308 #ifdef DEBUG_REFCOUNT
   4309     ALOGI("REFCOUNT: %d in decreaseRefCount %d %d", compileTable[index].refCount,
   4310             compileTable[index].regNum, compileTable[index].physicalType);
   4311 #endif
   4312     compileTable[index].refCount--;
   4313     if(compileTable[index].refCount < 0) {
   4314         ALOGE("refCount is negative for REG %d %d", compileTable[index].regNum, compileTable[index].physicalType);
   4315         dvmAbort();
   4316     }
   4317 }
   4318 //! reduce the reference count of a VR by 1
   4319 
   4320 //! input: reg & type
   4321 int updateRefCount(int reg, LowOpndRegType type) {
   4322     if(currentBB == NULL) return 0;
   4323     int index = searchCompileTable(LowOpndRegType_virtual | type, reg);
   4324     if(index < 0) {
   4325         ALOGE("virtual reg %d type %d not found in updateRefCount", reg, type);
   4326         return -1;
   4327     }
   4328     decreaseRefCount(index);
   4329     return 0;
   4330 }
   4331 //! reduce the reference count of a variable by 1
   4332 
   4333 //! The variable is named with lowering module's naming mechanism
   4334 int updateRefCount2(int reg, int type, bool isPhysical) {
   4335     if(currentBB == NULL) return 0;
   4336     int newType = convertType(type, reg, isPhysical);
   4337     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   4338     int index = searchCompileTable(newType, reg);
   4339     if(index < 0) {
   4340         ALOGE("reg %d type %d not found in updateRefCount", reg, newType);
   4341         return -1;
   4342     }
   4343     decreaseRefCount(index);
   4344     return 0;
   4345 }
   4346 //! check whether a glue variable is in physical register or spilled
   4347 
   4348 //!
   4349 bool isGlueHandled(int glue_reg) {
   4350     if(currentBB == NULL) return false;
   4351     int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
   4352     if(index < 0) {
   4353         ALOGE("glue reg %d not found in isGlueHandled", glue_reg);
   4354         return -1;
   4355     }
   4356     if(compileTable[index].spill_loc_index >= 0 ||
   4357        compileTable[index].physicalReg != PhysicalReg_Null) {
   4358 #ifdef DEBUG_GLUE
   4359         ALOGI("GLUE isGlueHandled for %d returns true", glue_reg);
   4360 #endif
   4361         return true;
   4362     }
   4363 #ifdef DEBUG_GLUE
   4364     ALOGI("GLUE isGlueHandled for %d returns false", glue_reg);
   4365 #endif
   4366     return false;
   4367 }
   4368 //! reset the state of a glue variable to not existant (not in physical register nor spilled)
   4369 
   4370 //!
   4371 void resetGlue(int glue_reg) {
   4372     if(currentBB == NULL) return;
   4373     int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
   4374     if(index < 0) {
   4375         ALOGE("glue reg %d not found in resetGlue", glue_reg);
   4376         return;
   4377     }
   4378 #ifdef DEBUG_GLUE
   4379     ALOGI("GLUE reset for %d", glue_reg);
   4380 #endif
   4381     compileTable[index].physicalReg = PhysicalReg_Null;
   4382     if(compileTable[index].spill_loc_index >= 0)
   4383         spillIndexUsed[compileTable[index].spill_loc_index >> 2] = 0;
   4384     compileTable[index].spill_loc_index = -1;
   4385 }
   4386 //! set a glue variable in a physical register allocated for a variable
   4387 
   4388 //! Variable is using lowering module's naming convention
   4389 void updateGlue(int reg, bool isPhysical, int glue_reg) {
   4390     if(currentBB == NULL) return;
   4391     int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
   4392     if(index < 0) {
   4393         ALOGE("glue reg %d not found in updateGlue", glue_reg);
   4394         return;
   4395     }
   4396     /* find the compileTable entry for variable <reg, isPhysical> */
   4397     int newType = convertType(LowOpndRegType_gp, reg, isPhysical);
   4398     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   4399     int index2 = searchCompileTable(newType, reg);
   4400     if(index2 < 0 || compileTable[index2].physicalReg == PhysicalReg_Null) {
   4401         ALOGE("updateGlue reg %d type %d", reg, newType);
   4402         return;
   4403     }
   4404 #ifdef DEBUG_GLUE
   4405     ALOGI("physical register for GLUE %d set to %d", glue_reg, compileTable[index2].physicalReg);
   4406 #endif
   4407     compileTable[index].physicalReg = compileTable[index2].physicalReg;
   4408     compileTable[index].spill_loc_index = -1;
   4409 }
   4410 
   4411 //! check whether a virtual register is in a physical register
   4412 
   4413 //! If updateRefCount is 0, do not update reference count;
   4414 //!If updateRefCount is 1, update reference count only when VR is in a physical register
   4415 //!If updateRefCount is 2, update reference count
   4416 int checkVirtualReg(int reg, LowOpndRegType type, int updateRefCount) {
   4417     if(currentBB == NULL) return PhysicalReg_Null;
   4418     int index = searchCompileTable(LowOpndRegType_virtual | type, reg);
   4419     if(index < 0) {
   4420         ALOGE("virtual reg %d type %d not found in checkVirtualReg", reg, type);
   4421         return PhysicalReg_Null;
   4422     }
   4423     //reduce reference count
   4424     if(compileTable[index].physicalReg != PhysicalReg_Null) {
   4425         if(updateRefCount != 0) decreaseRefCount(index);
   4426         return compileTable[index].physicalReg;
   4427     }
   4428     if(updateRefCount == 2) decreaseRefCount(index);
   4429     return PhysicalReg_Null;
   4430 }
   4431 //!check whether a temporary can share the same physical register with a VR
   4432 
   4433 //!This is called in get_virtual_reg
   4434 //!If this function returns false, new register will be allocated for this temporary
   4435 bool checkTempReg2(int reg, int type, bool isPhysical, int physicalRegForVR) {
   4436     if(currentBB == NULL) return false;
   4437     if(isPhysical) return false;
   4438 
   4439     int newType = convertType(type, reg, isPhysical);
   4440     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   4441     int k;
   4442     for(k = 0; k < num_temp_regs_per_bytecode; k++) {
   4443         if(infoByteCodeTemp[k].physicalType == newType &&
   4444            infoByteCodeTemp[k].regNum == reg) {
   4445 #ifdef DEBUG_MOVE_OPT
   4446             ALOGI("MOVE_OPT checkTempRegs for %d %d returns %d %d",
   4447                    reg, newType, infoByteCodeTemp[k].shareWithVR, infoByteCodeTemp[k].is8Bit);
   4448 #endif
   4449             if(!infoByteCodeTemp[k].is8Bit) return infoByteCodeTemp[k].shareWithVR;
   4450             //is8Bit true for gp type only
   4451             if(!infoByteCodeTemp[k].shareWithVR) return false;
   4452             //both true
   4453             if(physicalRegForVR >= PhysicalReg_EAX && physicalRegForVR <= PhysicalReg_EDX) return true;
   4454 #ifdef DEBUG_MOVE_OPT
   4455             ALOGI("MOVE_OPT registerAllocMove not used for 8-bit register");
   4456 #endif
   4457             return false;
   4458         }
   4459     }
   4460     ALOGE("checkTempReg2 %d %d", reg, newType);
   4461     return false;
   4462 }
   4463 //!check whether a temporary can share the same physical register with a VR
   4464 
   4465 //!This is called in set_virtual_reg
   4466 int checkTempReg(int reg, int type, bool isPhysical, int vrNum) {
   4467     if(currentBB == NULL) return PhysicalReg_Null;
   4468 
   4469     int newType = convertType(type, reg, isPhysical);
   4470     if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
   4471     int index = searchCompileTable(newType, reg);
   4472     if(index < 0) {
   4473         ALOGE("temp reg %d type %d not found in checkTempReg", reg, newType);
   4474         return PhysicalReg_Null;
   4475     }
   4476 
   4477     //a temporary register can share the same physical reg with a VR if registerAllocMove is called
   4478     //this will cause problem with move bytecode
   4479     //get_VR(v1, t1) t1 and v1 point to the same physical reg
   4480     //set_VR(t1, v2) t1 and v2 point to the same physical reg
   4481     //this will cause v1 and v2 point to the same physical reg
   4482     //FIX: if this temp reg shares a physical reg with another reg
   4483     if(compileTable[index].physicalReg != PhysicalReg_Null) {
   4484         int k;
   4485         for(k = 0; k < num_compile_entries; k++) {
   4486             if(k == index) continue;
   4487             if(compileTable[k].physicalReg == compileTable[index].physicalReg) {
   4488                 return PhysicalReg_Null; //will allocate a register for VR
   4489             }
   4490         }
   4491         decreaseRefCount(index);
   4492         return compileTable[index].physicalReg;
   4493     }
   4494     if(compileTable[index].spill_loc_index >= 0) {
   4495         //registerAlloc will call unspillLogicalReg (load from memory)
   4496 #ifdef DEBUG_REGALLOC
   4497         ALOGW("in checkTempReg, the temporary register %d %d was spilled", reg, type);
   4498 #endif
   4499         int regAll = registerAlloc(type, reg, isPhysical, true/* updateRefCount */);
   4500         return regAll;
   4501     }
   4502     return PhysicalReg_Null;
   4503 }
   4504 //!check whether a variable has exposed usage in a basic block
   4505 
   4506 //!It calls hasExposedUsage2
   4507 bool hasExposedUsage(LowOpndRegType type, int regNum, BasicBlock_O1* bb) {
   4508     int index = searchVirtualInfoOfBB(type, regNum, bb);
   4509     if(index >= 0 && hasExposedUsage2(bb, index)) {
   4510         return true;
   4511     }
   4512     return false;
   4513 }
   4514 //!check whether a variable has exposed usage in other basic blocks
   4515 
   4516 //!
   4517 bool hasOtherExposedUsage(OpndSize size, int regNum, BasicBlock_O1* bb) {
   4518     return true; //assume the worst case
   4519 }
   4520 
   4521 //! handles constant VRs at end of a basic block
   4522 
   4523 //!If a VR is constant at end of a basic block and (it has exposed usage in other basic blocks or reaches a GG VR), dump immediate to memory
   4524 void constVREndOfBB() {
   4525     BasicBlock_O1* bb = currentBB;
   4526     int k, k2;
   4527     //go through GG VRs, update a bool array
   4528     int constUsedByGG[MAX_CONST_REG];
   4529     for(k = 0; k < num_const_vr; k++)
   4530         constUsedByGG[k] = 0;
   4531     for(k = 0; k < num_compile_entries; k++) {
   4532         if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType == GLOBALTYPE_GG) {
   4533             OpndSize size = getRegSize(compileTable[k].physicalType);
   4534             int regNum = compileTable[k].regNum;
   4535             int indexL = -1;
   4536             int indexH = -1;
   4537             for(k2 = 0; k2 < num_const_vr; k2++) {
   4538                 if(constVRTable[k2].regNum == regNum) {
   4539                     indexL = k2;
   4540                     continue;
   4541                 }
   4542                 if(constVRTable[k2].regNum == regNum + 1 && size == OpndSize_64) {
   4543                     indexH = k2;
   4544                     continue;
   4545                 }
   4546             }
   4547             if(indexL >= 0) constUsedByGG[indexL] = 1;
   4548             if(indexH >= 0) constUsedByGG[indexH] = 1;
   4549         } //GG VR
   4550     }
   4551     for(k = 0; k < num_const_vr; k++) {
   4552         if(!constVRTable[k].isConst) continue;
   4553         bool hasExp = false;
   4554         if(constUsedByGG[k] == 0)
   4555             hasExp = hasOtherExposedUsage(OpndSize_32, constVRTable[k].regNum, bb);
   4556         if(constUsedByGG[k] != 0 || hasExp) {
   4557             dumpImmToMem(constVRTable[k].regNum, OpndSize_32, constVRTable[k].value);
   4558             setVRToMemory(constVRTable[k].regNum, OpndSize_32);
   4559 #ifdef DEBUG_ENDOFBB
   4560             ALOGI("ENDOFBB: exposed VR %d is const %d (%x)",
   4561                   constVRTable[k].regNum, constVRTable[k].value, constVRTable[k].value);
   4562 #endif
   4563         } else {
   4564 #ifdef DEBUG_ENDOFBB
   4565             ALOGI("ENDOFBB: unexposed VR %d is const %d (%x)",
   4566                   constVRTable[k].regNum, constVRTable[k].value, constVRTable[k].value);
   4567 #endif
   4568         }
   4569     }
   4570 }
   4571 
   4572 //!handles GG VRs at end of a basic block
   4573 
   4574 //!make sure all GG VRs are in pre-defined physical registers
   4575 void globalVREndOfBB(const Method* method) {
   4576     //fix: freeReg first to write LL VR back to memory to avoid it gets overwritten by GG VRs
   4577     freeReg(true);
   4578     int k;
   4579     //spill GG VR first if it is not mapped to the specific reg
   4580     //release GLUE regs
   4581     for(k = 0; k < num_compile_entries; k++) {
   4582         if(compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
   4583            compileTable[k].regNum != PhysicalReg_GLUE) {
   4584             compileTable[k].physicalReg = PhysicalReg_Null;
   4585             compileTable[k].spill_loc_index = -1;
   4586         }
   4587         //if part of a GG VR is const, the physical reg is set to null
   4588         if(isVirtualReg(compileTable[k].physicalType) &&
   4589            compileTable[k].gType == GLOBALTYPE_GG && compileTable[k].physicalReg != PhysicalReg_Null &&
   4590            compileTable[k].physicalReg != compileTable[k].physicalReg_prev) {
   4591 #ifdef DEBUG_ENDOFBB
   4592             ALOGW("end of BB GG VR is not mapped to the specific reg: %d %d %d",
   4593                   compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg);
   4594             ALOGW("ENDOFBB SPILL VR %d %d", compileTable[k].regNum, compileTable[k].physicalType);
   4595 #endif
   4596             spillLogicalReg(k, true); //the next section will load VR from memory to the specific reg
   4597         }
   4598     }
   4599     syncAllRegs();
   4600     for(k = 0; k < num_compile_entries; k++) {
   4601         if(isVirtualReg(compileTable[k].physicalType)) {
   4602             if(compileTable[k].gType == GLOBALTYPE_GG &&
   4603                compileTable[k].physicalReg == PhysicalReg_Null && (!currentBB->endsWithReturn)) {
   4604 #ifdef DEBUG_ENDOFBB
   4605                 ALOGI("ENDOFBB GET GG VR %d %d to physical register %d", compileTable[k].regNum,
   4606                       compileTable[k].physicalType, compileTable[k].physicalReg_prev);
   4607 #endif
   4608                 compileTable[k].physicalReg = compileTable[k].physicalReg_prev;
   4609                 if(allRegs[compileTable[k].physicalReg_prev].isUsed) {
   4610                     ALOGE("physical register for GG VR is still used");
   4611                 }
   4612                 get_virtual_reg_noalloc(compileTable[k].regNum,
   4613                                         getRegSize(compileTable[k].physicalType),
   4614                                         compileTable[k].physicalReg_prev,
   4615                                         true);
   4616             }
   4617         }//not const
   4618     }
   4619     if(indexForGlue >= 0 &&
   4620         compileTable[indexForGlue].physicalReg == PhysicalReg_Null) {
   4621         unspillLogicalReg(indexForGlue, PhysicalReg_EBP); //load %ebp
   4622     }
   4623 }
   4624 
   4625 //! get ready for the next version of a hard-coded register
   4626 
   4627 //!set its physicalReg to Null and update its reference count
   4628 int nextVersionOfHardReg(PhysicalReg pReg, int refCount) {
   4629     int indexT = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_hard, pReg);
   4630     if(indexT < 0)
   4631         return -1;
   4632     compileTable[indexT].physicalReg = PhysicalReg_Null;
   4633 #ifdef DEBUG_REFCOUNT
   4634     ALOGI("REFCOUNT: to %d in nextVersionOfHardReg %d", refCount, pReg);
   4635 #endif
   4636     compileTable[indexT].refCount = refCount;
   4637     return 0;
   4638 }
   4639 
   4640 /** update compileTable with bb->infoBasicBlock[k]
   4641 */
   4642 void insertFromVirtualInfo(BasicBlock_O1* bb, int k) {
   4643     int index = searchCompileTable(LowOpndRegType_virtual | bb->infoBasicBlock[k].physicalType, bb->infoBasicBlock[k].regNum);
   4644     if(index < 0) {
   4645         /* the virtual register is not in compileTable, insert it */
   4646         index = num_compile_entries;
   4647         compileTable[num_compile_entries].physicalType = (LowOpndRegType_virtual | bb->infoBasicBlock[k].physicalType);
   4648         compileTable[num_compile_entries].regNum = bb->infoBasicBlock[k].regNum;
   4649         compileTable[num_compile_entries].physicalReg = PhysicalReg_Null;
   4650         compileTable[num_compile_entries].bb = bb;
   4651         compileTable[num_compile_entries].indexToInfoBB = k;
   4652         compileTable[num_compile_entries].spill_loc_index = -1;
   4653         compileTable[num_compile_entries].gType = bb->infoBasicBlock[k].gType;
   4654         num_compile_entries++;
   4655         if(num_compile_entries >= COMPILE_TABLE_SIZE) {
   4656             ALOGE("compileTable overflow");
   4657             dvmAbort();
   4658         }
   4659     }
   4660     /* re-set reference count of all VRs */
   4661     compileTable[index].refCount = bb->infoBasicBlock[k].refCount;
   4662     compileTable[index].accessType = bb->infoBasicBlock[k].accessType;
   4663     if(compileTable[index].gType == GLOBALTYPE_GG)
   4664         compileTable[index].physicalReg_prev = bb->infoBasicBlock[k].physicalReg_GG;
   4665 }
   4666 
   4667 /** update compileTable with infoByteCodeTemp[k]
   4668 */
   4669 void insertFromTempInfo(int k) {
   4670     int index = searchCompileTable(infoByteCodeTemp[k].physicalType, infoByteCodeTemp[k].regNum);
   4671     if(index < 0) {
   4672         /* the temporary is not in compileTable, insert it */
   4673         index = num_compile_entries;
   4674         compileTable[num_compile_entries].physicalType = infoByteCodeTemp[k].physicalType;
   4675         compileTable[num_compile_entries].regNum = infoByteCodeTemp[k].regNum;
   4676         num_compile_entries++;
   4677         if(num_compile_entries >= COMPILE_TABLE_SIZE) {
   4678             ALOGE("compileTable overflow");
   4679             dvmAbort();
   4680         }
   4681     }
   4682     compileTable[index].physicalReg = PhysicalReg_Null;
   4683     compileTable[index].refCount = infoByteCodeTemp[k].refCount;
   4684     compileTable[index].linkageToVR = infoByteCodeTemp[k].linkageToVR;
   4685     compileTable[index].gType = GLOBALTYPE_L;
   4686     compileTable[index].spill_loc_index = -1;
   4687 }
   4688 
   4689 /* insert a glue-related register GLUE_DVMDEX to compileTable */
   4690 void insertGlueReg() {
   4691     compileTable[num_compile_entries].physicalType = LowOpndRegType_gp;
   4692     compileTable[num_compile_entries].regNum = PhysicalReg_GLUE_DVMDEX;
   4693     compileTable[num_compile_entries].refCount = 2;
   4694     compileTable[num_compile_entries].physicalReg = PhysicalReg_Null;
   4695     compileTable[num_compile_entries].bb = NULL;
   4696     compileTable[num_compile_entries].spill_loc_index = -1;
   4697     compileTable[num_compile_entries].accessType = REGACCESS_N;
   4698     compileTable[num_compile_entries].linkageToVR = -1;
   4699     compileTable[num_compile_entries].gType = GLOBALTYPE_L;
   4700 
   4701     num_compile_entries++;
   4702     if(num_compile_entries >= COMPILE_TABLE_SIZE) {
   4703         ALOGE("compileTable overflow");
   4704         dvmAbort();
   4705     }
   4706 }
   4707 
   4708 /** print infoBasicBlock of the given basic block
   4709 */
   4710 void dumpVirtualInfoOfBasicBlock(BasicBlock_O1* bb) {
   4711     int jj;
   4712     ALOGI("Virtual Info for BB%d --------", bb->bb_index);
   4713     for(jj = 0; jj < bb->num_regs; jj++) {
   4714         ALOGI("regNum %d physicalType %d accessType %d refCount %d def ",
   4715                bb->infoBasicBlock[jj].regNum, bb->infoBasicBlock[jj].physicalType,
   4716                bb->infoBasicBlock[jj].accessType, bb->infoBasicBlock[jj].refCount);
   4717         int k;
   4718         for(k = 0; k < bb->infoBasicBlock[jj].num_reaching_defs; k++)
   4719             ALOGI("[%x %d %d %d] ", bb->infoBasicBlock[jj].reachingDefs[k].offsetPC,
   4720                    bb->infoBasicBlock[jj].reachingDefs[k].regNum,
   4721                    bb->infoBasicBlock[jj].reachingDefs[k].physicalType,
   4722                    bb->infoBasicBlock[jj].reachingDefs[k].accessType);
   4723         ALOGI("");
   4724     }
   4725 }
   4726 
   4727 /** print compileTable
   4728 */
   4729 void dumpCompileTable() {
   4730     int jj;
   4731     ALOGI("Compile Table for method ----------");
   4732     for(jj = 0; jj < num_compile_entries; jj++) {
   4733         ALOGI("regNum %d physicalType %d refCount %d isConst %d physicalReg %d type %d",
   4734                compileTable[jj].regNum, compileTable[jj].physicalType,
   4735                compileTable[jj].refCount, compileTable[jj].isConst, compileTable[jj].physicalReg, compileTable[jj].gType);
   4736     }
   4737 }
   4738 
   4739 //!check whether a basic block is the start of an exception handler
   4740 
   4741 //!
   4742 bool isFirstOfHandler(BasicBlock_O1* bb) {
   4743     int i;
   4744     for(i = 0; i < num_exception_handlers; i++) {
   4745         if(bb->pc_start == exceptionHandlers[i]) return true;
   4746     }
   4747     return false;
   4748 }
   4749 
   4750 //! create a basic block that starts at src_pc and ends at end_pc
   4751 
   4752 //!
   4753 BasicBlock_O1* createBasicBlock(int src_pc, int end_pc) {
   4754     BasicBlock_O1* bb = (BasicBlock_O1*)malloc(sizeof(BasicBlock_O1));
   4755     if(bb == NULL) {
   4756         ALOGE("out of memory");
   4757         return NULL;
   4758     }
   4759     bb->pc_start = src_pc;
   4760     bb->bb_index = num_bbs_for_method;
   4761     if(bb_entry == NULL) bb_entry = bb;
   4762 
   4763     /* insert the basic block to method_bbs_sorted in ascending order of pc_start */
   4764     int k;
   4765     int index = -1;
   4766     for(k = 0; k < num_bbs_for_method; k++)
   4767         if(method_bbs_sorted[k]->pc_start > src_pc) {
   4768             index = k;
   4769             break;
   4770         }
   4771     if(index == -1)
   4772         method_bbs_sorted[num_bbs_for_method] = bb;
   4773     else {
   4774         /* push the elements from index by 1 */
   4775         for(k = num_bbs_for_method-1; k >= index; k--)
   4776             method_bbs_sorted[k+1] = method_bbs_sorted[k];
   4777         method_bbs_sorted[index] = bb;
   4778     }
   4779     num_bbs_for_method++;
   4780     if(num_bbs_for_method >= MAX_NUM_BBS_PER_METHOD) {
   4781         ALOGE("too many basic blocks");
   4782         dvmAbort();
   4783     }
   4784     return bb;
   4785 }
   4786 
   4787 /* BEGIN code to handle state transfers */
   4788 //! save the current state of register allocator to a state table
   4789 
   4790 //!
   4791 void rememberState(int stateNum) {
   4792 #ifdef DEBUG_STATE
   4793     ALOGI("STATE: remember state %d", stateNum);
   4794 #endif
   4795     int k;
   4796     for(k = 0; k < num_compile_entries; k++) {
   4797         if(stateNum == 1) {
   4798             stateTable1_1[k].physicalReg = compileTable[k].physicalReg;
   4799             stateTable1_1[k].spill_loc_index = compileTable[k].spill_loc_index;
   4800         }
   4801         else if(stateNum == 2) {
   4802             stateTable1_2[k].physicalReg = compileTable[k].physicalReg;
   4803             stateTable1_2[k].spill_loc_index = compileTable[k].spill_loc_index;
   4804         }
   4805         else if(stateNum == 3) {
   4806             stateTable1_3[k].physicalReg = compileTable[k].physicalReg;
   4807             stateTable1_3[k].spill_loc_index = compileTable[k].spill_loc_index;
   4808         }
   4809         else if(stateNum == 4) {
   4810             stateTable1_4[k].physicalReg = compileTable[k].physicalReg;
   4811             stateTable1_4[k].spill_loc_index = compileTable[k].spill_loc_index;
   4812         }
   4813         else ALOGE("state table overflow");
   4814 #ifdef DEBUG_STATE
   4815         ALOGI("logical reg %d %d mapped to physical reg %d with spill index %d refCount %d",
   4816                compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg,
   4817                compileTable[k].spill_loc_index, compileTable[k].refCount);
   4818 #endif
   4819     }
   4820     for(k = 0; k < num_memory_vr; k++) {
   4821         if(stateNum == 1) {
   4822             stateTable2_1[k].regNum = memVRTable[k].regNum;
   4823             stateTable2_1[k].inMemory = memVRTable[k].inMemory;
   4824         }
   4825         else if(stateNum == 2) {
   4826             stateTable2_2[k].regNum = memVRTable[k].regNum;
   4827             stateTable2_2[k].inMemory = memVRTable[k].inMemory;
   4828         }
   4829         else if(stateNum == 3) {
   4830             stateTable2_3[k].regNum = memVRTable[k].regNum;
   4831             stateTable2_3[k].inMemory = memVRTable[k].inMemory;
   4832         }
   4833         else if(stateNum == 4) {
   4834             stateTable2_4[k].regNum = memVRTable[k].regNum;
   4835             stateTable2_4[k].inMemory = memVRTable[k].inMemory;
   4836         }
   4837         else ALOGE("state table overflow");
   4838 #ifdef DEBUG_STATE
   4839         ALOGI("virtual reg %d in memory %d", memVRTable[k].regNum, memVRTable[k].inMemory);
   4840 #endif
   4841     }
   4842 }
   4843 
   4844 //!update current state of register allocator with a state table
   4845 
   4846 //!
   4847 void goToState(int stateNum) {
   4848     int k;
   4849 #ifdef DEBUG_STATE
   4850     ALOGI("STATE: go to state %d", stateNum);
   4851 #endif
   4852     for(k = 0; k < num_compile_entries; k++) {
   4853         if(stateNum == 1) {
   4854             compileTable[k].physicalReg = stateTable1_1[k].physicalReg;
   4855             compileTable[k].spill_loc_index = stateTable1_1[k].spill_loc_index;
   4856         }
   4857         else if(stateNum == 2) {
   4858             compileTable[k].physicalReg = stateTable1_2[k].physicalReg;
   4859             compileTable[k].spill_loc_index = stateTable1_2[k].spill_loc_index;
   4860         }
   4861         else if(stateNum == 3) {
   4862             compileTable[k].physicalReg = stateTable1_3[k].physicalReg;
   4863             compileTable[k].spill_loc_index = stateTable1_3[k].spill_loc_index;
   4864         }
   4865         else if(stateNum == 4) {
   4866             compileTable[k].physicalReg = stateTable1_4[k].physicalReg;
   4867             compileTable[k].spill_loc_index = stateTable1_4[k].spill_loc_index;
   4868         }
   4869         else ALOGE("state table overflow");
   4870     }
   4871     updateSpillIndexUsed();
   4872     syncAllRegs(); //to sync up allRegs CAN'T call freeReg here
   4873     //since it will change the state!!!
   4874     for(k = 0; k < num_memory_vr; k++) {
   4875         if(stateNum == 1) {
   4876             memVRTable[k].regNum = stateTable2_1[k].regNum;
   4877             memVRTable[k].inMemory = stateTable2_1[k].inMemory;
   4878         }
   4879         else if(stateNum == 2) {
   4880             memVRTable[k].regNum = stateTable2_2[k].regNum;
   4881             memVRTable[k].inMemory = stateTable2_2[k].inMemory;
   4882         }
   4883         else if(stateNum == 3) {
   4884             memVRTable[k].regNum = stateTable2_3[k].regNum;
   4885             memVRTable[k].inMemory = stateTable2_3[k].inMemory;
   4886         }
   4887         else if(stateNum == 4) {
   4888             memVRTable[k].regNum = stateTable2_4[k].regNum;
   4889             memVRTable[k].inMemory = stateTable2_4[k].inMemory;
   4890         }
   4891         else ALOGE("state table overflow");
   4892     }
   4893 }
   4894 typedef struct TransferOrder {
   4895     int targetReg;
   4896     int targetSpill;
   4897     int compileIndex;
   4898 } TransferOrder;
   4899 #define MAX_NUM_DEST 20
   4900 //! a source register is used as a source in transfer
   4901 //! it can have a maximum of MAX_NUM_DEST destinations
   4902 typedef struct SourceReg {
   4903     int physicalReg;
   4904     int num_dests; //check bound
   4905     TransferOrder dsts[MAX_NUM_DEST];
   4906 } SourceReg;
   4907 int num_src_regs = 0; //check bound
   4908 //! physical registers that are used as a source in transfer
   4909 //! we allow a maximum of MAX_NUM_DEST sources in a transfer
   4910 SourceReg srcRegs[MAX_NUM_DEST];
   4911 //! tell us whether a source register is handled already
   4912 bool handledSrc[MAX_NUM_DEST];
   4913 //! in what order should the source registers be handled
   4914 int handledOrder[MAX_NUM_DEST];
   4915 //! insert a source register with a single destination
   4916 
   4917 //!
   4918 void insertSrcReg(int srcPhysical, int targetReg, int targetSpill, int index) {
   4919     int k = 0;
   4920     for(k = 0; k < num_src_regs; k++) {
   4921         if(srcRegs[k].physicalReg == srcPhysical) { //increase num_dests
   4922             if(srcRegs[k].num_dests >= MAX_NUM_DEST) {
   4923                 ALOGE("exceed number dst regs for a source reg");
   4924                 dvmAbort();
   4925             }
   4926             srcRegs[k].dsts[srcRegs[k].num_dests].targetReg = targetReg;
   4927             srcRegs[k].dsts[srcRegs[k].num_dests].targetSpill = targetSpill;
   4928             srcRegs[k].dsts[srcRegs[k].num_dests].compileIndex = index;
   4929             srcRegs[k].num_dests++;
   4930             return;
   4931         }
   4932     }
   4933     if(num_src_regs >= MAX_NUM_DEST) {
   4934         ALOGE("exceed number of source regs");
   4935         dvmAbort();
   4936     }
   4937     srcRegs[num_src_regs].physicalReg = srcPhysical;
   4938     srcRegs[num_src_regs].num_dests = 1;
   4939     srcRegs[num_src_regs].dsts[0].targetReg = targetReg;
   4940     srcRegs[num_src_regs].dsts[0].targetSpill = targetSpill;
   4941     srcRegs[num_src_regs].dsts[0].compileIndex = index;
   4942     num_src_regs++;
   4943 }
   4944 //! check whether a register is a source and the source is not yet handled
   4945 
   4946 //!
   4947 bool dstStillInUse(int dstReg) {
   4948     if(dstReg == PhysicalReg_Null) return false;
   4949     int k;
   4950     int index = -1;
   4951     for(k = 0; k < num_src_regs; k++) {
   4952         if(dstReg == srcRegs[k].physicalReg) {
   4953             index = k;
   4954             break;
   4955         }
   4956     }
   4957     if(index < 0) return false; //not in use
   4958     if(handledSrc[index]) return false; //not in use
   4959     return true;
   4960 }
   4961 //! reset the state of glue variables in a state table
   4962 
   4963 //!
   4964 void resetStateOfGlue(int stateNum, int k) {
   4965 #ifdef DEBUG_STATE
   4966     ALOGI("resetStateOfGlue state %d regNum %d", stateNum, compileTable[k].regNum);
   4967 #endif
   4968     if(stateNum == 1) {
   4969         stateTable1_1[k].physicalReg = PhysicalReg_Null;
   4970         stateTable1_1[k].spill_loc_index = -1;
   4971     }
   4972     else if(stateNum == 2) {
   4973         stateTable1_2[k].physicalReg = PhysicalReg_Null;
   4974         stateTable1_2[k].spill_loc_index = -1;
   4975     }
   4976     else if(stateNum == 3) {
   4977         stateTable1_3[k].physicalReg = PhysicalReg_Null;
   4978         stateTable1_3[k].spill_loc_index = -1;
   4979     }
   4980     else if(stateNum == 4) {
   4981         stateTable1_4[k].physicalReg = PhysicalReg_Null;
   4982         stateTable1_4[k].spill_loc_index = -1;
   4983     }
   4984 }
   4985 //! construct a legal order of the source registers in this transfer
   4986 
   4987 //!
   4988 void constructSrcRegs(int stateNum) {
   4989     int k;
   4990     num_src_regs = 0;
   4991 #ifdef DEBUG_STATE
   4992     ALOGI("IN constructSrcRegs");
   4993 #endif
   4994 
   4995     for(k = 0; k < num_compile_entries; k++) {
   4996 #ifdef DEBUG_STATE
   4997         ALOGI("logical reg %d %d mapped to physical reg %d with spill index %d refCount %d",
   4998                compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg,
   4999                compileTable[k].spill_loc_index, compileTable[k].refCount);
   5000 #endif
   5001 
   5002         int pType = compileTable[k].physicalType;
   5003         //ignore hardcoded logical registers
   5004         if((pType & LowOpndRegType_hard) != 0) continue;
   5005         //ignore type _fs
   5006         if((pType & MASK_FOR_TYPE) == LowOpndRegType_fs) continue;
   5007         if((pType & MASK_FOR_TYPE) == LowOpndRegType_fs_s) continue;
   5008 
   5009         //GL VR refCount is zero, can't ignore
   5010         //L VR refCount is zero, ignore
   5011         //GG VR refCount is zero, can't ignore
   5012         //temporary refCount is zero, ignore
   5013 
   5014         //for GLUE variables, if they do not exist, reset the entries in state table
   5015         if(compileTable[k].physicalReg == PhysicalReg_Null &&
   5016            compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
   5017            compileTable[k].regNum != PhysicalReg_GLUE &&
   5018            compileTable[k].spill_loc_index < 0) {
   5019             resetStateOfGlue(stateNum, k);
   5020         }
   5021 
   5022         /* get the target state */
   5023         int targetReg = PhysicalReg_Null;
   5024         int targetSpill = -1;
   5025         if(stateNum == 1) {
   5026             targetReg = stateTable1_1[k].physicalReg;
   5027             targetSpill = stateTable1_1[k].spill_loc_index;
   5028         }
   5029         else if(stateNum == 2) {
   5030             targetReg = stateTable1_2[k].physicalReg;
   5031             targetSpill = stateTable1_2[k].spill_loc_index;
   5032         }
   5033         else if(stateNum == 3) {
   5034             targetReg = stateTable1_3[k].physicalReg;
   5035             targetSpill = stateTable1_3[k].spill_loc_index;
   5036         }
   5037         else if(stateNum == 4) {
   5038             targetReg = stateTable1_4[k].physicalReg;
   5039             targetSpill = stateTable1_4[k].spill_loc_index;
   5040         }
   5041 
   5042         /* there exists an ordering problem
   5043            for example:
   5044              for a VR, move from memory to a physical reg esi
   5045              for a temporary regsiter, from esi to ecx
   5046              if we handle VR first, content of the temporary reg. will be overwritten
   5047            there are 4 cases:
   5048              I: a variable is currently in memory and its target is in physical reg
   5049              II: a variable is currently in a register and its target is in memory
   5050              III: a variable is currently in a different register
   5051              IV: a variable is currently in a different memory location (for non-VRs)
   5052            for GLUE, since it can only be allocated to %ebp, we don't have case III
   5053            For now, case IV is not handled since it didn't show
   5054         */
   5055         if(compileTable[k].physicalReg != targetReg &&
   5056            isVirtualReg(compileTable[k].physicalType)) {
   5057             /* handles VR for case I to III */
   5058 
   5059             if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5060                 /* handles VR for case I:
   5061                    insert a xfer order from PhysicalReg_Null to targetReg */
   5062                 insertSrcReg(PhysicalReg_Null, targetReg, targetSpill, k);
   5063 #ifdef DEBUG_STATE
   5064                 ALOGI("insert for VR Null %d %d %d", targetReg, targetSpill, k);
   5065 #endif
   5066             }
   5067 
   5068             if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5069                 /* handles VR for case III
   5070                    insert a xfer order from srcReg to targetReg */
   5071                 insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
   5072             }
   5073 
   5074             if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
   5075                 /* handles VR for case II
   5076                    insert a xfer order from srcReg to memory */
   5077                 insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
   5078             }
   5079         }
   5080 
   5081         if(compileTable[k].physicalReg != targetReg &&
   5082            !isVirtualReg(compileTable[k].physicalType)) {
   5083             /* handles non-VR for case I to III */
   5084 
   5085             if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5086                 /* handles non-VR for case I */
   5087                 if(compileTable[k].spill_loc_index < 0) {
   5088                     /* this variable is freed, no need to transfer */
   5089 #ifdef DEBUG_STATE
   5090                     ALOGW("in transferToState spill_loc_index is negative for temporary %d", compileTable[k].regNum);
   5091 #endif
   5092                 } else {
   5093                     /* insert a xfer order from memory to targetReg */
   5094 #ifdef DEBUG_STATE
   5095                     ALOGI("insert Null %d %d %d", targetReg, targetSpill, k);
   5096 #endif
   5097                     insertSrcReg(PhysicalReg_Null, targetReg, targetSpill, k);
   5098                 }
   5099             }
   5100 
   5101             if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5102                 /* handles non-VR for case III
   5103                    insert a xfer order from srcReg to targetReg */
   5104                 insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
   5105             }
   5106 
   5107             if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
   5108                 /* handles non-VR for case II */
   5109                 if(targetSpill < 0) {
   5110                     /* this variable is freed, no need to transfer */
   5111 #ifdef DEBUG_STATE
   5112                     ALOGW("in transferToState spill_loc_index is negative for temporary %d", compileTable[k].regNum);
   5113 #endif
   5114                 } else {
   5115                     /* insert a xfer order from srcReg to memory */
   5116                     insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
   5117                 }
   5118             }
   5119 
   5120         }
   5121     }//for compile entries
   5122 
   5123     int k2;
   5124 #ifdef DEBUG_STATE
   5125     for(k = 0; k < num_src_regs; k++) {
   5126         ALOGI("SRCREG %d: ", srcRegs[k].physicalReg);
   5127         for(k2 = 0; k2 < srcRegs[k].num_dests; k2++) {
   5128             int index = srcRegs[k].dsts[k2].compileIndex;
   5129             ALOGI("[%d %d %d: %d %d %d] ", srcRegs[k].dsts[k2].targetReg,
   5130                    srcRegs[k].dsts[k2].targetSpill, srcRegs[k].dsts[k2].compileIndex,
   5131                    compileTable[index].regNum, compileTable[index].physicalType,
   5132                    compileTable[index].spill_loc_index);
   5133         }
   5134         ALOGI("");
   5135     }
   5136 #endif
   5137 
   5138     /* construct an order: xfers from srcReg first, then xfers from memory */
   5139     int num_handled = 0;
   5140     int num_in_order = 0;
   5141     for(k = 0; k < num_src_regs; k++) {
   5142         if(srcRegs[k].physicalReg == PhysicalReg_Null) {
   5143             handledSrc[k] = true;
   5144             num_handled++;
   5145         } else {
   5146             handledSrc[k] = false;
   5147         }
   5148     }
   5149     while(num_handled < num_src_regs) {
   5150         int prev_handled = num_handled;
   5151         for(k = 0; k < num_src_regs; k++) {
   5152             if(handledSrc[k]) continue;
   5153             bool canHandleNow = true;
   5154             for(k2 = 0; k2 < srcRegs[k].num_dests; k2++) {
   5155                 if(dstStillInUse(srcRegs[k].dsts[k2].targetReg)) {
   5156                     canHandleNow = false;
   5157                     break;
   5158                 }
   5159             }
   5160             if(canHandleNow) {
   5161                 handledSrc[k] = true;
   5162                 num_handled++;
   5163                 handledOrder[num_in_order] = k;
   5164                 num_in_order++;
   5165             }
   5166         } //for k
   5167         if(num_handled == prev_handled) {
   5168             ALOGE("no progress in selecting order");
   5169             dvmAbort();
   5170         }
   5171     } //while
   5172     for(k = 0; k < num_src_regs; k++) {
   5173         if(srcRegs[k].physicalReg == PhysicalReg_Null) {
   5174             handledOrder[num_in_order] = k;
   5175             num_in_order++;
   5176         }
   5177     }
   5178     if(num_in_order != num_src_regs) {
   5179         ALOGE("num_in_order != num_src_regs");
   5180         dvmAbort();
   5181     }
   5182 #ifdef DEBUG_STATE
   5183     ALOGI("ORDER: ");
   5184     for(k = 0; k < num_src_regs; k++) {
   5185         ALOGI("%d ", handledOrder[k]);
   5186     }
   5187     ALOGI("");
   5188 #endif
   5189 }
   5190 //! transfer the state of register allocator to a state specified in a state table
   5191 
   5192 //!
   5193 void transferToState(int stateNum) {
   5194     freeReg(false); //do not spill GL
   5195     int k;
   5196 #ifdef DEBUG_STATE
   5197     ALOGI("STATE: transfer to state %d", stateNum);
   5198 #endif
   5199     if(stateNum > 4 || stateNum < 1) ALOGE("state table overflow");
   5200     constructSrcRegs(stateNum);
   5201     int k4, k3;
   5202     for(k4 = 0; k4 < num_src_regs; k4++) {
   5203         int k2 = handledOrder[k4]; //index to srcRegs
   5204         for(k3 = 0; k3 < srcRegs[k2].num_dests; k3++) {
   5205             k = srcRegs[k2].dsts[k3].compileIndex;
   5206             int targetReg = srcRegs[k2].dsts[k3].targetReg;
   5207             int targetSpill = srcRegs[k2].dsts[k3].targetSpill;
   5208             if(compileTable[k].physicalReg != targetReg && isVirtualReg(compileTable[k].physicalType)) {
   5209                 OpndSize oSize = getRegSize(compileTable[k].physicalType);
   5210                 bool isSS = ((compileTable[k].physicalType & MASK_FOR_TYPE) == LowOpndRegType_ss);
   5211                 if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5212                     if(isSS)
   5213                         move_ss_mem_to_reg_noalloc(4*compileTable[k].regNum,
   5214                                                    PhysicalReg_FP, true,
   5215                                                    MemoryAccess_VR, compileTable[k].regNum,
   5216                                                    targetReg, true);
   5217                     else
   5218                         move_mem_to_reg_noalloc(oSize, 4*compileTable[k].regNum,
   5219                                                 PhysicalReg_FP, true,
   5220                                                 MemoryAccess_VR, compileTable[k].regNum,
   5221                                                 targetReg, true);
   5222                 }
   5223                 if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5224                     move_reg_to_reg_noalloc((isSS ? OpndSize_64 : oSize),
   5225                                             compileTable[k].physicalReg, true,
   5226                                             targetReg, true);
   5227                 }
   5228                 if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
   5229                     dumpToMem(compileTable[k].regNum, (LowOpndRegType)(compileTable[k].physicalType & MASK_FOR_TYPE),
   5230                               compileTable[k].physicalReg);
   5231                 }
   5232             } //VR
   5233             if(compileTable[k].physicalReg != targetReg && !isVirtualReg(compileTable[k].physicalType)) {
   5234                 OpndSize oSize = getRegSize(compileTable[k].physicalType);
   5235                 if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5236                     loadFromSpillRegion(oSize, targetReg,
   5237                                         compileTable[k].spill_loc_index);
   5238                 }
   5239                 //both are not null, move from one to the other
   5240                 if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
   5241                     move_reg_to_reg_noalloc(oSize, compileTable[k].physicalReg, true,
   5242                                             targetReg, true);
   5243                 }
   5244                 //current is not null, target is null (move from reg to memory)
   5245                 if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
   5246                     saveToSpillRegion(oSize, compileTable[k].physicalReg, targetSpill);
   5247                 }
   5248             } //temporary
   5249         }//for
   5250     }//for
   5251     for(k = 0; k < num_memory_vr; k++) {
   5252         bool targetBool = false;
   5253         int targetReg = -1;
   5254         if(stateNum == 1) {
   5255             targetReg = stateTable2_1[k].regNum;
   5256             targetBool = stateTable2_1[k].inMemory;
   5257         }
   5258         else if(stateNum == 2) {
   5259             targetReg = stateTable2_2[k].regNum;
   5260             targetBool = stateTable2_2[k].inMemory;
   5261         }
   5262         else if(stateNum == 3) {
   5263             targetReg = stateTable2_3[k].regNum;
   5264             targetBool = stateTable2_3[k].inMemory;
   5265         }
   5266         else if(stateNum == 4) {
   5267             targetReg = stateTable2_4[k].regNum;
   5268             targetBool = stateTable2_4[k].inMemory;
   5269         }
   5270         if(targetReg != memVRTable[k].regNum)
   5271             ALOGE("regNum mismatch in transferToState");
   5272         if(targetBool && (!memVRTable[k].inMemory)) {
   5273             //dump to memory, check entries in compileTable: vA gp vA xmm vA ss
   5274 #ifdef DEBUG_STATE
   5275             ALOGW("inMemory mismatch for VR %d in transferToState", targetReg);
   5276 #endif
   5277             bool doneXfer = false;
   5278             int index = searchCompileTable(LowOpndRegType_xmm | LowOpndRegType_virtual, targetReg);
   5279             if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   5280                 dumpToMem(targetReg, LowOpndRegType_xmm, compileTable[index].physicalReg);
   5281                 doneXfer = true;
   5282             }
   5283             if(!doneXfer) { //vA-1, xmm
   5284                 index = searchCompileTable(LowOpndRegType_xmm | LowOpndRegType_virtual, targetReg-1);
   5285                 if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   5286                     dumpToMem(targetReg-1, LowOpndRegType_xmm, compileTable[index].physicalReg);
   5287                     doneXfer = true;
   5288                 }
   5289             }
   5290             if(!doneXfer) { //vA gp
   5291                 index = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_virtual, targetReg);
   5292                 if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   5293                     dumpToMem(targetReg, LowOpndRegType_gp, compileTable[index].physicalReg);
   5294                     doneXfer = true;
   5295                 }
   5296             }
   5297             if(!doneXfer) { //vA, ss
   5298                 index = searchCompileTable(LowOpndRegType_ss | LowOpndRegType_virtual, targetReg);
   5299                 if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
   5300                     dumpToMem(targetReg, LowOpndRegType_ss, compileTable[index].physicalReg);
   5301                     doneXfer = true;
   5302                 }
   5303             }
   5304             if(!doneXfer) ALOGW("can't match inMemory of VR %d in transferToState", targetReg);
   5305         }
   5306         if((!targetBool) && memVRTable[k].inMemory) {
   5307             //do nothing
   5308         }
   5309     }
   5310 #ifdef DEBUG_STATE
   5311     ALOGI("END transferToState %d", stateNum);
   5312 #endif
   5313     goToState(stateNum);
   5314 }
   5315 /* END code to handle state transfers */
   5316