Index: em/src/em_intf.cpp =================================================================== --- em/src/em_intf.cpp (版本 735635) +++ em/src/em_intf.cpp (工作副本) @@ -26,6 +26,8 @@ #include "DrlEMImpl.h" #include "port_malloc.h" +#include "CallGraphProfileCollector.h" + #include #ifdef __cplusplus @@ -183,6 +185,8 @@ vm_intf->ProfilerThreadTimeout = ProfilerThreadTimeout; vm_intf->ClassloaderUnloadingCallback = ClassloaderUnloadingCallback; + vm_intf->callgph_profiler_indirect_call_helper = callgph_profiler_indirect_call_helper; //CallGph indirect call helper interface + *p_component = (OpenComponentHandle) c_intf; *p_allocator = (OpenInstanceAllocatorHandle) a_intf; em_vm_interface = (OpenEmVmHandle) vm_intf; Index: em/src/EBProfileCollector.h =================================================================== --- em/src/EBProfileCollector.h (版本 735635) +++ em/src/EBProfileCollector.h (工作副本) @@ -111,7 +111,7 @@ Method_Profile_Handle eb_profiler_create_profile(PC_Handle ph, Method_Handle mh); void* eb_profiler_get_entry_counter_addr(Method_Profile_Handle mph); -void*eb_profiler_get_backedge_counter_addr(Method_Profile_Handle mph); +void* eb_profiler_get_backedge_counter_addr(Method_Profile_Handle mph); void __stdcall eb_profiler_sync_mode_callback(PC_Handle mph); char eb_profiler_is_in_sync_mode(PC_Handle pch); U_32 eb_profiler_get_entry_threshold(PC_Handle pch); Index: em/src/DrlEMImpl.cpp =================================================================== --- em/src/DrlEMImpl.cpp (版本 735635) +++ em/src/DrlEMImpl.cpp (工作副本) @@ -25,6 +25,7 @@ #include "EBProfileCollector.h" #include "EdgeProfileCollector.h" #include "NValueProfileCollector.h" +#include "CallGraphProfileCollector.h" //..CallGph #include "open/vm_properties.h" #include "open/vm_ee.h" @@ -46,6 +47,7 @@ #define EDGE_PROFILER_STR "EDGE_PROFILER" #define VALUE_PROFILER_STR "VALUE_PROFILER" #define ENTRY_BACKEDGE_PROFILER_STR "EB_PROFILER" +#define CALLGPH_PROFILER_STR "CALLGPH_PROFILER" //used when creating CALLGPH ProfileCollector #define EM_CONFIG_EXT std::string(".emconf") @@ -144,7 +146,20 @@ profileAccessInterface.edge_profiler_get_entry_threshold = edge_profiler_get_entry_threshold; profileAccessInterface.edge_profiler_get_backedge_threshold = edge_profiler_get_backedge_threshold; - + //CALLGPH profile + profileAccessInterface.callgph_profiler_create_profile = callgph_profiler_create_profile; + profileAccessInterface.callgph_profiler_get_num_counters = callgph_profiler_get_num_counters; + profileAccessInterface.callgph_profiler_get_checksum = callgph_profiler_get_checksum; + profileAccessInterface.callgph_profiler_get_counter_addr = callgph_profiler_get_counter_addr; + profileAccessInterface.callgph_profiler_get_counter_obj_addr = callgph_profiler_get_counter_obj_addr; + profileAccessInterface.callgph_profiler_get_entry_counter_addr = callgph_profiler_get_entry_counter_addr; + profileAccessInterface.callgph_profiler_get_entry_threshold = callgph_profiler_get_entry_threshold; + profileAccessInterface.callgph_profiler_get_backedge_threshold = callgph_profiler_get_backedge_threshold; + profileAccessInterface.callgph_profiler_set_callerBB_id = callgph_profiler_set_callerBB_id; + profileAccessInterface.callgph_profiler_add_dirctcallee_addr = callgph_profiler_add_dirctcallee_addr; + profileAccessInterface.callgph_profiler_set_md_strtAddr = callgph_profiler_set_md_strtAddr; + profileAccessInterface.callgph_profiler_set_jit_name = callgph_profiler_set_jit_name; + //Value profile profileAccessInterface.value_profiler_create_profile = value_profiler_create_profile; profileAccessInterface.value_profiler_add_value = value_profiler_add_value; @@ -154,8 +169,24 @@ return; } +////Used to dump CallGph profile statistics +void DrlEMImpl::dumpProfiles() { + fstream* fp = new fstream("callGphDump.txt", ios::out); + CallGphProfileCollector* cpc=NULL; + ProfileCollector* pc=NULL; + for (ProfileCollectors::iterator it = collectors.begin(), end = collectors.end(); it!=end; ++it) { + ProfileCollector* pc = *it; + if(pc != NULL){ + if(pc->type == EM_PCTYPE_CALLGPH) + { + cpc = (CallGphProfileCollector*)pc; + cpc->dumpProfilers(fp); + return; + } + } + } +} - void DrlEMImpl::deallocateResources() { tbsClients.clear(); @@ -513,6 +544,7 @@ } void DrlEMImpl::deinit() { + dumpProfiles(); //Dump CallGph statistics } //______________________________________________________________________________ @@ -593,7 +625,7 @@ return NULL; } std::string profilerType = getParam(config, profilerName+".profilerType"); - if (profilerType!=ENTRY_BACKEDGE_PROFILER_STR && profilerType!=EDGE_PROFILER_STR && profilerType!=VALUE_PROFILER_STR) { + if (profilerType!=ENTRY_BACKEDGE_PROFILER_STR && profilerType!=EDGE_PROFILER_STR && profilerType!=VALUE_PROFILER_STR && profilerType!=CALLGPH_PROFILER_STR) {//CallGph profiler is also checked LECHO(7, "EM: Unsupported profiler type"); return NULL; } @@ -638,7 +670,16 @@ } else { pc = new EBProfileCollector(this, profilerName, step->jit, ebMode, eThreshold, bThreshold, tbsInitialTimeout, tbsTimeout); } - } else if (profilerType == VALUE_PROFILER_STR) { + }else if(profilerType == CALLGPH_PROFILER_STR){ //if CallGph profiler is also chosen in .emconf file + int tbsInitialTimeout = 0; + int tbsTimeout = 100; + int eThreshold = 10000; + int bThreshold = 300000; + + pc = new CallGphProfileCollector(this, profilerName, step->jit, tbsInitialTimeout, tbsTimeout, eThreshold, bThreshold); + + } + else if (profilerType == VALUE_PROFILER_STR) { typedef ValueProfileCollector VPC; int vpSteadySize = 4, vpClearSize = 0, vpClearInterval = 0; std::string vpalgo = getParam(config, profilerName+".vpalgo"); Index: em/src/DrlEMImpl.h =================================================================== --- em/src/DrlEMImpl.h (版本 735635) +++ em/src/DrlEMImpl.h (工作副本) @@ -110,6 +110,8 @@ virtual void tbsTimeout(); virtual int getTbsTimeout() const; + void dumpProfiles(); //used to dump CallGph statistics + //EM PC access interface ProfileCollector* getProfileCollector(EM_PCTYPE type, JIT_Handle jh, EM_JIT_PC_Role jitRole) const; Index: include/open/em_vm.h =================================================================== --- include/open/em_vm.h (版本 735635) +++ include/open/em_vm.h (工作副本) @@ -131,6 +131,8 @@ void (*ClassloaderUnloadingCallback) (Class_Loader_Handle class_handle); + bool (*callgph_profiler_indirect_call_helper)(U_8* dest_addr, void* counter_addr, U_32 callerBB_Id); //....CallGph...CallGphHelper + }; typedef const struct _OpenEmVm* OpenEmVmHandle; Index: include/open/types.h =================================================================== --- include/open/types.h (版本 735635) +++ include/open/types.h (工作副本) @@ -73,6 +73,7 @@ typedef struct VTable *VTable_Handle; typedef struct Field *Field_Handle; typedef struct Method *Method_Handle; +typedef struct Method *CallerMthd_Handle; typedef struct Method_Signature *Method_Signature_Handle; typedef struct TypeDesc *Type_Info_Handle; typedef UDATA Allocation_Handle; Index: include/open/rt_helpers.h =================================================================== --- include/open/rt_helpers.h (版本 735635) +++ include/open/rt_helpers.h (工作副本) @@ -559,6 +559,9 @@ * Write barrier for GC. */ + + VM_RT_CALLGPH_INDIRECT_CALL_HELPER, //....CallGph + } VM_RT_SUPPORT; /** Index: include/open/hythread_ext.h =================================================================== --- include/open/hythread_ext.h (版本 735635) +++ include/open/hythread_ext.h (工作副本) @@ -362,6 +362,8 @@ */ IDATA thread_id; + unsigned int my_thread_id; + } HyThread; /** Index: include/open/em_profile_access.h =================================================================== --- include/open/em_profile_access.h (版本 735635) +++ include/open/em_profile_access.h (工作副本) @@ -21,11 +21,15 @@ #include "open/types.h" #include "open/em.h" #include +#include #ifdef __cplusplus extern "C" { #endif +using namespace std; + + /** * Known profiler types. Each of the profilers * is represented with separate interface to @@ -50,7 +54,13 @@ * Value profiler. * Collects profile for each given instruction. */ - EM_PCTYPE_VALUE=3 + EM_PCTYPE_VALUE=3, + +/** + * CallGph profiler. + * Collects profile for each given call site. + */ + EM_PCTYPE_CALLGPH=4 }; @@ -222,8 +232,75 @@ U_32 (*edge_profiler_get_backedge_threshold)(PC_Handle pch); // Value profiler interface + + + //Call Graph profiler interface /** + * Create an call graph profile for a method. + * Only one profile per method can be created for a single + * profile collector instance. + * + * @param ph - edge profile collector handle + * @param mh - method handle to create profile for + * @param numEdgeCounters - number of edge counters in a method + * @param counterKeys - the keys, or numbers, will be associated with + * each counter. The key must be used to access to + * counter value + * @param checksum - profile checksum + * + * @return A handle to access method profile data. + */ + + Method_Profile_Handle (*callgph_profiler_create_profile) (PC_Handle ph, Method_Handle mh, U_32 numCallGphCounters, U_32 numIndCalls, vector* counterKeysVector, U_32 checkSum); + + + /** + * Return number of edge counters in profile. + */ + U_32 (*callgph_profiler_get_num_counters)(Method_Profile_Handle mph); + + /** + * Return profile checksum. + */ + U_32 (*callgph_profiler_get_checksum)(Method_Profile_Handle mph); + + /** + * Return the address of counter associated with key. + */ + void* (*callgph_profiler_get_counter_addr)(Method_Profile_Handle mph, U_32 key); + + + /** + * Return the address of counter object[instance of Counter class] associated with key. + */ + void* (*callgph_profiler_get_counter_obj_addr)(Method_Profile_Handle mph, U_32 key); + + /** + * Return the address of entry counter. + */ + void* (*callgph_profiler_get_entry_counter_addr)(Method_Profile_Handle mph); + + /** + * Return the entry threshold for profile collector. + */ + U_32 (*callgph_profiler_get_entry_threshold)(PC_Handle pch); + + /** + * Return the edge threshold for profile collector. + */ + + U_32 (*callgph_profiler_get_backedge_threshold)(PC_Handle pch); + + bool (*callgph_profiler_set_callerBB_id)(PC_Handle,int id, U_32 key); + bool (*callgph_profiler_add_dirctcallee_addr)(PC_Handle, U_8* addr, U_32 key); + + bool (*callgph_profiler_set_md_strtAddr)(PC_Handle, U_8* addr, U_32 key); + bool (*callgph_profiler_set_jit_name)(PC_Handle mph, std::string jitName); + + // Value profiler interface + + /** * Create an value profile for a method. * Only one profile per method can be created for a single * profile collector instance. @@ -251,6 +328,7 @@ } EM_ProfileAccessInterface; +void* callgph_getPtrFun(); #ifdef __cplusplus } Index: thread/src/thread_native_basic.c =================================================================== --- thread/src/thread_native_basic.c (版本 735635) +++ thread/src/thread_native_basic.c (工作副本) @@ -70,6 +70,7 @@ * @param[in] func a function to run in the new thread * @param[in] data an argument to be passed to starting function */ +unsigned int g_thread_id = 0; //CallGph.... IDATA VMCALL hythread_create_ex(hythread_t new_thread, hythread_group_t group, UDATA stacksize, @@ -117,8 +118,11 @@ stacksize ? stacksize : TM_DEFAULT_STACKSIZE, priority, wrapper, data); assert(/* error */ result || new_thread->os_handle /* or thread created ok */); + g_thread_id++; + new_thread->my_thread_id = g_thread_id; + hythread_global_unlock(); - + return result; } @@ -150,7 +154,10 @@ if (handle) { *handle = thread; } + return hythread_create_ex(thread, NULL, stacksize, priority, NULL, func, data); + + } /** @@ -202,6 +209,11 @@ hythread_remove_from_group(self); self->thread_id = new_thread->thread_id; } + hythread_global_lock(); + g_thread_id++; + new_thread->my_thread_id = g_thread_id; + hythread_global_unlock(); + return status; } Index: vmcore/src/jni/jni.cpp =================================================================== --- vmcore/src/jni/jni.cpp (版本 735635) +++ vmcore/src/jni/jni.cpp (工作副本) @@ -59,6 +59,7 @@ #include "component_manager.h" #ifdef _IPF_ + #include "stub_code_utils.h" #endif // _IPF_ @@ -492,6 +493,7 @@ start_monitor_malloc(); #endif + //.... initFpDmpLp(); //....LoopDump..... // TODO implement support for JDK1_1InitArgs if (((JavaVMInitArgs *)args)->version == JNI_VERSION_1_1) { return JNI_EVERSION; Index: vmcore/src/jit/rt_helper_info.cpp =================================================================== --- vmcore/src/jit/rt_helper_info.cpp (版本 735635) +++ vmcore/src/jit/rt_helper_info.cpp (工作副本) @@ -174,6 +174,10 @@ {VM_RT_INITIALIZE_CLASS_WITHRESOLVE, "VM_RT_INITIALIZE_CLASS_WITHRESOLVE", INTERRUPTIBLE_ALWAYS, CALLING_CONVENTION_STDCALL, 2, NULL, NULL, NULL, NULL}, + {VM_RT_CALLGPH_INDIRECT_CALL_HELPER, "VM_RT_CALLGPH_INDIRECT_CALL_HELPER", //...CallGph....indirect call helper + INTERRUPTIBLE_ALWAYS, CALLING_CONVENTION_STDCALL, 3, + NULL, NULL, NULL, NULL}, + }; static JIT_RT_Function_Entry *jit_rt_function_entries = &(_jit_rt_function_entries_base[0]); Index: vmcore/src/jit/compile.cpp =================================================================== --- vmcore/src/jit/compile.cpp (版本 735635) +++ vmcore/src/jit/compile.cpp (工作副本) @@ -46,6 +46,11 @@ #include "dump.h" #include "port_threadunsafe.h" +#include //..CallGph... +#include +#include +using namespace std; + extern bool parallel_jit; #define METHOD_NAME_BUF_SIZE 512 @@ -738,6 +743,8 @@ static JIT_Result compile_do_compilation(Method* method) { + static fstream* fp=NULL; + ASSERT_RAISE_AREA; assert(hythread_is_suspend_enabled()); tmn_suspend_disable(); @@ -760,6 +767,17 @@ } if (method->is_native()) { + //Output method information if it is a native method for CallGph + if(fp==NULL) + { + fp = new fstream("callGphNativeMethods.txt", ios::out); + } + + const char * c = method->get_class()->get_name()->bytes; + const char * m = method_get_name(method); + const char * d = method->get_descriptor()->bytes; + *fp<< "native_methd:"<TI; JIT_Result res = compile_do_compilation(method); @@ -812,8 +831,9 @@ tmn_suspend_disable(); return NULL; } - tmn_suspend_disable(); + tmn_suspend_disable(); + NativeCodePtr entry_point = method->get_code_addr(); INFO2("compile.code", "Compiled method " << method << ", entry " << entry_point); Index: vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp =================================================================== --- vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (版本 735635) +++ vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (工作副本) @@ -22,6 +22,7 @@ #include "cxxlog.h" #include "open/types.h" +#include "open/em_profile_access.h" //CallGph #include "open/gc.h" #include "open/vm_class_manipulation.h" #include "vtable.h" @@ -1012,7 +1013,48 @@ return addr; } //getaddress__vm_throw_linking_exception_naked +//generate the stub which invokes indirect call counting helper for CallGph +void * getaddress__vm_helper_callgraph_indirect_call() +{ + static void *addr = 0; + if (addr) { + return addr; + } + const int stub_size = 100; + char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_COLD, CAA_Allocate); +#ifdef _DEBUG + memset(stub, 0xcc /*int 3*/, stub_size); +#endif + char *ss = stub; + + ss = push(ss, M_Base_Opnd(esp_reg, 0xc)); + ss = push(ss, M_Base_Opnd(esp_reg, 0xc)); + ss = push(ss, M_Base_Opnd(esp_reg, 0xc)); + + + //jint status; + Global_Env* vm_env = VM_Global_State::loader_env; + + ss = call(ss, (char*)vm_env->em_interface->callgph_profiler_indirect_call_helper); + ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(0xc)); + ss = ret(ss, Imm_Opnd(0xc)); + + addr = stub; + assert((ss - stub) <= stub_size); + + compile_add_dynamic_generated_code_chunk("getaddress__vm_helper_callgraph_indirect_call", false, stub, stub_size); + + DUMP_STUB(stub, "getaddress__vm_helper_callgraph_indirect_call", ss - stub); + + return addr; + +} + + + + + #ifdef VM_STATS static void register_request_for_rt_function(VM_RT_SUPPORT f) { @@ -1033,6 +1075,7 @@ void * getaddress__vm_monitor_exit_static_naked(); void *vm_helper_get_addr(VM_RT_SUPPORT f) { + #ifdef VM_STATS register_request_for_rt_function(f); #endif // VM_STATS @@ -1081,9 +1124,12 @@ case VM_RT_THROW_LINKING_EXCEPTION: return getaddress__vm_throw_linking_exception_naked(); + case VM_RT_CALLGPH_INDIRECT_CALL_HELPER: //generate the stub which invokes indirect call counting helper for CallGph + return getaddress__vm_helper_callgraph_indirect_call(); + case VM_RT_GC_HEAP_WRITE_REF: return (void*)gc_heap_slot_write_ref; - + case VM_RT_GET_IDENTITY_HASHCODE: return getaddress__vm_gethashcode_java_object_resolved_using_gethashcode_naked(); Index: vmcore/src/util/ia32/base/compile_IA32.cpp =================================================================== --- vmcore/src/util/ia32/base/compile_IA32.cpp (版本 735635) +++ vmcore/src/util/ia32/base/compile_IA32.cpp (工作副本) @@ -55,6 +55,13 @@ #include "vm_stats.h" #include "dump.h" +#include //CallGph + +using namespace std; + +fstream* fpCallGphStubComplMe = NULL; +Lock_Manager* mylock; ///CallGph ...compileme stub + void compile_flush_generated_code_block(U_8*, size_t) { // Nothing to do on IA32 } @@ -228,6 +235,8 @@ const char * c = method->get_class()->get_name()->bytes; const char * m = method->get_name()->bytes; const char * d = method->get_descriptor()->bytes; + const char * s = method->get_signature()->bytes; + size_t sz = strlen(c) + strlen(m) + strlen(d) + 12; name = (char*)STD_MALLOC(sz); sprintf(name, "compileme.%s.%s%s", c, m, d); @@ -236,6 +245,15 @@ if (jvmti_should_report_event(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) { jvmti_send_dynamic_code_generated_event(name, addr, STUB_SIZE); } + //Output stub method information for CallGph + if(fpCallGphStubComplMe==NULL) + { + fpCallGphStubComplMe = new fstream("CallGph_StubInfo.txt", ios::out); + mylock = new Lock_Manager(); + } + mylock->_lock(); + (*fpCallGphStubComplMe)<<"Method:"<_unlock(); #ifndef NDEBUG static unsigned done = 0; Index: jitrino/src/codegenerator/ia32/Ia32Inst.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32Inst.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32Inst.h (工作副本) @@ -44,6 +44,30 @@ class I8Lowerer; class ConstantAreaItem; +/** instruction and callsite property of LIR for CallGph */ + +enum Instrm_Type{ //used for HIR2LIR + Unknown_Instrm_Type, + Edge_Instrm_Type, + CallGph_Instrm_Type +}; + +enum CallSite_Type{ //HIR2LIR + UnKnown, + DirectCall_Type, + InDirectCall_Type, + InDirectMemCall_Type, + VirtualCall_Type, + + CallGphInDirctCallHelper_Type, +}; + +struct CallGphRuntimeInfo{//used for vm helper..indirectcall + bool isBBidTagPushInst; + U_32 parentBBid; +}; + + //========================================================================================================= // class Opnd //========================================================================================================= @@ -162,6 +186,7 @@ Kind_Method_Value_Profile_Handle, /** more ... */ + Kind_CallGph_BB_id, ////Represents that this opond represents the id of the basic block containing the indirect call counting helper instruction for CallGph }; /** Constructs a RuntimeInfo instance of RuntimeInfo::Type t and initialize it with given values */ @@ -176,6 +201,10 @@ /** Returns the kind of the info */ RuntimeInfo::Kind getKind()const { return kind; } + + /** Set the kind of the info used for CallGph, Can also be used for ohter purposes */ + bool setKind(RuntimeInfo::Kind inKind){ return kind = inKind;} + private: RuntimeInfo::Kind kind; void * value[4]; @@ -247,6 +276,13 @@ return memOpndAlignment; } + + /* + CallGph, set and get the push instruction which contains this opnd + */ + bool set_owner_inst(Inst* inst){return ownerInst = inst; } + Inst* get_owner_inst(){return ownerInst;} + /** * Sets desirable memory operand alignment. */ @@ -378,6 +414,8 @@ memOpndAlignment(MemOpndAlignment_Any), immValue(0), runtimeInfo(NULL) { constraints[ConstraintKind_Initial]=constraints[ConstraintKind_Calculated]=c; + ownerInst = NULL; //initilize the instruction supposed to contain the Opnd to NULL for CallGph + } //------------------------------------------------------------------------- @@ -388,6 +426,7 @@ DefScope defScope; Inst * definingInst; + Inst * ownerInst; //the basic block(id info) containing the indirect call helper instruction for CallGph U_32 refCount; RegName segReg; @@ -566,8 +605,24 @@ }; //--------------------------------------------------------------- -public: +public: + //* The following functions are used for building CallGph*/ + bool isCallGphInstrm() { return instrm_type == CallGph_Instrm_Type; }//for HIR2LIR + bool setCallGph_Instrm_Type() { return instrm_type = CallGph_Instrm_Type; } //for HIR2LIR + bool setKey(U_32 inKey) {return key = inKey;} + U_32 getKey() {return key;} + CallSite_Type getCallSiteType(){return callsite_type;} + bool setCallSiteType(CallSite_Type inType){return callsite_type = inType;} + bool set_IndCall_Counter_Addr(U_32* addr){return ptrCnt = addr;} + U_32* get_IndCall_Counter_Addr(){return ptrCnt;}//HIR2LIR + bool isIndirctMemCall(){return callsite_type==InDirectMemCall_Type;} + bool isDirctCallHelper(){return callsite_type == CallGphInDirctCallHelper_Type;} + bool setDirctCallHelper(){return callsite_type = CallGphInDirctCallHelper_Type;} + CallGphRuntimeInfo* getCallGphRuntimeInfo() {return &callgphRuntimeInfo;} + bool setPushBBidInstr(){return callgphRuntimeInfo.isBBidTagPushInst = true; } + bool isPushBBidInstr() const {return callgphRuntimeInfo.isBBidTagPushInst;} + /** Returns the next inst in a double-linked list. */ Inst* getNextInst() const {return (Inst*)next();} /** Returns the previous inst in a double-linked list. */ @@ -823,6 +878,14 @@ return (BasicBlock*)node; } + /** Set the basic block which this instrution belong to for CallGph. */ + bool setBasicBlock(Node* bb) + { + assert(bb->isBlockNode()); + return node = bb; + } + + /** * Returns the kind of edge according to the kind of the inst. * Called by CFG to detect BB->BB block edges. @@ -847,7 +910,13 @@ // WARN! commented opnds are assigned in overloaded 'new' operator before the constructor // : void* Inst::operator new(size_t sz, MemoryManager& mm, U_32 opndCount) - {} + { + /** the following statements are to initilize the members for building CallGph */ + callgphRuntimeInfo.isBBidTagPushInst = false; + callsite_type = UnKnown; + instrm_type = Unknown_Instrm_Type; + + } virtual ~Inst(){}; static U_32 getOpndChunkSize(U_32 opndCount){ return opndCount * (sizeof(Opnd*) + sizeof(U_32) * 2); } @@ -899,6 +968,13 @@ Opnd ** opnds; + /** the following members are used for building CallGph */ + Instrm_Type instrm_type; + CallSite_Type callsite_type; + U_32 key; + U_32* ptrCnt; + CallGphRuntimeInfo callgphRuntimeInfo; + //--------------------------------------------------------------- friend class IRManager; friend class Encoder; Index: jitrino/src/codegenerator/ia32/Ia32IRManager.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (工作副本) @@ -521,9 +521,28 @@ Opnd * target=newImmOpnd(typeManager.getInt32Type(), Opnd::RuntimeInfo::Kind_HelperAddress, (void*)helperId); const CallingConvention * cc=getCallingConvention(helperId); appendToInstList(instList,newCallInst(target, cc, numArgs, args, retOpnd)); + return (CallInst *)instList; } + +////create helper inst for CallGph when doing HIR2LIR____________________________________________________________________________________________ +CallInst * IRManager::newRuntimeHelperCallInstCallGph(VM_RT_SUPPORT helperId, + U_32 numArgs, Opnd ** args, Opnd * retOpnd) +{ + Inst * instList = NULL; + Opnd * target=newImmOpnd(typeManager.getInt32Type(), Opnd::RuntimeInfo::Kind_HelperAddress, (void*)helperId); + const CallingConvention * cc=getCallingConvention(helperId); + appendToInstList(instList,newCallInst(target, cc, numArgs, args, retOpnd)); + +/* //CALLGPH_DEBUG_INDCALL_HELPER + std::cout<<" ********** Create Helper HIR2LIR**test***** "<prependInst(newInst(Mnemonic_SUB, getRegOpnd(STACK_REG), newImmOpnd(typeManager.getInt32Type(), callInst->getArgStackDepthAlignment())), inst); } - + + //// used to memorize the current bb id where the first push instruction is in for CallGph + if(inst->isDirctCallHelper()) + { + for (U_32 i = 0, n = (U_32)stackOpndInfos.size(); i < n; i++) { + Opnd* opnd = opnds[stackOpndInfos[i].opndIndex]; + Inst * pushInst = newCopyPseudoInst(Mnemonic_PUSH, opnd); + pushInst->insertBefore(instToPrepend); + instToPrepend = pushInst; + if(i == n-1) + { + pushInst->setPushBBidInstr(); + bool test = pushInst->isPushBBidInstr(); + } + } + }//end for memorizing the current bb id where the first push instruction is in + else{ // Put inputs on the stack. - for (U_32 i = 0, n = (U_32)stackOpndInfos.size(); i < n; i++) { - Opnd* opnd = opnds[stackOpndInfos[i].opndIndex]; - Inst * pushInst = newCopyPseudoInst(Mnemonic_PUSH, opnd); - pushInst->insertBefore(instToPrepend); - instToPrepend = pushInst; - } + for (U_32 i = 0, n = (U_32)stackOpndInfos.size(); i < n; i++) { + Opnd* opnd = opnds[stackOpndInfos[i].opndIndex]; + Inst * pushInst = newCopyPseudoInst(Mnemonic_PUSH, opnd); + pushInst->insertBefore(instToPrepend); + instToPrepend = pushInst; + } + } #ifdef _WIN64 // Assert that shadow doesn't break stack alignment computed earlier. @@ -1777,6 +1813,7 @@ } } } + } //_____________________________________________________________________________________________ @@ -2147,6 +2184,7 @@ /** The value of the operand is Method_Profile_Handle for the value profile of the compiled method */ value=(POINTER_SIZE_INT)(getProfilingInterface()->getMethodProfileHandle(ProfileType_Value, getMethodDesc())); break; + default: assert(0); } Index: jitrino/src/codegenerator/ia32/Ia32CgUtils.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32CgUtils.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32CgUtils.h (工作副本) @@ -27,6 +27,7 @@ namespace Jitrino { namespace Ia32 { + class IRManagerHolder { public: IRManagerHolder() Index: jitrino/src/codegenerator/ia32/Ia32CodeSelector.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32CodeSelector.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32CodeSelector.h (工作副本) @@ -31,6 +31,7 @@ { class CompilationInterface; class EdgeMethodProfile; +class CallGphMethodProfile; //CallGph method profiler namespace Ia32{ @@ -197,6 +198,7 @@ MethodDesc * methodDesc; EdgeMethodProfile* edgeProfile; + CallGphMethodProfile* callgphProfile; //CallGph profiler, HIR2LIR friend class CFGCodeSelector; friend class VarGenerator; Index: jitrino/src/codegenerator/ia32/Ia32Printer.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32Printer.cpp (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32Printer.cpp (工作副本) @@ -307,6 +307,12 @@ ::std::ostream& os = getStream(); os<<"I"<getId()<<": "; + //if the instruction is to passing the basic block id information to indirect call counting VMHelper, CallGph + if(inst->isPushBBidInstr()) + { + os<<"CG_Push_BBId " <isPushBBidInstr(); + } + if (opndRolesFilter & Inst::OpndRole_Def){ U_32 printedOpndsTotal=0, printedOpnds=0; if (inst->getForm()==Inst::Form_Extended) @@ -525,11 +531,16 @@ { os<<"em_pi"; }break; - case Opnd::RuntimeInfo::Kind_Method_Value_Profile_Handle: + case Opnd::RuntimeInfo::Kind_Method_Value_Profile_Handle: /** The value of the operand is Method_Profile_Handle for the value profile of the compiled method */ { os<<"mvph"; }break; + case Opnd::RuntimeInfo::Kind_CallGph_BB_id: + /** The value of the operand is Method_Profile_Handle for the value profile of the compiled method */ + { + os<<"cg_bbid"; + }break; default: assert(0); } Index: jitrino/src/codegenerator/ia32/Ia32IRManager.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32IRManager.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32IRManager.h (工作副本) @@ -207,6 +207,9 @@ /** A specialization of the newCallInst to create an internal helper CallInst. */ CallInst * newInternalRuntimeHelperCallInst(const char * internalHelperID, U_32 numArgs, Opnd ** args, Opnd * retOpnd); + /** create an internal helper CallInst for CallGph */ + CallInst * newRuntimeHelperCallInstCallGph(VM_RT_SUPPORT helperId, U_32 numArgs, Opnd ** args, Opnd * retOpnd); + void registerInternalHelperInfo(const char * internalHelperID, const InternalHelperInfo& info); const InternalHelperInfo * getInternalHelperInfo(const char * internalHelperID)const { InternalHelperInfos::const_iterator it=internalHelperInfos.find(internalHelperID); return it!=internalHelperInfos.end()?&it->second:NULL; } Index: jitrino/src/codegenerator/ia32/Ia32Printer.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32Printer.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32Printer.h (工作副本) @@ -32,6 +32,9 @@ #include "LogStream.h" #include +//...int CALLGPH_DEBUG_INDCALL_HELPER = 0; + + namespace Jitrino { namespace Ia32{ Index: jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp (工作副本) @@ -432,6 +432,7 @@ calculatingRegUsage=true; } copySequence = irManager->newCopySequence(mn, inst->getOpnd(0), NULL, gpRegUsageMask, flagsRegUsageMask); + if(inst->isPushBBidInstr()) {copySequence->setPushBBidInstr();} //keep the instruction property when translate a instrumentation instruction from one level to another...CallGph...Helper... } // CopyPseudoInst map entries should be changed by new copy sequence instructions in byte code map if (compIntfc.isBCMapInfoRequired() && copySequence != NULL) { Index: jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (工作副本) @@ -32,6 +32,8 @@ #include #include +class CallCounter; + namespace Jitrino { namespace Ia32{ @@ -2459,6 +2461,28 @@ appendInsts(inst); } +//CallGph profiler, generate LIR direct call instrumentation instruction when HIR2LIR +void InstCodeSelector::incCounterCallGph(Type *counterType,U_32 key) +{ + + assert( counterType->isUInt4() ); + CallGphMethodProfile* callgphProfile = this->codeSelector.methodCodeSelector.callgphProfile; + assert(callgphProfile!=NULL); + U_32* ptr = callgphProfile->getCounter(key); + assert( ptr != NULL /*&& *ptr == 0 if compilation is locked*/); + + Opnd* baseOpnd = irManager.newImmOpnd(typeManager.getUnmanagedPtrType(typeManager.getUIntPtrType()), (POINTER_SIZE_INT)ptr); + Opnd* memOpnd = irManager.newMemOpnd(typeManager.getUIntPtrType(), MemOpndKind_Heap, baseOpnd, NULL, NULL, NULL); + const Mnemonic mn = Mnemonic_ADD; + Inst* inst = irManager.newInst(mn, memOpnd, irManager.newImmOpnd(typeManager.getInt8Type(), 1)); + //Todo..assign instrm_type to this instruction + inst->setCallGph_Instrm_Type(); + inst->setKey(key); + appendInsts(inst); +} + + + //_______________________________________________________________________________________________________________ // Return with a value @@ -2628,6 +2652,37 @@ } //_______________________________________________________________________________________________________________ +//CallGph profiler when HIR2LIR, Indirect call with the tau that indicates that first argument is non-null, for callgraph, key + +CG_OpndHandle* InstCodeSelector::tau_calli_callgph(U_32 numArgs, + CG_OpndHandle** args, + Type* retType, + CG_OpndHandle* methodPtr, + CG_OpndHandle* nonNullFirstArgTau, + CG_OpndHandle* tauTypesChecked, + U_32 key) +{ + + CallGphMethodProfile* callgphProfile = this->codeSelector.methodCodeSelector.callgphProfile; + assert(callgphProfile!=NULL); + //....U_32* ptr = key == 0 ? callgphProfile->getEntryCounter() : callgphProfile->getCounter(key ); + U_32* ptr = callgphProfile->getCounter(key);// getCounter(key ); + assert( ptr != NULL /*&& *ptr == 0 if compilation is locked*/); + + Opnd * target=irManager.newMemOpnd(typeManager.getUnmanagedPtrType(typeManager.getUIntPtrType()), (Opnd*)methodPtr); + Opnd * retOpnd=createResultOpnd(retType); + CallInst * callInst=irManager.newCallInst(target, irManager.getDefaultManagedCallingConvention(), numArgs, (Opnd **)args, retOpnd); + + callInst->setCallSiteType(InDirectMemCall_Type); + ///callInst->setCallGph_Instrm_Type(); + callInst->set_IndCall_Counter_Addr(ptr); + appendInsts(callInst); + + return retOpnd; +} + + +//_______________________________________________________________________________________________________________ // Direct call to the method. Depending on the code generator flags we // either expand direct call into loading method address into a register and // indirect call or true direct call that will be patched if method is recompiled. @@ -2939,20 +2994,31 @@ case VM_RT_GET_INVOKE_SPECIAL_ADDR_WITHRESOLVE: case VM_RT_INITIALIZE_CLASS_WITHRESOLVE: case VM_RT_MULTIANEWARRAY_RESOLVED: - case VM_RT_GET_IDENTITY_HASHCODE: -{ + { + dstOpnd = retType==NULL ? NULL: irManager.newOpnd(retType); CallInst * callInst=irManager.newRuntimeHelperCallInst(callId, numArgs, (Opnd**)args, dstOpnd); appendInsts(callInst); break; } + //helper used to count functions calls for CallGph + case VM_RT_CALLGPH_INDIRECT_CALL_HELPER: + { + dstOpnd = retType==NULL ? NULL: irManager.newOpnd(retType); + CallInst * callInst=irManager.newRuntimeHelperCallInst(callId, numArgs, (Opnd**)args, dstOpnd); + callInst->setDirctCallHelper(); + appendInsts(callInst); + break; + } + default: assert(0); } return dstOpnd; } + //_______________________________________________________________________________________________________________ // Box a value Index: jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (工作副本) @@ -19,6 +19,8 @@ * @version $Revision: 1.12.14.1.4.3 $ */ + + #include "Ia32IRManager.h" #include "Log.h" #include "Ia32RuntimeInterface.h" @@ -29,11 +31,24 @@ #include "EMInterface.h" #include "Ia32CgUtils.h" +#include +#include +#include + +#include "mkernel.h" + +using namespace std; + +fstream* fpLpDmp=NULL; //file used for loop information dumping for CallGph + namespace Jitrino { + + Mutex* myMutexp; //Mutex for locking the file used to dump the loop information for CallGph and hot loop profiler + namespace Ia32 { - + /** class CodeEmitter @@ -63,7 +78,14 @@ void emitCode(); void registerExceptionHandlers(); void registerExceptionRegion(void * regionStart, void * regionEnd, Node * regionDispatchNode); - int packCode(); + int packCode(); + + /** used to dump the info of loops and methods for building CallGph and profiling hot loops */ + bool isRealLoop(LoopNode * lp); + U_32 getNumInstOfBB(const BasicBlock * bb); + void Loop_Info_Dumping_CFG_file(fstream* fp); + void Dump_Loop_file(LoopTree* lt, LoopNode * lp, fstream* info); + void postPass(); void registerDirectCall(MethodDesc * md, void * instStartAddr); @@ -286,7 +308,29 @@ } } +/* resolve bbid in the opnd for PUSH instructions for indirect calls in building CallGph */ +bool resolvePushOpndBBid(IRManager* irManager) +{ + const Nodes& nodes = irManager->getFlowGraph()->getNodes(); + for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { + Node* node = *it; + if(!node->isBlockNode()) continue; + assert(node->getLastInst()!=NULL); + + for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) { + if(inst->isPushBBidInstr()) + { + Opnd* immOpnd = inst->getOpnd(0); + immOpnd->assignImmValue(node->getId()); + } + }//for + }//for + + return true; +} + + //======================================================================================== // class CodeEmitter //======================================================================================== @@ -296,9 +340,24 @@ { constantAreaLayout.doLayout(irManager); irManager->resolveRuntimeInfo(); + + /**This function is to resolve the id of the basic block which contains the push instruction for CallGph. + The push instruction is to pass the id of the call site basic block to helper function*/ + resolvePushOpndBBid(irManager); + emitCode(); //packCode(); //.this phase of function is moved into code emit phase postPass(); + + //* used to dump the method and loop information when jit a method for building CallGph and profiling hot loops*/ + if(fpLpDmp==NULL) + { + fpLpDmp = new fstream("myInfo.txt", ios::out); + myMutexp = new Mutex(); + } + AutoUnlock lock(myMutexp); + Loop_Info_Dumping_CFG_file(fpLpDmp); + constantAreaLayout.finalizeSwitchTables(); traversalInfo.resize(irManager->getFlowGraph()->getMaxNodeId() + 1, 0); registerExceptionHandlers(); @@ -448,7 +507,7 @@ } return !failed; } - + //________________________________________________________________________________________ void CodeEmitter::emitCode( void ) { @@ -457,6 +516,14 @@ // as the current scheme only process basic blocks as jmp targets const unsigned maxMethodSize = (irManager->getMaxInstId() + irManager->getFlowGraph()->getMaxNodeId())*MAX_NATIVE_INST_SIZE; + /** The followings are used to get callgph profiler for building CallGph */ + U_32 key = 0; + CallGphMethodProfile* callgphProfile = NULL; + ProfilingInterface* pi = irManager->getProfilingInterface(); + if (pi!=NULL && pi->isProfilingEnabled(ProfileType_CallGph, JITProfilingRole_GEN)) { + callgphProfile = pi->getCallGphMethodProfile(irManager->getMemoryManager(), irManager->getMethodDesc(), JITProfilingRole_GEN); + } + // U_8 * codeStreamStart = (U_8*)malloc( maxMethodSize ); //+---- free() below @@ -472,6 +539,7 @@ LoopTree * lt = irManager->getFlowGraph()->getLoopTree(); U_8 * ip = codeStreamStart; + for( BasicBlock * bb = (BasicBlock*)irManager->getFlowGraph()->getEntryNode(); bb != NULL; bb=bb->getLayoutSucc()) { assert(bb->getFirstInst()!=NULL); @@ -479,6 +547,7 @@ unsigned align = alignment - (unsigned)((POINTER_SIZE_INT)ip & (alignment-1)); ip = (U_8*)EncoderBase::nops((char*)ip, align); } + U_8 * blockStartIp = ip; assert(fit32(blockStartIp-codeStreamStart)); @@ -519,7 +588,30 @@ ip = (U_8*)EncoderBase::nops((char*)ip, 10); #endif } - + + //memorize direct call address for CallGph + if(inst->isCallGphInstrm()&&(callgphProfile!=NULL)) + { + key = inst->getKey(); + callgphProfile->setCallerBBId(bb->getId(),key); + for (Inst* tmp_inst = (Inst*)bb->getFirstInst(); tmp_inst!=NULL; tmp_inst = tmp_inst->getNextInst()) + { + if (tmp_inst->hasKind(Inst::Kind_ControlTransferInst) &&(((ControlTransferInst*)tmp_inst)->isDirect()) && + (tmp_inst->hasKind(Inst::Kind_CallInst))){ + U_8 * instCodeStartAddr=(U_8*)tmp_inst->getCodeStartAddr(); + U_8 * instCodeEndAddr=(U_8*)instCodeStartAddr+tmp_inst->getCodeSize(); + U_8 * targetCodeStartAddr=0; + U_32 targetOpndIndex = ((ControlTransferInst*)tmp_inst)->getTargetOpndIndex(); + + Opnd * targetOpnd=tmp_inst->getOpnd(targetOpndIndex); + targetCodeStartAddr=(U_8*)(POINTER_SIZE_INT)targetOpnd->getImmValue(); + callgphProfile->addDirctCalleeAddr(targetCodeStartAddr,key); + int i = 0; + } + } + }//if(inst->....) + //end CallGph + U_8 * instStartIp = ip; assert(fit32(instStartIp-blockStartIp)); inst->setCodeOffset( (U_32)(instStartIp-blockStartIp) ); @@ -538,10 +630,11 @@ stackInfo->setSOECheckAreaOffset(inst->getCodeOffset()); } + - unsigned codeSize = (unsigned)(ip-codeStreamStart); assert( codeSize < maxMethodSize ); + /*....Perform code pack to resolve target addresses of branck instructions before copy the native code to code buffer....*/ irManager->setCodeStartAddr(codeStreamStart); @@ -550,9 +643,19 @@ U_8 * codeBlock = (U_8*)irManager->getCompilationInterface().allocateCodeBlock( codeSize , JMP_TARGET_ALIGMENT, getCodeSectionHeat(0), 0, false ); + memcpy(codeBlock, codeStreamStart, codeSize); irManager->setCodeStartAddr(codeBlock); + //set the method entry address for CallGph profiler + if(pi->isProfilingEnabled(ProfileType_CallGph, JITProfilingRole_GEN)) + { + if(callgphProfile!=NULL) + { + callgphProfile->setMdStartAddr(codeBlock,key); + } + } + //^ //| //+---- malloc() above @@ -560,6 +663,7 @@ // } + //________________________________________________________________________________________ int CodeEmitter::packCode() { int bbDisplacement = 0; @@ -612,6 +716,179 @@ return bbDisplacement; } +bool CodeEmitter::isRealLoop(LoopNode * lp) +{ + Node* header = lp->getHeader(); + const Edges& edges = header->getInEdges(); + for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) + { + Edge* e = *ite; + const BasicBlock* pre_bb = (const BasicBlock*) e->getSourceNode(); + if(pre_bb->isBlockNode()) return true; + } + return false; +} + +U_32 CodeEmitter::getNumInstOfBB(const BasicBlock * bb) +{ + int numInst = 0; + for (Inst* tmp_inst = (Inst*)bb->getFirstInst(); tmp_inst!=NULL; tmp_inst = tmp_inst->getNextInst()) + { + numInst++; + } + return numInst; +} + +void CodeEmitter::Loop_Info_Dumping_CFG_file(fstream* fp) +{ + int maxDept = 0; + int currDept = 0; + MethodDesc &method = irManager->getMethodDesc(); + const char* methodTypeName = method.getParentType()->getName(); + const char* methodName = method.getName(); + const char* methodSig = method.getSignatureString(); + + unsigned mdsize = method.getCodeBlockSize(0); + U_8* mdstart = mdsize ? method.getCodeBlockAddress(0) : 0; + + string jitName = irManager->getCompilationContext()->getCurrentContext()->getCurrentJITContext()->getJITName(); + + + (*fp) <<" "<getFlowGraph(); + LoopTree * lt = irManager->getFlowGraph()->getLoopTree(); + + maxDept = lt->getMaxLoopDepth(); + if(lt==NULL) {*fp << "No Loop Tree " << std::endl<getNodes().begin(); iter != fg->getNodes().end(); iter++) + { + Node* bb = *iter; + bool is_header = lt->isLoopHeader(bb); + if(is_header) + { + LoopNode * lp = lt->getLoopNode(bb,false); + if(lp!=NULL) { + if(!isRealLoop(lp)) continue; //if it is a pseudo loop, then will not dump its information + currDept = lt->getLoopDepth(bb); + *fp << "***Loop Dump Loop:Depth:" << currDept; + if(currDept==maxDept){*fp << ":InnerLp:";} + else {*fp << ":NonInLp:";} + *fp<<" Code range:" << (void*)mdstart << ":" << (void*)(mdstart+mdsize)<<":id:"<getId(); + *fp<< std::endl<getHeader(); + unsigned lpDepth = lp->getDepth(); + + node = lp->getHeader(); + if(node!=NULL) + { + if(node->isBlockNode()) { + const BasicBlock * bb=(const BasicBlock*)node; + start_addr = (char *)bb->getCodeStartAddr(); + end_addr = start_addr + bb->getCodeSize(); + + *fp << "HeaderBB:" << node->getId(); + *fp <<":_starAddr_:" <<(void *) start_addr << ":_endAddr_:"<< (void *) end_addr<<":InstNum:"<getExecCount()<< std::endl<getInEdges(); + for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) + { + Edge* e = *ite; + const BasicBlock* pre_bb = (const BasicBlock*) e->getSourceNode(); + start_addr = (char *)pre_bb->getCodeStartAddr(); + end_addr = start_addr + pre_bb->getCodeSize(); + //...if(pre_bb->isBlockNode()) + *fp << "pred_BB:" << pre_bb->getId()<< ":_starAddr_:" << (void *) start_addr << ":_endAddr_:"<< (void *) end_addr<<":size:"<< end_addr - start_addr<<":Ex-cnt:"<< pre_bb->getExecCount()<<":Basc:"<isBlockNode()<getId() <<", Non Basic Block"<< std::endl<getChild(); + if (loopChild!=NULL) { + for (; loopChild!=NULL; loopChild = loopChild->getSiblings()) { + const Node * lp_hdr = loopChild->getHeader(); + *fp <<":"<getId()<getNodesInLoop().begin(); iter != lp->getNodesInLoop().end(); iter++) + { + node = *iter; + if(!node->isBlockNode()) continue; //only dump basic block nodes + const BasicBlock * bodybb=(const BasicBlock*)node; + if(lt->getLoopDepth(node)!=lpDepth) continue; //donnot print bbs in its inner loop + + start_addr = (char *)bodybb->getCodeStartAddr(); + end_addr = start_addr + bodybb->getCodeSize(); + *fp << "bodyBB:" << node->getId()<< ":_starAddr_:" << (void *) start_addr << ":_endAddr_:"<< (void *) end_addr<<":size:"<< end_addr - start_addr<< ":Ex-cnt:" << node->getExecCount()<getOutEdges(); + for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) + { + Edge* e = *ite; + Node *succ_bb = (Node *)e->getTargetNode(); + *fp << "BB" << succ_bb->getId() << "," <<"Basc("<isBlockNode()<<")"<isProfilingEnabled(ProfileType_Edge, JITProfilingRole_GEN)) { edgeProfile = pi->getEdgeMethodProfile(irMM, irM.getMethodDesc(), JITProfilingRole_GEN); } + if (pi!=NULL && pi->isProfilingEnabled(ProfileType_CallGph, JITProfilingRole_GEN)) { + callgphProfile = pi->getCallGphMethodProfile(irMM, irM.getMethodDesc(), JITProfilingRole_GEN); + } //get CallGph profiler for HIR2LIR, CallGph + } Index: jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (版本 735635) +++ jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (工作副本) @@ -194,6 +194,18 @@ CG_OpndHandle* ldRef(Type *dstType, MethodDesc* enclosingMethod,U_32 stringToken, bool uncompress); void incCounter(Type *counterType,U_32 counter); + + //The following two functions are used for building CallGph + void incCounterCallGph(Type *counterType,U_32 key); // + CG_OpndHandle* tau_calli_callgph(U_32 numArgs, + CG_OpndHandle** args, + Type* retType, + CG_OpndHandle* methodPtr, + CG_OpndHandle* nonNullFirstArgTau, + CG_OpndHandle* tauTypesChecked, + U_32 key); // + + void ret(); void ret(CG_OpndHandle* returnValue); @@ -218,7 +230,7 @@ CG_OpndHandle* callhelper(U_32 numArgs, CG_OpndHandle** args, Type* retType,JitHelperCallOp::Id callId); CG_OpndHandle* callvmhelper(U_32 numArgs, CG_OpndHandle** args, Type* retType, VM_RT_SUPPORT callId); - + CG_OpndHandle* box(ObjectType * boxedType, CG_OpndHandle* val); CG_OpndHandle* unbox(Type * dstType, CG_OpndHandle* objHandle); CG_OpndHandle* ldValueObj(Type* objType, CG_OpndHandle *srcAddr); Index: jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h =================================================================== --- jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (版本 735635) +++ jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (工作副本) @@ -175,6 +175,7 @@ CG_OpndHandle *call(U_32, CG_OpndHandle**, Type*, MethodDesc*); CG_OpndHandle *tau_call(U_32, CG_OpndHandle**, Type*, MethodDesc*, CG_OpndHandle*, CG_OpndHandle*); CG_OpndHandle *tau_calli(U_32,CG_OpndHandle**, Type*, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*); + CG_OpndHandle *tau_calli_callgph(U_32,CG_OpndHandle**, Type*, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*, U_32){return NULL;} //...CallGph void ret(); void ret(CG_OpndHandle*); Index: jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp =================================================================== --- jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (版本 735635) +++ jitrino/src/codegenerator/ipf/IpfInstCodeSelector.cpp (工作副本) @@ -1315,7 +1315,31 @@ } //----------------------------------------------------------------------------// +// Indirect call +CG_OpndHandle *IpfInstCodeSelector::tau_calli_callgph(U_32 numArgs, + CG_OpndHandle **args, + Type *retType, + CG_OpndHandle *methodPtr, + CG_OpndHandle *nonNullFirstArgTau, + CG_OpndHandle *tauTypesChecked, + U_32 key) { + IPF_LOG << " tau_calli; numArgs=" << numArgs + << ", retType=" << (retType ? Type::tag2str(retType->tag) : "NULL") << endl; + IPF_ASSERT(((Opnd *)methodPtr)->isReg()); + + RegOpnd *retOpnd = NULL; + if(retType != NULL) { + retOpnd = opndManager->newRegOpnd(toOpndKind(retType->tag), toDataKind(retType->tag)); + } + + indirectCall(numArgs, (Opnd **)args, retOpnd, (RegOpnd *)methodPtr, p0); + return retOpnd; +} + + +//----------------------------------------------------------------------------// + void IpfInstCodeSelector::ret() { IPF_LOG << " ret" << endl; Index: jitrino/src/codegenerator/CodeGenIntfc.h =================================================================== --- jitrino/src/codegenerator/CodeGenIntfc.h (版本 735635) +++ jitrino/src/codegenerator/CodeGenIntfc.h (工作副本) @@ -268,11 +268,20 @@ CG_OpndHandle* methodPtr, CG_OpndHandle* tauNullChecked, CG_OpndHandle* tauTypesChecked) = 0; + + + virtual CG_OpndHandle* tau_calli_callgph(U_32 numArgs,CG_OpndHandle** args, Type* retType, + CG_OpndHandle* methodPtr, + CG_OpndHandle* tauNullChecked, + CG_OpndHandle* tauTypesChecked, + U_32 key) = 0; //CallGph + virtual CG_OpndHandle* callhelper(U_32 numArgs, CG_OpndHandle** args, Type* retType, JitHelperCallOp::Id callId) = 0; virtual CG_OpndHandle* callvmhelper(U_32 numArgs, CG_OpndHandle** args, Type* retType, VM_RT_SUPPORT callId) = 0; + virtual CG_OpndHandle* ldc_i4(I_32 val) = 0; virtual CG_OpndHandle* ldc_i8(int64 val) = 0; virtual CG_OpndHandle* ldc_s(float val) = 0; @@ -405,6 +414,7 @@ virtual CG_OpndHandle* newMultiArray(ArrayType* arrayType, U_32 numDims, CG_OpndHandle** dims) = 0; virtual CG_OpndHandle* ldRef(Type* type,MethodDesc* enclosingMethod,U_32 stringToken, bool autouncompress) = 0; virtual void incCounter(Type *counterType,U_32 counter) = 0; + virtual void incCounterCallGph(Type *counterType,U_32 counter) = 0; //...CallGph...HIR2LIR virtual void ret() = 0; virtual void ret(CG_OpndHandle* returnValue) = 0; Index: jitrino/src/optimizer/Inst.h =================================================================== --- jitrino/src/optimizer/Inst.h (版本 735635) +++ jitrino/src/optimizer/Inst.h (工作副本) @@ -76,6 +76,21 @@ class MethodCallInst; class TauPiInst; +/** instruction and callsite property for CallGph */ +enum Instrm_Type{ //for HIR2LIR + Unknown_Instrm_Type, + Edge_Instrm_Type, + CallGph_Instrm_Type +}; + +enum CallSite_Type{ //for HIR2LIR + UnKnown_CallSite_Type, + DirectCall_Type, + InDirectCall_Type, + InDirectMemCall_Type, + VirtualCall_Type +}; + // // visitor pattern for the different instruction formats // @@ -245,6 +260,7 @@ return operation.isSigned(); } + virtual bool isBranch() const { return false; }; virtual bool isCall() const { return false; }; virtual bool isCatchLabel() const { return false; }; @@ -273,6 +289,18 @@ bool isJSR() const {return getOpcode() == Op_JSR; } bool isRet() const {return getOpcode() == Op_Ret; } + /** follwoing functions are for building CallGph*/ + bool isCallGphInstrm() { return (getOpcode()==Op_IncCounter)&&(instrm_type==CallGph_Instrm_Type); }//...CallGph...for HIR2LIR + bool setCallGph_Instrm_Type() { return instrm_type = CallGph_Instrm_Type; } //for HIR2LIR + bool isUnknownType(){return instrm_type == Unknown_Instrm_Type;} + bool setEdge_Instrm_Type(){return instrm_type = Edge_Instrm_Type; } //for HIR2LIR + CallSite_Type getCallSite_Type() { return callsite_type; }//for indirect calls.for HIR2LIR + bool setCallSite_Type(CallSite_Type in_callsite_type) { return callsite_type = in_callsite_type; } //...CallGph..for indirect calls.for HIR2LIR + bool isDirectCallInstrm() { return callsite_type == DirectCall_Type; } + bool setKey(U_32 inKey){return key = inKey;} + U_32 getKey(){return key;} + + bool isUnconditionalBranch() const {return getOpcode() == Op_Jump;} bool isConditionalBranch() const {return getOpcode() == Op_Branch;} @@ -375,7 +403,11 @@ PersistentInstructionId pid; U_32 id; - + /** instruction property for CallGph */ + Instrm_Type instrm_type; + CallSite_Type callsite_type; // mainly for indirect calls + U_32 key; + // called from CFG to detect BB->BB block edges virtual Edge::Kind getEdgeKind(const Edge* edge) const; @@ -973,6 +1005,8 @@ bool isVMHelperCallInst() const { return true; } VM_RT_SUPPORT getVMHelperId() const {return vmHelperId;} bool isThrowLazy() const {return vmHelperId == VM_RT_THROW_LAZY;} + + private: virtual void handlePrintEscape(::std::ostream&, char code) const; friend class InstFactory; @@ -1001,10 +1035,9 @@ } Opnd** args; VM_RT_SUPPORT vmHelperId; + //...U_32 key; }; - -// phi instructions class PhiInst : public MultiSrcInst { public: void visit(InstFormatVisitor& visitor) {visitor.accept(this);} Index: jitrino/src/optimizer/Inst.cpp =================================================================== --- jitrino/src/optimizer/Inst.cpp (版本 735635) +++ jitrino/src/optimizer/Inst.cpp (工作副本) @@ -38,6 +38,9 @@ : operation(opcode, type, mod), numSrcs(0), dst(0) { setDst(dst_); + /** initilize members representing property of instructions used for CallGph */ + instrm_type = Unknown_Instrm_Type; + callsite_type = UnKnown_CallSite_Type; } Inst::Inst(Opcode opcode, Modifier mod, Type::Tag type, Opnd* dst_, Opnd* src) @@ -45,6 +48,9 @@ { setDst(dst_); srcs[0] = src; + /** initilize members representing property of instructions used for CallGph */ + instrm_type = Unknown_Instrm_Type; + callsite_type = UnKnown_CallSite_Type; } Inst::Inst(Opcode opcode, Modifier mod, Type::Tag type, Opnd* dst_, @@ -54,12 +60,18 @@ setDst(dst_); srcs[0] = src1; srcs[1] = src2; + /** initilize members representing property of instructions used for CallGph */ + instrm_type = Unknown_Instrm_Type; + callsite_type = UnKnown_CallSite_Type; } Inst::Inst(Opcode opcode, Modifier mod, Type::Tag type, Opnd* dst_, U_32 nSrcs) : operation(opcode, type, mod), numSrcs(nSrcs), dst(0) { setDst(dst_); + /** initilize members representing property of instructions used for CallGph */ + instrm_type = Unknown_Instrm_Type; + callsite_type = UnKnown_CallSite_Type; } Opnd* Inst::getSrcExtended(U_32 srcIndex) const { Index: jitrino/src/optimizer/escanalyzer.h =================================================================== --- jitrino/src/optimizer/escanalyzer.h (版本 735635) +++ jitrino/src/optimizer/escanalyzer.h (工作副本) @@ -69,7 +69,7 @@ EscAnalyzer(EscAnalyzer* parent, IRManager& irm); // initial level to start callee method escape analysis - static const int maxMethodExamLevel_default = 0; + static const int maxMethodExamLevel_default = 2; // Connection Graph Structure // CnG node types Index: jitrino/src/optimizer/CodeSelectors.cpp =================================================================== --- jitrino/src/optimizer/CodeSelectors.cpp (版本 735635) +++ jitrino/src/optimizer/CodeSelectors.cpp (工作副本) @@ -839,13 +839,15 @@ assert(tauNullChecked->getType()->tag == Type::Tau); assert(tauTypesChecked->getType()->tag == Type::Tau); assert(inst->isCall()); - cgInst = + + cgInst = instructionCallback.tau_calli(inst->getNumSrcOperands() - 3, // omit taus andfnAddr genCallArgs(inst, 3), // omit taus and fnAddr inst->getDst()->getType(), getCGInst(fnAddr), getCGInst(tauNullChecked), getCGInst(tauTypesChecked)); + } break; case Op_JitHelperCall: @@ -866,8 +868,8 @@ convertJitHelperId(callId)); } break; - case Op_VMHelperCall: - { + case Op_VMHelperCall: + { VMHelperCallInst* call = inst->asVMHelperCallInst(); VM_RT_SUPPORT callId = call->getVMHelperId(); cgInst = @@ -1773,10 +1775,22 @@ } break; case Op_IncCounter: - { - TokenInst *counterInst = (TokenInst *)inst; - U_32 counter = counterInst->getToken(); - instructionCallback.incCounter(irmanager.getTypeManager().getUInt32Type(), counter); + { + if(inst->isCallGphInstrm())//if instrumentation instruction for CallGph + { + if(inst->isDirectCallInstrm()){ + TokenInst *counterInst = (TokenInst *)inst; + U_32 counter = counterInst->getToken(); //...the key of the counter... + instructionCallback.incCounterCallGph(irmanager.getTypeManager().getUInt32Type(), counter); + } + } + else//Edge Profile, etc + { + TokenInst *counterInst = (TokenInst *)inst; + U_32 counter = counterInst->getToken(); + bool debug = counterInst->isUnknownType(); + instructionCallback.incCounter(irmanager.getTypeManager().getUInt32Type(), counter); + } } break; case Op_Prefetch: Index: jitrino/src/vm/EMInterface.cpp =================================================================== --- jitrino/src/vm/EMInterface.cpp (版本 735635) +++ jitrino/src/vm/EMInterface.cpp (工作副本) @@ -30,6 +30,8 @@ return edgePCHandle; case ProfileType_Value: return valuePCHandle; + case ProfileType_CallGph: + return callgphPCHandle; //for CallGph building default: assert(0); } @@ -47,7 +49,10 @@ p = new (mm) EdgeMethodProfile(mpHandle, md, profileAccessInterface); } else if (type == ProfileType_Value) { p = new (mm) ValueMethodProfile(mpHandle, md, profileAccessInterface); - } else { + } else if (type == ProfileType_CallGph){ + p = new (mm) CallGphMethodProfile(mpHandle, md, profileAccessInterface); //return CallGph profier (used for HIR2LIR) + } + else { U_32* eCounter = (U_32*)profileAccessInterface->eb_profiler_get_entry_counter_addr(mpHandle); U_32* bCounter = (U_32*)profileAccessInterface->eb_profiler_get_backedge_counter_addr(mpHandle); p = new (mm) EntryBackedgeMethodProfile(mpHandle, md, eCounter, bCounter); @@ -105,7 +110,7 @@ bool ProfilingInterface::enableProfiling(PC_Handle pc, JITProfilingRole role) { EM_PCTYPE _pcType = profileAccessInterface->get_pc_type(emHandle, pc); - if (_pcType != EM_PCTYPE_EDGE && _pcType != EM_PCTYPE_ENTRY_BACKEDGE && _pcType != EM_PCTYPE_VALUE) { + if (_pcType != EM_PCTYPE_EDGE && _pcType != EM_PCTYPE_ENTRY_BACKEDGE && _pcType != EM_PCTYPE_VALUE && _pcType != EM_PCTYPE_CALLGPH) {//...CallGph return false; } JITInstanceContext* jitMode = JITInstanceContext::getContextForJIT(jitHandle); @@ -131,6 +136,10 @@ case EM_PCTYPE_VALUE: valuePCHandle = pc; break; + case EM_PCTYPE_CALLGPH: //CallGph + callgphPCHandle = pc; + break; + default: assert(0); return false; @@ -140,7 +149,7 @@ } bool ProfilingInterface::isProfilingEnabled(ProfileType pcType, JITProfilingRole role) const { - if(!profilingEnabled || (jitRole != role) || (getPCHandle(pcType) == NULL)){ + if(!profilingEnabled || (jitRole != role)&&(pcType != ProfileType_CallGph) || (getPCHandle(pcType) == NULL)){ ///CallGph is considered...SD2 return false; } return true; @@ -175,6 +184,30 @@ return p; } +/** Create callgraph profiler for building CallGph */ +CallGphMethodProfile* ProfilingInterface::createCallGphMethodProfile( MemoryManager& mm, + MethodDesc& md, + U_32 numCounters, + U_32 numIndCalls, + vector* counterKeysVector, + U_32 checkSum ) +{ + if(!isProfilingEnabled(ProfileType_CallGph, JITProfilingRole_GEN)) //debug CallGph + { + int i=4; + } + assert(isProfilingEnabled(ProfileType_CallGph, JITProfilingRole_GEN)); + PC_Handle pcHandle = getPCHandle(ProfileType_CallGph); + Method_Profile_Handle mpHandle = profileAccessInterface->callgph_profiler_create_profile( + pcHandle, md.getMethodHandle(), numCounters, numIndCalls, counterKeysVector, checkSum); + assert( mpHandle != NULL ); + + CallGphMethodProfile* p = new (mm) CallGphMethodProfile(mpHandle, md, profileAccessInterface); + return p; +} + + + ValueMethodProfile* ProfilingInterface::createValueMethodProfile(MemoryManager& mm, MethodDesc& md, U_32 numKeys, @@ -242,6 +275,43 @@ return counter; } +//for CallGph +U_32* CallGphMethodProfile::getCounter(U_32 key) const { + U_32* counter = (U_32*)profileAccessInterface->callgph_profiler_get_counter_addr(getHandle(), key); + return counter; +} + + + +U_32* CallGphMethodProfile::getCounterObj(U_32 key) const { + U_32* counterObj = (U_32*)profileAccessInterface->callgph_profiler_get_counter_obj_addr(getHandle(), key); + return counterObj; +} + +bool CallGphMethodProfile::setCallerBBId(int id, U_32 key) const { + bool tmp = (U_32*)profileAccessInterface->callgph_profiler_set_callerBB_id(getHandle(),id, key); + return tmp; +} + +bool CallGphMethodProfile::addDirctCalleeAddr(U_8* addr, U_32 key) const{ + bool tmp = (U_32*)profileAccessInterface->callgph_profiler_add_dirctcallee_addr(getHandle(),addr, key); + return tmp; +} + +bool CallGphMethodProfile::setMdStartAddr(U_8* addr, U_32 key) const { + bool tmp = (U_32*)profileAccessInterface->callgph_profiler_set_md_strtAddr(getHandle(), addr, key); + return tmp; +} + +bool CallGphMethodProfile::setJitName(std::string inJitName, U_32 reserve) const { + bool tmp = (U_32*)profileAccessInterface->callgph_profiler_set_jit_name(getHandle(), inJitName); + return tmp; +} + + +//bool setCalleeName(string callee); + + POINTER_SIZE_INT ValueMethodProfile::getTopValue(U_32 instructionKey) const { return profileAccessInterface->value_profiler_get_top_value(getHandle(), instructionKey); } Index: jitrino/src/vm/EMInterface.h =================================================================== --- jitrino/src/vm/EMInterface.h (版本 735635) +++ jitrino/src/vm/EMInterface.h (工作副本) @@ -21,13 +21,16 @@ #include "open/em_profile_access.h" #include "VMInterface.h" + namespace Jitrino { enum ProfileType { ProfileType_Invalid = 0, ProfileType_EntryBackedge = 1, ProfileType_Edge = 2, - ProfileType_Value = 3 + ProfileType_Value = 3, + ProfileType_CallGph = 4 //CallGph Profiler Type + }; enum JITProfilingRole{ @@ -83,6 +86,29 @@ EM_ProfileAccessInterface* profileAccessInterface; }; +//CallGph profiler +class CallGphMethodProfile : public MethodProfile { +public: + CallGphMethodProfile (Method_Profile_Handle handle, MethodDesc& md, EM_ProfileAccessInterface* _profileAccessInterface) + : MethodProfile(handle, ProfileType_Edge, md), profileAccessInterface(_profileAccessInterface){} + + U_32 getNumCounters() const; + U_32 getCheckSum() const; + U_32* getEntryCounter() const; + U_32* getCounter(U_32 key) const; + U_32* getCounterObj(U_32 key) const; + + bool setCallerBBId(int id, U_32 key) const; + bool setMdStartAddr(U_8* addr, U_32 key) const; + bool setJitName(std::string inJitName, U_32 reserve) const; + bool addDirctCalleeAddr(U_8* addr, U_32 key) const; + //bool setCalleeName(string callee); + +private: + EM_ProfileAccessInterface* profileAccessInterface; +}; + + class ValueMethodProfile: public MethodProfile { public: ValueMethodProfile (Method_Profile_Handle handle, MethodDesc& md, EM_ProfileAccessInterface* _profileAccessInterface) @@ -125,6 +151,7 @@ EdgeMethodProfile* createEdgeMethodProfile(MemoryManager& mm, MethodDesc& md, U_32 numEdgeCounters, U_32* counterKeys, U_32 checkSum); + CallGphMethodProfile* createCallGphMethodProfile(MemoryManager& mm, MethodDesc& md, U_32 numCallSiteCounters, U_32 numIndCalls, vector* counterKeysVector, U_32 checkSum); U_32 getMethodEntryThreshold() const; U_32 getBackedgeThreshold() const; @@ -136,8 +163,12 @@ EdgeMethodProfile* getEdgeMethodProfile(MemoryManager& mm, MethodDesc& md, JITProfilingRole role=JITProfilingRole_USE) const { return (EdgeMethodProfile*)getMethodProfile(mm, ProfileType_Edge, md, role); } + + //CallGph profiler + CallGphMethodProfile* getCallGphMethodProfile(MemoryManager& mm, MethodDesc& md, JITProfilingRole role=JITProfilingRole_USE) const { + return (CallGphMethodProfile*)getMethodProfile(mm, ProfileType_CallGph, md, role); + } - // value profiler ValueMethodProfile* createValueMethodProfile (MemoryManager& mm, MethodDesc& md, U_32 numKeys, U_32* Keys); @@ -146,13 +177,13 @@ } ProfilingInterface(EM_Handle _em, JIT_Handle _jit, EM_ProfileAccessInterface* emProfileAccess) - : emHandle(_em), ebPCHandle(NULL), edgePCHandle(NULL), valuePCHandle(NULL), jitHandle(_jit), profileAccessInterface(emProfileAccess), + : emHandle(_em), ebPCHandle(NULL), edgePCHandle(NULL), callgphPCHandle(NULL), valuePCHandle(NULL), jitHandle(_jit), profileAccessInterface(emProfileAccess), jitRole(JITProfilingRole_USE), profilingEnabled(false){} private: EM_Handle emHandle; // Various types of the profile collectors - PC_Handle ebPCHandle, edgePCHandle, valuePCHandle; + PC_Handle ebPCHandle, edgePCHandle, valuePCHandle, callgphPCHandle; //CallGphPCHandle for CallGph building // ProfileType pcType; JIT_Handle jitHandle; EM_ProfileAccessInterface* profileAccessInterface; Index: jitrino/src/vm/JITInterface.cpp =================================================================== --- jitrino/src/vm/JITInterface.cpp (版本 735635) +++ jitrino/src/vm/JITInterface.cpp (工作副本) @@ -200,15 +200,7 @@ cs.setPipeline((HPipeline*)pipep); LogStreams::current(jitContext).beginMethod(methodTypeName, methodName, methodSig, method_seqnb); Str pipename = pipep->getName(); - LogStream& info = LogStream::log(LogStream::INFO, (HPipeline*)pipep); - if (info.isEnabled()) { - info << "<" << current_nb << "\t" - << jitContext->getJITName() << "." << pipename - << "\tstart " - << methodTypeName << "." << methodName << methodSig - << "\tbyte code size=" << md->getByteCodeSize() - << std::endl; - } + #ifdef _DEBUG Jitrino::incCompilationRecursionLevel(); #endif @@ -228,26 +220,7 @@ Jitrino::decCompilationRecursionLevel(); #endif - if (info.isEnabled()) { - info << current_nb << ">\t" - << jitContext->getJITName() << "." << pipename - << "\t end "; - //<< methodTypeName << "." << methodName << methodSig; - - if (result == JIT_SUCCESS) { - unsigned size = md->getCodeBlockSize(0); - U_8* start = size ? md->getCodeBlockAddress(0) : 0; - info << "\tnative code size=" << size - << " code range=[" << (void*)start << "," << (void*)(start+size) << "]"; - } - else - info << "\tFAILURE"; - - info << std::endl; - } - - LogStreams::current(jitContext).endMethod(); - return result; +return result; } extern "C" Index: jitrino/src/main/Log.h =================================================================== --- jitrino/src/main/Log.h (版本 735635) +++ jitrino/src/main/Log.h (工作副本) @@ -28,7 +28,6 @@ #include "open/types.h" #include - namespace Jitrino { Index: jitrino/src/shared/LoopTree.h =================================================================== --- jitrino/src/shared/LoopTree.h (版本 735635) +++ jitrino/src/shared/LoopTree.h (工作副本) @@ -28,6 +28,8 @@ #include "Stl.h" #include "MemoryManager.h" #include "ControlFlowGraph.h" +#include +using namespace std; namespace Jitrino { @@ -40,6 +42,7 @@ class LoopNode : public TreeNode { public: + LoopNode* getChild() const {return (LoopNode*)child;} LoopNode* getSiblings() const {return (LoopNode*)siblings;} LoopNode* getParent() const {return (LoopNode*)parent;} @@ -57,18 +60,26 @@ // return true is this edge is a back edge for this loop. bool isBackEdge(const Edge* e) const; + /** the following two functions are used to set and get the id + identifying a loop for merging CallGph and hotloops information later */ + void setId(U_32 in_id); + U_32 getId(); + private: friend class LoopTree; - LoopNode(MemoryManager& mm, LoopTree* lt, Node* hd) : loopTree(lt), header(hd), nodesInLoop(mm){} + LoopNode(MemoryManager& mm, LoopTree* lt, Node* hd) : loopTree(lt), header(hd), nodesInLoop(mm) + { + } void markNodesOfLoop(); void backwardMarkNode(Node* currentTail, DominatorTree* dom); void clear(); - + LoopTree* loopTree; Node* header; // loop entry point Nodes nodesInLoop; + U_32 id; //id used to identify a loop for CallGph and hot loops }; typedef StlVector LoopNodes; @@ -106,6 +117,9 @@ bool isNormalized() const { return normalized;} U_32 getMaxLoopDepth() const {return getHeight()-1;} + + //added for building CallGph + LoopNodes* getLoopNodes() {return &headerMap;}; private: void findLoopHeaders(Nodes& headers); @@ -129,6 +143,8 @@ //indicates that loop tree was normalized during previous rebuild bool normalized; + U_32 loopId; //id used to identify loops for CallGph + }; } Index: jitrino/src/shared/LoopTree.cpp =================================================================== --- jitrino/src/shared/LoopTree.cpp (版本 735635) +++ jitrino/src/shared/LoopTree.cpp (工作副本) @@ -31,6 +31,8 @@ { // create a root loop containing all loops within the method root = new (mm) LoopNode(mm, this, NULL); + + loopId=0; //init id that is used to identify loops for CallGph } // @@ -130,10 +132,16 @@ assert(fg->hasValidOrdering()); + /**since loop hierarchy is created at different phases, so it is necessary to + reset id to zero for each phase...CallGph + */ + loopId = 0; // create loops in df num order for (Nodes::const_iterator it = headers.begin(), end = headers.end(); it!=end; ++it) { + loopId++; //increment id for CallGph Node* header = *it; - createLoop(header); + createLoop(header); + } } @@ -181,10 +189,21 @@ } } +void LoopNode::setId(U_32 in_id) //CallGph +{ + id = in_id; +} +U_32 LoopNode::getId() //CallGph +{ + return id; +} + + void LoopTree::createLoop(Node* header) { // walk up the hierarchy to find which loop contains it LoopNode* loop = new (mm) LoopNode(mm, this, header); + loop->setId(loopId); //set id for the new created loop...CallGph LoopNode* parent = findEnclosingLoop(header); parent->addChild(loop); loop->markNodesOfLoop(); Index: jitrino/src/dynopt/EdgeProfiler.cpp =================================================================== --- jitrino/src/dynopt/EdgeProfiler.cpp (版本 735635) +++ jitrino/src/dynopt/EdgeProfiler.cpp (工作副本) @@ -106,7 +106,10 @@ StlVector counterKeys(mm); // Instrument method entry first. Node* entryNode = flowGraph.getEntryNode(); - entryNode->prependInst(instFactory.makeIncCounter(0)); + Inst* entry_inst = instFactory.makeIncCounter(0); + entryNode->prependInst(entry_inst); + entry_inst->setEdge_Instrm_Type(); //....CallGph...HIR2LIR + bool methodIsTrivial = isMethodTrivial(flowGraph); if (!methodIsTrivial) { // Scan the CFG node in topological order and record the blocks and @@ -133,6 +136,7 @@ U_32 key = counterKeys[i]; Inst* incInst = instFactory.makeIncCounter( key ); assert(((Inst*)nodeToInstrument->getFirstInst())->getOpcode() != Op_IncCounter ); + incInst->setEdge_Instrm_Type(); //....CallGph...HIR2LIR nodeToInstrument->prependInst(incInst); } @@ -157,6 +161,9 @@ } + + + DEFINE_SESSION_ACTION_WITH_ACTION(EdgeProfilerAnnotationPass, EdgeProfilerAction, edge_annotate, "Perform edge annotation pass") void EdgeProfilerAnnotationPass::_run(IRManager& irm) {