/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*! \file lower.h \brief A header file to define interface between lowering and register allocator */ #ifndef _DALVIK_LOWER #define _DALVIK_LOWER #define CODE_CACHE_PADDING 1024 //code space for a single bytecode // comment out for phase 1 porting #define PREDICTED_CHAINING #define JIT_CHAIN #define NUM_DEPENDENCIES 24 /* max number of dependencies from a LowOp */ //compilaton flags used by NCG O1 #define DUMP_EXCEPTION //to measure performance, required to have correct exception handling /*! multiple versions for hardcoded registers */ #define HARDREG_OPT #define CFG_OPT /*! remove redundant move ops when accessing virtual registers */ #define MOVE_OPT /*! remove redundant spill of virtual registers */ #define SPILL_OPT #define XFER_OPT //#define DSE_OPT //no perf improvement for cme /*! use live range analysis to allocate registers */ #define LIVERANGE_OPT /*! remove redundant null check */ #define NULLCHECK_OPT //#define BOUNDCHECK_OPT /*! optimize the access to glue structure */ #define GLUE_OPT #define CALL_FIX #define NATIVE_FIX #define INVOKE_FIX //optimization #define GETVR_FIX //optimization #include "Dalvik.h" #include "enc_wrapper.h" #include "AnalysisO1.h" #include "compiler/CompilerIR.h" //compilation flags for debugging //#define DEBUG_INFO //#define DEBUG_CALL_STACK //#define DEBUG_IGET_OBJ //#define DEBUG_NCG_CODE_SIZE //#define DEBUG_NCG //#define DEBUG_NCG_1 //#define DEBUG_LOADING //#define USE_INTERPRETER //#define DEBUG_EACH_BYTECODE /*! registers for functions are hardcoded */ #define HARDCODE_REG_CALL #define HARDCODE_REG_SHARE #define HARDCODE_REG_HELPER #define PhysicalReg_FP PhysicalReg_EDI #define PhysicalReg_Glue PhysicalReg_EBP //COPIED from interp/InterpDefs.h #define FETCH(_offset) (rPC[(_offset)]) #define INST_INST(_inst) ((_inst) & 0xff) #define INST_A(_inst) (((_inst) >> 8) & 0x0f) #define INST_B(_inst) ((_inst) >> 12) #define INST_AA(_inst) ((_inst) >> 8) //#include "vm/mterp/common/asm-constants.h" #define offEBP_self 8 #define offEBP_spill -56 #define offThread_exception 68 #define offClassObject_descriptor 24 #define offArrayObject_length 8 #ifdef PROFILE_FIELD_ACCESS #define offStaticField_value 24 #define offInstField_byteOffset 24 #else #define offStaticField_value 16 #define offInstField_byteOffset 16 #endif #ifdef EASY_GDB #define offStackSaveArea_prevFrame 4 #define offStackSaveArea_savedPc 8 #define offStackSaveArea_method 12 #define offStackSaveArea_localRefTop 16 // -> StackSaveArea.xtra.locakRefCookie #define offStackSaveArea_returnAddr 20 #define offStackSaveArea_isDebugInterpreted 24 #define sizeofStackSaveArea 24 #else #define offStackSaveArea_prevFrame 0 #define offStackSaveArea_savedPc 4 #define offStackSaveArea_method 8 #define offStackSaveArea_localRefTop 12 // -> StackSaveArea.xtra.locakRefCookie #define offStackSaveArea_returnAddr 16 #define offStackSaveArea_isDebugInterpreted 20 #define sizeofStackSaveArea 20 #endif #define offClassObject_status 44 #define offClassObject_accessFlags 32 #ifdef MTERP_NO_UNALIGN_64 #define offArrayObject_contents 16 #else #define offArrayObject_contents 12 #endif #define offField_clazz 0 #define offObject_clazz 0 #define offClassObject_vtable 116 #define offClassObject_pDvmDex 40 #define offClassObject_super 72 #define offClassObject_vtableCount 112 #define offMethod_name 16 #define offMethod_accessFlags 4 #define offMethod_methodIndex 8 #define offMethod_registersSize 10 #define offMethod_outsSize 12 #define offGlue_interpStackEnd 32 #define offThread_inJitCodeCache 124 #define offThread_jniLocal_nextEntry 168 #define offMethod_insns 32 #ifdef ENABLE_TRACING #define offMethod_insns_bytecode 44 #define offMethod_insns_ncg 48 #endif #define offGlue_pc 0 #define offGlue_fp 4 #define offGlue_retval 8 #define offThread_curFrame 4 #define offGlue_method 16 #define offGlue_methodClassDex 20 #define offGlue_self 24 #define offGlue_pSelfSuspendCount 36 #define offGlue_cardTable 40 #define offGlue_pDebuggerActive 44 #define offGlue_pActiveProfilers 48 #define offGlue_entryPoint 52 #define offGlue_icRechainCount 84 #define offGlue_espEntry 88 #define offGlue_spillRegion 92 #define offDvmDex_pResStrings 8 #define offDvmDex_pResClasses 12 #define offDvmDex_pResMethods 16 #define offDvmDex_pResFields 20 #define offMethod_clazz 0 // Definitions must be consistent with vm/mterp/x86/header.S #define FRAME_SIZE 124 typedef enum ArgsDoneType { ArgsDone_Normal = 0, ArgsDone_Native, ArgsDone_Full } ArgsDoneType; /*! An enum type to list bytecodes for AGET, APUT */ typedef enum ArrayAccess { AGET, AGET_WIDE, AGET_CHAR, AGET_SHORT, AGET_BOOLEAN, AGET_BYTE, APUT, APUT_WIDE, APUT_CHAR, APUT_SHORT, APUT_BOOLEAN, APUT_BYTE } ArrayAccess; /*! An enum type to list bytecodes for IGET, IPUT */ typedef enum InstanceAccess { IGET, IGET_WIDE, IPUT, IPUT_WIDE } InstanceAccess; /*! An enum type to list bytecodes for SGET, SPUT */ typedef enum StaticAccess { SGET, SGET_WIDE, SPUT, SPUT_WIDE } StaticAccess; typedef enum JmpCall_type { JmpCall_uncond = 1, JmpCall_cond, JmpCall_reg, //jump reg32 JmpCall_call } JmpCall_type; //////////////////////////////////////////////////////////////// /* data structure for native codes */ /* Due to space considation, a lowered op (LowOp) has two operands (LowOpnd), depending on the type of the operand, LowOpndReg or LowOpndImm or LowOpndMem will follow */ /*! type of an operand can be immediate, register or memory */ typedef enum LowOpndType { LowOpndType_Imm = 0, LowOpndType_Reg, LowOpndType_Mem, LowOpndType_Label, LowOpndType_NCG, LowOpndType_Chain } LowOpndType; typedef enum LowOpndDefUse { LowOpndDefUse_Def = 0, LowOpndDefUse_Use, LowOpndDefUse_UseDef } LowOpndDefUse; /*! \brief base data structure for an operand */ typedef struct LowOpnd { LowOpndType type; OpndSize size; LowOpndDefUse defuse; } LowOpnd; /*! \brief data structure for a register operand */ typedef struct LowOpndReg { LowOpndRegType regType; int logicalReg; int physicalReg; } LowOpndReg; /*! \brief data structure for an immediate operand */ typedef struct LowOpndImm { union { s4 value; unsigned char bytes[4]; }; } LowOpndImm; typedef struct LowOpndNCG { union { s4 value; unsigned char bytes[4]; }; } LowOpndNCG; #define LABEL_SIZE 256 typedef struct LowOpndLabel { char label[LABEL_SIZE]; bool isLocal; } LowOpndLabel; /* get ready for optimizations at LIR add MemoryAccessType & virtualRegNum to memory operands */ typedef enum MemoryAccessType { MemoryAccess_GLUE, MemoryAccess_VR, MemoryAccess_SPILL, MemoryAccess_Unknown } MemoryAccessType; typedef enum UseDefEntryType { UseDefType_Ctrl = 0, UseDefType_Float, UseDefType_MemVR, UseDefType_MemSpill, UseDefType_MemUnknown, UseDefType_Reg } UseDefEntryType; typedef struct UseDefProducerEntry { UseDefEntryType type; int index; //enum PhysicalReg for "Reg" type int producerSlot; } UseDefProducerEntry; #define MAX_USE_PER_ENTRY 50 /* at most 10 uses for each entry */ typedef struct UseDefUserEntry { UseDefEntryType type; int index; int useSlots[MAX_USE_PER_ENTRY]; int num_uses_per_entry; } UseDefUserEntry; /*! \brief data structure for a memory operand */ typedef struct LowOpndMem { LowOpndImm m_disp; LowOpndImm m_scale; LowOpndReg m_index; LowOpndReg m_base; bool hasScale; MemoryAccessType mType; int index; } LowOpndMem; typedef enum AtomOpCode { ATOM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH = -15, ATOM_NORMAL_ALU = -14, ATOM_PSEUDO_ENTRY_BLOCK = -13, ATOM_PSEUDO_EXIT_BLOCK = -12, ATOM_PSEUDO_TARGET_LABEL = -11, ATOM_PSEUDO_CHAINING_CELL_HOT = -10, ATOM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED = -9, ATOM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON = -8, ATOM_PSEUDO_CHAINING_CELL_NORMAL = -7, ATOM_PSEUDO_DALVIK_BYTECODE_BOUNDARY = -6, ATOM_PSEUDO_ALIGN4 = -5, ATOM_PSEUDO_PC_RECONSTRUCTION_CELL = -4, ATOM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL = -3, ATOM_PSEUDO_EH_BLOCK_LABEL = -2, ATOM_PSEUDO_NORMAL_BLOCK_LABEL = -1, ATOM_NORMAL, } AtomOpCode; typedef enum DependencyType { Dependency_RAW, Dependency_WAW, Dependency_WAR, Dependency_FLAG } DependencyType; typedef struct DependencyStruct { DependencyType dType; int nodeId; int latency; } DependencyStruct; typedef struct LowOpBlock { LIR generic; Mnemonic opCode; AtomOpCode opCode2; } LowOpBlock; /*! \brief data structure for a lowered operation */ typedef struct LowOp { LIR generic; Mnemonic opCode; AtomOpCode opCode2; LowOpnd opnd1; LowOpnd opnd2; int numOperands; } LowOp; typedef struct LowOpLabel { LowOp lop; LowOpndLabel labelOpnd; }LowOpLabel; typedef struct LowOpNCG { LowOp lop; LowOpndNCG ncgOpnd; }LowOpNCG; typedef struct LowOpBlockLabel { LowOpBlock lop; LowOpndImm immOpnd; } LowOpBlockLabel; typedef struct LowOpImm { LowOp lop; LowOpndImm immOpnd; } LowOpImm; typedef struct LowOpMem { LowOp lop; LowOpndMem memOpnd; } LowOpMem; typedef struct LowOpReg { LowOp lop; LowOpndReg regOpnd; } LowOpReg; typedef struct LowOpImmImm { LowOp lop; LowOpndImm immOpnd1; LowOpndImm immOpnd2; } LowOpImmImm; typedef struct LowOpImmReg { LowOp lop; LowOpndImm immOpnd1; LowOpndReg regOpnd2; } LowOpImmReg; typedef struct LowOpImmMem { LowOp lop; LowOpndImm immOpnd1; LowOpndMem memOpnd2; } LowOpImmMem; typedef struct LowOpRegImm { LowOp lop; LowOpndReg regOpnd1; LowOpndImm immOpnd2; } LowOpRegImm; typedef struct LowOpRegReg { LowOp lop; LowOpndReg regOpnd1; LowOpndReg regOpnd2; } LowOpRegReg; typedef struct LowOpRegMem { LowOp lop; LowOpndReg regOpnd1; LowOpndMem memOpnd2; } LowOpRegMem; typedef struct LowOpMemImm { LowOp lop; LowOpndMem memOpnd1; LowOpndImm immOpnd2; } LowOpMemImm; typedef struct LowOpMemReg { LowOp lop; LowOpndMem memOpnd1; LowOpndReg regOpnd2; } LowOpMemReg; typedef struct LowOpMemMem { LowOp lop; LowOpndMem memOpnd1; LowOpndMem memOpnd2; } LowOpMemMem; /*! \brief data structure for labels used when lowering a method four label maps are defined: globalMap globalShortMap globalWorklist globalShortWorklist globalMap: global labels where codePtr points to the label freeLabelMap called in clearNCG globalWorklist: global labels where codePtr points to an instruciton using the label standalone NCG ------- accessed by insertLabelWorklist & performLabelWorklist code cache ------ inserted by performLabelWorklist(false), handled & cleared by generateRelocation in NcgFile.c globalShortMap: local labels where codePtr points to the label freeShortMap called after generation of one bytecode globalShortWorklist: local labels where codePtr points to an instruction using the label accessed by insertShortWorklist & insertLabel definition of local label: life time of the label is within a bytecode or within a helper function extra label maps are used by code cache: globalDataWorklist VMAPIWorklist */ typedef struct LabelMap { char label[LABEL_SIZE]; char* codePtr; //code corresponding to the label or code that uses the label struct LabelMap* nextItem; OpndSize size; uint addend; } LabelMap; /*! \brief data structure to handle forward jump (GOTO, IF) accessed by insertNCGWorklist & performNCGWorklist */ typedef struct NCGWorklist { //when WITH_JIT, relativePC stores the target basic block id s4 relativePC; //relative offset in bytecode int offsetPC; //PC in bytecode int offsetNCG; //PC in native code char* codePtr; //code for native jump instruction struct NCGWorklist* nextItem; OpndSize size; }NCGWorklist; /*! \brief data structure to handle SWITCH & FILL_ARRAY_DATA two data worklist are defined: globalDataWorklist (used by code cache) & methodDataWorklist methodDataWorklist is accessed by insertDataWorklist & performDataWorklist */ typedef struct DataWorklist { s4 relativePC; //relative offset in bytecode to access the data int offsetPC; //PC in bytecode int offsetNCG; //PC in native code char* codePtr; //code for native instruction add_imm_reg imm, %edx char* codePtr2;//code for native instruction add_reg_reg %eax, %edx for SWITCH // add_imm_reg imm, %edx for FILL_ARRAY_DATA struct DataWorklist* nextItem; }DataWorklist; #ifdef ENABLE_TRACING typedef struct MapWorklist { u4 offsetPC; u4 offsetNCG; int isStartOfPC; //1 --> true 0 --> false struct MapWorklist* nextItem; } MapWorklist; #endif #define BUFFER_SIZE 1024 //# of Low Ops buffered //the following three numbers are hardcoded, please CHECK #define BYTECODE_SIZE_PER_METHOD 81920 #define NATIVE_SIZE_PER_DEX 19000000 //FIXME for core.jar: 16M --> 18M for O1 #define NATIVE_SIZE_FOR_VM_STUBS 100000 #define MAX_HANDLER_OFFSET 1024 //maximal number of handler offsets extern int LstrClassCastExceptionPtr, LstrInstantiationErrorPtr, LstrInternalError, LstrFilledNewArrayNotImpl; extern int LstrArithmeticException, LstrArrayIndexException, LstrArrayStoreException, LstrStringIndexOutOfBoundsException; extern int LstrDivideByZero, LstrNegativeArraySizeException, LstrNoSuchMethodError, LstrNullPointerException; extern int LdoubNeg, LvaluePosInfLong, LvalueNegInfLong, LvalueNanLong, LshiftMask, Lvalue64, L64bits, LintMax, LintMin; extern LabelMap* globalMap; extern LabelMap* globalShortMap; extern LabelMap* globalWorklist; extern LabelMap* globalShortWorklist; extern NCGWorklist* globalNCGWorklist; extern DataWorklist* methodDataWorklist; #ifdef ENABLE_TRACING extern MapWorklist* methodMapWorklist; #endif extern PhysicalReg scratchRegs[4]; #define C_SCRATCH_1 scratchRegs[0] #define C_SCRATCH_2 scratchRegs[1] #define C_SCRATCH_3 scratchRegs[2] //scratch reg inside callee extern LowOp* ops[BUFFER_SIZE]; extern bool isScratchPhysical; extern u2* rPC; extern u2 inst; extern int offsetPC; extern int offsetNCG; extern int mapFromBCtoNCG[BYTECODE_SIZE_PER_METHOD]; extern char* streamStart; extern char* streamCode; extern char* streamMethodStart; //start of the method extern char* stream; //current stream pointer extern char* streamMisPred; extern int lowOpTimeStamp; extern Method* currentMethod; extern int currentExceptionBlockIdx; extern int globalMapNum; extern int globalWorklistNum; extern int globalDataWorklistNum; extern int globalPCWorklistNum; extern int chainingWorklistNum; extern int VMAPIWorklistNum; extern LabelMap* globalDataWorklist; extern LabelMap* globalPCWorklist; extern LabelMap* chainingWorklist; extern LabelMap* VMAPIWorklist; extern int ncgClassNum; extern int ncgMethodNum; extern LowOp* lirTable[200]; //Number of LIRs for all bytecodes do not exceed 200 extern int num_lirs_in_table; bool existATryBlock(Method* method, int startPC, int endPC); // interface between register allocator & lowering extern int num_removed_nullCheck; int registerAlloc(int type, int reg, bool isPhysical, bool updateRef); int registerAllocMove(int reg, int type, bool isPhysical, int srcReg); int checkVirtualReg(int reg, LowOpndRegType type, int updateRef); //returns the physical register int updateRefCount(int reg, LowOpndRegType type); int updateRefCount2(int reg, int type, bool isPhysical); int spillVirtualReg(int vrNum, LowOpndRegType type, bool updateTable); int isVirtualRegConstant(int regNum, LowOpndRegType type, int* valuePtr, bool updateRef); int checkTempReg(int reg, int type, bool isPhysical, int vA); bool checkTempReg2(int reg, int type, bool isPhysical, int physicalRegForVR); int freeReg(bool spillGL); int nextVersionOfHardReg(PhysicalReg pReg, int refCount); int updateVirtualReg(int reg, LowOpndRegType type); void setVRNullCheck(int regNum, OpndSize size); bool isVRNullCheck(int regNum, OpndSize size); void setVRBoundCheck(int vr_array, int vr_index); bool isVRBoundCheck(int vr_array, int vr_index); int requestVRFreeDelay(int regNum, u4 reason); void cancelVRFreeDelayRequest(int regNum, u4 reason); bool getVRFreeDelayRequested(int regNum); bool isGlueHandled(int glue_reg); void resetGlue(int glue_reg); void updateGlue(int reg, bool isPhysical, int glue_reg); int updateVRAtUse(int reg, LowOpndRegType pType, int regAll); int touchEcx(); int touchEax(); int touchEdx(); int beforeCall(const char* target); int afterCall(const char* target); void startBranch(); void endBranch(); void rememberState(int); void goToState(int); void transferToState(int); void globalVREndOfBB(const Method*); void constVREndOfBB(); void startNativeCode(int num, int type); void endNativeCode(); void donotSpillReg(int physicalReg); void doSpillReg(int physicalReg); #define XMM_1 PhysicalReg_XMM0 #define XMM_2 PhysicalReg_XMM1 #define XMM_3 PhysicalReg_XMM2 #define XMM_4 PhysicalReg_XMM3 ///////////////////////////////////////////////////////////////////////////////// //LR[reg] = disp + PR[base_reg] or disp + LR[base_reg] void load_effective_addr(int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void load_effective_addr_scale(int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical); void load_fpu_cw(int disp, int base_reg, bool isBasePhysical); void store_fpu_cw(bool checkException, int disp, int base_reg, bool isBasePhysical); void convert_integer(OpndSize srcSize, OpndSize dstSize); void load_fp_stack(LowOp* op, OpndSize size, int disp, int base_reg, bool isBasePhysical); void load_int_fp_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical); void load_int_fp_stack_imm(OpndSize size, int imm); void store_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical); void store_int_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical); void load_fp_stack_VR(OpndSize size, int vA); void load_int_fp_stack_VR(OpndSize size, int vA); void store_fp_stack_VR(bool pop, OpndSize size, int vA); void store_int_fp_stack_VR(bool pop, OpndSize size, int vA); void compare_VR_ss_reg(int vA, int reg, bool isPhysical); void compare_VR_sd_reg(int vA, int reg, bool isPhysical); void fpu_VR(ALU_Opcode opc, OpndSize size, int vA); void compare_reg_mem(LowOp* op, OpndSize size, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical); void compare_mem_reg(OpndSize size, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void compare_VR_reg(OpndSize size, int vA, int reg, bool isPhysical); void compare_imm_reg(OpndSize size, int imm, int reg, bool isPhysical); void compare_imm_mem(OpndSize size, int imm, int disp, int base_reg, bool isBasePhysical); void compare_imm_VR(OpndSize size, int imm, int vA); void compare_reg_reg(int reg1, bool isPhysical1, int reg2, bool isPhysical2); void compare_reg_reg_16(int reg1, bool isPhysical1, int reg2, bool isPhysical2); void compare_ss_mem_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void compare_ss_reg_with_reg(LowOp* op, int reg1, bool isPhysical1, int reg2, bool isPhysical2); void compare_sd_mem_with_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void compare_sd_reg_with_reg(LowOp* op, int reg1, bool isPhysical1, int reg2, bool isPhysical2); void compare_fp_stack(bool pop, int reg, bool isDouble); void test_imm_reg(OpndSize size, int imm, int reg, bool isPhysical); void test_imm_mem(OpndSize size, int imm, int disp, int reg, bool isPhysical); void conditional_move_reg_to_reg(OpndSize size, ConditionCode cc, int reg1, bool isPhysical1, int reg, bool isPhysical); void move_ss_mem_to_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void move_ss_reg_to_mem(LowOp* op, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical); LowOpRegMem* move_ss_mem_to_reg_noalloc(int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, int reg, bool isPhysical); LowOpMemReg* move_ss_reg_to_mem_noalloc(int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex); void move_sd_mem_to_reg(int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void move_sd_reg_to_mem(LowOp* op, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical); void conditional_jump(ConditionCode cc, const char* target, bool isShortTerm); void unconditional_jump(const char* target, bool isShortTerm); void conditional_jump_int(ConditionCode cc, int target, OpndSize size); void unconditional_jump_int(int target, OpndSize size); void unconditional_jump_reg(int reg, bool isPhysical); void call(const char* target); void call_reg(int reg, bool isPhysical); void call_reg_noalloc(int reg, bool isPhysical); void call_mem(int disp, int reg, bool isPhysical); void x86_return(); void alu_unary_reg(OpndSize size, ALU_Opcode opc, int reg, bool isPhysical); void alu_unary_mem(LowOp* op, OpndSize size, ALU_Opcode opc, int disp, int base_reg, bool isBasePhysical); void alu_binary_imm_mem(OpndSize size, ALU_Opcode opc, int imm, int disp, int base_reg, bool isBasePhysical); void alu_binary_imm_reg(OpndSize size, ALU_Opcode opc, int imm, int reg, bool isPhysical); void alu_binary_mem_reg(OpndSize size, ALU_Opcode opc, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void alu_binary_VR_reg(OpndSize size, ALU_Opcode opc, int vA, int reg, bool isPhysical); void alu_sd_binary_VR_reg(ALU_Opcode opc, int vA, int reg, bool isPhysical, bool isSD); void alu_binary_reg_reg(OpndSize size, ALU_Opcode opc, int reg1, bool isPhysical1, int reg2, bool isPhysical2); void alu_binary_reg_mem(OpndSize size, ALU_Opcode opc, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical); void fpu_mem(LowOp* op, ALU_Opcode opc, OpndSize size, int disp, int base_reg, bool isBasePhysical); void alu_ss_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical, int reg2, bool isPhysical2); void alu_sd_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical, int reg2, bool isPhysical2); void push_mem_to_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical); void push_reg_to_stack(OpndSize size, int reg, bool isPhysical); //returns the pointer to end of the native code void move_reg_to_mem(OpndSize size, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical); LowOpRegMem* move_mem_to_reg(OpndSize size, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void movez_mem_to_reg(OpndSize size, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void movez_reg_to_reg(OpndSize size, int reg, bool isPhysical, int reg2, bool isPhysical2); void moves_mem_to_reg(LowOp* op, OpndSize size, int disp, int base_reg, bool isBasePhysical, int reg, bool isPhysical); void movez_mem_disp_scale_to_reg(OpndSize size, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical); void moves_mem_disp_scale_to_reg(OpndSize size, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical); void move_reg_to_reg(OpndSize size, int reg, bool isPhysical, int reg2, bool isPhysical2); void move_reg_to_reg_noalloc(OpndSize size, int reg, bool isPhysical, int reg2, bool isPhysical2); void move_mem_scale_to_reg(OpndSize size, int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical); void move_mem_disp_scale_to_reg(OpndSize size, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical); void move_reg_to_mem_scale(OpndSize size, int reg, bool isPhysical, int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale); void move_reg_to_mem_disp_scale(OpndSize size, int reg, bool isPhysical, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale); void move_imm_to_mem(OpndSize size, int imm, int disp, int base_reg, bool isBasePhysical); void set_VR_to_imm(u2 vA, OpndSize size, int imm); void set_VR_to_imm_noalloc(u2 vA, OpndSize size, int imm); void set_VR_to_imm_noupdateref(LowOp* op, u2 vA, OpndSize size, int imm); void move_imm_to_reg(OpndSize size, int imm, int reg, bool isPhysical); void move_imm_to_reg_noalloc(OpndSize size, int imm, int reg, bool isPhysical); //LR[reg] = VR[vB] //or //PR[reg] = VR[vB] void get_virtual_reg(u2 vB, OpndSize size, int reg, bool isPhysical); void get_virtual_reg_noalloc(u2 vB, OpndSize size, int reg, bool isPhysical); //VR[v] = LR[reg] //or //VR[v] = PR[reg] void set_virtual_reg(u2 vA, OpndSize size, int reg, bool isPhysical); void set_virtual_reg_noalloc(u2 vA, OpndSize size, int reg, bool isPhysical); void get_VR_ss(int vB, int reg, bool isPhysical); void set_VR_ss(int vA, int reg, bool isPhysical); void get_VR_sd(int vB, int reg, bool isPhysical); void set_VR_sd(int vA, int reg, bool isPhysical); int spill_reg(int reg, bool isPhysical); int unspill_reg(int reg, bool isPhysical); void move_reg_to_mem_noalloc(OpndSize size, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex); LowOpRegMem* move_mem_to_reg_noalloc(OpndSize size, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, int reg, bool isPhysical); ////////////////////////////////////////////////////////////// int insertLabel(const char* label, bool checkDup); int export_pc(); int simpleNullCheck(int reg, bool isPhysical, int vr); int nullCheck(int reg, bool isPhysical, int exceptionNum, int vr); int handlePotentialException( ConditionCode code_excep, ConditionCode code_okay, int exceptionNum, const char* errName); int get_currentpc(int reg, bool isPhysical); int get_self_pointer(int reg, bool isPhysical); int get_res_strings(int reg, bool isPhysical); int get_res_classes(int reg, bool isPhysical); int get_res_fields(int reg, bool isPhysical); int get_res_methods(int reg, bool isPhysical); int get_glue_method_class(int reg, bool isPhysical); int get_glue_method(int reg, bool isPhysical); int set_glue_method(int reg, bool isPhysical); int get_glue_dvmdex(int reg, bool isPhysical); int set_glue_dvmdex(int reg, bool isPhysical); int get_suspendCount(int reg, bool isPhysical); int get_return_value(OpndSize size, int reg, bool isPhysical); int set_return_value(OpndSize size, int reg, bool isPhysical); int clear_exception(); int get_exception(int reg, bool isPhysical); int set_exception(int reg, bool isPhysical); int save_pc_fp_to_glue(); int savearea_from_fp(int reg, bool isPhysical); int call_moddi3(); int call_divdi3(); int call_fmod(); int call_fmodf(); int call_dvmFindCatchBlock(); int call_dvmThrowVerificationError(); int call_dvmAllocObject(); int call_dvmAllocArrayByClass(); int call_dvmResolveMethod(); int call_dvmResolveClass(); int call_dvmInstanceofNonTrivial(); int call_dvmThrow(); int call_dvmThrowWithMessage(); int call_dvmCheckSuspendPending(); int call_dvmLockObject(); int call_dvmUnlockObject(); int call_dvmInitClass(); int call_dvmAllocPrimitiveArray(); int call_dvmInterpHandleFillArrayData(); int call_dvmNcgHandlePackedSwitch(); int call_dvmNcgHandleSparseSwitch(); int call_dvmJitHandlePackedSwitch(); int call_dvmJitHandleSparseSwitch(); int call_dvmJitToInterpTraceSelectNoChain(); int call_dvmJitToPatchPredictedChain(); int call_dvmJitToInterpNormal(); int call_dvmJitToInterpTraceSelect(); int call_dvmQuasiAtomicSwap64(); int call_dvmQuasiAtomicRead64(); int call_dvmCanPutArrayElement(); int call_dvmFindInterfaceMethodInCache(); int call_dvmHandleStackOverflow(); int call_dvmResolveString(); int call_dvmResolveInstField(); int call_dvmResolveStaticField(); //labels and branches //shared branch to resolve class: 2 specialized versions //OPTION 1: call & ret //OPTION 2: store jump back label in a fixed register or memory //jump to .class_resolve, then jump back //OPTION 3: share translator code /* global variables: ncg_rPC */ int resolve_class( int startLR/*logical register index*/, bool isPhysical, int tmp/*const pool index*/, int thirdArg); /* EXPORT_PC; movl exceptionPtr, -8(%esp); movl descriptor, -4(%esp); lea; call; lea; jmp */ int throw_exception_message(int exceptionPtr, int obj_reg, bool isPhysical, int startLR/*logical register index*/, bool startPhysical); /* EXPORT_PC; movl exceptionPtr, -8(%esp); movl imm, -4(%esp); lea; call; lea; jmp */ int throw_exception(int exceptionPtr, int imm, int startLR/*logical register index*/, bool startPhysical); void freeShortMap(); int insertDataWorklist(s4 relativePC, char* codePtr1); #ifdef ENABLE_TRACING int insertMapWorklist(s4 BCOffset, s4 NCGOffset, int isStartOfPC); #endif int performNCGWorklist(); int performDataWorklist(); void performLabelWorklist(); void performMethodLabelWorklist(); void freeLabelMap(); void performSharedWorklist(); void performChainingWorklist(); void freeNCGWorklist(); void freeDataWorklist(); void freeLabelWorklist(); void freeChainingWorklist(); int common_invokeArgsDone(ArgsDoneType form, bool isJitFull); int common_backwardBranch(); int common_exceptionThrown(); int common_errNullObject(); int common_errArrayIndex(); int common_errArrayStore(); int common_errNegArraySize(); int common_errNoSuchMethod(); int common_errDivideByZero(); int common_periodicChecks_entry(); int common_periodicChecks4(); int common_gotoBail(); int common_gotoBail_0(); int common_StringIndexOutOfBounds(); void goto_invokeArgsDone(); //lower a bytecode int lowerByteCode(const Method* method); int op_nop(); int op_move(); int op_move_from16(); int op_move_16(); int op_move_wide(); int op_move_wide_from16(); int op_move_wide_16(); int op_move_result(); int op_move_result_wide(); int op_move_exception(); int op_return_void(); int op_return(); int op_return_wide(); int op_const_4(); int op_const_16(); int op_const(); int op_const_high16(); int op_const_wide_16(); int op_const_wide_32(); int op_const_wide(); int op_const_wide_high16(); int op_const_string(); int op_const_string_jumbo(); int op_const_class(); int op_monitor_enter(); int op_monitor_exit(); int op_check_cast(); int op_instance_of(); int op_array_length(); int op_new_instance(); int op_new_array(); int op_filled_new_array(); int op_filled_new_array_range(); int op_fill_array_data(); int op_throw(); int op_throw_verification_error(); int op_goto(); int op_goto_16(); int op_goto_32(); int op_packed_switch(); int op_sparse_switch(); int op_if_ge(); int op_aget(); int op_aget_wide(); int op_aget_object(); int op_aget_boolean(); int op_aget_byte(); int op_aget_char(); int op_aget_short(); int op_aput(); int op_aput_wide(); int op_aput_object(); int op_aput_boolean(); int op_aput_byte(); int op_aput_char(); int op_aput_short(); int op_iget(); int op_iget_wide(bool isVolatile); int op_iget_object(); int op_iget_boolean(); int op_iget_byte(); int op_iget_char(); int op_iget_short(); int op_iput(); int op_iput_wide(bool isVolatile); int op_iput_object(); int op_iput_boolean(); int op_iput_byte(); int op_iput_char(); int op_iput_short(); int op_sget(); int op_sget_wide(bool isVolatile); int op_sget_object(); int op_sget_boolean(); int op_sget_byte(); int op_sget_char(); int op_sget_short(); int op_sput(bool isObj); int op_sput_wide(bool isVolatile); int op_sput_object(); int op_sput_boolean(); int op_sput_byte(); int op_sput_char(); int op_sput_short(); int op_invoke_virtual(); int op_invoke_super(); int op_invoke_direct(); int op_invoke_static(); int op_invoke_interface(); int op_invoke_virtual_range(); int op_invoke_super_range(); int op_invoke_direct_range(); int op_invoke_static_range(); int op_invoke_interface_range(); int op_int_to_long(); int op_add_long_2addr(); int op_add_int_lit8(); int op_cmpl_float(); int op_cmpg_float(); int op_cmpl_double(); int op_cmpg_double(); int op_cmp_long(); int op_if_eq(); int op_if_ne(); int op_if_lt(); int op_if_gt(); int op_if_le(); int op_if_eqz(); int op_if_nez(); int op_if_ltz(); int op_if_gez(); int op_if_gtz(); int op_if_lez(); int op_neg_int(); int op_not_int(); int op_neg_long(); int op_not_long(); int op_neg_float(); int op_neg_double(); int op_int_to_float(); int op_int_to_double(); int op_long_to_int(); int op_long_to_float(); int op_long_to_double(); int op_float_to_int(); int op_float_to_long(); int op_float_to_double(); int op_double_to_int(); int op_double_to_long(); int op_double_to_float(); int op_int_to_byte(); int op_int_to_char(); int op_int_to_short(); int op_add_int(); int op_sub_int(); int op_mul_int(); int op_div_int(); int op_rem_int(); int op_and_int(); int op_or_int(); int op_xor_int(); int op_shl_int(); int op_shr_int(); int op_ushr_int(); int op_add_long(); int op_sub_long(); int op_mul_long(); int op_div_long(); int op_rem_long(); int op_and_long(); int op_or_long(); int op_xor_long(); int op_shl_long(); int op_shr_long(); int op_ushr_long(); int op_add_float(); int op_sub_float(); int op_mul_float(); int op_div_float(); int op_rem_float(); int op_add_double(); int op_sub_double(); int op_mul_double(); int op_div_double(); int op_rem_double(); int op_add_int_2addr(); int op_sub_int_2addr(); int op_mul_int_2addr(); int op_div_int_2addr(); int op_rem_int_2addr(); int op_and_int_2addr(); int op_or_int_2addr(); int op_xor_int_2addr(); int op_shl_int_2addr(); int op_shr_int_2addr(); int op_ushr_int_2addr(); int op_sub_long_2addr(); int op_mul_long_2addr(); int op_div_long_2addr(); int op_rem_long_2addr(); int op_and_long_2addr(); int op_or_long_2addr(); int op_xor_long_2addr(); int op_shl_long_2addr(); int op_shr_long_2addr(); int op_ushr_long_2addr(); int op_add_float_2addr(); int op_sub_float_2addr(); int op_mul_float_2addr(); int op_div_float_2addr(); int op_rem_float_2addr(); int op_add_double_2addr(); int op_sub_double_2addr(); int op_mul_double_2addr(); int op_div_double_2addr(); int op_rem_double_2addr(); int op_add_int_lit16(); int op_rsub_int(); int op_mul_int_lit16(); int op_div_int_lit16(); int op_rem_int_lit16(); int op_and_int_lit16(); int op_or_int_lit16(); int op_xor_int_lit16(); int op_rsub_int_lit8(); int op_mul_int_lit8(); int op_div_int_lit8(); int op_rem_int_lit8(); int op_and_int_lit8(); int op_or_int_lit8(); int op_xor_int_lit8(); int op_shl_int_lit8(); int op_shr_int_lit8(); int op_ushr_int_lit8(); int op_execute_inline(bool isRange); int op_invoke_object_init_range(); int op_iget_quick(); int op_iget_wide_quick(); int op_iget_object_quick(); int op_iput_quick(); int op_iput_wide_quick(); int op_iput_object_quick(); int op_invoke_virtual_quick(); int op_invoke_virtual_quick_range(); int op_invoke_super_quick(); int op_invoke_super_quick_range(); /////////////////////////////////////////////// void set_reg_opnd(LowOpndReg* op_reg, int reg, bool isPhysical, LowOpndRegType type); void set_mem_opnd(LowOpndMem* mem, int disp, int base, bool isPhysical); void set_mem_opnd_scale(LowOpndMem* mem, int base, bool isPhysical, int disp, int index, bool indexPhysical, int scale); LowOpImm* dump_imm(Mnemonic m, OpndSize size, int imm); LowOpNCG* dump_ncg(Mnemonic m, OpndSize size, int imm); LowOpImm* dump_imm_with_codeaddr(Mnemonic m, OpndSize size, int imm, char* codePtr); LowOpImm* dump_special(AtomOpCode cc, int imm); LowOpMem* dump_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int disp, int base_reg, bool isBasePhysical); LowOpReg* dump_reg(Mnemonic m, AtomOpCode m2, OpndSize size, int reg, bool isPhysical, LowOpndRegType type); LowOpReg* dump_reg_noalloc(Mnemonic m, OpndSize size, int reg, bool isPhysical, LowOpndRegType type); LowOpMemImm* dump_imm_mem_noalloc(Mnemonic m, OpndSize size, int imm, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex); LowOpRegReg* dump_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size, int reg, bool isPhysical, int reg2, bool isPhysical2, LowOpndRegType type); LowOpRegReg* dump_movez_reg_reg(Mnemonic m, OpndSize size, int reg, bool isPhysical, int reg2, bool isPhysical2); LowOpRegMem* dump_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, int reg, bool isPhysical, LowOpndRegType type); LowOpRegMem* dump_mem_reg_noalloc(Mnemonic m, OpndSize size, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, int reg, bool isPhysical, LowOpndRegType type); LowOpRegMem* dump_mem_scale_reg(Mnemonic m, OpndSize size, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, int reg, bool isPhysical, LowOpndRegType type); LowOpMemReg* dump_reg_mem_scale(Mnemonic m, OpndSize size, int reg, bool isPhysical, int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, LowOpndRegType type); LowOpMemReg* dump_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, LowOpndRegType type); LowOpMemReg* dump_reg_mem_noalloc(Mnemonic m, OpndSize size, int reg, bool isPhysical, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, LowOpndRegType type); LowOpRegImm* dump_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size, int imm, int reg, bool isPhysical, LowOpndRegType type, bool chaining); LowOpMemImm* dump_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int imm, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, bool chaining); LowOpMemReg* dump_fp_mem(Mnemonic m, OpndSize size, int reg, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex); LowOpRegMem* dump_mem_fp(Mnemonic m, OpndSize size, int disp, int base_reg, bool isBasePhysical, MemoryAccessType mType, int mIndex, int reg); LowOpLabel* dump_label(Mnemonic m, OpndSize size, int imm, const char* label, bool isLocal); unsigned getJmpCallInstSize(OpndSize size, JmpCall_type type); bool lowerByteCodeJit(const Method* method, const u2* codePtr, MIR* mir); void startOfBasicBlock(struct BasicBlock* bb); extern LowOpBlockLabel* traceLabelList; extern struct BasicBlock* traceCurrentBB; extern struct MIR* traceCurrentMIR; void startOfTrace(const Method* method, LowOpBlockLabel* labelList, int, CompilationUnit*); void endOfTrace(bool freeOnly); LowOp* jumpToBasicBlock(char* instAddr, int targetId); LowOp* condJumpToBasicBlock(char* instAddr, ConditionCode cc, int targetId); bool jumpToException(const char* target); int codeGenBasicBlockJit(const Method* method, BasicBlock* bb); void endOfBasicBlock(struct BasicBlock* bb); void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir); int insertChainingWorklist(int bbId, char * codeStart); void startOfTraceO1(const Method* method, LowOpBlockLabel* labelList, int exceptionBlockId, CompilationUnit *cUnit); void endOfTraceO1(); int isPowerOfTwo(int imm); void move_chain_to_mem(OpndSize size, int imm, int disp, int base_reg, bool isBasePhysical); void move_chain_to_reg(OpndSize size, int imm, int reg, bool isPhysical); void dumpImmToMem(int vrNum, OpndSize size, int value); bool isInMemory(int regNum, OpndSize size); int touchEbx(); int boundCheck(int vr_array, int reg_array, bool isPhysical_array, int vr_index, int reg_index, bool isPhysical_index, int exceptionNum); int getRelativeOffset(const char* target, bool isShortTerm, JmpCall_type type, bool* unknown, OpndSize* immSize); int getRelativeNCG(s4 tmp, JmpCall_type type, bool* unknown, OpndSize* size); void freeAtomMem(); OpndSize estOpndSizeFromImm(int target); void preprocessingBB(BasicBlock* bb); void preprocessingTrace(); void dump_nop(int size); #endif