1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,264 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "asm/macroAssembler.hpp" 1.30 +#include "code/vtableStubs.hpp" 1.31 +#include "interp_masm_x86.hpp" 1.32 +#include "memory/resourceArea.hpp" 1.33 +#include "oops/instanceKlass.hpp" 1.34 +#include "oops/klassVtable.hpp" 1.35 +#include "runtime/sharedRuntime.hpp" 1.36 +#include "vmreg_x86.inline.hpp" 1.37 +#ifdef COMPILER2 1.38 +#include "opto/runtime.hpp" 1.39 +#endif 1.40 + 1.41 +// machine-dependent part of VtableStubs: create VtableStub of correct size and 1.42 +// initialize its code 1.43 + 1.44 +#define __ masm-> 1.45 + 1.46 +#ifndef PRODUCT 1.47 +extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); 1.48 +#endif 1.49 + 1.50 +// These stubs are used by the compiler only. 1.51 +// Argument registers, which must be preserved: 1.52 +// rcx - receiver (always first argument) 1.53 +// rdx - second argument (if any) 1.54 +// Other registers that might be usable: 1.55 +// rax - inline cache register (is interface for itable stub) 1.56 +// rbx - method (used when calling out to interpreter) 1.57 +// Available now, but may become callee-save at some point: 1.58 +// rsi, rdi 1.59 +// Note that rax and rdx are also used for return values. 1.60 +// 1.61 +VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { 1.62 + const int i486_code_length = VtableStub::pd_code_size_limit(true); 1.63 + VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index); 1.64 + // Can be NULL if there is no free space in the code cache. 1.65 + if (s == NULL) { 1.66 + return NULL; 1.67 + } 1.68 + 1.69 + ResourceMark rm; 1.70 + CodeBuffer cb(s->entry_point(), i486_code_length); 1.71 + MacroAssembler* masm = new MacroAssembler(&cb); 1.72 + 1.73 +#ifndef PRODUCT 1.74 + 1.75 + if (CountCompiledCalls) { 1.76 + __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); 1.77 + } 1.78 +#endif /* PRODUCT */ 1.79 + 1.80 + // get receiver (need to skip return address on top of stack) 1.81 + assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); 1.82 + 1.83 + // get receiver klass 1.84 + address npe_addr = __ pc(); 1.85 + __ movptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes())); 1.86 + 1.87 +#ifndef PRODUCT 1.88 + if (DebugVtables) { 1.89 + Label L; 1.90 + // check offset vs vtable length 1.91 + __ cmpl(Address(rax, InstanceKlass::vtable_length_offset()*wordSize), vtable_index*vtableEntry::size()); 1.92 + __ jcc(Assembler::greater, L); 1.93 + __ movl(rbx, vtable_index); 1.94 + __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), rcx, rbx); 1.95 + __ bind(L); 1.96 + } 1.97 +#endif // PRODUCT 1.98 + 1.99 + const Register method = rbx; 1.100 + 1.101 + // load Method* and target address 1.102 + __ lookup_virtual_method(rax, vtable_index, method); 1.103 + 1.104 + if (DebugVtables) { 1.105 + Label L; 1.106 + __ cmpptr(method, (int32_t)NULL_WORD); 1.107 + __ jcc(Assembler::equal, L); 1.108 + __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD); 1.109 + __ jcc(Assembler::notZero, L); 1.110 + __ stop("Vtable entry is NULL"); 1.111 + __ bind(L); 1.112 + } 1.113 + 1.114 + // rax,: receiver klass 1.115 + // method (rbx): Method* 1.116 + // rcx: receiver 1.117 + address ame_addr = __ pc(); 1.118 + __ jmp( Address(method, Method::from_compiled_offset())); 1.119 + 1.120 + masm->flush(); 1.121 + 1.122 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 1.123 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 1.124 + vtable_index, p2i(s->entry_point()), 1.125 + (int)(s->code_end() - s->entry_point()), 1.126 + (int)(s->code_end() - __ pc())); 1.127 + } 1.128 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 1.129 + // shut the door on sizing bugs 1.130 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 1.131 + assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 1.132 + 1.133 + s->set_exception_points(npe_addr, ame_addr); 1.134 + return s; 1.135 +} 1.136 + 1.137 + 1.138 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 1.139 + // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you 1.140 + // add code here, bump the code stub size returned by pd_code_size_limit! 1.141 + const int i486_code_length = VtableStub::pd_code_size_limit(false); 1.142 + VtableStub* s = new(i486_code_length) VtableStub(false, itable_index); 1.143 + // Can be NULL if there is no free space in the code cache. 1.144 + if (s == NULL) { 1.145 + return NULL; 1.146 + } 1.147 + 1.148 + ResourceMark rm; 1.149 + CodeBuffer cb(s->entry_point(), i486_code_length); 1.150 + MacroAssembler* masm = new MacroAssembler(&cb); 1.151 + 1.152 + // Entry arguments: 1.153 + // rax,: Interface 1.154 + // rcx: Receiver 1.155 + 1.156 +#ifndef PRODUCT 1.157 + if (CountCompiledCalls) { 1.158 + __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); 1.159 + } 1.160 +#endif /* PRODUCT */ 1.161 + // get receiver (need to skip return address on top of stack) 1.162 + 1.163 + assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); 1.164 + 1.165 + // get receiver klass (also an implicit null-check) 1.166 + address npe_addr = __ pc(); 1.167 + __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); 1.168 + 1.169 + // Most registers are in use; we'll use rax, rbx, rsi, rdi 1.170 + // (If we need to make rsi, rdi callee-save, do a push/pop here.) 1.171 + const Register method = rbx; 1.172 + Label throw_icce; 1.173 + 1.174 + // Get Method* and entrypoint for compiler 1.175 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 1.176 + rsi, rax, itable_index, 1.177 + // outputs: method, scan temp. reg 1.178 + method, rdi, 1.179 + throw_icce); 1.180 + 1.181 + // method (rbx): Method* 1.182 + // rcx: receiver 1.183 + 1.184 +#ifdef ASSERT 1.185 + if (DebugVtables) { 1.186 + Label L1; 1.187 + __ cmpptr(method, (int32_t)NULL_WORD); 1.188 + __ jcc(Assembler::equal, L1); 1.189 + __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD); 1.190 + __ jcc(Assembler::notZero, L1); 1.191 + __ stop("Method* is null"); 1.192 + __ bind(L1); 1.193 + } 1.194 +#endif // ASSERT 1.195 + 1.196 + address ame_addr = __ pc(); 1.197 + __ jmp(Address(method, Method::from_compiled_offset())); 1.198 + 1.199 + __ bind(throw_icce); 1.200 + __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 1.201 + masm->flush(); 1.202 + 1.203 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 1.204 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 1.205 + itable_index, p2i(s->entry_point()), 1.206 + (int)(s->code_end() - s->entry_point()), 1.207 + (int)(s->code_end() - __ pc())); 1.208 + } 1.209 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 1.210 + // shut the door on sizing bugs 1.211 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 1.212 + assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 1.213 + 1.214 + s->set_exception_points(npe_addr, ame_addr); 1.215 + return s; 1.216 +} 1.217 + 1.218 + 1.219 + 1.220 +int VtableStub::pd_code_size_limit(bool is_vtable_stub) { 1.221 + if (is_vtable_stub) { 1.222 + // Vtable stub size 1.223 + return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); 1.224 + } else { 1.225 + // Itable stub size 1.226 + return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); 1.227 + } 1.228 + // In order to tune these parameters, run the JVM with VM options 1.229 + // +PrintMiscellaneous and +WizardMode to see information about 1.230 + // actual itable stubs. Look for lines like this: 1.231 + // itable #1 at 0x5551212[65] left over: 3 1.232 + // Reduce the constants so that the "left over" number is >=3 1.233 + // for the common cases. 1.234 + // Do not aim at a left-over number of zero, because a 1.235 + // large vtable or itable index (> 16) will require a 32-bit 1.236 + // immediate displacement instead of an 8-bit one. 1.237 + // 1.238 + // The JVM98 app. _202_jess has a megamorphic interface call. 1.239 + // The itable code looks like this: 1.240 + // Decoding VtableStub itbl[1]@1 1.241 + // mov 0x4(%ecx),%esi 1.242 + // mov 0xe8(%esi),%edi 1.243 + // lea 0x130(%esi,%edi,4),%edi 1.244 + // add $0x7,%edi 1.245 + // and $0xfffffff8,%edi 1.246 + // lea 0x4(%esi),%esi 1.247 + // mov (%edi),%ebx 1.248 + // cmp %ebx,%eax 1.249 + // je success 1.250 + // loop: 1.251 + // test %ebx,%ebx 1.252 + // je throw_icce 1.253 + // add $0x8,%edi 1.254 + // mov (%edi),%ebx 1.255 + // cmp %ebx,%eax 1.256 + // jne loop 1.257 + // success: 1.258 + // mov 0x4(%edi),%edi 1.259 + // mov (%esi,%edi,1),%ebx 1.260 + // jmp *0x44(%ebx) 1.261 + // throw_icce: 1.262 + // jmp throw_ICCE_entry 1.263 +} 1.264 + 1.265 +int VtableStub::pd_code_alignment() { 1.266 + return wordSize; 1.267 +}