Index: vm/gc_gen/src/jni/java_natives.cpp =================================================================== --- vm/gc_gen/src/jni/java_natives.cpp (revision 699565) +++ vm/gc_gen/src/jni/java_natives.cpp (working copy) @@ -119,6 +119,25 @@ return (jint) GC_LOS_OBJ_SIZE_THRESHOLD; } +#define OFFSET(structure, member) ((int) &((structure *)0)->member) + +JNIEXPORT jlong JNICALL Java_org_apache_harmony_drlvm_gc_1gen_GCHelper_getVTBase(JNIEnv *e, jclass c) +{ + return (jlong)vtable_base; +} +JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_gc_1gen_GCHelper_getArrayElemSizeOffsetInGCVT(JNIEnv *e, jclass c) +{ + return (jint)OFFSET(GC_VTable_Info,array_elem_size); +} +JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_gc_1gen_GCHelper_getArrayFirstElemOffsetInGCVT(JNIEnv *e, jclass c) +{ + return (jint)OFFSET(GC_VTable_Info,array_first_elem_offset); +} +JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_gc_1gen_GCHelper_getGCAllocatedSizeOffsetInGCVT(JNIEnv *e, jclass c) +{ + return (jint)OFFSET(GC_VTable_Info,gc_allocated_size); +} + #ifdef __cplusplus } #endif Index: vm/gc_gen/src/common/gc_for_vm.cpp =================================================================== --- vm/gc_gen/src/common/gc_for_vm.cpp (revision 699565) +++ vm/gc_gen/src/common/gc_for_vm.cpp (working copy) @@ -62,6 +62,7 @@ vm_helper_register_magic_helper(VM_RT_NEW_RESOLVED_USING_VTABLE_AND_SIZE, "org/apache/harmony/drlvm/gc_gen/GCHelper", "alloc"); vm_helper_register_magic_helper(VM_RT_NEW_VECTOR_USING_VTABLE, "org/apache/harmony/drlvm/gc_gen/GCHelper", "allocArray"); vm_helper_register_magic_helper(VM_RT_GC_HEAP_WRITE_REF, "org/apache/harmony/drlvm/gc_gen/GCHelper", "write_barrier_slot_rem"); + vm_helper_register_magic_helper(VM_RT_GET_IDENTITY_HASHCODE, "org/apache/harmony/drlvm/gc_gen/GCHelper", "get_hashcode"); } int gc_init() Index: vm/gc_gen/javasrc/org/apache/harmony/drlvm/gc_gen/GCHelper.java =================================================================== --- vm/gc_gen/javasrc/org/apache/harmony/drlvm/gc_gen/GCHelper.java (revision 699565) +++ vm/gc_gen/javasrc/org/apache/harmony/drlvm/gc_gen/GCHelper.java (working copy) @@ -259,6 +259,71 @@ VMHelper.writeBarrier(p_objBase, p_objSlot, p_target); } + private static final long VT_BASE = getVTBase(); + private static final int OBJ_INFO_OFFSET = 4; + private static final int HASHCODE_UNSET = 0x0; + private static final int HASHCODE_SET_ATTACHED = 0x0c; + private static final int HASHCODE_SET_UNALLOCATED = 0x04; + private static final int HASHCODE_MASK = 0x1c; + private static final int GC_CLASS_FLAG_ARRAY = 0x02; + private static final long GC_CLASS_FLAGS_MASK = ~((long)0x07); + private static final int GC_OBJ_ALIGN_MASK = GC_OBJECT_ALIGNMENT - 1; + private static final int ARRAY_ELEM_SIZE_OFFSET_IN_GCVT = getArrayElemSizeOffsetInGCVT(); + private static final int ARRAY_FIRST_ELEM_OFFSET_IN_GCVT = getArrayFirstElemOffsetInGCVT(); + private static final int GC_ALLOCATED_SIZE_OFFSET_IN_GCVT= getGCAllocatedSizeOffsetInGCVT(); + + @Inline + public static int get_hashcode(Object object){ + Address p_obj = ObjectReference.fromObject(object).toAddress(); + int obj_info = p_obj.loadInt(Offset.fromIntZeroExtend(OBJ_INFO_OFFSET)); + + int hashcodeFlag = obj_info & HASHCODE_MASK; + + if (hashcodeFlag == HASHCODE_SET_UNALLOCATED) { + return (p_obj.toInt())>>2; + } else if(hashcodeFlag == HASHCODE_SET_ATTACHED) { + int obj_size; +// Address vt_address = Address.fromLong((p_obj.loadLong()>>32) + VT_BASE); //TODO: support uncompressed 64-bit + Address vt_address = Address.fromLong(p_obj.loadInt() + VT_BASE); //TODO: support uncompressed 64-bit + Address gcvt_raw_address = vt_address.loadAddress(); + Address gcvt_address = Address.fromLong(gcvt_raw_address.toLong() & GC_CLASS_FLAGS_MASK); + + long gcvt = gcvt_raw_address.toLong(); + + if((gcvt & GC_CLASS_FLAG_ARRAY) != 0){ + int array_first_elem_offset + = gcvt_address.loadInt(Offset.fromIntZeroExtend(ARRAY_FIRST_ELEM_OFFSET_IN_GCVT)); + int array_elem_size + = gcvt_address.loadInt(Offset.fromIntZeroExtend(ARRAY_ELEM_SIZE_OFFSET_IN_GCVT)); + + int array_len + = p_obj.loadInt(Offset.fromIntZeroExtend(ARRAY_LEN_OFFSET)); + + obj_size + = (array_first_elem_offset + array_elem_size * array_len + GC_OBJ_ALIGN_MASK)& (~GC_OBJ_ALIGN_MASK); + + } else { + obj_size = gcvt_address.loadInt(Offset.fromIntZeroExtend(GC_ALLOCATED_SIZE_OFFSET_IN_GCVT)); + } + + return p_obj.loadInt(Offset.fromIntZeroExtend(obj_size)); + + } else if(hashcodeFlag == HASHCODE_UNSET) { + obj_info = p_obj.prepareInt(Offset.fromIntZeroExtend(OBJ_INFO_OFFSET)); + int new_obj_info = obj_info | HASHCODE_SET_UNALLOCATED; + while(! p_obj.attempt(obj_info, new_obj_info, Offset.fromIntZeroExtend(OBJ_INFO_OFFSET))){ + obj_info = p_obj.prepareInt(Offset.fromIntZeroExtend(OBJ_INFO_OFFSET)); + if((obj_info & HASHCODE_SET_UNALLOCATED) != 0 ) break; + new_obj_info = obj_info | HASHCODE_SET_UNALLOCATED; + } + return (p_obj.toInt())>>2; + + } else { + return VMHelper.getHashcode(p_obj); + } + } + + private static native boolean isPrefetchEnabled(); private static native int getLargeObjectSize(); private static native int getTlaFreeOffset(); @@ -272,6 +337,13 @@ private static native boolean getGenMode(); private static native long getNosBoundary(); private static native int TLSGCOffset(); + + + private static native long getVTBase(); + private static native int getArrayElemSizeOffsetInGCVT(); + private static native int getArrayFirstElemOffsetInGCVT(); + private static native int getGCAllocatedSizeOffsetInGCVT(); + } Index: vm/include/open/rt_helpers.h =================================================================== --- vm/include/open/rt_helpers.h (revision 699565) +++ vm/include/open/rt_helpers.h (working copy) @@ -512,7 +512,7 @@ // Non-VM specific helpers for the JIT ///// - + VM_RT_GET_IDENTITY_HASHCODE, /** * @param The parameters are the following: * arg\ Object reference for the source array. Must be non-null and refer to an array Index: vm/vmcore/src/jit/rt_helper_info.cpp =================================================================== --- vm/vmcore/src/jit/rt_helper_info.cpp (revision 699565) +++ vm/vmcore/src/jit/rt_helper_info.cpp (working copy) @@ -72,6 +72,11 @@ INTERRUPTIBLE_ALWAYS, CALLING_CONVENTION_STDCALL, 1, NULL, NULL, NULL, NULL}, + {VM_RT_GET_IDENTITY_HASHCODE, "VM_RT_GET_IDENTITY_HASHCODE", + INTERRUPTIBLE_ALWAYS, CALLING_CONVENTION_STDCALL, 1, + NULL, NULL, "(Ljava/lang/Object;)I", NULL}, + + {VM_RT_MONITOR_ENTER, "VM_RT_MONITOR_ENTER", INTERRUPTIBLE_SOMETIMES, CALLING_CONVENTION_STDCALL, 1, "org/apache/harmony/drlvm/thread/ThreadHelper", "monitorEnterUseReservation", Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java (revision 699565) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/System.java (working copy) @@ -34,6 +34,8 @@ import org.apache.harmony.lang.RuntimePermissionCollection; import org.apache.harmony.vm.VMStack; import org.apache.harmony.luni.platform.Environment; +//import org.apache.harmony.drlvm.VMHelper; +//import org.apache.harmony.drlvm.gc_gen.GCHelper; /** * @com.intel.drl.spec_ref @@ -188,6 +190,11 @@ * @com.intel.drl.spec_ref */ public static int identityHashCode(Object object) { +// if (VMHelper.isVMMagicPackageSupported()) { +// return GCHelper.get_hashcode(object); +// } else { +// return VMMemoryManager.getIdentityHashCode(object); +// } return VMMemoryManager.getIdentityHashCode(object); } Index: vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/drlvm/VMHelper.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/drlvm/VMHelper.java (revision 699565) +++ vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/drlvm/VMHelper.java (working copy) @@ -80,6 +80,8 @@ public static void writeBarrier(Address objBase, Address objSlot, Address source) {fail();} + public static int getHashcode(Address p_obj){fail(); return 0;} + public static Address getInterfaceVTable(Object obj, Address intfTypePtr) {fail(); return null;} public static void checkCast(Object obj, Address castTypePtr) {fail();} Index: vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp =================================================================== --- vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (revision 699565) +++ vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (working copy) @@ -378,6 +378,32 @@ } //generate_object_allocation_stub_with_thread_pointer +static void *getaddress__vm_gethashcode_java_object_resolved_using_gethashcode_naked() +{ + const int stub_size = 52; + char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); +#ifdef _DEBUG + memset(stub, 0xcc /*int 3*/, stub_size); +#endif + char *ss = stub; + + ss = push(ss, M_Base_Opnd(esp_reg, 4)); + ss = call(ss, (char *)gc_get_hashcode0); + ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); + ss = ret(ss, Imm_Opnd(4)); + assert((ss - stub) <= stub_size); + + compile_add_dynamic_generated_code_chunk("gethashcode_java_object_resolved_using_gethashcode_naked", false, stub, stub_size); + + if (jvmti_should_report_event(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) { + jvmti_send_dynamic_code_generated_event("gethashcode_java_object_resolved_using_gethashcode_naked", stub, stub_size); + } + + DUMP_STUB(stub, "getaddress__vm_gethashcode_java_object_resolved_using_gethashcode_naked", ss - stub); + + return (void *)stub; +} //generate_object_allocation_stub_with_thread_pointer + static void *getaddress__vm_alloc_java_object_resolved_using_vtable_and_size_naked() { static void *addr = 0; @@ -1057,6 +1083,10 @@ 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(); + default: LDIE(50, "Unexpected helper id {0}" << f); return 0; Index: vm/jitrino/config/ia32/server.emconf =================================================================== --- vm/jitrino/config/ia32/server.emconf (revision 699565) +++ vm/jitrino/config/ia32/server.emconf (working copy) @@ -128,6 +128,10 @@ -XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_GET_INTERFACE_VTABLE_VER0=on -XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_GET_INTERFACE_VTABLE_VER0_hotnessPercent=1 +-XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_GET_IDENTITY_HASHCODE=on +-XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_GET_IDENTITY_HASHCODE_hotnessPercent=1 +-XX:jit.arg.getIdentityHashCode=true + -XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_CHECKCAST=on -XX:jit.SD2_OPT.arg.optimizer.inline_helpers.VM_RT_CHECKCAST_hotnessPercent=1 Index: vm/jitrino/src/codegenerator/ia32/Ia32GCMap.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32GCMap.cpp (revision 699565) +++ vm/jitrino/src/codegenerator/ia32/Ia32GCMap.cpp (working copy) @@ -134,7 +134,8 @@ Log::out()<<"GCMap::checkManaged2UnmanagedConv failure, managedOpnd="<getFirstId()<getIRManager(); + InstFactory& instFactory = builder->getInstFactory(); + ControlFlowGraph& cfg = builder->getControlFlowGraph(); + + // the fist two are tau operands + Opnd* dst = callInst->getDst(); + Opnd* obj = callInst->getSrc(2); + + Opnd * opnds[] = { obj }; + + Node* firstNode = callInst->getNode(); + builder->setCurrentBCOffset(callInst->getBCOffset()); + builder->setCurrentNode(firstNode); + +// builder->appendInst(instFactory.makeVMHelperCall(dst, VM_RT_GET_IDENTITY_HASHCODE, 1, opnds)); + builder->appendInst(instFactory.makeIdentHC(dst, obj)); + callInst->unlink(); + +} + Node* HLOAPIMagicIRBuilder::genNodeAfter(Node* srcNode, LabelInst* label, Node* dispatch) { currentNode = cfg.createBlockNode(label); Index: vm/jitrino/src/optimizer/Opcode.cpp =================================================================== --- vm/jitrino/src/optimizer/Opcode.cpp (revision 699565) +++ vm/jitrino/src/optimizer/Opcode.cpp (working copy) @@ -215,6 +215,7 @@ { Op_TauHasType, false, MB::Movable, MK::None, "tauhastype ", "tauhastype %0,%d -) %l", }, // temporary declaration that source is of given type { Op_TauHasExactType, false, MB::CSEable, MK::None, "tauexacttype ", "tauexacttype %0,%d -) %l", }, // temporary declaration that source is exactly of given type { Op_TauIsNonNull, true, MB::CSEable, MK::None, "tauisnonnull ", "tauisnonnull %0 -) %l", }, // temporary declaration that source null + { Op_IdentHC, true, MB::Call, MK::None, "identityHC", "identityHC %s -) %l ", }, }; unsigned short Modifier::encode(Opcode opcode, U_32 numbits) const Index: vm/jitrino/src/optimizer/codelowerer.h =================================================================== --- vm/jitrino/src/optimizer/codelowerer.h (revision 699565) +++ vm/jitrino/src/optimizer/codelowerer.h (working copy) @@ -322,6 +322,8 @@ Inst* caseTauIsNonNull(Inst* inst) {return caseDefault(inst);} + Inst* caseIdentHC(Inst* inst) { return caseDefault(inst); } + IRManager& _irm; bool _preserveSsa; }; Index: vm/jitrino/src/optimizer/HLOAPIMagics.h =================================================================== --- vm/jitrino/src/optimizer/HLOAPIMagics.h (revision 699565) +++ vm/jitrino/src/optimizer/HLOAPIMagics.h (working copy) @@ -128,6 +128,7 @@ DECLARE_HLO_MAGIC_INLINER(String_compareTo_HLO_Handler); DECLARE_HLO_MAGIC_INLINER(String_regionMatches_HLO_Handler); DECLARE_HLO_MAGIC_INLINER(String_indexOf_HLO_Handler); +DECLARE_HLO_MAGIC_INLINER(System_identityHashCode_Handler); DEFINE_SESSION_ACTION(HLOAPIMagicSession, hlo_api_magic, "APIMagics HLO Pass") @@ -159,6 +160,11 @@ if(getBoolArg("System_arraycopy_as_magic", true) && arraycopyOptimizable(callInst, irm.getCompilationInterface().needWriteBarriers())) handlers.push_back(new (mm) System_arraycopy_HLO_Handler(callInst)); } + if (!strcmp(methodName, "identityHashCode")) { + if (getBoolArg("getIdentityHashCode", false)) { + handlers.push_back(new (mm) System_identityHashCode_Handler(callInst)); + } + } } if (!strcmp(className, "java/lang/String")) { if (!strcmp(methodName, "compareTo") && !strcmp(signature, "(Ljava/lang/String;)I")) { Index: vm/jitrino/src/optimizer/Inst.h =================================================================== --- vm/jitrino/src/optimizer/Inst.h (revision 699565) +++ vm/jitrino/src/optimizer/Inst.h (working copy) @@ -1097,6 +1097,7 @@ Inst* makeVMHelperCall(Opnd* dst, VM_RT_SUPPORT id, U_32 numArgs, Opnd** args); + Inst* makeIdentHC(Opnd* dst, Opnd* src); Inst* makeReturn(Opnd* src); Inst* makeReturn(); // void return type @@ -1908,6 +1909,9 @@ caseTauIsNonNull(Inst* inst)=0;// {return caseDefault(inst);} virtual Inst* + caseIdentHC(Inst* inst)=0;// {return caseDefault(inst);} + + virtual Inst* caseDefault(Inst* inst)=0;// {return NULL;} protected: Index: vm/jitrino/src/optimizer/Inst.cpp =================================================================== --- vm/jitrino/src/optimizer/Inst.cpp (revision 699565) +++ vm/jitrino/src/optimizer/Inst.cpp (working copy) @@ -1918,6 +1918,10 @@ return makeInst(Op_Prefetch, Modifier(), Type::Void, OpndManager::getNullOpnd(), addr); } +Inst* InstFactory::makeIdentHC(Opnd* dst, Opnd* src) { + return makeInst(Op_IdentHC, Modifier(), dst->getType()->tag, dst, src); +} + Inst* InstFactory::makeDirectCall(Opnd* dst, Opnd* tauNullChecked, @@ -2722,6 +2726,7 @@ case Op_TauHasType: return caseTauHasType(inst->asTypeInst()); case Op_TauHasExactType: return caseTauHasExactType(inst->asTypeInst()); case Op_TauIsNonNull: return caseTauIsNonNull(inst); + case Op_IdentHC: return caseIdentHC(inst); default: ::std::cerr << "Unknown opcode! " << inst->getOpcode() << " : " Index: vm/jitrino/src/optimizer/hashvaluenumberer.cpp =================================================================== --- vm/jitrino/src/optimizer/hashvaluenumberer.cpp (revision 699565) +++ vm/jitrino/src/optimizer/hashvaluenumberer.cpp (working copy) @@ -949,7 +949,11 @@ return found; return hashInst(inst); } - + + Inst* caseIdentHC(Inst* inst) { + return inst; + } + // default Inst* caseDefault(Inst* inst) { return inst; } private: Index: vm/jitrino/src/optimizer/simplifier.h =================================================================== --- vm/jitrino/src/optimizer/simplifier.h (revision 699565) +++ vm/jitrino/src/optimizer/simplifier.h (working copy) @@ -935,6 +935,10 @@ return opnd->getInst(); return inst; } + + Inst* caseIdentHC(Inst* inst) { + return caseDefault(inst); + } // default Inst* caseDefault(Inst* inst) { Index: vm/jitrino/src/optimizer/Opcode.h =================================================================== --- vm/jitrino/src/optimizer/Opcode.h (revision 699565) +++ vm/jitrino/src/optimizer/Opcode.h (working copy) @@ -453,7 +453,9 @@ Op_TauIsNonNull, // prefixes: unaligned, volatile, tail, - NumOpcodes, + Op_IdentHC, + + NumOpcodes, }; class Modifier { Index: vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 699565) +++ vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -3134,6 +3134,13 @@ return true; } + if (!strcmp(mname,"getHashcode")) { + assert(numArgs == 1); + Opnd* res = irBuilder.genVMHelperCall(VM_RT_GET_IDENTITY_HASHCODE, resType, numArgs, srcOpnds); + pushOpnd(res); + return true; + } + return false; } Index: make/vm/kernel.xml =================================================================== --- make/vm/kernel.xml (revision 699565) +++ make/vm/kernel.xml (working copy) @@ -59,6 +59,7 @@ +