7074 pop(tmp); |
7074 pop(tmp); |
7075 } |
7075 } |
7076 } |
7076 } |
7077 |
7077 |
7078 |
7078 |
|
7079 // Look up the method for a megamorphic invokeinterface call. |
|
7080 // The target method is determined by <intf_klass, itable_index>. |
|
7081 // The receiver klass is in recv_klass. |
|
7082 // On success, the result will be in method_result, and execution falls through. |
|
7083 // On failure, execution transfers to the given label. |
|
7084 void MacroAssembler::lookup_interface_method(Register recv_klass, |
|
7085 Register intf_klass, |
|
7086 RegisterConstant itable_index, |
|
7087 Register method_result, |
|
7088 Register scan_temp, |
|
7089 Label& L_no_such_interface) { |
|
7090 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); |
|
7091 assert(itable_index.is_constant() || itable_index.as_register() == method_result, |
|
7092 "caller must use same register for non-constant itable index as for method"); |
|
7093 |
|
7094 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
|
7095 int vtable_base = instanceKlass::vtable_start_offset() * wordSize; |
|
7096 int itentry_off = itableMethodEntry::method_offset_in_bytes(); |
|
7097 int scan_step = itableOffsetEntry::size() * wordSize; |
|
7098 int vte_size = vtableEntry::size() * wordSize; |
|
7099 Address::ScaleFactor times_vte_scale = Address::times_ptr; |
|
7100 assert(vte_size == wordSize, "else adjust times_vte_scale"); |
|
7101 |
|
7102 movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize)); |
|
7103 |
|
7104 // %%% Could store the aligned, prescaled offset in the klassoop. |
|
7105 lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); |
|
7106 if (HeapWordsPerLong > 1) { |
|
7107 // Round up to align_object_offset boundary |
|
7108 // see code for instanceKlass::start_of_itable! |
|
7109 round_to(scan_temp, BytesPerLong); |
|
7110 } |
|
7111 |
|
7112 // Adjust recv_klass by scaled itable_index, so we can free itable_index. |
|
7113 assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); |
|
7114 lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); |
|
7115 |
|
7116 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
|
7117 // if (scan->interface() == intf) { |
|
7118 // result = (klass + scan->offset() + itable_index); |
|
7119 // } |
|
7120 // } |
|
7121 Label search, found_method; |
|
7122 |
|
7123 for (int peel = 1; peel >= 0; peel--) { |
|
7124 movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); |
|
7125 cmpptr(intf_klass, method_result); |
|
7126 |
|
7127 if (peel) { |
|
7128 jccb(Assembler::equal, found_method); |
|
7129 } else { |
|
7130 jccb(Assembler::notEqual, search); |
|
7131 // (invert the test to fall through to found_method...) |
|
7132 } |
|
7133 |
|
7134 if (!peel) break; |
|
7135 |
|
7136 bind(search); |
|
7137 |
|
7138 // Check that the previous entry is non-null. A null entry means that |
|
7139 // the receiver class doesn't implement the interface, and wasn't the |
|
7140 // same as when the caller was compiled. |
|
7141 testptr(method_result, method_result); |
|
7142 jcc(Assembler::zero, L_no_such_interface); |
|
7143 addptr(scan_temp, scan_step); |
|
7144 } |
|
7145 |
|
7146 bind(found_method); |
|
7147 |
|
7148 // Got a hit. |
|
7149 movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); |
|
7150 movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); |
|
7151 } |
|
7152 |
|
7153 |
7079 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { |
7154 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { |
7080 ucomisd(dst, as_Address(src)); |
7155 ucomisd(dst, as_Address(src)); |
7081 } |
7156 } |
7082 |
7157 |
7083 void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { |
7158 void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { |