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