# HG changeset patch # User Doug Simon # Date 1342445046 -7200 # Node ID a9ce56ad1860e2695396b2499f76d20697a52d14 # Parent f84d11672a869a1c5b7af23ed7ca9077f24c3dd8# Parent 610f9e377c70d2e74a63cb78a7c31accf72b8bbb Merge. diff -r 610f9e377c70 -r a9ce56ad1860 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jul 16 11:07:07 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jul 16 15:24:06 2012 +0200 @@ -181,7 +181,7 @@ public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; static boolean UseTypeCheckHints = true; - public static boolean InlineVTableStubs = ____; + public static boolean InlineVTableStubs = true; public static boolean AlwaysInlineVTableStubs = ____; public static boolean GenAssertionCode = ____; diff -r 610f9e377c70 -r a9ce56ad1860 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 16 11:07:07 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 16 15:24:06 2012 +0200 @@ -246,13 +246,10 @@ GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || invoke.isMegamorphic())) { - // TODO (dnsimon) I'm not sure of other invariants of HotSpot's calling conventions that may - // be required for register indirect calls. - assert false : "HotSpot expects the methodOop of the callee to be in rbx - this is yet to be implemented for inline vtable dispatch"; - - // TODO: successive inlined invokevirtuals to the same method cause register allocation to fail - fix this! HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); if (!hsMethod.holder().isInterface()) { + // We use LocationNode.ANY_LOCATION for the reads that access the vtable entry and the compiled code entry + // as HotSpot does not guarantee they are final values. int vtableEntryOffset = hsMethod.vtableEntryOffset(); assert vtableEntryOffset != 0; SafeReadNode hub = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); @@ -260,7 +257,11 @@ Stamp nonNullWordStamp = StampFactory.forWord(wordKind, true); ReadNode methodOop = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), nonNullWordStamp)); ReadNode compiledEntry = graph.add(new ReadNode(methodOop, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), nonNullWordStamp)); - callTarget.setAddress(compiledEntry); + callTarget.setComputedAddress(compiledEntry); + + // Append the methodOop to the arguments so that it can be explicitly passed in RBX as + // is required for all compiled calls in HotSpot. + callTarget.arguments().add(methodOop); graph.addBeforeFixed(invoke.node(), hub); graph.addAfterFixed(hub, methodOop); diff -r 610f9e377c70 -r a9ce56ad1860 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Mon Jul 16 11:07:07 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Mon Jul 16 15:24:06 2012 +0200 @@ -112,12 +112,33 @@ Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind()); CallingConvention cc = frameMap.registerConfig.getCallingConvention(JavaCall, signature, target(), false); frameMap.callsMethod(cc, JavaCall); + + Value address = Constant.forLong(0L); + + ValueNode methodOopNode = null; + + if (callTarget.computedAddress() != null) { + // If a virtual dispatch address was computed, then an extra argument + // was append for passing the methodOop in RBX + methodOopNode = callTarget.arguments().remove(callTarget.arguments().size() - 1); + + if (invokeKind == Virtual) { + address = operand(callTarget.computedAddress()); + } else { + // An invokevirtual may have been canonicalized into an invokespecial; + // the methodOop argument is ignored in this case + } + } + List argList = visitInvokeArguments(cc, callTarget.arguments()); - Value address = callTarget.address() == null ? Constant.forLong(0L) : operand(callTarget.address()); + if (methodOopNode != null) { + Value methodOopArg = operand(methodOopNode); + emitMove(methodOopArg, AMD64.rbx.asValue()); + argList.add(methodOopArg); + } final Mark[] callsiteForStaticCallStub = {null}; - if (invokeKind == Static || invokeKind == Special) { lir.stubs.add(new AMD64Code() { public String description() { @@ -145,12 +166,12 @@ // that loads the klassOop from the inline cache so that the C++ code can find it // and replace the inline null value with Universe::non_oop_word() assert invokeKind == Virtual || invokeKind == Interface; - if (callTarget.address() == null) { + if (invokeKind == Virtual && callTarget.computedAddress() != null) { + tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL); + } else { tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE); AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT); - } else { - tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL); } } } diff -r 610f9e377c70 -r a9ce56ad1860 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Jul 16 11:07:07 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Jul 16 15:24:06 2012 +0200 @@ -31,15 +31,18 @@ @Input protected final NodeInputList arguments; - @Input protected ValueNode address; + /** + * The address computation for an indirect call (e.g., invokevirtual or invokeinterface). + */ + @Input protected ValueNode computedAddress; - public ValueNode address() { - return address; + public ValueNode computedAddress() { + return computedAddress; } - public void setAddress(ValueNode address) { - updateUsages(this.address, address); - this.address = address; + public void setComputedAddress(ValueNode address) { + updateUsages(this.computedAddress, address); + this.computedAddress = address; } public CallTargetNode(ValueNode[] arguments) { diff -r 610f9e377c70 -r a9ce56ad1860 src/cpu/x86/vm/nativeInst_x86.hpp --- a/src/cpu/x86/vm/nativeInst_x86.hpp Mon Jul 16 11:07:07 2012 +0200 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp Mon Jul 16 15:24:06 2012 +0200 @@ -186,21 +186,17 @@ public: enum Intel_specific_constants { instruction_code = 0xFF, - instruction_size = 2, instruction_offset = 0, - return_address_offset = 2 + return_address_offset_norex = 2, + return_address_offset_rex = 3 }; - address instruction_address() const { return addr_at(instruction_offset); } - address next_instruction_address() const { return addr_at(return_address_offset); } - - - static bool is_call_reg_at(address instr) { - return ((*instr) & 0xFF) == NativeCallReg::instruction_code; - } - - static bool is_call_reg_before(address return_address) { - return is_call_reg_at(return_address - NativeCallReg::return_address_offset); + int next_instruction_offset() const { + if (ubyte_at(0) == NativeCallReg::instruction_code) { + return return_address_offset_norex; + } else { + return return_address_offset_rex; + } } }; @@ -555,7 +551,9 @@ inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; } inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; } -inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code; } +inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code || + (ubyte_at(1) == NativeCallReg::instruction_code && + (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); } inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code || ubyte_at(0) == NativeReturnX::instruction_code; } inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code || diff -r 610f9e377c70 -r a9ce56ad1860 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 16 11:07:07 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 16 15:24:06 2012 +0200 @@ -273,22 +273,22 @@ } // constructor used to create a method -CodeInstaller::CodeInstaller(Handle& target_method, nmethod*& nm, bool install_code) { +CodeInstaller::CodeInstaller(Handle& comp_result, nmethod*& nm, bool install_code) { _env = CURRENT_ENV; GraalCompiler::initialize_buffer_blob(); CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); - jobject target_method_obj = JNIHandles::make_local(target_method()); - initialize_assumptions(JNIHandles::resolve(target_method_obj)); + jobject comp_result_obj = JNIHandles::make_local(comp_result()); + initialize_assumptions(JNIHandles::resolve(comp_result_obj)); { No_Safepoint_Verifier no_safepoint; - initialize_fields(JNIHandles::resolve(target_method_obj)); + initialize_fields(JNIHandles::resolve(comp_result_obj)); initialize_buffer(buffer); process_exception_handlers(); } int stack_slots = _total_frame_size / HeapWordSize; // conversion to words - methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(JNIHandles::resolve(target_method_obj))); + methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(JNIHandles::resolve(comp_result_obj))); nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code); @@ -317,22 +317,23 @@ id = VmIds::addStub(blob->code_begin()); } -void CodeInstaller::initialize_fields(oop target_method) { - _citarget_method = HotSpotCompilationResult::comp(target_method); - _hotspot_method = HotSpotCompilationResult::method(target_method); +void CodeInstaller::initialize_fields(oop comp_result) { + _comp_result = HotSpotCompilationResult::comp(comp_result); + _hotspot_method = HotSpotCompilationResult::method(comp_result); if (_hotspot_method != NULL) { - _parameter_count = getMethodFromHotSpotMethod(_hotspot_method)->size_of_parameters(); + methodOop method = getMethodFromHotSpotMethod(_hotspot_method); + _parameter_count = method->size_of_parameters(); + TRACE_graal_1("installing code for %s", method->name_and_sig_as_C_string()); } - _name = HotSpotCompilationResult::name(target_method); - _sites = (arrayOop) HotSpotCompilationResult::sites(target_method); - _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(target_method); + _name = HotSpotCompilationResult::name(comp_result); + _sites = (arrayOop) HotSpotCompilationResult::sites(comp_result); + _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(comp_result); - _code = (arrayOop) InstalledCode::targetCode(_citarget_method); - _code_size = InstalledCode::targetCodeSize(_citarget_method); + _code = (arrayOop) InstalledCode::targetCode(_comp_result); + _code_size = InstalledCode::targetCodeSize(_comp_result); // The frame size we get from the target method does not include the return address, so add one word for it here. - _total_frame_size = InstalledCode::frameSize(_citarget_method) + HeapWordSize; - _custom_stack_area_offset = InstalledCode::customStackAreaOffset(_citarget_method); - + _total_frame_size = InstalledCode::frameSize(_comp_result) + HeapWordSize; + _custom_stack_area_offset = InstalledCode::customStackAreaOffset(_comp_result); // (very) conservative estimate: each site needs a constant section entry _constants_size = _sites->length() * (BytesPerLong*2); @@ -627,11 +628,12 @@ assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */ } else if (inst->is_call_reg()) { - // the inlined vtable stub contains a "call register" instruction, which isn't recognized here + // the inlined vtable stub contains a "call register" instruction assert(hotspot_method != NULL, "only valid for virtual calls"); is_call_reg = true; - next_pc_offset = pc_offset + NativeCallReg::instruction_size; + next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset(); } else { + tty->print_cr("at pc_offset %d", pc_offset); runtime_call->print(); fatal("unsupported type of instruction for call site"); } diff -r 610f9e377c70 -r a9ce56ad1860 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Mon Jul 16 11:07:07 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Mon Jul 16 15:24:06 2012 +0200 @@ -56,7 +56,7 @@ ciEnv* _env; - oop _citarget_method; + oop _comp_result; oop _hotspot_method; oop _name; arrayOop _sites; diff -r 610f9e377c70 -r a9ce56ad1860 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Jul 16 11:07:07 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jul 16 15:24:06 2012 +0200 @@ -876,15 +876,15 @@ } // public HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean installCode); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject comp, jboolean install_code, jobject info) { +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject compResult, jboolean install_code, jobject info) { VM_ENTRY_MARK; ResourceMark rm; HandleMark hm; - Handle targetMethodHandle = JNIHandles::resolve(comp); + Handle compResultHandle = JNIHandles::resolve(compResult); nmethod* nm = NULL; Arena arena; ciEnv env(&arena); - CodeInstaller installer(targetMethodHandle, nm, install_code != 0); + CodeInstaller installer(compResultHandle, nm, install_code != 0); if (info != NULL) { arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0); @@ -899,7 +899,7 @@ Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL); assert(obj() != NULL, "must succeed in allocating instance"); HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm); - HotSpotCompiledMethod::set_method(obj, HotSpotCompilationResult::method(comp)); + HotSpotCompiledMethod::set_method(obj, HotSpotCompilationResult::method(compResult)); nm->set_graal_compiled_method(obj()); return JNIHandles::make_local(obj()); } else {