32 |
32 |
33 #ifndef PRODUCT |
33 #ifndef PRODUCT |
34 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); |
34 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); |
35 #endif |
35 #endif |
36 |
36 |
37 // used by compiler only; may use only caller saved registers rax, rbx, rcx. |
37 // These stubs are used by the compiler only. |
38 // rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved. |
38 // Argument registers, which must be preserved: |
39 // Leave receiver in rcx; required behavior when +OptoArgsInRegisters |
39 // rcx - receiver (always first argument) |
40 // is modifed to put first oop in rcx. |
40 // rdx - second argument (if any) |
|
41 // Other registers that might be usable: |
|
42 // rax - inline cache register (is interface for itable stub) |
|
43 // rbx - method (used when calling out to interpreter) |
|
44 // Available now, but may become callee-save at some point: |
|
45 // rsi, rdi |
|
46 // Note that rax and rdx are also used for return values. |
41 // |
47 // |
42 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { |
48 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { |
43 const int i486_code_length = VtableStub::pd_code_size_limit(true); |
49 const int i486_code_length = VtableStub::pd_code_size_limit(true); |
44 VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index); |
50 VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index); |
45 ResourceMark rm; |
51 ResourceMark rm; |
92 // rcx: receiver |
98 // rcx: receiver |
93 address ame_addr = __ pc(); |
99 address ame_addr = __ pc(); |
94 __ jmp( Address(method, methodOopDesc::from_compiled_offset())); |
100 __ jmp( Address(method, methodOopDesc::from_compiled_offset())); |
95 |
101 |
96 masm->flush(); |
102 masm->flush(); |
|
103 |
|
104 if (PrintMiscellaneous && (WizardMode || Verbose)) { |
|
105 tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", |
|
106 vtable_index, s->entry_point(), |
|
107 (int)(s->code_end() - s->entry_point()), |
|
108 (int)(s->code_end() - __ pc())); |
|
109 } |
|
110 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); |
|
111 |
97 s->set_exception_points(npe_addr, ame_addr); |
112 s->set_exception_points(npe_addr, ame_addr); |
98 return s; |
113 return s; |
99 } |
114 } |
100 |
115 |
101 |
116 |
102 VtableStub* VtableStubs::create_itable_stub(int vtable_index) { |
117 VtableStub* VtableStubs::create_itable_stub(int itable_index) { |
103 // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you |
118 // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you |
104 // add code here, bump the code stub size returned by pd_code_size_limit! |
119 // add code here, bump the code stub size returned by pd_code_size_limit! |
105 const int i486_code_length = VtableStub::pd_code_size_limit(false); |
120 const int i486_code_length = VtableStub::pd_code_size_limit(false); |
106 VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index); |
121 VtableStub* s = new(i486_code_length) VtableStub(false, itable_index); |
107 ResourceMark rm; |
122 ResourceMark rm; |
108 CodeBuffer cb(s->entry_point(), i486_code_length); |
123 CodeBuffer cb(s->entry_point(), i486_code_length); |
109 MacroAssembler* masm = new MacroAssembler(&cb); |
124 MacroAssembler* masm = new MacroAssembler(&cb); |
110 |
125 |
111 // Entry arguments: |
126 // Entry arguments: |
121 |
136 |
122 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
137 assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); |
123 |
138 |
124 // get receiver klass (also an implicit null-check) |
139 // get receiver klass (also an implicit null-check) |
125 address npe_addr = __ pc(); |
140 address npe_addr = __ pc(); |
126 __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes())); |
141 __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); |
127 |
142 |
128 __ mov(rsi, rbx); // Save klass in free register |
143 // Most registers are in use; we'll use rax, rbx, rsi, rdi |
129 // Most registers are in use, so save a few |
144 // (If we need to make rsi, rdi callee-save, do a push/pop here.) |
130 __ push(rdx); |
145 const Register method = rbx; |
131 // compute itable entry offset (in words) |
146 Label throw_icce; |
132 const int base = instanceKlass::vtable_start_offset() * wordSize; |
|
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 |
|
135 __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base)); |
|
136 if (HeapWordsPerLong > 1) { |
|
137 // Round up to align_object_offset boundary |
|
138 __ round_to(rbx, BytesPerLong); |
|
139 } |
|
140 |
|
141 Label hit, next, entry, throw_icce; |
|
142 |
|
143 __ jmpb(entry); |
|
144 |
|
145 __ bind(next); |
|
146 __ addptr(rbx, itableOffsetEntry::size() * wordSize); |
|
147 |
|
148 __ bind(entry); |
|
149 |
|
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 |
|
152 __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); |
|
153 __ testptr(rdx, rdx); |
|
154 __ jcc(Assembler::zero, throw_icce); |
|
155 __ cmpptr(rax, rdx); |
|
156 __ jcc(Assembler::notEqual, next); |
|
157 |
|
158 // We found a hit, move offset into rbx, |
|
159 __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); |
|
160 |
|
161 // Compute itableMethodEntry. |
|
162 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); |
|
163 |
147 |
164 // Get methodOop and entrypoint for compiler |
148 // Get methodOop and entrypoint for compiler |
165 const Register method = rbx; |
149 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
166 __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset)); |
150 rsi, rax, itable_index, |
167 |
151 // outputs: method, scan temp. reg |
168 // Restore saved register, before possible trap. |
152 method, rdi, |
169 __ pop(rdx); |
153 throw_icce); |
170 |
154 |
171 // method (rbx): methodOop |
155 // method (rbx): methodOop |
172 // rcx: receiver |
156 // rcx: receiver |
173 |
157 |
174 #ifdef ASSERT |
158 #ifdef ASSERT |
185 |
169 |
186 address ame_addr = __ pc(); |
170 address ame_addr = __ pc(); |
187 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); |
171 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); |
188 |
172 |
189 __ bind(throw_icce); |
173 __ bind(throw_icce); |
190 // Restore saved register |
|
191 __ pop(rdx); |
|
192 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); |
174 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); |
193 |
|
194 masm->flush(); |
175 masm->flush(); |
195 |
176 |
|
177 if (PrintMiscellaneous && (WizardMode || Verbose)) { |
|
178 tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", |
|
179 itable_index, s->entry_point(), |
|
180 (int)(s->code_end() - s->entry_point()), |
|
181 (int)(s->code_end() - __ pc())); |
|
182 } |
196 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); |
183 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); |
197 |
184 |
198 s->set_exception_points(npe_addr, ame_addr); |
185 s->set_exception_points(npe_addr, ame_addr); |
199 return s; |
186 return s; |
200 } |
187 } |