47 MacroAssembler* masm = new MacroAssembler(&cb); |
47 MacroAssembler* masm = new MacroAssembler(&cb); |
48 |
48 |
49 #ifndef PRODUCT |
49 #ifndef PRODUCT |
50 |
50 |
51 if (CountCompiledCalls) { |
51 if (CountCompiledCalls) { |
52 __ increment(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
52 __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
53 } |
53 } |
54 #endif /* PRODUCT */ |
54 #endif /* PRODUCT */ |
55 |
55 |
56 // get receiver (need to skip return address on top of stack) |
56 // get receiver (need to skip return address on top of stack) |
57 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
57 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
58 |
58 |
59 // get receiver klass |
59 // get receiver klass |
60 address npe_addr = __ pc(); |
60 address npe_addr = __ pc(); |
61 __ movl(rax, Address(rcx, oopDesc::klass_offset_in_bytes())); |
61 __ movptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes())); |
62 // compute entry offset (in words) |
62 // compute entry offset (in words) |
63 int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); |
63 int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); |
64 #ifndef PRODUCT |
64 #ifndef PRODUCT |
65 if (DebugVtables) { |
65 if (DebugVtables) { |
66 Label L; |
66 Label L; |
74 #endif // PRODUCT |
74 #endif // PRODUCT |
75 |
75 |
76 const Register method = rbx; |
76 const Register method = rbx; |
77 |
77 |
78 // load methodOop and target address |
78 // load methodOop and target address |
79 __ movl(method, Address(rax, entry_offset*wordSize + vtableEntry::method_offset_in_bytes())); |
79 __ movptr(method, Address(rax, entry_offset*wordSize + vtableEntry::method_offset_in_bytes())); |
80 if (DebugVtables) { |
80 if (DebugVtables) { |
81 Label L; |
81 Label L; |
82 __ cmpl(method, NULL_WORD); |
82 __ cmpptr(method, (int32_t)NULL_WORD); |
83 __ jcc(Assembler::equal, L); |
83 __ jcc(Assembler::equal, L); |
84 __ cmpl(Address(method, methodOopDesc::from_compiled_offset()), NULL_WORD); |
84 __ cmpptr(Address(method, methodOopDesc::from_compiled_offset()), (int32_t)NULL_WORD); |
85 __ jcc(Assembler::notZero, L); |
85 __ jcc(Assembler::notZero, L); |
86 __ stop("Vtable entry is NULL"); |
86 __ stop("Vtable entry is NULL"); |
87 __ bind(L); |
87 __ bind(L); |
88 } |
88 } |
89 |
89 |
112 // rax,: Interface |
112 // rax,: Interface |
113 // rcx: Receiver |
113 // rcx: Receiver |
114 |
114 |
115 #ifndef PRODUCT |
115 #ifndef PRODUCT |
116 if (CountCompiledCalls) { |
116 if (CountCompiledCalls) { |
117 __ increment(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
117 __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); |
118 } |
118 } |
119 #endif /* PRODUCT */ |
119 #endif /* PRODUCT */ |
120 // get receiver (need to skip return address on top of stack) |
120 // get receiver (need to skip return address on top of stack) |
121 |
121 |
122 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
122 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
123 |
123 |
124 // get receiver klass (also an implicit null-check) |
124 // get receiver klass (also an implicit null-check) |
125 address npe_addr = __ pc(); |
125 address npe_addr = __ pc(); |
126 __ movl(rbx, Address(rcx, oopDesc::klass_offset_in_bytes())); |
126 __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes())); |
127 |
127 |
128 __ movl(rsi, rbx); // Save klass in free register |
128 __ mov(rsi, rbx); // Save klass in free register |
129 // Most registers are in use, so save a few |
129 // Most registers are in use, so save a few |
130 __ pushl(rdx); |
130 __ push(rdx); |
131 // compute itable entry offset (in words) |
131 // compute itable entry offset (in words) |
132 const int base = instanceKlass::vtable_start_offset() * wordSize; |
132 const int base = instanceKlass::vtable_start_offset() * wordSize; |
133 assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below"); |
133 assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below"); |
134 __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable |
134 __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable |
135 __ leal(rbx, Address(rbx, rdx, Address::times_4, base)); |
135 __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base)); |
136 if (HeapWordsPerLong > 1) { |
136 if (HeapWordsPerLong > 1) { |
137 // Round up to align_object_offset boundary |
137 // Round up to align_object_offset boundary |
138 __ round_to(rbx, BytesPerLong); |
138 __ round_to(rbx, BytesPerLong); |
139 } |
139 } |
140 |
140 |
141 Label hit, next, entry, throw_icce; |
141 Label hit, next, entry, throw_icce; |
142 |
142 |
143 __ jmpb(entry); |
143 __ jmpb(entry); |
144 |
144 |
145 __ bind(next); |
145 __ bind(next); |
146 __ addl(rbx, itableOffsetEntry::size() * wordSize); |
146 __ addptr(rbx, itableOffsetEntry::size() * wordSize); |
147 |
147 |
148 __ bind(entry); |
148 __ bind(entry); |
149 |
149 |
150 // If the entry is NULL then we've reached the end of the table |
150 // If the entry is NULL then we've reached the end of the table |
151 // without finding the expected interface, so throw an exception |
151 // without finding the expected interface, so throw an exception |
152 __ movl(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); |
152 __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); |
153 __ testl(rdx, rdx); |
153 __ testptr(rdx, rdx); |
154 __ jcc(Assembler::zero, throw_icce); |
154 __ jcc(Assembler::zero, throw_icce); |
155 __ cmpl(rax, rdx); |
155 __ cmpptr(rax, rdx); |
156 __ jcc(Assembler::notEqual, next); |
156 __ jcc(Assembler::notEqual, next); |
157 |
157 |
158 // We found a hit, move offset into rbx, |
158 // We found a hit, move offset into rbx, |
159 __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); |
159 __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); |
160 |
160 |
161 // Compute itableMethodEntry. |
161 // Compute itableMethodEntry. |
162 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); |
162 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); |
163 |
163 |
164 // Get methodOop and entrypoint for compiler |
164 // Get methodOop and entrypoint for compiler |
165 const Register method = rbx; |
165 const Register method = rbx; |
166 __ movl(method, Address(rsi, rdx, Address::times_1, method_offset)); |
166 __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset)); |
167 |
167 |
168 // Restore saved register, before possible trap. |
168 // Restore saved register, before possible trap. |
169 __ popl(rdx); |
169 __ pop(rdx); |
170 |
170 |
171 // method (rbx): methodOop |
171 // method (rbx): methodOop |
172 // rcx: receiver |
172 // rcx: receiver |
173 |
173 |
174 #ifdef ASSERT |
174 #ifdef ASSERT |
175 if (DebugVtables) { |
175 if (DebugVtables) { |
176 Label L1; |
176 Label L1; |
177 __ cmpl(method, NULL_WORD); |
177 __ cmpptr(method, (int32_t)NULL_WORD); |
178 __ jcc(Assembler::equal, L1); |
178 __ jcc(Assembler::equal, L1); |
179 __ cmpl(Address(method, methodOopDesc::from_compiled_offset()), NULL_WORD); |
179 __ cmpptr(Address(method, methodOopDesc::from_compiled_offset()), (int32_t)NULL_WORD); |
180 __ jcc(Assembler::notZero, L1); |
180 __ jcc(Assembler::notZero, L1); |
181 __ stop("methodOop is null"); |
181 __ stop("methodOop is null"); |
182 __ bind(L1); |
182 __ bind(L1); |
183 } |
183 } |
184 #endif // ASSERT |
184 #endif // ASSERT |