Mercurial > hg > graal-compiler
diff src/cpu/x86/vm/assembler_x86.cpp @ 710:e5b0439ef4ae
6655638: dynamic languages need method handles
Summary: initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.)
Reviewed-by: kvn, twisti, never
author | jrose |
---|---|
date | Wed, 08 Apr 2009 10:56:49 -0700 |
parents | fbde8ec322d0 |
children | 93c14e5562c4 |
line wrap: on
line diff
--- a/src/cpu/x86/vm/assembler_x86.cpp Wed Apr 08 00:12:59 2009 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Wed Apr 08 10:56:49 2009 -0700 @@ -7609,6 +7609,83 @@ } +// registers on entry: +// - rax ('check' register): required MethodType +// - rcx: method handle +// - rdx, rsi, or ?: killable temp +void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, + Register temp_reg, + Label& wrong_method_type) { + if (UseCompressedOops) unimplemented(); // field accesses must decode + // compare method type against that of the receiver + cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); + jcc(Assembler::notEqual, wrong_method_type); +} + + +// A method handle has a "vmslots" field which gives the size of its +// argument list in JVM stack slots. This field is either located directly +// in every method handle, or else is indirectly accessed through the +// method handle's MethodType. This macro hides the distinction. +void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, + Register temp_reg) { + if (UseCompressedOops) unimplemented(); // field accesses must decode + // load mh.type.form.vmslots + if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { + // hoist vmslots into every mh to avoid dependent load chain + movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); + } else { + Register temp2_reg = vmslots_reg; + movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); + movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); + movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); + } +} + + +// registers on entry: +// - rcx: method handle +// - rdx: killable temp (interpreted only) +// - rax: killable temp (compiled only) +void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { + assert(mh_reg == rcx, "caller must put MH object in rcx"); + assert_different_registers(mh_reg, temp_reg); + + if (UseCompressedOops) unimplemented(); // field accesses must decode + + // pick out the interpreted side of the handler + movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); + + // off we go... + jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); + + // for the various stubs which take control at this point, + // see MethodHandles::generate_method_handle_stub +} + + +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, + int extra_slot_offset) { + // cf. TemplateTable::prepare_invoke(), if (load_receiver). + int stackElementSize = Interpreter::stackElementSize(); + int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); +#ifdef ASSERT + int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); + assert(offset1 - offset == stackElementSize, "correct arithmetic"); +#endif + Register scale_reg = noreg; + Address::ScaleFactor scale_factor = Address::no_scale; + if (arg_slot.is_constant()) { + offset += arg_slot.as_constant() * stackElementSize; + } else { + scale_reg = arg_slot.as_register(); + scale_factor = Address::times(stackElementSize); + } + offset += wordSize; // return PC is on stack + return Address(rsp, scale_reg, scale_factor, offset); +} + + void MacroAssembler::verify_oop_addr(Address addr, const char* s) { if (!VerifyOops) return;