src/cpu/mips/vm/vtableStubs_mips_64.cpp

Fri, 29 Apr 2016 00:06:10 +0800

author
aoqi
date
Fri, 29 Apr 2016 00:06:10 +0800
changeset 1
2d8a650513c2
child 6880
52ea28d233d2
permissions
-rw-r--r--

Added MIPS 64-bit port.

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@1 3 * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
aoqi@1 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@1 5 *
aoqi@1 6 * This code is free software; you can redistribute it and/or modify it
aoqi@1 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@1 8 * published by the Free Software Foundation.
aoqi@1 9 *
aoqi@1 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@1 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@1 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@1 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@1 14 * accompanied this code).
aoqi@1 15 *
aoqi@1 16 * You should have received a copy of the GNU General Public License version
aoqi@1 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@1 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@1 19 *
aoqi@1 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@1 21 * or visit www.oracle.com if you need additional information or have any
aoqi@1 22 * questions.
aoqi@1 23 *
aoqi@1 24 */
aoqi@1 25
aoqi@1 26 #include "precompiled.hpp"
aoqi@1 27 #include "asm/macroAssembler.hpp"
aoqi@1 28 #include "code/vtableStubs.hpp"
aoqi@1 29 #include "interp_masm_mips_64.hpp"
aoqi@1 30 #include "memory/resourceArea.hpp"
aoqi@1 31 //#include "oops/InstanceKlass.hpp"
aoqi@1 32 #include "oops/klassVtable.hpp"
aoqi@1 33 #include "runtime/sharedRuntime.hpp"
aoqi@1 34 #include "vmreg_mips.inline.hpp"
aoqi@1 35 #ifdef COMPILER2
aoqi@1 36 #include "opto/runtime.hpp"
aoqi@1 37 #endif
aoqi@1 38
aoqi@1 39
aoqi@1 40 // machine-dependent part of VtableStubs: create VtableStub of correct size and
aoqi@1 41 // initialize its code
aoqi@1 42
aoqi@1 43 #define __ masm->
aoqi@1 44
aoqi@1 45 #ifndef PRODUCT
aoqi@1 46 extern "C" void bad_compiled_vtable_index(JavaThread* thread,
aoqi@1 47 oop receiver,
aoqi@1 48 int index);
aoqi@1 49 #endif
aoqi@1 50
aoqi@1 51 // used by compiler only; reciever in T0.
aoqi@1 52 // used registers :
aoqi@1 53 // Rmethod : receiver klass & method
aoqi@1 54 // NOTE: If this code is used by the C1, the receiver_location is always 0.
aoqi@1 55 // when reach here, receiver in T0, klass in T8
aoqi@1 56 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
aoqi@1 57 const int gs2_code_length = VtableStub::pd_code_size_limit(true);
aoqi@1 58 //VtableStub* s = new(gs2_code_length) VtableStub(true, vtable_index, receiver_location);
aoqi@1 59 //FIXME aoqi
aoqi@1 60 VtableStub* s = new(gs2_code_length) VtableStub(true, vtable_index);
aoqi@1 61 ResourceMark rm;
aoqi@1 62 CodeBuffer cb(s->entry_point(), gs2_code_length);
aoqi@1 63 MacroAssembler* masm = new MacroAssembler(&cb);
aoqi@1 64 Register t1 = T8, t2 = Rmethod;
aoqi@1 65 #ifndef PRODUCT
aoqi@1 66 //#ifdef COMPILER2
aoqi@1 67 if (CountCompiledCalls) {
aoqi@1 68 __ li(AT, SharedRuntime::nof_megamorphic_calls_addr());
aoqi@1 69 __ lw(t1, AT , 0);
aoqi@1 70 __ addiu(t1, t1, 1);
aoqi@1 71 __ sw(t1, AT,0);
aoqi@1 72 }
aoqi@1 73 //#endif
aoqi@1 74 #endif
aoqi@1 75
aoqi@1 76 // get receiver (need to skip return address on top of stack)
aoqi@1 77 //assert(receiver_location == T0->as_VMReg(), "receiver expected in T0");
aoqi@1 78
aoqi@1 79 // get receiver klass
aoqi@1 80 address npe_addr = __ pc();
aoqi@1 81 //__ ld_ptr(t1, T0, oopDesc::klass_offset_in_bytes());
aoqi@1 82 //add for compressedoops
aoqi@1 83 __ load_klass(t1, T0);
aoqi@1 84 // compute entry offset (in words)
aoqi@1 85 int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
aoqi@1 86 #ifndef PRODUCT
aoqi@1 87 if (DebugVtables) {
aoqi@1 88 Label L;
aoqi@1 89 // check offset vs vtable length
aoqi@1 90 __ lw(t2, t1, InstanceKlass::vtable_length_offset()*wordSize);
aoqi@1 91 assert(Assembler::is_simm16(vtable_index*vtableEntry::size()), "change this code");
aoqi@1 92 __ move(AT, vtable_index*vtableEntry::size());
aoqi@1 93 __ slt(AT, AT, t2);
aoqi@1 94 __ bne(AT, R0, L);
aoqi@1 95 __ delayed()->nop();
aoqi@1 96 __ move(A2, vtable_index);
aoqi@1 97 __ move(A1, A0);
aoqi@1 98 __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), A1, A2);
aoqi@1 99 __ bind(L);
aoqi@1 100 }
aoqi@1 101 #endif // PRODUCT
aoqi@1 102 // load methodOop and target address
aoqi@1 103 const Register method = Rmethod;
aoqi@1 104 __ ld_ptr(method, t1, entry_offset*wordSize + vtableEntry::method_offset_in_bytes());
aoqi@1 105 if (DebugVtables) {
aoqi@1 106 Label L;
aoqi@1 107 __ beq(method, R0, L);
aoqi@1 108 __ delayed()->nop();
aoqi@1 109 // __ cmpl(Address(method, Method::from_compiled_offset()), NULL_WORD);
aoqi@1 110 __ lw(AT, method,in_bytes(Method::from_compiled_offset()));
aoqi@1 111 //__ jcc(Assembler::notZero, L);
aoqi@1 112 __ bne(AT, R0, L);
aoqi@1 113 __ delayed()->nop();
aoqi@1 114 __ stop("Vtable entry is NULL");
aoqi@1 115 __ bind(L);
aoqi@1 116 }
aoqi@1 117 // T8: receiver klass
aoqi@1 118 // T0: receiver
aoqi@1 119 // Rmethod: methodOop
aoqi@1 120 // T9: entry
aoqi@1 121 address ame_addr = __ pc();
aoqi@1 122 __ ld_ptr(T9, method,in_bytes(Method::from_compiled_offset()));
aoqi@1 123 __ jr(T9);
aoqi@1 124 __ delayed()->nop();
aoqi@1 125 masm->flush();
aoqi@1 126 s->set_exception_points(npe_addr, ame_addr);
aoqi@1 127 return s;
aoqi@1 128 }
aoqi@1 129
aoqi@1 130
aoqi@1 131 // i am not sure which register to contain Interface, now i just assume A1. FIXME
aoqi@1 132 // used registers :
aoqi@1 133 // T1 T2
aoqi@1 134 // when reach here, the receiver in T0, klass in T1
aoqi@1 135 VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
aoqi@1 136 // Note well: pd_code_size_limit is the absolute minimum we can get
aoqi@1 137 // away with. If you add code here, bump the code stub size
aoqi@1 138 // returned by pd_code_size_limit!
aoqi@1 139 const int gs2_code_length = VtableStub::pd_code_size_limit(false);
aoqi@1 140 VtableStub* s = new(gs2_code_length) VtableStub(false, vtable_index);
aoqi@1 141 ResourceMark rm;
aoqi@1 142 CodeBuffer cb(s->entry_point(), gs2_code_length);
aoqi@1 143 MacroAssembler* masm = new MacroAssembler(&cb);
aoqi@1 144 // we T8,T9 as temparary register, they are free from register allocator
aoqi@1 145 Register t1 = T8, t2 = T2;
aoqi@1 146 // Entry arguments:
aoqi@1 147 // T1: Interface
aoqi@1 148 // T0: Receiver
aoqi@1 149 #ifndef PRODUCT
aoqi@1 150 if (CountCompiledCalls) {
aoqi@1 151 //__ incl(Address((int)SharedRuntime::nof_megamorphic_calls_addr(), relocInfo::none));
aoqi@1 152 __ li(AT, SharedRuntime::nof_megamorphic_calls_addr());
aoqi@1 153 __ lw(T8, AT, 0);
aoqi@1 154 __ addi(T8, T8,1);
aoqi@1 155 __ sw(T8, AT, 0);
aoqi@1 156 }
aoqi@1 157 #endif /* PRODUCT */
aoqi@1 158 //assert(receiver_location == T0->as_VMReg(), "receiver expected in T0");
aoqi@1 159 // get receiver klass (also an implicit null-check)
aoqi@1 160 address npe_addr = __ pc();
aoqi@1 161 //__ ld_ptr(t1, T0, oopDesc::klass_offset_in_bytes());
aoqi@1 162 //add for compressedoops
aoqi@1 163 __ load_klass(t1, T0);
aoqi@1 164 // compute itable entry offset (in words)
aoqi@1 165 const int base = InstanceKlass::vtable_start_offset() * wordSize;
aoqi@1 166 assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below");
aoqi@1 167 assert(Assembler::is_simm16(base), "change this code");
aoqi@1 168 __ daddi(t2, t1, base);
aoqi@1 169 assert(Assembler::is_simm16(InstanceKlass::vtable_length_offset() * wordSize), "change this code");
aoqi@1 170 __ lw(AT, t1, InstanceKlass::vtable_length_offset() * wordSize);
aoqi@1 171 __ dsll(AT, AT, Address::times_8);
aoqi@1 172 __ dadd(t2, t2, AT);
aoqi@1 173 if (HeapWordsPerLong > 1) {
aoqi@1 174 __ round_to(t2, BytesPerLong);
aoqi@1 175 }
aoqi@1 176
aoqi@1 177 Label hit, entry;
aoqi@1 178 assert(Assembler::is_simm16(itableOffsetEntry::size() * wordSize), "change this code");
aoqi@1 179 __ bind(entry);
aoqi@1 180
aoqi@1 181 #ifdef ASSERT
aoqi@1 182 // Check that the entry is non-null
aoqi@1 183 if (DebugVtables) {
aoqi@1 184 Label L;
aoqi@1 185 assert(Assembler::is_simm16(itableOffsetEntry::interface_offset_in_bytes()), "change this code");
aoqi@1 186 __ lw(AT, t1, itableOffsetEntry::interface_offset_in_bytes());
aoqi@1 187 __ bne(AT, R0, L);
aoqi@1 188 __ delayed()->nop();
aoqi@1 189 __ stop("null entry point found in itable's offset table");
aoqi@1 190 __ bind(L);
aoqi@1 191 }
aoqi@1 192 #endif
aoqi@1 193 assert(Assembler::is_simm16(itableOffsetEntry::interface_offset_in_bytes()), "change this code");
aoqi@1 194 __ ld_ptr(AT, t2, itableOffsetEntry::interface_offset_in_bytes());
aoqi@1 195 __ bne(AT, T1, entry);
aoqi@1 196 __ delayed()->addi(t2, t2, itableOffsetEntry::size() * wordSize);
aoqi@1 197
aoqi@1 198 // We found a hit, move offset into T9
aoqi@1 199 __ ld_ptr(t2, t2, itableOffsetEntry::offset_offset_in_bytes() - itableOffsetEntry::size() * wordSize);
aoqi@1 200
aoqi@1 201 // Compute itableMethodEntry.
aoqi@1 202 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
aoqi@1 203 itableMethodEntry::method_offset_in_bytes();
aoqi@1 204
aoqi@1 205 // Get methodOop and entrypoint for compiler
aoqi@1 206 // const Register method = ebx;
aoqi@1 207 const Register method = Rmethod;
aoqi@1 208 // __ movl(method, Address(esi, edx, Address::times_1, method_offset));
aoqi@1 209 __ dsll(AT, t2, Address::times_1);
aoqi@1 210 __ add(AT, AT, t1 );
aoqi@1 211 __ ld_ptr(method, AT, method_offset);
aoqi@1 212
aoqi@1 213
aoqi@1 214
aoqi@1 215 #ifdef ASSERT
aoqi@1 216 if (DebugVtables) {
aoqi@1 217 Label L1;
aoqi@1 218 // __ cmpl(method, NULL_WORD);
aoqi@1 219 // __ jcc(Assembler::equal, L1);
aoqi@1 220 __ beq(method, R0, L1);
aoqi@1 221 __ delayed()->nop();
aoqi@1 222 // __ cmpl(Address(method, Method::from_compiled_offset()), NULL_WORD);
aoqi@1 223 __ lw(AT, method,in_bytes(Method::from_compiled_offset()));
aoqi@1 224 // __ jcc(Assembler::notZero, L1);
aoqi@1 225 __ bne(AT, R0, L1);
aoqi@1 226 __ delayed()->nop();
aoqi@1 227 __ stop("methodOop is null");
aoqi@1 228 __ bind(L1);
aoqi@1 229 }
aoqi@1 230 #endif // ASSERT
aoqi@1 231 /*
aoqi@1 232 // Rmethod: methodOop
aoqi@1 233 // T0: receiver
aoqi@1 234 // T9: entry point
aoqi@1 235 __ jmp(T9);
aoqi@1 236 #endif // COMPILER2
aoqi@1 237 */
aoqi@1 238 address ame_addr = __ pc();
aoqi@1 239 __ ld_ptr(T9, method,in_bytes(Method::from_compiled_offset()));
aoqi@1 240 __ jr(T9);
aoqi@1 241 __ delayed()->nop();
aoqi@1 242 masm->flush();
aoqi@1 243 s->set_exception_points(npe_addr, ame_addr);
aoqi@1 244 return s;
aoqi@1 245 }
aoqi@1 246
aoqi@1 247 // NOTE : whenever you change the code above, dont forget to change the const here
aoqi@1 248 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
aoqi@1 249 if (is_vtable_stub) {
aoqi@1 250 return ( DebugVtables ? 600 : 28) + (CountCompiledCalls ? 24 : 0)+
aoqi@1 251 (UseCompressedOops ? 16 : 0);
aoqi@1 252 } else {
aoqi@1 253 return ( DebugVtables ? 636 : 72) + (CountCompiledCalls ? 24 : 0)+
aoqi@1 254 (UseCompressedOops ? 32 : 0);
aoqi@1 255 }
aoqi@1 256 }
aoqi@1 257
aoqi@1 258 int VtableStub::pd_code_alignment() {
aoqi@1 259 return wordSize;
aoqi@1 260 }

mercurial