Mercurial > hg > truffle
comparison src/cpu/x86/vm/vtableStubs_x86_64.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 | dc7f315e41f7 |
children | 1d037ecd7960 |
comparison
equal
deleted
inserted
replaced
622:56aae7be60d4 | 623:9adddb8c0fc8 |
---|---|
96 // rcx: receiver | 96 // rcx: receiver |
97 address ame_addr = __ pc(); | 97 address ame_addr = __ pc(); |
98 __ jmp( Address(rbx, methodOopDesc::from_compiled_offset())); | 98 __ jmp( Address(rbx, methodOopDesc::from_compiled_offset())); |
99 | 99 |
100 __ flush(); | 100 __ flush(); |
101 | |
102 if (PrintMiscellaneous && (WizardMode || Verbose)) { | |
103 tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", | |
104 vtable_index, s->entry_point(), | |
105 (int)(s->code_end() - s->entry_point()), | |
106 (int)(s->code_end() - __ pc())); | |
107 } | |
108 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); | |
109 | |
101 s->set_exception_points(npe_addr, ame_addr); | 110 s->set_exception_points(npe_addr, ame_addr); |
102 return s; | 111 return s; |
103 } | 112 } |
104 | 113 |
105 | 114 |
106 VtableStub* VtableStubs::create_itable_stub(int vtable_index) { | 115 VtableStub* VtableStubs::create_itable_stub(int itable_index) { |
107 // Note well: pd_code_size_limit is the absolute minimum we can get | 116 // Note well: pd_code_size_limit is the absolute minimum we can get |
108 // away with. If you add code here, bump the code stub size | 117 // away with. If you add code here, bump the code stub size |
109 // returned by pd_code_size_limit! | 118 // returned by pd_code_size_limit! |
110 const int amd64_code_length = VtableStub::pd_code_size_limit(false); | 119 const int amd64_code_length = VtableStub::pd_code_size_limit(false); |
111 VtableStub* s = new(amd64_code_length) VtableStub(false, vtable_index); | 120 VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index); |
112 ResourceMark rm; | 121 ResourceMark rm; |
113 CodeBuffer cb(s->entry_point(), amd64_code_length); | 122 CodeBuffer cb(s->entry_point(), amd64_code_length); |
114 MacroAssembler* masm = new MacroAssembler(&cb); | 123 MacroAssembler* masm = new MacroAssembler(&cb); |
115 | 124 |
116 #ifndef PRODUCT | 125 #ifndef PRODUCT |
129 | 138 |
130 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); | 139 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); |
131 // get receiver klass (also an implicit null-check) | 140 // get receiver klass (also an implicit null-check) |
132 address npe_addr = __ pc(); | 141 address npe_addr = __ pc(); |
133 | 142 |
134 __ load_klass(rbx, j_rarg0); | 143 // Most registers are in use; we'll use rax, rbx, r10, r11 |
144 // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) | |
145 __ load_klass(r10, j_rarg0); | |
135 | 146 |
136 // If we take a trap while this arg is on the stack we will not | 147 // If we take a trap while this arg is on the stack we will not |
137 // be able to walk the stack properly. This is not an issue except | 148 // be able to walk the stack properly. This is not an issue except |
138 // when there are mistakes in this assembly code that could generate | 149 // when there are mistakes in this assembly code that could generate |
139 // a spurious fault. Ask me how I know... | 150 // a spurious fault. Ask me how I know... |
140 | 151 |
141 __ push(j_rarg1); // Most registers are in use, so save one | 152 const Register method = rbx; |
142 | 153 Label throw_icce; |
143 // compute itable entry offset (in words) | |
144 const int base = instanceKlass::vtable_start_offset() * wordSize; | |
145 assert(vtableEntry::size() * wordSize == 8, | |
146 "adjust the scaling in the code below"); | |
147 // Get length of vtable | |
148 __ movl(j_rarg1, | |
149 Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); | |
150 __ lea(rbx, Address(rbx, j_rarg1, Address::times_8, base)); | |
151 | |
152 if (HeapWordsPerLong > 1) { | |
153 // Round up to align_object_offset boundary | |
154 __ round_to(rbx, BytesPerLong); | |
155 } | |
156 Label hit, next, entry, throw_icce; | |
157 | |
158 __ jmpb(entry); | |
159 | |
160 __ bind(next); | |
161 __ addptr(rbx, itableOffsetEntry::size() * wordSize); | |
162 | |
163 __ bind(entry); | |
164 | |
165 // If the entry is NULL then we've reached the end of the table | |
166 // without finding the expected interface, so throw an exception | |
167 __ movptr(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); | |
168 __ testptr(j_rarg1, j_rarg1); | |
169 __ jcc(Assembler::zero, throw_icce); | |
170 __ cmpptr(rax, j_rarg1); | |
171 __ jccb(Assembler::notEqual, next); | |
172 | |
173 // We found a hit, move offset into j_rarg1 | |
174 __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); | |
175 | |
176 // Compute itableMethodEntry | |
177 const int method_offset = | |
178 (itableMethodEntry::size() * wordSize * vtable_index) + | |
179 itableMethodEntry::method_offset_in_bytes(); | |
180 | 154 |
181 // Get methodOop and entrypoint for compiler | 155 // Get methodOop and entrypoint for compiler |
182 | 156 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
183 // Get klass pointer again | 157 r10, rax, itable_index, |
184 __ load_klass(rax, j_rarg0); | 158 // outputs: method, scan temp. reg |
185 | 159 method, r11, |
186 const Register method = rbx; | 160 throw_icce); |
187 __ movptr(method, Address(rax, j_rarg1, Address::times_1, method_offset)); | |
188 | |
189 // Restore saved register, before possible trap. | |
190 __ pop(j_rarg1); | |
191 | 161 |
192 // method (rbx): methodOop | 162 // method (rbx): methodOop |
193 // j_rarg0: receiver | 163 // j_rarg0: receiver |
194 | |
195 | 164 |
196 #ifdef ASSERT | 165 #ifdef ASSERT |
197 if (DebugVtables) { | 166 if (DebugVtables) { |
198 Label L2; | 167 Label L2; |
199 __ cmpptr(method, (int32_t)NULL_WORD); | 168 __ cmpptr(method, (int32_t)NULL_WORD); |
209 // j_rarg0: receiver | 178 // j_rarg0: receiver |
210 address ame_addr = __ pc(); | 179 address ame_addr = __ pc(); |
211 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); | 180 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); |
212 | 181 |
213 __ bind(throw_icce); | 182 __ bind(throw_icce); |
214 // Restore saved register | |
215 __ pop(j_rarg1); | |
216 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); | 183 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); |
217 | 184 |
218 __ flush(); | 185 __ flush(); |
219 | 186 |
187 if (PrintMiscellaneous && (WizardMode || Verbose)) { | |
188 tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", | |
189 itable_index, s->entry_point(), | |
190 (int)(s->code_end() - s->entry_point()), | |
191 (int)(s->code_end() - __ pc())); | |
192 } | |
220 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); | 193 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); |
221 | 194 |
222 s->set_exception_points(npe_addr, ame_addr); | 195 s->set_exception_points(npe_addr, ame_addr); |
223 return s; | 196 return s; |
224 } | 197 } |
228 // Vtable stub size | 201 // Vtable stub size |
229 return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) + | 202 return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) + |
230 (UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long | 203 (UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long |
231 } else { | 204 } else { |
232 // Itable stub size | 205 // Itable stub size |
233 return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) + | 206 return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) + |
234 (UseCompressedOops ? 32 : 0); // 2 leaqs | 207 (UseCompressedOops ? 32 : 0); // 2 leaqs |
235 } | 208 } |
236 } | 209 } |
237 | 210 |
238 int VtableStub::pd_code_alignment() { | 211 int VtableStub::pd_code_alignment() { |