Mercurial > hg > truffle
comparison src/cpu/x86/vm/vtableStubs_x86_32.cpp @ 623:9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
Summary: Code in vtableStubs and templateTable moved into MacroAssembler.
Reviewed-by: kvn
author | jrose |
---|---|
date | Fri, 06 Mar 2009 21:36:50 -0800 |
parents | 9ee9cf798b59 |
children | 1d037ecd7960 |
comparison
equal
deleted
inserted
replaced
622:56aae7be60d4 | 623:9adddb8c0fc8 |
---|---|
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 } |
205 if (is_vtable_stub) { | 192 if (is_vtable_stub) { |
206 // Vtable stub size | 193 // Vtable stub size |
207 return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); | 194 return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); |
208 } else { | 195 } else { |
209 // Itable stub size | 196 // Itable stub size |
210 return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0); | 197 return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); |
211 } | 198 } |
212 } | 199 } |
213 | 200 |
214 int VtableStub::pd_code_alignment() { | 201 int VtableStub::pd_code_alignment() { |
215 return wordSize; | 202 return wordSize; |