src/cpu/x86/vm/assembler_x86.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
hotspot-dvm Cdiff src/cpu/x86/vm/assembler_x86.cpp
src/cpu/x86/vm/assembler_x86.cpp
Print this page
rev 522 : [mq]: meth.patch
*** 6242,6251 ****
--- 6242,6273 ----
movw(dst, src);
}
return off;
}
+ void MacroAssembler::load_sized_value(Register dst, Address src,
+ int size_in_bytes, bool is_signed) {
+ switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
+ #ifndef _LP64
+ // For case 8, caller is responsible for manually loading
+ // the high word into another register.
+ case ~8: // fall through:
+ case 8: movl( dst, src ); break;
+ #else
+ case ~8: // fall through:
+ case 8: movq( dst, src ); break;
+ #endif
+ case ~4: // fall through:
+ case 4: movl( dst, src ); break;
+ case ~2: load_signed_word( dst, src ); break;
+ case 2: load_unsigned_word( dst, src ); break;
+ case ~1: load_signed_byte( dst, src ); break;
+ case 1: load_unsigned_byte( dst, src ); break;
+ default: ShouldNotReachHere();
+ }
+ }
+
void MacroAssembler::mov32(AddressLiteral dst, Register src) {
if (reachable(dst)) {
movl(as_Address(dst), src);
} else {
lea(rscratch1, dst);
*** 7092,7101 ****
--- 7114,7358 ----
movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address()));
call(rax);
}
+ RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, Register tmp) {
+ intptr_t value = *delayed_value_addr;
+ if (value != 0)
+ return value;
+ movptr(tmp, ExternalAddress((address) delayed_value_addr));
+ #ifdef ASSERT
+ Label L;
+ testl(tmp, tmp);
+ jccb(Assembler::notZero, L);
+ hlt();
+ bind(L);
+ #endif
+ return tmp;
+ }
+
+
+ void MacroAssembler::lookup_interface_method(Register recv_klass,
+ Register intf_klass,
+ RegisterConstant itable_index,
+ Register method_result,
+ Register scan_temp,
+ Label& L_no_such_interface) {
+ assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
+ assert(itable_index.is_constant() || itable_index.as_register() == method_result,
+ "caller must use same register for non-constant itable index as for method");
+
+ // Compute start of first itableOffsetEntry (which is at the end of the vtable)
+ int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
+ int scan_step = itableOffsetEntry::size() * wordSize;
+ int vte_size = vtableEntry::size() * wordSize;
+ Address::ScaleFactor times_vte_scale = Address::times_ptr;
+ assert(vte_size == wordSize, "else adjust times_vte_scale");
+
+ movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
+ lea( scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
+ if (HeapWordsPerLong > 1) {
+ // Round up to align_object_offset boundary
+ round_to(scan_temp, BytesPerLong);
+ }
+
+ // Adjust recv_klass by scaled itable_index, so we can free itable_index.
+ assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
+ lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr));
+
+ // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
+ // if (scan->interface() == intf) {
+ // result = (klass + scan->offset() + itable_index);
+ // }
+ // }
+ Label search, found_method;
+
+ for (int peel = 1; peel >= 0; peel--) {
+ movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
+ cmpptr(intf_klass, method_result);
+ jccb(Assembler::notEqual, search);
+
+ // Got a hit.
+ movl(method_result, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
+ movptr(method_result, Address(recv_klass, method_result, Address::times_1));
+
+ if (!peel) break;
+ jmp(found_method);
+
+ bind(search);
+ // Check that the previous entry is non-null. A null entry means that
+ // the reciever class doesn't implement the interface, and wasn't the
+ // same as when the caller was compiled.
+ testptr(method_result, method_result);
+ jcc(Assembler::zero, L_no_such_interface);
+ addptr(scan_temp, scan_step);
+ }
+
+ bind(found_method);
+ }
+
+
+ // Test sub_klass against super_klass.
+ // Fall through on failure, but branch to L_success if there is a match.
+ // Use up the given temp_reg, but don't kill any other register.
+ // Update the sub's secondary super cache if necesary.
+ void MacroAssembler::check_klass_subtype(Register sub_klass,
+ Register super_klass,
+ Register temp_reg,
+ Label& L_success) {
+ Label L_failure; // fallthrough label
+
+ assert_different_registers(sub_klass, super_klass, temp_reg);
+
+ // a couple of useful fields in sub_klass:
+ int ss_offset = (klassOopDesc::header_size() * HeapWordSize +
+ Klass::secondary_supers_offset_in_bytes());
+ int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
+ Klass::secondary_super_cache_offset_in_bytes());
+ Address secondary_supers_addr(sub_klass, ss_offset);
+ Address super_cache_addr( sub_klass, sc_offset);
+
+ int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
+ Klass::super_check_offset_offset_in_bytes());
+ Address super_check_offset_addr(super_klass, sco_offset);
+
+ // if the pointers are equal, we are done (e.g., String[] elements)
+ cmpptr(sub_klass, super_klass);
+ jcc(Assembler::equal, L_success);
+
+ // check the supertype display:
+ movl(temp_reg, super_check_offset_addr);
+ Address super_check_addr(sub_klass, temp_reg, Address::times_1, 0);
+ cmpptr(super_klass, super_check_addr); // load displayed supertype
+ jcc(Assembler::equal, L_success);
+
+ // if it was a primary super, we can just fail immediately
+ cmpl(temp_reg, sc_offset);
+ jcc(Assembler::notEqual, L_failure);
+
+ // Now do a linear scan of the secondary super-klass chain.
+ // This code is rarely used, so simplicity is a virtue here.
+ {
+ // The repne_scan instruction uses fixed registers, which we must spill.
+ // Don't bother to figure out pre-existing connections with the input regs.
+ push(rax);
+ push(rcx);
+ push(rdi);
+ push(super_klass);
+
+ movptr(rdi, secondary_supers_addr);
+ // Load the array length.
+ movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
+ // Skip to start of data.
+ addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
+ // Scan rcx words at [edi] for occurance of rax,
+ // Set NZ/Z based on last compare
+ pop(rax); // super_klass value, even if it was in rdi or rcx
+
+
+ #ifdef _LP64
+ // This part is tricky, as values in supers array could be 32 or 64 bit wide
+ // and we store values in objArrays always encoded, thus we need to encode
+ // the value of rax before repne. Note that rax is dead after the repne.
+ if (UseCompressedOops) {
+ encode_heap_oop_not_null(rax);
+ repne_scanl();
+ } else
+ #endif // _LP64
+ repne_scan();
+
+ // Unspill the temp. registers:
+ pop(rdi);
+ pop(rcx);
+ pop(rax);
+ }
+ jcc(Assembler::notEqual, L_failure);
+
+ // Success. Cache the super we found and proceed in triumph.
+ movptr(super_cache_addr, super_klass);
+
+ jmp(L_success);
+
+ // Fall through on failure!
+ bind(L_failure);
+ }
+
+
+ // 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);
+ }
+
+
+ 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, MethodEntry::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(RegisterConstant 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;
// Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord);
// Pass register number to verify_oop_subroutine
src/cpu/x86/vm/assembler_x86.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File