Fri, 07 Dec 2018 14:53:37 +0800
#7987 implements tieredcompilation in mips template interpreter
------- Effect (scores, higher is better) ----------
SPECjvm2008 Benchmarks C2-only Tiered
startup.helloworld 70.51 74.81
startup.compiler.compiler 2.17 4.68
startup.compiler.sunflow 2.31 3.76
startup.compress 12.64 12.90
startup.crypto.aes 4.19 4.30
startup.crypto.rsa 13.86 14.10
startup.crypto.signverify 13.97 15.22
startup.mpegaudio 5.76 6.18
startup.scimark.fft 20.58 20.86
startup.scimark.lu 20.32 21.23
startup.scimark.monte_carlo 7.21 6.10
startup.scimark.sor 8.50 8.58
startup.scimark.sparse 10.35 10.80
startup.serial 4.82 5.26
startup.sunflow 5.52 7.02
startup.xml.transform 0.57 0.61
startup.xml.validation 5.48 8.71
aoqi@1 | 1 | /* |
aoqi@1 | 2 | * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@8863 | 3 | * Copyright (c) 2015, 2018, 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 "interpreter/bytecodeHistogram.hpp" |
aoqi@1 | 29 | #include "interpreter/interpreter.hpp" |
aoqi@1 | 30 | #include "interpreter/interpreterGenerator.hpp" |
aoqi@1 | 31 | #include "interpreter/interpreterRuntime.hpp" |
aoqi@1 | 32 | #include "interpreter/templateTable.hpp" |
aoqi@1 | 33 | #include "oops/arrayOop.hpp" |
aoqi@1 | 34 | #include "oops/methodData.hpp" |
aoqi@1 | 35 | #include "oops/method.hpp" |
aoqi@1 | 36 | #include "oops/oop.inline.hpp" |
aoqi@1 | 37 | #include "prims/jvmtiExport.hpp" |
aoqi@1 | 38 | #include "prims/jvmtiThreadState.hpp" |
aoqi@1 | 39 | #include "runtime/arguments.hpp" |
aoqi@1 | 40 | #include "runtime/deoptimization.hpp" |
aoqi@1 | 41 | #include "runtime/frame.inline.hpp" |
aoqi@1 | 42 | #include "runtime/sharedRuntime.hpp" |
aoqi@1 | 43 | #include "runtime/stubRoutines.hpp" |
aoqi@1 | 44 | #include "runtime/synchronizer.hpp" |
aoqi@1 | 45 | #include "runtime/timer.hpp" |
aoqi@1 | 46 | #include "runtime/vframeArray.hpp" |
aoqi@1 | 47 | #include "utilities/debug.hpp" |
aoqi@1 | 48 | |
aoqi@1 | 49 | #define __ _masm-> |
aoqi@1 | 50 | |
aoqi@1 | 51 | #ifndef CC_INTERP |
aoqi@1 | 52 | |
aoqi@1 | 53 | // asm based interpreter deoptimization helpers |
aoqi@1 | 54 | int AbstractInterpreter::size_activation(int max_stack, |
aoqi@1 | 55 | int temps, |
aoqi@1 | 56 | int extra_args, |
aoqi@1 | 57 | int monitors, |
aoqi@1 | 58 | int callee_params, |
aoqi@1 | 59 | int callee_locals, |
aoqi@1 | 60 | bool is_top_frame) { |
aoqi@1 | 61 | // Note: This calculation must exactly parallel the frame setup |
aoqi@1 | 62 | // in AbstractInterpreterGenerator::generate_method_entry. |
aoqi@1 | 63 | |
aoqi@1 | 64 | // fixed size of an interpreter frame: |
aoqi@1 | 65 | int overhead = frame::sender_sp_offset - |
aoqi@1 | 66 | frame::interpreter_frame_initial_sp_offset; |
aoqi@1 | 67 | // Our locals were accounted for by the caller (or last_frame_adjust |
aoqi@1 | 68 | // on the transistion) Since the callee parameters already account |
aoqi@1 | 69 | // for the callee's params we only need to account for the extra |
aoqi@1 | 70 | // locals. |
aoqi@1 | 71 | int size = overhead + |
aoqi@1 | 72 | (callee_locals - callee_params)*Interpreter::stackElementWords + |
aoqi@1 | 73 | monitors * frame::interpreter_frame_monitor_size() + |
aoqi@1 | 74 | temps* Interpreter::stackElementWords + extra_args; |
aoqi@1 | 75 | |
aoqi@1 | 76 | return size; |
aoqi@1 | 77 | } |
aoqi@1 | 78 | |
aoqi@1 | 79 | |
aoqi@1 | 80 | const int Interpreter::return_sentinel = 0xfeedbeed; |
aoqi@1 | 81 | const int method_offset = frame::interpreter_frame_method_offset * wordSize; |
aoqi@1 | 82 | const int bci_offset = frame::interpreter_frame_bcx_offset * wordSize; |
aoqi@1 | 83 | const int locals_offset = frame::interpreter_frame_locals_offset * wordSize; |
aoqi@1 | 84 | |
aoqi@1 | 85 | //----------------------------------------------------------------------------- |
aoqi@1 | 86 | |
aoqi@1 | 87 | address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { |
aoqi@1 | 88 | address entry = __ pc(); |
aoqi@1 | 89 | |
aoqi@1 | 90 | #ifdef ASSERT |
aoqi@1 | 91 | { |
aoqi@1 | 92 | Label L; |
aoqi@6880 | 93 | __ addi(T1, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); |
aoqi@6880 | 94 | __ sub(T1, T1, SP); // T1 = maximal sp for current fp |
aoqi@6880 | 95 | __ bgez(T1, L); // check if frame is complete |
aoqi@6880 | 96 | __ delayed()->nop(); |
aoqi@6880 | 97 | __ stop("interpreter frame not set up"); |
aoqi@6880 | 98 | __ bind(L); |
aoqi@1 | 99 | } |
aoqi@1 | 100 | #endif // ASSERT |
aoqi@1 | 101 | // Restore bcp under the assumption that the current frame is still |
aoqi@1 | 102 | // interpreted |
aoqi@6880 | 103 | // FIXME: please change the func restore_bcp |
aoqi@6880 | 104 | // S0 is the conventional register for bcp |
aoqi@1 | 105 | __ restore_bcp(); |
aoqi@1 | 106 | |
aoqi@1 | 107 | // expression stack must be empty before entering the VM if an |
aoqi@1 | 108 | // exception happened |
aoqi@1 | 109 | __ empty_expression_stack(); |
aoqi@1 | 110 | // throw exception |
aoqi@6880 | 111 | // FIXME: why do not pass parameter thread ? |
aoqi@6880 | 112 | __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_StackOverflowError)); |
aoqi@1 | 113 | return entry; |
aoqi@1 | 114 | } |
aoqi@1 | 115 | |
aoqi@1 | 116 | address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler( |
aoqi@1 | 117 | const char* name) { |
aoqi@1 | 118 | address entry = __ pc(); |
aoqi@1 | 119 | // expression stack must be empty before entering the VM if an |
aoqi@1 | 120 | // exception happened |
aoqi@1 | 121 | __ empty_expression_stack(); |
aoqi@1 | 122 | __ li(A1, (long)name); |
aoqi@6880 | 123 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 124 | InterpreterRuntime::throw_ArrayIndexOutOfBoundsException), A1, A2); |
aoqi@1 | 125 | return entry; |
aoqi@1 | 126 | } |
aoqi@1 | 127 | |
aoqi@1 | 128 | address TemplateInterpreterGenerator::generate_ClassCastException_handler() { |
aoqi@1 | 129 | address entry = __ pc(); |
aoqi@1 | 130 | |
aoqi@1 | 131 | // expression stack must be empty before entering the VM if an |
aoqi@1 | 132 | // exception happened |
aoqi@1 | 133 | __ empty_expression_stack(); |
aoqi@1 | 134 | __ empty_FPU_stack(); |
aoqi@1 | 135 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ClassCastException), FSR); |
aoqi@1 | 136 | return entry; |
aoqi@1 | 137 | } |
aoqi@1 | 138 | |
aoqi@1 | 139 | address TemplateInterpreterGenerator::generate_exception_handler_common( |
aoqi@1 | 140 | const char* name, const char* message, bool pass_oop) { |
aoqi@6880 | 141 | assert(!pass_oop || message == NULL, "either oop or message but not both"); |
aoqi@6880 | 142 | address entry = __ pc(); |
aoqi@1 | 143 | |
aoqi@6880 | 144 | // expression stack must be empty before entering the VM if an exception happened |
aoqi@6880 | 145 | __ empty_expression_stack(); |
aoqi@6880 | 146 | // setup parameters |
aoqi@6880 | 147 | __ li(A1, (long)name); |
aoqi@6880 | 148 | if (pass_oop) { |
aoqi@6880 | 149 | __ call_VM(V0, |
aoqi@6880 | 150 | CAST_FROM_FN_PTR(address, InterpreterRuntime::create_klass_exception), A1, FSR); |
aoqi@6880 | 151 | } else { |
aoqi@6880 | 152 | __ li(A2, (long)message); |
aoqi@6880 | 153 | __ call_VM(V0, |
aoqi@6880 | 154 | CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), A1, A2); |
aoqi@6880 | 155 | } |
aoqi@6880 | 156 | // throw exception |
aoqi@6880 | 157 | __ jmp(Interpreter::throw_exception_entry(), relocInfo::none); |
aoqi@6880 | 158 | __ delayed()->nop(); |
aoqi@6880 | 159 | return entry; |
aoqi@1 | 160 | } |
aoqi@1 | 161 | |
aoqi@1 | 162 | |
aoqi@1 | 163 | address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { |
aoqi@1 | 164 | address entry = __ pc(); |
aoqi@1 | 165 | // NULL last_sp until next java call |
aoqi@6880 | 166 | __ sd(R0,Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); |
aoqi@6880 | 167 | __ dispatch_next(state); |
aoqi@1 | 168 | return entry; |
aoqi@1 | 169 | } |
aoqi@1 | 170 | |
aoqi@1 | 171 | |
aoqi@1 | 172 | address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { |
aoqi@1 | 173 | |
aoqi@1 | 174 | address entry = __ pc(); |
aoqi@1 | 175 | |
aoqi@1 | 176 | // Restore stack bottom in case i2c adjusted stack |
aoqi@1 | 177 | __ ld(SP, Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); |
aoqi@1 | 178 | // and NULL it as marker that esp is now tos until next java call |
aoqi@1 | 179 | __ sd(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 180 | |
aoqi@1 | 181 | __ restore_bcp(); |
aoqi@1 | 182 | __ restore_locals(); |
aoqi@6880 | 183 | |
aoqi@1 | 184 | // 2014/11/24 Fu |
aoqi@1 | 185 | // mdp: T8 |
aoqi@6880 | 186 | // ret: FSR |
aoqi@1 | 187 | // tmp: T9 |
aoqi@1 | 188 | if (state == atos) { |
aoqi@1 | 189 | Register mdp = T8; |
aoqi@1 | 190 | Register tmp = T9; |
aoqi@1 | 191 | __ profile_return_type(mdp, FSR, tmp); |
aoqi@1 | 192 | } |
aoqi@1 | 193 | |
aoqi@1 | 194 | |
aoqi@1 | 195 | const Register cache = T9; |
aoqi@1 | 196 | const Register index = T3; |
aoqi@1 | 197 | __ get_cache_and_index_at_bcp(cache, index, 1, index_size); |
aoqi@1 | 198 | |
aoqi@1 | 199 | const Register flags = cache; |
aoqi@1 | 200 | __ dsll(AT, index, Address::times_ptr); |
aoqi@1 | 201 | __ daddu(AT, cache, AT); |
aoqi@1 | 202 | __ lw(flags, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); |
aoqi@1 | 203 | __ andi(flags, flags, ConstantPoolCacheEntry::parameter_size_mask); |
aoqi@1 | 204 | __ dsll(AT, flags, Interpreter::stackElementScale()); |
aoqi@1 | 205 | __ daddu(SP, SP, AT); |
aoqi@1 | 206 | |
aoqi@1 | 207 | __ dispatch_next(state, step); |
aoqi@1 | 208 | |
aoqi@1 | 209 | return entry; |
aoqi@1 | 210 | } |
aoqi@1 | 211 | |
aoqi@1 | 212 | |
aoqi@1 | 213 | address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, |
aoqi@1 | 214 | int step) { |
aoqi@1 | 215 | address entry = __ pc(); |
aoqi@1 | 216 | // NULL last_sp until next java call |
aoqi@1 | 217 | __ sd(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 218 | __ restore_bcp(); |
aoqi@1 | 219 | __ restore_locals(); |
aoqi@1 | 220 | // handle exceptions |
aoqi@1 | 221 | { |
aoqi@1 | 222 | Label L; |
aoqi@6880 | 223 | const Register thread = TREG; |
aoqi@1 | 224 | #ifndef OPT_THREAD |
aoqi@6880 | 225 | __ get_thread(thread); |
aoqi@1 | 226 | #endif |
aoqi@6880 | 227 | __ lw(AT, thread, in_bytes(Thread::pending_exception_offset())); |
aoqi@6880 | 228 | __ beq(AT, R0, L); |
aoqi@6880 | 229 | __ delayed()->nop(); |
aoqi@6880 | 230 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_pending_exception)); |
aoqi@6880 | 231 | __ should_not_reach_here(); |
aoqi@6880 | 232 | __ bind(L); |
aoqi@1 | 233 | } |
aoqi@1 | 234 | __ dispatch_next(state, step); |
aoqi@1 | 235 | return entry; |
aoqi@1 | 236 | } |
aoqi@1 | 237 | |
aoqi@1 | 238 | int AbstractInterpreter::BasicType_as_index(BasicType type) { |
aoqi@1 | 239 | int i = 0; |
aoqi@1 | 240 | switch (type) { |
aoqi@1 | 241 | case T_BOOLEAN: i = 0; break; |
aoqi@1 | 242 | case T_CHAR : i = 1; break; |
aoqi@1 | 243 | case T_BYTE : i = 2; break; |
aoqi@1 | 244 | case T_SHORT : i = 3; break; |
aoqi@6880 | 245 | case T_INT : // fall through |
aoqi@6880 | 246 | case T_LONG : // fall through |
aoqi@6880 | 247 | case T_VOID : i = 4; break; |
aoqi@6880 | 248 | case T_FLOAT : i = 5; break; |
aoqi@6880 | 249 | case T_DOUBLE : i = 6; break; |
aoqi@6880 | 250 | case T_OBJECT : // fall through |
aoqi@6880 | 251 | case T_ARRAY : i = 7; break; |
aoqi@1 | 252 | default : ShouldNotReachHere(); |
aoqi@1 | 253 | } |
aoqi@1 | 254 | assert(0 <= i && i < AbstractInterpreter::number_of_result_handlers, |
aoqi@1 | 255 | "index out of bounds"); |
aoqi@1 | 256 | return i; |
aoqi@1 | 257 | } |
aoqi@1 | 258 | |
aoqi@1 | 259 | |
aoqi@1 | 260 | address TemplateInterpreterGenerator::generate_result_handler_for( |
aoqi@1 | 261 | BasicType type) { |
aoqi@6880 | 262 | address entry = __ pc(); |
aoqi@6880 | 263 | switch (type) { |
aoqi@6880 | 264 | case T_BOOLEAN: __ c2bool(V0); break; |
aoqi@6880 | 265 | case T_CHAR : __ andi(V0, V0, 0xFFFF); break; |
aoqi@6880 | 266 | case T_BYTE : __ sign_extend_byte (V0); break; |
aoqi@6880 | 267 | case T_SHORT : __ sign_extend_short(V0); break; |
aoqi@6880 | 268 | case T_INT : /* nothing to do */ break; |
aoqi@6880 | 269 | case T_FLOAT : /* nothing to do */ break; |
aoqi@6880 | 270 | case T_DOUBLE : /* nothing to do */ break; |
aoqi@6880 | 271 | case T_OBJECT : |
aoqi@6880 | 272 | { |
aoqi@6880 | 273 | __ ld(V0, FP, frame::interpreter_frame_oop_temp_offset * wordSize); |
aoqi@6880 | 274 | __ verify_oop(V0); // and verify it |
aoqi@6880 | 275 | } |
aoqi@6880 | 276 | break; |
aoqi@6880 | 277 | default : ShouldNotReachHere(); |
aoqi@6880 | 278 | } |
aoqi@6880 | 279 | __ jr(RA); // return from result handler |
aoqi@6880 | 280 | __ delayed()->nop(); |
aoqi@6880 | 281 | return entry; |
aoqi@1 | 282 | } |
aoqi@1 | 283 | |
aoqi@1 | 284 | address TemplateInterpreterGenerator::generate_safept_entry_for( |
aoqi@1 | 285 | TosState state, |
aoqi@1 | 286 | address runtime_entry) { |
aoqi@1 | 287 | address entry = __ pc(); |
aoqi@1 | 288 | __ push(state); |
aoqi@1 | 289 | __ call_VM(noreg, runtime_entry); |
aoqi@1 | 290 | __ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos)); |
aoqi@1 | 291 | return entry; |
aoqi@1 | 292 | } |
aoqi@1 | 293 | |
aoqi@1 | 294 | |
aoqi@1 | 295 | |
aoqi@1 | 296 | // Helpers for commoning out cases in the various type of method entries. |
aoqi@1 | 297 | // |
aoqi@1 | 298 | |
aoqi@1 | 299 | |
aoqi@1 | 300 | // increment invocation count & check for overflow |
aoqi@1 | 301 | // |
aoqi@1 | 302 | // Note: checking for negative value instead of overflow |
aoqi@1 | 303 | // so we have a 'sticky' overflow test |
aoqi@1 | 304 | // |
fujie@9274 | 305 | // Rmethod: method |
fujie@9274 | 306 | // T3 : invocation counter |
fujie@9274 | 307 | // |
aoqi@1 | 308 | void InterpreterGenerator::generate_counter_incr( |
aoqi@1 | 309 | Label* overflow, |
aoqi@1 | 310 | Label* profile_method, |
aoqi@6880 | 311 | Label* profile_method_continue) { |
aoqi@1 | 312 | Label done; |
fujie@9274 | 313 | if (TieredCompilation) { |
fujie@9274 | 314 | int increment = InvocationCounter::count_increment; |
fujie@9274 | 315 | int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift; |
fujie@9274 | 316 | Label no_mdo; |
fujie@9274 | 317 | if (ProfileInterpreter) { |
fujie@9274 | 318 | // Are we profiling? |
fujie@9274 | 319 | __ ld(FSR, Address(Rmethod, Method::method_data_offset())); |
fujie@9274 | 320 | __ beq(FSR, R0, no_mdo); |
fujie@9274 | 321 | __ delayed()->nop(); |
fujie@9274 | 322 | // Increment counter in the MDO |
fujie@9274 | 323 | const Address mdo_invocation_counter(FSR, in_bytes(MethodData::invocation_counter_offset()) + |
fujie@9274 | 324 | in_bytes(InvocationCounter::counter_offset())); |
fujie@9274 | 325 | __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, T3, false, Assembler::zero, overflow); |
fujie@9274 | 326 | __ beq(R0, R0, done); |
fujie@9274 | 327 | __ delayed()->nop(); |
fujie@9274 | 328 | } |
fujie@9274 | 329 | __ bind(no_mdo); |
fujie@9274 | 330 | // Increment counter in MethodCounters |
fujie@9274 | 331 | const Address invocation_counter(FSR, |
fujie@9274 | 332 | MethodCounters::invocation_counter_offset() + |
fujie@9274 | 333 | InvocationCounter::counter_offset()); |
fujie@9274 | 334 | __ get_method_counters(Rmethod, FSR, done); |
fujie@9274 | 335 | __ increment_mask_and_jump(invocation_counter, increment, mask, T3, false, Assembler::zero, overflow); |
fujie@9274 | 336 | __ bind(done); |
fujie@9274 | 337 | } else { |
fujie@9274 | 338 | const Address invocation_counter(FSR, in_bytes(MethodCounters::invocation_counter_offset()) |
fujie@9274 | 339 | + in_bytes(InvocationCounter::counter_offset())); |
fujie@9274 | 340 | const Address backedge_counter (FSR, in_bytes(MethodCounters::backedge_counter_offset()) |
fujie@9274 | 341 | + in_bytes(InvocationCounter::counter_offset())); |
aoqi@1 | 342 | |
fujie@9274 | 343 | __ get_method_counters(Rmethod, FSR, done); |
aoqi@1 | 344 | |
fujie@9274 | 345 | if (ProfileInterpreter) { // %%% Merge this into methodDataOop |
fujie@9274 | 346 | __ lw(T9, FSR, in_bytes(MethodCounters::interpreter_invocation_counter_offset())); |
fujie@9274 | 347 | __ incrementl(T9, 1); |
fujie@9274 | 348 | __ sw(T9, FSR, in_bytes(MethodCounters::interpreter_invocation_counter_offset())); |
fujie@9274 | 349 | } |
fujie@9274 | 350 | // Update standard invocation counters |
fujie@9274 | 351 | __ lw(T3, invocation_counter); |
fujie@9274 | 352 | __ increment(T3, InvocationCounter::count_increment); |
fujie@9274 | 353 | __ sw(T3, invocation_counter); // save invocation count |
aoqi@1 | 354 | |
fujie@9274 | 355 | __ lw(FSR, backedge_counter); // load backedge counter |
fujie@9274 | 356 | __ li(AT, InvocationCounter::count_mask_value); // mask out the status bits |
fujie@9274 | 357 | __ andr(FSR, FSR, AT); |
aoqi@1 | 358 | |
fujie@9274 | 359 | __ dadd(T3, T3, FSR); // add both counters |
aoqi@1 | 360 | |
fujie@9274 | 361 | if (ProfileInterpreter && profile_method != NULL) { |
fujie@9274 | 362 | // Test to see if we should create a method data oop |
fujie@9274 | 363 | if (Assembler::is_simm16(InvocationCounter::InterpreterProfileLimit)) { |
fujie@9274 | 364 | __ slti(AT, T3, InvocationCounter::InterpreterProfileLimit); |
fujie@9274 | 365 | } else { |
fujie@9274 | 366 | __ li(AT, (long)&InvocationCounter::InterpreterProfileLimit); |
fujie@9274 | 367 | __ lw(AT, AT, 0); |
fujie@9274 | 368 | __ slt(AT, T3, AT); |
fujie@9274 | 369 | } |
fujie@9274 | 370 | |
fujie@9274 | 371 | __ bne_far(AT, R0, *profile_method_continue); |
fujie@9274 | 372 | __ delayed()->nop(); |
fujie@9274 | 373 | |
fujie@9274 | 374 | // if no method data exists, go to profile_method |
fujie@9274 | 375 | __ test_method_data_pointer(FSR, *profile_method); |
fujie@9274 | 376 | } |
fujie@9274 | 377 | |
fujie@9274 | 378 | if (Assembler::is_simm16(CompileThreshold)) { |
fujie@9274 | 379 | __ srl(AT, T3, InvocationCounter::count_shift); |
fujie@9274 | 380 | __ slti(AT, AT, CompileThreshold); |
fujie@6895 | 381 | } else { |
fujie@9274 | 382 | __ li(AT, (long)&InvocationCounter::InterpreterInvocationLimit); |
fujie@6895 | 383 | __ lw(AT, AT, 0); |
fujie@6895 | 384 | __ slt(AT, T3, AT); |
fujie@6895 | 385 | } |
fujie@6895 | 386 | |
fujie@9274 | 387 | __ beq_far(AT, R0, *overflow); |
aoqi@1 | 388 | __ delayed()->nop(); |
fujie@9274 | 389 | __ bind(done); |
aoqi@1 | 390 | } |
aoqi@1 | 391 | } |
aoqi@1 | 392 | |
aoqi@1 | 393 | void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { |
aoqi@1 | 394 | |
aoqi@6880 | 395 | // Asm interpreter on entry |
aoqi@6880 | 396 | // S7 - locals |
aoqi@6880 | 397 | // S0 - bcp |
aoqi@6880 | 398 | // Rmethod - method |
aoqi@6880 | 399 | // FP - interpreter frame |
aoqi@1 | 400 | |
aoqi@6880 | 401 | // On return (i.e. jump to entry_point) |
aoqi@6880 | 402 | // Rmethod - method |
aoqi@6880 | 403 | // RA - return address of interpreter caller |
aoqi@6880 | 404 | // tos - the last parameter to Java method |
aoqi@6880 | 405 | // SP - sender_sp |
aoqi@1 | 406 | |
aoqi@6880 | 407 | //const Address size_of_parameters(Rmethod,in_bytes( Method::size_of_parameters_offset())); |
aoqi@1 | 408 | |
aoqi@6880 | 409 | // the bcp is valid if and only if it's not null |
aoqi@6880 | 410 | __ call_VM(NOREG, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 411 | InterpreterRuntime::frequency_counter_overflow), R0); |
aoqi@6880 | 412 | __ ld(Rmethod, FP, method_offset); |
aoqi@6880 | 413 | // Preserve invariant that esi/edi contain bcp/locals of sender frame |
fujie@6896 | 414 | __ b_far(*do_continue); |
aoqi@6880 | 415 | __ delayed()->nop(); |
aoqi@1 | 416 | } |
aoqi@1 | 417 | |
aoqi@1 | 418 | // See if we've got enough room on the stack for locals plus overhead. |
aoqi@1 | 419 | // The expression stack grows down incrementally, so the normal guard |
aoqi@1 | 420 | // page mechanism will work for that. |
aoqi@1 | 421 | // |
aoqi@1 | 422 | // NOTE: Since the additional locals are also always pushed (wasn't |
aoqi@1 | 423 | // obvious in generate_method_entry) so the guard should work for them |
aoqi@1 | 424 | // too. |
aoqi@1 | 425 | // |
aoqi@1 | 426 | // Args: |
aoqi@1 | 427 | // rdx: number of additional locals this frame needs (what we must check) |
aoqi@1 | 428 | // rbx: Method* |
aoqi@1 | 429 | // |
aoqi@1 | 430 | // Kills: |
aoqi@1 | 431 | // rax |
aoqi@1 | 432 | void InterpreterGenerator::generate_stack_overflow_check(void) { |
aoqi@1 | 433 | // see if we've got enough room on the stack for locals plus overhead. |
aoqi@1 | 434 | // the expression stack grows down incrementally, so the normal guard |
aoqi@1 | 435 | // page mechanism will work for that. |
aoqi@1 | 436 | // |
aoqi@1 | 437 | // Registers live on entry: |
aoqi@1 | 438 | // |
aoqi@1 | 439 | // T0: Method* |
aoqi@1 | 440 | // T2: number of additional locals this frame needs (what we must check) |
aoqi@1 | 441 | |
aoqi@1 | 442 | // NOTE: since the additional locals are also always pushed (wasn't obvious in |
aoqi@6880 | 443 | // generate_method_entry) so the guard should work for them too. |
aoqi@1 | 444 | // |
aoqi@1 | 445 | |
aoqi@1 | 446 | // monitor entry size: see picture of stack set (generate_method_entry) and frame_i486.hpp |
aoqi@1 | 447 | const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; |
aoqi@1 | 448 | |
aoqi@1 | 449 | // total overhead size: entry_size + (saved ebp thru expr stack bottom). |
aoqi@1 | 450 | // be sure to change this if you add/subtract anything to/from the overhead area |
aoqi@6880 | 451 | const int overhead_size = -(frame::interpreter_frame_initial_sp_offset*wordSize) |
aoqi@1 | 452 | + entry_size; |
aoqi@1 | 453 | |
aoqi@1 | 454 | const int page_size = os::vm_page_size(); |
aoqi@1 | 455 | |
aoqi@1 | 456 | Label after_frame_check; |
aoqi@1 | 457 | |
aoqi@1 | 458 | // see if the frame is greater than one page in size. If so, |
aoqi@1 | 459 | // then we need to verify there is enough stack space remaining |
aoqi@1 | 460 | // for the additional locals. |
aoqi@1 | 461 | __ move(AT, (page_size - overhead_size) / Interpreter::stackElementSize); |
aoqi@1 | 462 | __ slt(AT, AT, T2); |
aoqi@1 | 463 | __ beq(AT, R0, after_frame_check); |
aoqi@1 | 464 | __ delayed()->nop(); |
aoqi@1 | 465 | |
aoqi@1 | 466 | // compute sp as if this were going to be the last frame on |
aoqi@1 | 467 | // the stack before the red zone |
aoqi@1 | 468 | #ifndef OPT_THREAD |
aoqi@1 | 469 | Register thread = T1; |
aoqi@1 | 470 | __ get_thread(thread); |
aoqi@1 | 471 | #else |
aoqi@1 | 472 | Register thread = TREG; |
aoqi@1 | 473 | #endif |
aoqi@1 | 474 | |
aoqi@1 | 475 | // locals + overhead, in bytes |
aoqi@6880 | 476 | __ dsll(T3, T2, Interpreter::stackElementScale()); |
aoqi@6880 | 477 | __ daddiu(T3, T3, overhead_size); // locals * 4 + overhead_size --> T3 |
aoqi@1 | 478 | |
aoqi@1 | 479 | #ifdef ASSERT |
aoqi@1 | 480 | Label stack_base_okay, stack_size_okay; |
aoqi@1 | 481 | // verify that thread stack base is non-zero |
aoqi@1 | 482 | __ ld(AT, thread, in_bytes(Thread::stack_base_offset())); |
aoqi@1 | 483 | __ bne(AT, R0, stack_base_okay); |
aoqi@1 | 484 | __ delayed()->nop(); |
aoqi@1 | 485 | __ stop("stack base is zero"); |
aoqi@1 | 486 | __ bind(stack_base_okay); |
aoqi@1 | 487 | // verify that thread stack size is non-zero |
aoqi@1 | 488 | __ ld(AT, thread, in_bytes(Thread::stack_size_offset())); |
aoqi@1 | 489 | __ bne(AT, R0, stack_size_okay); |
aoqi@1 | 490 | __ delayed()->nop(); |
aoqi@1 | 491 | __ stop("stack size is zero"); |
aoqi@1 | 492 | __ bind(stack_size_okay); |
aoqi@1 | 493 | #endif |
aoqi@1 | 494 | |
aoqi@1 | 495 | // Add stack base to locals and subtract stack size |
aoqi@1 | 496 | __ ld(AT, thread, in_bytes(Thread::stack_base_offset())); // stack_base --> AT |
aoqi@6880 | 497 | __ dadd(T3, T3, AT); // locals * 4 + overhead_size + stack_base--> T3 |
aoqi@1 | 498 | __ ld(AT, thread, in_bytes(Thread::stack_size_offset())); // stack_size --> AT |
aoqi@6880 | 499 | __ dsub(T3, T3, AT); // locals * 4 + overhead_size + stack_base - stack_size --> T3 |
aoqi@1 | 500 | |
aoqi@1 | 501 | |
aoqi@1 | 502 | // add in the redzone and yellow size |
aoqi@1 | 503 | __ move(AT, (StackRedPages+StackYellowPages) * page_size); |
aoqi@1 | 504 | __ add(T3, T3, AT); |
aoqi@1 | 505 | |
aoqi@1 | 506 | // check against the current stack bottom |
aoqi@1 | 507 | __ slt(AT, T3, SP); |
aoqi@1 | 508 | __ bne(AT, R0, after_frame_check); |
aoqi@1 | 509 | __ delayed()->nop(); |
fujie@407 | 510 | |
fujie@407 | 511 | // Note: the restored frame is not necessarily interpreted. |
fujie@407 | 512 | // Use the shared runtime version of the StackOverflowError. |
fujie@407 | 513 | __ move(SP, Rsender); |
fujie@407 | 514 | assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "stub not yet generated"); |
fujie@407 | 515 | __ jmp(StubRoutines::throw_StackOverflowError_entry(), relocInfo::runtime_call_type); |
aoqi@1 | 516 | __ delayed()->nop(); |
aoqi@1 | 517 | |
aoqi@1 | 518 | // all done with frame size check |
aoqi@1 | 519 | __ bind(after_frame_check); |
aoqi@1 | 520 | } |
aoqi@1 | 521 | |
aoqi@1 | 522 | // Allocate monitor and lock method (asm interpreter) |
aoqi@1 | 523 | // Rmethod - Method* |
aoqi@1 | 524 | void InterpreterGenerator::lock_method(void) { |
aoqi@1 | 525 | // synchronize method |
aoqi@1 | 526 | const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; |
aoqi@1 | 527 | |
aoqi@1 | 528 | #ifdef ASSERT |
aoqi@1 | 529 | { Label L; |
aoqi@1 | 530 | __ lw(T0, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 531 | __ andi(T0, T0, JVM_ACC_SYNCHRONIZED); |
aoqi@1 | 532 | __ bne(T0, R0, L); |
aoqi@1 | 533 | __ delayed()->nop(); |
aoqi@1 | 534 | __ stop("method doesn't need synchronization"); |
aoqi@1 | 535 | __ bind(L); |
aoqi@1 | 536 | } |
aoqi@1 | 537 | #endif // ASSERT |
aoqi@1 | 538 | // get synchronization object |
aoqi@6880 | 539 | { |
aoqi@6880 | 540 | Label done; |
aoqi@1 | 541 | const int mirror_offset = in_bytes(Klass::java_mirror_offset()); |
aoqi@1 | 542 | __ lw(T0, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 543 | __ andi(T2, T0, JVM_ACC_STATIC); |
aoqi@6880 | 544 | __ ld(T0, LVP, Interpreter::local_offset_in_bytes(0)); |
aoqi@1 | 545 | __ beq(T2, R0, done); |
aoqi@1 | 546 | __ delayed()->nop(); |
aoqi@1 | 547 | __ ld(T0, Rmethod, in_bytes(Method::const_offset())); |
aoqi@1 | 548 | __ ld(T0, T0, in_bytes(ConstMethod::constants_offset())); |
aoqi@1 | 549 | __ ld(T0, T0, ConstantPool::pool_holder_offset_in_bytes()); |
aoqi@1 | 550 | __ ld(T0, T0, mirror_offset); |
aoqi@1 | 551 | __ bind(done); |
aoqi@1 | 552 | } |
aoqi@1 | 553 | // add space for monitor & lock |
aoqi@1 | 554 | __ daddi(SP, SP, (-1) * entry_size); // add space for a monitor entry |
aoqi@1 | 555 | __ sd(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); |
aoqi@1 | 556 | // set new monitor block top |
aoqi@1 | 557 | __ sd(T0, SP, BasicObjectLock::obj_offset_in_bytes()); // store object |
aoqi@1 | 558 | // FIXME: I do not know what lock_object will do and what it will need |
aoqi@1 | 559 | __ move(c_rarg0, SP); // object address |
aoqi@6880 | 560 | __ lock_object(c_rarg0); |
aoqi@1 | 561 | } |
aoqi@1 | 562 | |
aoqi@1 | 563 | // Generate a fixed interpreter frame. This is identical setup for |
aoqi@1 | 564 | // interpreted methods and for native methods hence the shared code. |
aoqi@1 | 565 | void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { |
aoqi@1 | 566 | |
aoqi@1 | 567 | // [ local var m-1 ] <--- sp |
aoqi@1 | 568 | // ... |
aoqi@6880 | 569 | // [ local var 0 ] |
aoqi@1 | 570 | // [ argumnet word n-1 ] <--- T0(sender's sp) |
aoqi@1 | 571 | // ... |
aoqi@1 | 572 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 573 | |
aoqi@1 | 574 | // initialize fixed part of activation frame |
aoqi@1 | 575 | // sender's sp in Rsender |
aoqi@1 | 576 | int i = 0; |
aoqi@6880 | 577 | __ sd(RA, SP, (-1) * wordSize); // save return address |
aoqi@6880 | 578 | __ sd(FP, SP, (-2) * wordSize); // save sender's fp |
aoqi@1 | 579 | __ daddiu(FP, SP, (-2) * wordSize); |
aoqi@6880 | 580 | __ sd(Rsender, FP, (-++i) * wordSize); // save sender's sp |
aoqi@9228 | 581 | __ sd(R0, FP,(-++i)*wordSize); //save last_sp as null |
aoqi@6880 | 582 | __ sd(LVP, FP, (-++i) * wordSize); // save locals offset |
aoqi@1 | 583 | __ ld(BCP, Rmethod, in_bytes(Method::const_offset())); // get constMethodOop |
aoqi@1 | 584 | __ daddiu(BCP, BCP, in_bytes(ConstMethod::codes_offset())); // get codebase |
aoqi@1 | 585 | __ sd(Rmethod, FP, (-++i) * wordSize); // save Method* |
aoqi@1 | 586 | #ifndef CORE |
aoqi@1 | 587 | if (ProfileInterpreter) { |
aoqi@1 | 588 | Label method_data_continue; |
aoqi@6880 | 589 | __ ld(AT, Rmethod, in_bytes(Method::method_data_offset())); |
aoqi@6880 | 590 | __ beq(AT, R0, method_data_continue); |
aoqi@6880 | 591 | __ delayed()->nop(); |
aoqi@6880 | 592 | __ daddi(AT, AT, in_bytes(MethodData::data_offset())); |
aoqi@1 | 593 | __ bind(method_data_continue); |
aoqi@1 | 594 | __ sd(AT, FP, (-++i) * wordSize); |
aoqi@1 | 595 | } else { |
aoqi@1 | 596 | __ sd(R0, FP, (-++i) * wordSize); |
aoqi@1 | 597 | } |
aoqi@1 | 598 | #endif // !CORE |
aoqi@1 | 599 | |
aoqi@1 | 600 | __ ld(T2, Rmethod, in_bytes(Method::const_offset())); |
aoqi@1 | 601 | __ ld(T2, T2, in_bytes(ConstMethod::constants_offset())); |
aoqi@1 | 602 | __ ld(T2, T2, ConstantPool::cache_offset_in_bytes()); |
aoqi@1 | 603 | __ sd(T2, FP, (-++i) * wordSize); // set constant pool cache |
aoqi@1 | 604 | if (native_call) { |
aoqi@6880 | 605 | __ sd(R0, FP, (-++i) * wordSize); // no bcp |
aoqi@1 | 606 | } else { |
aoqi@6880 | 607 | __ sd(BCP, FP, (-++i) * wordSize); // set bcp |
aoqi@1 | 608 | } |
aoqi@1 | 609 | __ daddiu(SP, FP, (-++i) * wordSize); |
aoqi@6880 | 610 | __ sd(SP, FP, (-i) * wordSize); // reserve word for pointer to expression stack bottom |
aoqi@1 | 611 | } |
aoqi@1 | 612 | |
aoqi@1 | 613 | // End of helpers |
aoqi@1 | 614 | |
aoqi@1 | 615 | // Various method entries |
aoqi@1 | 616 | //------------------------------------------------------------------------------------------------------------------------ |
aoqi@1 | 617 | // |
aoqi@1 | 618 | // |
aoqi@1 | 619 | |
aoqi@1 | 620 | // Call an accessor method (assuming it is resolved, otherwise drop |
aoqi@1 | 621 | // into vanilla (slow path) entry |
aoqi@1 | 622 | address InterpreterGenerator::generate_accessor_entry(void) { |
aoqi@1 | 623 | |
aoqi@1 | 624 | // Rmethod: Method* |
aoqi@1 | 625 | // V0: receiver (preserve for slow entry into asm interpreter) |
aoqi@1 | 626 | // Rsender: senderSP must preserved for slow path, set SP to it on fast path |
aoqi@1 | 627 | |
aoqi@1 | 628 | address entry_point = __ pc(); |
aoqi@1 | 629 | Label xreturn_path; |
aoqi@1 | 630 | // do fastpath for resolved accessor methods |
aoqi@1 | 631 | if (UseFastAccessorMethods) { |
aoqi@1 | 632 | Label slow_path; |
aoqi@6880 | 633 | __ li(T2, SafepointSynchronize::address_of_state()); |
aoqi@1 | 634 | __ lw(AT, T2, 0); |
aoqi@1 | 635 | __ daddi(AT, AT, -(SafepointSynchronize::_not_synchronized)); |
aoqi@6880 | 636 | __ bne(AT, R0, slow_path); |
aoqi@6880 | 637 | __ delayed()->nop(); |
aoqi@6880 | 638 | // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; |
aoqi@1 | 639 | // parameter size = 1 |
aoqi@1 | 640 | // Note: We can only use this code if the getfield has been resolved |
aoqi@1 | 641 | // and if we don't have a null-pointer exception => check for |
aoqi@1 | 642 | // these conditions first and use slow path if necessary. |
aoqi@1 | 643 | // Rmethod: method |
aoqi@1 | 644 | // V0: receiver |
aoqi@1 | 645 | |
aoqi@1 | 646 | // [ receiver ] <-- sp |
aoqi@1 | 647 | __ ld(T0, SP, 0); |
aoqi@1 | 648 | |
aoqi@1 | 649 | // check if local 0 != NULL and read field |
aoqi@1 | 650 | __ beq(T0, R0, slow_path); |
aoqi@1 | 651 | __ delayed()->nop(); |
aoqi@1 | 652 | __ ld(T2, Rmethod, in_bytes(Method::const_offset())); |
aoqi@1 | 653 | __ ld(T2, T2, in_bytes(ConstMethod::constants_offset())); |
aoqi@1 | 654 | // read first instruction word and extract bytecode @ 1 and index @ 2 |
aoqi@1 | 655 | __ ld(T3, Rmethod, in_bytes(Method::const_offset())); |
aoqi@1 | 656 | __ lw(T3, T3, in_bytes(ConstMethod::codes_offset())); |
aoqi@1 | 657 | // Shift codes right to get the index on the right. |
aoqi@1 | 658 | // The bytecode fetched looks like <index><0xb4><0x2a> |
aoqi@1 | 659 | __ dsrl(T3, T3, 2 * BitsPerByte); |
aoqi@1 | 660 | // FIXME: maybe it's wrong |
aoqi@1 | 661 | __ dsll(T3, T3, exact_log2(in_words(ConstantPoolCacheEntry::size()))); |
aoqi@1 | 662 | __ ld(T2, T2, ConstantPool::cache_offset_in_bytes()); |
aoqi@1 | 663 | |
aoqi@1 | 664 | // T0: local 0 eax |
aoqi@1 | 665 | // Rmethod: method ebx |
aoqi@1 | 666 | // V0: receiver - do not destroy since it is needed for slow path! ecx |
aoqi@6880 | 667 | // ecx: scratch use which register instead ? |
aoqi@6880 | 668 | // T1: scratch use which register instead ? |
aoqi@6880 | 669 | // T3: constant pool cache index edx |
aoqi@6880 | 670 | // T2: constant pool cache edi |
aoqi@1 | 671 | // esi: send's sp |
aoqi@1 | 672 | // Rsender: send's sp |
aoqi@1 | 673 | // check if getfield has been resolved and read constant pool cache entry |
aoqi@1 | 674 | // check the validity of the cache entry by testing whether _indices field |
aoqi@1 | 675 | // contains Bytecode::_getfield in b1 byte. |
aoqi@1 | 676 | assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below"); |
aoqi@6880 | 677 | // __ movl(esi, |
aoqi@6880 | 678 | // Address(edi, |
aoqi@6880 | 679 | // edx, |
aoqi@6880 | 680 | // Address::times_4, ConstantPoolCache::base_offset() |
aoqi@6880 | 681 | // + ConstantPoolCacheEntry::indices_offset())); |
aoqi@1 | 682 | |
aoqi@1 | 683 | |
aoqi@1 | 684 | __ dsll(T8, T3, Address::times_8); |
aoqi@6880 | 685 | __ move(T1, in_bytes(ConstantPoolCache::base_offset() |
aoqi@6880 | 686 | + ConstantPoolCacheEntry::indices_offset())); |
aoqi@1 | 687 | __ dadd(T1, T8, T1); |
aoqi@1 | 688 | __ dadd(T1, T1, T2); |
aoqi@1 | 689 | __ lw(T1, T1, 0); |
aoqi@1 | 690 | __ dsrl(T1, T1, 2 * BitsPerByte); |
aoqi@1 | 691 | __ andi(T1, T1, 0xFF); |
aoqi@1 | 692 | __ daddi(T1, T1, (-1) * Bytecodes::_getfield); |
aoqi@1 | 693 | __ bne(T1, R0, slow_path); |
aoqi@1 | 694 | __ delayed()->nop(); |
aoqi@1 | 695 | |
aoqi@1 | 696 | // Note: constant pool entry is not valid before bytecode is resolved |
aoqi@1 | 697 | |
aoqi@6880 | 698 | __ move(T1, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); |
aoqi@1 | 699 | __ dadd(T1, T1, T8); |
aoqi@1 | 700 | __ dadd(T1, T1, T2); |
aoqi@1 | 701 | __ lw(AT, T1, 0); |
aoqi@1 | 702 | |
aoqi@6880 | 703 | __ move(T1, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); |
aoqi@1 | 704 | __ dadd(T1, T1, T8); |
aoqi@1 | 705 | __ dadd(T1, T1, T2); |
aoqi@1 | 706 | __ lw(T3, T1, 0); |
aoqi@1 | 707 | |
fujie@8858 | 708 | Label notByte, notBool, notShort, notChar, notObj; |
aoqi@1 | 709 | // const Address field_address (eax, esi, Address::times_1); |
aoqi@1 | 710 | |
aoqi@1 | 711 | // Need to differentiate between igetfield, agetfield, bgetfield etc. |
aoqi@1 | 712 | // because they are different sizes. |
aoqi@1 | 713 | // Use the type from the constant pool cache |
fujie@8864 | 714 | __ srl(T3, T3, ConstantPoolCacheEntry::tos_state_shift); |
aoqi@1 | 715 | // Make sure we don't need to mask edx for tosBits after the above shift |
aoqi@1 | 716 | ConstantPoolCacheEntry::verify_tos_state_shift(); |
aoqi@1 | 717 | // btos = 0 |
aoqi@1 | 718 | __ bne(T3, R0, notByte); |
aoqi@1 | 719 | __ delayed()->dadd(T0, T0, AT); |
aoqi@1 | 720 | |
aoqi@1 | 721 | __ lb(V0, T0, 0); |
aoqi@1 | 722 | __ b(xreturn_path); |
aoqi@1 | 723 | __ delayed()->nop(); |
aoqi@1 | 724 | |
fujie@8858 | 725 | //ztos |
fujie@8858 | 726 | __ bind(notByte); |
fujie@8858 | 727 | __ daddi(T1, T3, (-1) * ztos); |
fujie@8858 | 728 | __ bne(T1, R0, notBool); |
fujie@8858 | 729 | __ delayed()->nop(); |
fujie@8858 | 730 | __ lb(V0, T0, 0); |
fujie@8858 | 731 | __ b(xreturn_path); |
fujie@8858 | 732 | __ delayed()->nop(); |
fujie@8858 | 733 | |
aoqi@1 | 734 | //stos |
fujie@8858 | 735 | __ bind(notBool); |
aoqi@1 | 736 | __ daddi(T1, T3, (-1) * stos); |
aoqi@1 | 737 | __ bne(T1, R0, notShort); |
aoqi@1 | 738 | __ delayed()->nop(); |
aoqi@1 | 739 | __ lh(V0, T0, 0); |
aoqi@1 | 740 | __ b(xreturn_path); |
aoqi@1 | 741 | __ delayed()->nop(); |
aoqi@1 | 742 | |
aoqi@1 | 743 | //ctos |
aoqi@1 | 744 | __ bind(notShort); |
aoqi@1 | 745 | __ daddi(T1, T3, (-1) * ctos); |
aoqi@1 | 746 | __ bne(T1, R0, notChar); |
aoqi@1 | 747 | __ delayed()->nop(); |
aoqi@1 | 748 | __ lhu(V0, T0, 0); |
aoqi@1 | 749 | __ b(xreturn_path); |
aoqi@1 | 750 | __ delayed()->nop(); |
aoqi@6880 | 751 | |
aoqi@1 | 752 | //atos |
aoqi@1 | 753 | __ bind(notChar); |
aoqi@1 | 754 | __ daddi(T1, T3, (-1) * atos); |
aoqi@1 | 755 | __ bne(T1, R0, notObj); |
aoqi@1 | 756 | __ delayed()->nop(); |
aoqi@1 | 757 | //add for compressedoops |
aoqi@1 | 758 | __ load_heap_oop(V0, Address(T0, 0)); |
aoqi@1 | 759 | __ b(xreturn_path); |
aoqi@1 | 760 | __ delayed()->nop(); |
aoqi@1 | 761 | |
aoqi@1 | 762 | //itos |
aoqi@1 | 763 | __ bind(notObj); |
aoqi@1 | 764 | #ifdef ASSERT |
aoqi@1 | 765 | Label okay; |
aoqi@1 | 766 | __ daddi(T1, T3, (-1) * itos); |
aoqi@1 | 767 | __ beq(T1, R0, okay); |
aoqi@1 | 768 | __ delayed()->nop(); |
aoqi@1 | 769 | __ stop("what type is this?"); |
aoqi@1 | 770 | __ bind(okay); |
aoqi@1 | 771 | #endif // ASSERT |
aoqi@1 | 772 | __ lw(V0, T0, 0); |
aoqi@1 | 773 | |
aoqi@1 | 774 | __ bind(xreturn_path); |
aoqi@1 | 775 | |
aoqi@1 | 776 | // _ireturn/_areturn |
aoqi@6880 | 777 | //FIXME |
aoqi@6880 | 778 | __ move(SP, Rsender);//FIXME, set sender's fp to SP |
aoqi@1 | 779 | __ jr(RA); |
aoqi@1 | 780 | __ delayed()->nop(); |
aoqi@1 | 781 | |
aoqi@1 | 782 | // generate a vanilla interpreter entry as the slow path |
aoqi@1 | 783 | __ bind(slow_path); |
aoqi@1 | 784 | (void) generate_normal_entry(false); |
aoqi@1 | 785 | } else { |
aoqi@1 | 786 | (void) generate_normal_entry(false); |
aoqi@1 | 787 | } |
aoqi@1 | 788 | |
aoqi@1 | 789 | return entry_point; |
aoqi@1 | 790 | } |
aoqi@1 | 791 | |
aoqi@1 | 792 | // Method entry for java.lang.ref.Reference.get. |
aoqi@1 | 793 | address InterpreterGenerator::generate_Reference_get_entry(void) { |
aoqi@6880 | 794 | #if INCLUDE_ALL_GCS |
aoqi@1 | 795 | // Code: _aload_0, _getfield, _areturn |
aoqi@1 | 796 | // parameter size = 1 |
aoqi@1 | 797 | // |
aoqi@1 | 798 | // The code that gets generated by this routine is split into 2 parts: |
aoqi@1 | 799 | // 1. The "intrinsified" code for G1 (or any SATB based GC), |
aoqi@1 | 800 | // 2. The slow path - which is an expansion of the regular method entry. |
aoqi@1 | 801 | // |
aoqi@1 | 802 | // Notes:- |
aoqi@1 | 803 | // * In the G1 code we do not check whether we need to block for |
aoqi@1 | 804 | // a safepoint. If G1 is enabled then we must execute the specialized |
aoqi@1 | 805 | // code for Reference.get (except when the Reference object is null) |
aoqi@1 | 806 | // so that we can log the value in the referent field with an SATB |
aoqi@1 | 807 | // update buffer. |
aoqi@1 | 808 | // If the code for the getfield template is modified so that the |
aoqi@1 | 809 | // G1 pre-barrier code is executed when the current method is |
aoqi@1 | 810 | // Reference.get() then going through the normal method entry |
aoqi@1 | 811 | // will be fine. |
aoqi@1 | 812 | // * The G1 code can, however, check the receiver object (the instance |
aoqi@1 | 813 | // of java.lang.Reference) and jump to the slow path if null. If the |
aoqi@1 | 814 | // Reference object is null then we obviously cannot fetch the referent |
aoqi@1 | 815 | // and so we don't need to call the G1 pre-barrier. Thus we can use the |
aoqi@1 | 816 | // regular method entry code to generate the NPE. |
aoqi@1 | 817 | // |
aoqi@1 | 818 | // This code is based on generate_accessor_enty. |
aoqi@1 | 819 | // |
fujie@8004 | 820 | // rbx: Method* (Rmethod) |
aoqi@1 | 821 | |
fujie@8004 | 822 | // r13: senderSP must preserve for slow path, set SP to it on fast path (Rsender) |
fujie@8004 | 823 | |
fujie@8004 | 824 | // rax: V0 |
fujie@8004 | 825 | // rbx: Rmethod |
fujie@8004 | 826 | // r13: Rsender |
aoqi@8027 | 827 | // rdi: T9 |
aoqi@1 | 828 | |
aoqi@1 | 829 | address entry = __ pc(); |
aoqi@1 | 830 | |
aoqi@1 | 831 | const int referent_offset = java_lang_ref_Reference::referent_offset; |
aoqi@1 | 832 | guarantee(referent_offset > 0, "referent offset not initialized"); |
aoqi@1 | 833 | |
aoqi@1 | 834 | if (UseG1GC) { |
aoqi@1 | 835 | Label slow_path; |
aoqi@1 | 836 | |
aoqi@1 | 837 | // Check if local 0 != NULL |
aoqi@1 | 838 | // If the receiver is null then it is OK to jump to the slow path. |
fujie@8004 | 839 | __ ld(V0, SP, 0); |
fujie@8004 | 840 | |
fujie@8004 | 841 | __ beq(V0, R0, slow_path); |
zhaixiang@9144 | 842 | __ delayed()->nop(); |
aoqi@1 | 843 | |
aoqi@1 | 844 | // Generate the G1 pre-barrier code to log the value of |
aoqi@1 | 845 | // the referent field in an SATB buffer. |
aoqi@1 | 846 | |
aoqi@1 | 847 | // Load the value of the referent field. |
fujie@8004 | 848 | const Address field_address(V0, referent_offset); |
fujie@8004 | 849 | __ load_heap_oop(V0, field_address); |
fujie@8004 | 850 | |
fujie@8008 | 851 | __ push(RA); |
fujie@8004 | 852 | // Generate the G1 pre-barrier code to log the value of |
fujie@8004 | 853 | // the referent field in an SATB buffer. |
fujie@8004 | 854 | __ g1_write_barrier_pre(noreg /* obj */, |
fujie@8004 | 855 | V0 /* pre_val */, |
fujie@8004 | 856 | TREG /* thread */, |
fujie@8004 | 857 | Rmethod /* tmp */, |
fujie@8004 | 858 | true /* tosca_live */, |
fujie@8004 | 859 | true /* expand_call */); |
fujie@8008 | 860 | __ pop(RA); |
fujie@8004 | 861 | |
fujie@8004 | 862 | __ jr(RA); |
fujie@8008 | 863 | __ delayed()->daddu(SP, Rsender, R0); // set sp to sender sp |
fujie@8004 | 864 | |
fujie@8004 | 865 | // generate a vanilla interpreter entry as the slow path |
fujie@8004 | 866 | __ bind(slow_path); |
fujie@8004 | 867 | (void) generate_normal_entry(false); |
aoqi@1 | 868 | |
aoqi@1 | 869 | return entry; |
aoqi@1 | 870 | } |
aoqi@6880 | 871 | #endif // INCLUDE_ALL_GCS |
aoqi@1 | 872 | |
aoqi@1 | 873 | // If G1 is not enabled then attempt to go through the accessor entry point |
aoqi@1 | 874 | // Reference.get is an accessor |
aoqi@1 | 875 | return generate_accessor_entry(); |
aoqi@1 | 876 | } |
fujie@8004 | 877 | |
aoqi@1 | 878 | // Interpreter stub for calling a native method. (asm interpreter) |
aoqi@1 | 879 | // This sets up a somewhat different looking stack for calling the |
aoqi@1 | 880 | // native method than the typical interpreter frame setup. |
aoqi@1 | 881 | address InterpreterGenerator::generate_native_entry(bool synchronized) { |
aoqi@1 | 882 | // determine code generation flags |
aoqi@1 | 883 | bool inc_counter = UseCompiler || CountCompiledCalls; |
aoqi@1 | 884 | // Rsender: sender's sp |
aoqi@1 | 885 | // Rmethod: Method* |
aoqi@1 | 886 | address entry_point = __ pc(); |
aoqi@1 | 887 | |
aoqi@1 | 888 | #ifndef CORE |
aoqi@1 | 889 | const Address invocation_counter(Rmethod,in_bytes(MethodCounters::invocation_counter_offset() + // Fu: 20130814 |
aoqi@6880 | 890 | InvocationCounter::counter_offset())); |
aoqi@1 | 891 | #endif |
aoqi@1 | 892 | |
aoqi@1 | 893 | // get parameter size (always needed) |
aoqi@1 | 894 | // the size in the java stack |
aoqi@6880 | 895 | __ ld(V0, Rmethod, in_bytes(Method::const_offset())); |
aoqi@1 | 896 | __ lhu(V0, V0, in_bytes(ConstMethod::size_of_parameters_offset())); // Fu: 20130814 |
aoqi@1 | 897 | |
aoqi@1 | 898 | // native calls don't need the stack size check since they have no expression stack |
aoqi@1 | 899 | // and the arguments are already on the stack and we only add a handful of words |
aoqi@6880 | 900 | // to the stack |
aoqi@1 | 901 | |
aoqi@1 | 902 | // Rmethod: Method* |
aoqi@1 | 903 | // V0: size of parameters |
aoqi@1 | 904 | // Layout of frame at this point |
aoqi@1 | 905 | // |
aoqi@1 | 906 | // [ argument word n-1 ] <--- sp |
aoqi@1 | 907 | // ... |
aoqi@1 | 908 | // [ argument word 0 ] |
aoqi@1 | 909 | |
aoqi@1 | 910 | // for natives the size of locals is zero |
aoqi@1 | 911 | |
aoqi@1 | 912 | // compute beginning of parameters (S7) |
aoqi@1 | 913 | __ dsll(LVP, V0, Address::times_8); |
aoqi@1 | 914 | __ daddiu(LVP, LVP, (-1) * wordSize); |
aoqi@1 | 915 | __ dadd(LVP, LVP, SP); |
aoqi@1 | 916 | |
aoqi@1 | 917 | |
aoqi@1 | 918 | // add 2 zero-initialized slots for native calls |
aoqi@1 | 919 | __ daddi(SP, SP, (-2) * wordSize); |
aoqi@6880 | 920 | __ sd(R0, SP, 1 * wordSize); // slot for native oop temp offset (setup via runtime) |
aoqi@6880 | 921 | __ sd(R0, SP, 0 * wordSize); // slot for static native result handler3 (setup via runtime) |
aoqi@1 | 922 | |
aoqi@1 | 923 | // Layout of frame at this point |
aoqi@6880 | 924 | // [ method holder mirror ] <--- sp |
aoqi@6880 | 925 | // [ result type info ] |
aoqi@6880 | 926 | // [ argument word n-1 ] <--- T0 |
aoqi@1 | 927 | // ... |
aoqi@6880 | 928 | // [ argument word 0 ] <--- LVP |
aoqi@1 | 929 | |
aoqi@1 | 930 | |
aoqi@1 | 931 | #ifndef CORE |
aoqi@1 | 932 | if (inc_counter) __ lw(T3, invocation_counter); // (pre-)fetch invocation count |
aoqi@1 | 933 | #endif |
aoqi@1 | 934 | |
aoqi@1 | 935 | // initialize fixed part of activation frame |
aoqi@1 | 936 | generate_fixed_frame(true); |
aoqi@1 | 937 | // after this function, the layout of frame is as following |
aoqi@1 | 938 | // |
aoqi@1 | 939 | // [ monitor block top ] <--- sp ( the top monitor entry ) |
aoqi@1 | 940 | // [ byte code pointer (0) ] (if native, bcp = 0) |
aoqi@1 | 941 | // [ constant pool cache ] |
aoqi@1 | 942 | // [ Method* ] |
aoqi@1 | 943 | // [ locals offset ] |
aoqi@1 | 944 | // [ sender's sp ] |
aoqi@1 | 945 | // [ sender's fp ] |
aoqi@1 | 946 | // [ return address ] <--- fp |
aoqi@1 | 947 | // [ method holder mirror ] |
aoqi@1 | 948 | // [ result type info ] |
aoqi@6880 | 949 | // [ argumnet word n-1 ] <--- sender's sp |
aoqi@6880 | 950 | // ... |
aoqi@1 | 951 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 952 | |
aoqi@1 | 953 | |
aoqi@1 | 954 | // make sure method is native & not abstract |
aoqi@1 | 955 | #ifdef ASSERT |
aoqi@1 | 956 | __ lw(T0, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 957 | { |
aoqi@1 | 958 | Label L; |
aoqi@1 | 959 | __ andi(AT, T0, JVM_ACC_NATIVE); |
aoqi@1 | 960 | __ bne(AT, R0, L); |
aoqi@1 | 961 | __ delayed()->nop(); |
aoqi@1 | 962 | __ stop("tried to execute native method as non-native"); |
aoqi@1 | 963 | __ bind(L); |
aoqi@1 | 964 | } |
aoqi@6880 | 965 | { |
aoqi@6880 | 966 | Label L; |
aoqi@1 | 967 | __ andi(AT, T0, JVM_ACC_ABSTRACT); |
aoqi@1 | 968 | __ beq(AT, R0, L); |
aoqi@1 | 969 | __ delayed()->nop(); |
aoqi@1 | 970 | __ stop("tried to execute abstract method in interpreter"); |
aoqi@1 | 971 | __ bind(L); |
aoqi@1 | 972 | } |
aoqi@1 | 973 | #endif |
aoqi@1 | 974 | |
aoqi@1 | 975 | // Since at this point in the method invocation the exception handler |
aoqi@1 | 976 | // would try to exit the monitor of synchronized methods which hasn't |
aoqi@1 | 977 | // been entered yet, we set the thread local variable |
aoqi@1 | 978 | // _do_not_unlock_if_synchronized to true. The remove_activation will |
aoqi@1 | 979 | // check this flag. |
aoqi@1 | 980 | Register thread = TREG; |
aoqi@1 | 981 | #ifndef OPT_THREAD |
aoqi@1 | 982 | __ get_thread(thread); |
aoqi@1 | 983 | #endif |
aoqi@1 | 984 | __ move(AT, (int)true); |
aoqi@1 | 985 | __ sb(AT, thread, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
aoqi@1 | 986 | |
aoqi@1 | 987 | #ifndef CORE |
aoqi@1 | 988 | // increment invocation count & check for overflow |
aoqi@1 | 989 | Label invocation_counter_overflow; |
aoqi@1 | 990 | if (inc_counter) { |
aoqi@1 | 991 | generate_counter_incr(&invocation_counter_overflow, NULL, NULL); |
aoqi@1 | 992 | } |
aoqi@6880 | 993 | |
aoqi@1 | 994 | Label continue_after_compile; |
aoqi@1 | 995 | __ bind(continue_after_compile); |
aoqi@1 | 996 | #endif // CORE |
aoqi@1 | 997 | |
aoqi@1 | 998 | bang_stack_shadow_pages(true); |
aoqi@1 | 999 | |
aoqi@1 | 1000 | // reset the _do_not_unlock_if_synchronized flag |
aoqi@1 | 1001 | #ifndef OPT_THREAD |
aoqi@1 | 1002 | __ get_thread(thread); |
aoqi@1 | 1003 | #endif |
aoqi@1 | 1004 | __ sb(R0, thread, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
aoqi@1 | 1005 | |
aoqi@1 | 1006 | // check for synchronized methods |
aoqi@1 | 1007 | // Must happen AFTER invocation_counter check and stack overflow check, |
aoqi@1 | 1008 | // so method is not locked if overflows. |
aoqi@1 | 1009 | if (synchronized) { |
aoqi@1 | 1010 | lock_method(); |
aoqi@1 | 1011 | } else { |
aoqi@1 | 1012 | // no synchronization necessary |
aoqi@1 | 1013 | #ifdef ASSERT |
aoqi@1 | 1014 | { |
aoqi@1 | 1015 | Label L; |
aoqi@1 | 1016 | __ lw(T0, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1017 | __ andi(AT, T0, JVM_ACC_SYNCHRONIZED); |
aoqi@1 | 1018 | __ beq(AT, R0, L); |
aoqi@1 | 1019 | __ delayed()->nop(); |
aoqi@1 | 1020 | __ stop("method needs synchronization"); |
aoqi@1 | 1021 | __ bind(L); |
aoqi@1 | 1022 | } |
aoqi@1 | 1023 | #endif |
aoqi@1 | 1024 | } |
aoqi@1 | 1025 | |
aoqi@1 | 1026 | // after method_lock, the layout of frame is as following |
aoqi@1 | 1027 | // |
aoqi@1 | 1028 | // [ monitor entry ] <--- sp |
aoqi@1 | 1029 | // ... |
aoqi@1 | 1030 | // [ monitor entry ] |
aoqi@6880 | 1031 | // [ monitor block top ] ( the top monitor entry ) |
aoqi@1 | 1032 | // [ byte code pointer (0) ] (if native, bcp = 0) |
aoqi@1 | 1033 | // [ constant pool cache ] |
aoqi@1 | 1034 | // [ Method* ] |
aoqi@6880 | 1035 | // [ locals offset ] |
aoqi@1 | 1036 | // [ sender's sp ] |
aoqi@1 | 1037 | // [ sender's fp ] |
aoqi@1 | 1038 | // [ return address ] <--- fp |
aoqi@1 | 1039 | // [ method holder mirror ] |
aoqi@1 | 1040 | // [ result type info ] |
aoqi@1 | 1041 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@6880 | 1042 | // ... |
aoqi@1 | 1043 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 1044 | |
aoqi@1 | 1045 | // start execution |
aoqi@1 | 1046 | #ifdef ASSERT |
aoqi@6880 | 1047 | { |
aoqi@6880 | 1048 | Label L; |
aoqi@1 | 1049 | __ ld(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); |
aoqi@1 | 1050 | __ beq(AT, SP, L); |
aoqi@1 | 1051 | __ delayed()->nop(); |
aoqi@1 | 1052 | __ stop("broken stack frame setup in interpreter in asm"); |
aoqi@1 | 1053 | __ bind(L); |
aoqi@1 | 1054 | } |
aoqi@1 | 1055 | #endif |
aoqi@1 | 1056 | |
aoqi@1 | 1057 | // jvmti/jvmpi support |
aoqi@1 | 1058 | __ notify_method_entry(); |
aoqi@1 | 1059 | |
aoqi@1 | 1060 | // work registers |
aoqi@1 | 1061 | const Register method = Rmethod; |
aoqi@1 | 1062 | //const Register thread = T2; |
aoqi@6880 | 1063 | const Register t = RT4; |
aoqi@1 | 1064 | |
aoqi@1 | 1065 | __ get_method(method); |
aoqi@1 | 1066 | __ verify_oop(method); |
aoqi@6880 | 1067 | { |
aoqi@6880 | 1068 | Label L, Lstatic; |
aoqi@6880 | 1069 | __ ld(t,method,in_bytes(Method::const_offset())); |
aoqi@9228 | 1070 | __ lhu(t, t, in_bytes(ConstMethod::size_of_parameters_offset())); |
aoqi@1 | 1071 | // MIPS n64 ABI: caller does not reserve space for the register auguments. |
aoqi@1 | 1072 | // A0 and A1(if needed) |
aoqi@1 | 1073 | __ lw(AT, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1074 | __ andi(AT, AT, JVM_ACC_STATIC); |
aoqi@1 | 1075 | __ beq(AT, R0, Lstatic); |
aoqi@1 | 1076 | __ delayed()->nop(); |
aoqi@1 | 1077 | __ daddiu(t, t, 1); |
aoqi@1 | 1078 | __ bind(Lstatic); |
aoqi@1 | 1079 | __ daddiu(t, t, -7); |
aoqi@1 | 1080 | __ blez(t, L); |
aoqi@1 | 1081 | __ delayed()->nop(); |
aoqi@1 | 1082 | __ dsll(t, t, Address::times_8); |
aoqi@1 | 1083 | __ dsub(SP, SP, t); |
aoqi@1 | 1084 | __ bind(L); |
aoqi@1 | 1085 | } |
aoqi@1 | 1086 | __ move(AT, -(StackAlignmentInBytes)); |
aoqi@6880 | 1087 | __ andr(SP, SP, AT); |
aoqi@1 | 1088 | __ move(AT, SP); |
aoqi@6880 | 1089 | // [ ] <--- sp |
aoqi@1 | 1090 | // ... (size of parameters - 8 ) |
aoqi@6880 | 1091 | // [ monitor entry ] |
aoqi@1 | 1092 | // ... |
aoqi@1 | 1093 | // [ monitor entry ] |
aoqi@6880 | 1094 | // [ monitor block top ] ( the top monitor entry ) |
aoqi@1 | 1095 | // [ byte code pointer (0) ] (if native, bcp = 0) |
aoqi@1 | 1096 | // [ constant pool cache ] |
aoqi@1 | 1097 | // [ Method* ] |
aoqi@1 | 1098 | // [ locals offset ] |
aoqi@1 | 1099 | // [ sender's sp ] |
aoqi@1 | 1100 | // [ sender's fp ] |
aoqi@1 | 1101 | // [ return address ] <--- fp |
aoqi@1 | 1102 | // [ method holder mirror ] |
aoqi@1 | 1103 | // [ result type info ] |
aoqi@1 | 1104 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@6880 | 1105 | // ... |
aoqi@1 | 1106 | // [ argument word 0 ] <--- LVP |
aoqi@1 | 1107 | |
aoqi@1 | 1108 | // get signature handler |
aoqi@6880 | 1109 | { |
aoqi@1 | 1110 | Label L; |
aoqi@1 | 1111 | __ ld(T9, method, in_bytes(Method::signature_handler_offset())); |
aoqi@1 | 1112 | __ bne(T9, R0, L); |
aoqi@1 | 1113 | __ delayed()->nop(); |
aoqi@6880 | 1114 | __ call_VM(NOREG, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 1115 | InterpreterRuntime::prepare_native_call), method); |
aoqi@1 | 1116 | __ get_method(method); |
aoqi@1 | 1117 | __ ld(T9, method, in_bytes(Method::signature_handler_offset())); |
aoqi@1 | 1118 | __ bind(L); |
aoqi@1 | 1119 | } |
aoqi@1 | 1120 | |
aoqi@1 | 1121 | // call signature handler |
aoqi@1 | 1122 | // FIXME: when change codes in InterpreterRuntime, note this point |
aoqi@1 | 1123 | // from: begin of parameters |
aoqi@1 | 1124 | assert(InterpreterRuntime::SignatureHandlerGenerator::from() == LVP, "adjust this code"); |
aoqi@1 | 1125 | // to: current sp |
aoqi@1 | 1126 | assert(InterpreterRuntime::SignatureHandlerGenerator::to () == SP, "adjust this code"); |
aoqi@1 | 1127 | // temp: T3 |
aoqi@1 | 1128 | assert(InterpreterRuntime::SignatureHandlerGenerator::temp() == t , "adjust this code"); |
aoqi@1 | 1129 | |
aoqi@1 | 1130 | __ jalr(T9); |
aoqi@1 | 1131 | __ delayed()->nop(); |
aoqi@6880 | 1132 | __ get_method(method); // slow path call blows EBX on DevStudio 5.0 |
aoqi@1 | 1133 | |
aoqi@6880 | 1134 | /* |
aoqi@1 | 1135 | if native function is static, and its second parameter has type length of double word, |
aoqi@1 | 1136 | and first parameter has type length of word, we have to reserve one word |
aoqi@1 | 1137 | for the first parameter, according to mips o32 abi. |
aoqi@1 | 1138 | if native function is not static, and its third parameter has type length of double word, |
aoqi@1 | 1139 | and second parameter has type length of word, we have to reserve one word for the second |
aoqi@1 | 1140 | parameter. |
aoqi@1 | 1141 | */ |
aoqi@1 | 1142 | |
aoqi@1 | 1143 | |
aoqi@1 | 1144 | // result handler is in V0 |
aoqi@1 | 1145 | // set result handler |
aoqi@1 | 1146 | __ sd(V0, FP, (frame::interpreter_frame_result_handler_offset)*wordSize); |
aoqi@1 | 1147 | |
aoqi@1 | 1148 | #define FIRSTPARA_SHIFT_COUNT 5 |
aoqi@1 | 1149 | #define SECONDPARA_SHIFT_COUNT 9 |
aoqi@1 | 1150 | #define THIRDPARA_SHIFT_COUNT 13 |
aoqi@6880 | 1151 | #define PARA_MASK 0xf |
aoqi@1 | 1152 | |
aoqi@1 | 1153 | // pass mirror handle if static call |
aoqi@6880 | 1154 | { |
aoqi@1 | 1155 | Label L; |
aoqi@1 | 1156 | const int mirror_offset = in_bytes(Klass::java_mirror_offset()); |
aoqi@1 | 1157 | __ lw(t, method, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1158 | __ andi(AT, t, JVM_ACC_STATIC); |
aoqi@1 | 1159 | __ beq(AT, R0, L); |
aoqi@1 | 1160 | __ delayed()->nop(); |
aoqi@1 | 1161 | |
aoqi@1 | 1162 | // get mirror |
aoqi@1 | 1163 | __ ld(t, method, in_bytes(Method:: const_offset())); |
aoqi@1 | 1164 | __ ld(t, t, in_bytes(ConstMethod::constants_offset())); //?? |
aoqi@1 | 1165 | __ ld(t, t, ConstantPool::pool_holder_offset_in_bytes()); |
aoqi@1 | 1166 | __ ld(t, t, mirror_offset); |
aoqi@1 | 1167 | // copy mirror into activation frame |
aoqi@1 | 1168 | //__ sw(t, FP, frame::interpreter_frame_oop_temp_offset * wordSize); |
aoqi@1 | 1169 | // pass handle to mirror |
aoqi@1 | 1170 | __ sd(t, FP, frame::interpreter_frame_oop_temp_offset * wordSize); |
aoqi@1 | 1171 | __ daddi(t, FP, frame::interpreter_frame_oop_temp_offset * wordSize); |
aoqi@1 | 1172 | __ move(A1, t); |
aoqi@1 | 1173 | __ bind(L); |
aoqi@1 | 1174 | } |
aoqi@1 | 1175 | |
aoqi@1 | 1176 | // [ mthd holder mirror ptr ] <--- sp --------------------| (only for static method) |
aoqi@1 | 1177 | // [ ] | |
aoqi@1 | 1178 | // ... size of parameters(or +1) | |
aoqi@1 | 1179 | // [ monitor entry ] | |
aoqi@1 | 1180 | // ... | |
aoqi@1 | 1181 | // [ monitor entry ] | |
aoqi@1 | 1182 | // [ monitor block top ] ( the top monitor entry ) | |
aoqi@1 | 1183 | // [ byte code pointer (0) ] (if native, bcp = 0) | |
aoqi@1 | 1184 | // [ constant pool cache ] | |
aoqi@1 | 1185 | // [ Method* ] | |
aoqi@1 | 1186 | // [ locals offset ] | |
aoqi@1 | 1187 | // [ sender's sp ] | |
aoqi@1 | 1188 | // [ sender's fp ] | |
aoqi@1 | 1189 | // [ return address ] <--- fp | |
aoqi@6880 | 1190 | // [ method holder mirror ] <----------------------------| |
aoqi@1 | 1191 | // [ result type info ] |
aoqi@1 | 1192 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@6880 | 1193 | // ... |
aoqi@1 | 1194 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 1195 | |
aoqi@1 | 1196 | // get native function entry point |
aoqi@1 | 1197 | { Label L; |
aoqi@1 | 1198 | __ ld(T9, method, in_bytes(Method::native_function_offset())); |
aoqi@1 | 1199 | __ li(V1, SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); |
aoqi@1 | 1200 | __ bne(V1, T9, L); |
aoqi@1 | 1201 | __ delayed()->nop(); |
aoqi@1 | 1202 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), method); |
aoqi@1 | 1203 | __ get_method(method); |
aoqi@1 | 1204 | __ verify_oop(method); |
aoqi@1 | 1205 | __ ld(T9, method, in_bytes(Method::native_function_offset())); |
aoqi@1 | 1206 | __ bind(L); |
aoqi@1 | 1207 | } |
aoqi@1 | 1208 | /* |
aoqi@1 | 1209 | __ pushad(); |
aoqi@1 | 1210 | __ move(A0, T9); |
aoqi@1 | 1211 | __ call(CAST_FROM_FN_PTR(address, SharedRuntime::func_debug),relocInfo::runtime_call_type); |
aoqi@1 | 1212 | __ popad(); |
aoqi@1 | 1213 | */ |
aoqi@1 | 1214 | |
aoqi@1 | 1215 | // pass JNIEnv |
aoqi@1 | 1216 | // native function in T9 |
aoqi@1 | 1217 | #ifndef OPT_THREAD |
aoqi@1 | 1218 | __ get_thread(thread); |
aoqi@1 | 1219 | #endif |
aoqi@1 | 1220 | __ daddi(t, thread, in_bytes(JavaThread::jni_environment_offset())); |
aoqi@1 | 1221 | __ move(A0, t); |
aoqi@1 | 1222 | // [ jni environment ] <--- sp |
aoqi@1 | 1223 | // [ mthd holder mirror ptr ] ---------------------------->| (only for static method) |
aoqi@1 | 1224 | // [ ] | |
aoqi@1 | 1225 | // ... size of parameters | |
aoqi@1 | 1226 | // [ monitor entry ] | |
aoqi@1 | 1227 | // ... | |
aoqi@1 | 1228 | // [ monitor entry ] | |
aoqi@1 | 1229 | // [ monitor block top ] ( the top monitor entry ) | |
aoqi@1 | 1230 | // [ byte code pointer (0) ] (if native, bcp = 0) | |
aoqi@1 | 1231 | // [ constant pool cache ] | |
aoqi@1 | 1232 | // [ Method* ] | |
aoqi@1 | 1233 | // [ locals offset ] | |
aoqi@1 | 1234 | // [ sender's sp ] | |
aoqi@1 | 1235 | // [ sender's fp ] | |
aoqi@1 | 1236 | // [ return address ] <--- fp | |
aoqi@6880 | 1237 | // [ method holder mirror ] <----------------------------| |
aoqi@1 | 1238 | // [ result type info ] |
aoqi@1 | 1239 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@6880 | 1240 | // ... |
aoqi@1 | 1241 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 1242 | |
aoqi@1 | 1243 | // set_last_Java_frame_before_call |
aoqi@1 | 1244 | __ sd(FP, thread, in_bytes(JavaThread::last_Java_fp_offset())); |
aoqi@1 | 1245 | // Change state to native (we save the return address in the thread, since it might not |
aoqi@1 | 1246 | // be pushed on the stack when we do a a stack traversal). It is enough that the pc() |
aoqi@1 | 1247 | // points into the right code segment. It does not have to be the correct return pc. |
aoqi@1 | 1248 | __ li(t, __ pc()); |
aoqi@6880 | 1249 | __ sd(t, thread, in_bytes(JavaThread::last_Java_pc_offset())); |
aoqi@1 | 1250 | __ sd(SP, thread, in_bytes(JavaThread::last_Java_sp_offset())); |
aoqi@1 | 1251 | |
aoqi@1 | 1252 | // change thread state |
aoqi@1 | 1253 | #ifdef ASSERT |
aoqi@6880 | 1254 | { |
aoqi@6880 | 1255 | Label L; |
aoqi@1 | 1256 | __ lw(t, thread, in_bytes(JavaThread::thread_state_offset())); |
aoqi@1 | 1257 | __ daddi(t, t, (-1) * _thread_in_Java); |
aoqi@1 | 1258 | __ beq(t, R0, L); |
aoqi@1 | 1259 | __ delayed()->nop(); |
aoqi@1 | 1260 | __ stop("Wrong thread state in native stub"); |
aoqi@1 | 1261 | __ bind(L); |
aoqi@1 | 1262 | } |
aoqi@1 | 1263 | #endif |
aoqi@1 | 1264 | |
aoqi@1 | 1265 | __ move(t, _thread_in_native); |
aoqi@1 | 1266 | __ sw(t, thread, in_bytes(JavaThread::thread_state_offset())); |
aoqi@1 | 1267 | |
aoqi@1 | 1268 | // call native method |
aoqi@1 | 1269 | __ jalr(T9); |
aoqi@1 | 1270 | __ delayed()->nop(); |
aoqi@1 | 1271 | // result potentially in V2:V1 or F0:F1 |
aoqi@1 | 1272 | |
aoqi@1 | 1273 | |
aoqi@1 | 1274 | // via _last_native_pc and not via _last_jave_sp |
aoqi@1 | 1275 | // NOTE: the order of theses push(es) is known to frame::interpreter_frame_result. |
aoqi@1 | 1276 | // If the order changes or anything else is added to the stack the code in |
aoqi@1 | 1277 | // interpreter_frame_result will have to be changed. |
aoqi@1 | 1278 | //FIXME, should modify here |
aoqi@1 | 1279 | // save return value to keep the value from being destroyed by other calls |
aoqi@1 | 1280 | __ move(S1, V0); |
aoqi@1 | 1281 | __ move(S3, V1); |
aoqi@1 | 1282 | __ dmfc1(S4, F0); |
aoqi@1 | 1283 | __ dmfc1(S2, F1); |
aoqi@1 | 1284 | |
aoqi@1 | 1285 | // change thread state |
aoqi@6880 | 1286 | __ get_thread(thread); |
aoqi@1 | 1287 | __ move(t, _thread_in_native_trans); |
aoqi@1 | 1288 | __ sw(t, thread, in_bytes(JavaThread::thread_state_offset())); |
aoqi@1 | 1289 | |
aoqi@1 | 1290 | if( os::is_MP() ) __ sync(); // Force this write out before the read below |
aoqi@1 | 1291 | |
aoqi@1 | 1292 | // check for safepoint operation in progress and/or pending suspend requests |
aoqi@1 | 1293 | { Label Continue; |
aoqi@1 | 1294 | |
aoqi@1 | 1295 | // Don't use call_VM as it will see a possible pending exception and forward it |
aoqi@1 | 1296 | // and never return here preventing us from clearing _last_native_pc down below. |
aoqi@1 | 1297 | // Also can't use call_VM_leaf either as it will check to see if esi & edi are |
aoqi@1 | 1298 | // preserved and correspond to the bcp/locals pointers. So we do a runtime call |
aoqi@1 | 1299 | // by hand. |
aoqi@1 | 1300 | // |
aoqi@1 | 1301 | Label L; |
aoqi@1 | 1302 | __ li(AT, SafepointSynchronize::address_of_state()); |
aoqi@1 | 1303 | __ lw(AT, AT, 0); |
aoqi@1 | 1304 | __ bne(AT, R0, L); |
aoqi@1 | 1305 | __ delayed()->nop(); |
aoqi@1 | 1306 | __ lw(AT, thread, in_bytes(JavaThread::suspend_flags_offset())); |
aoqi@1 | 1307 | __ beq(AT, R0, Continue); |
aoqi@1 | 1308 | __ delayed()->nop(); |
aoqi@1 | 1309 | __ bind(L); |
aoqi@1 | 1310 | __ move(A0, thread); |
aoqi@6880 | 1311 | __ call(CAST_FROM_FN_PTR(address, |
aoqi@6880 | 1312 | JavaThread::check_special_condition_for_native_trans), |
aoqi@6880 | 1313 | relocInfo::runtime_call_type); |
aoqi@1 | 1314 | __ delayed()->nop(); |
aoqi@1 | 1315 | |
aoqi@1 | 1316 | #ifndef OPT_THREAD |
aoqi@1 | 1317 | __ get_thread(thread); |
aoqi@1 | 1318 | #endif |
aoqi@1 | 1319 | //add for compressedoops |
aoqi@1 | 1320 | __ reinit_heapbase(); |
aoqi@1 | 1321 | __ bind(Continue); |
aoqi@1 | 1322 | } |
aoqi@1 | 1323 | |
aoqi@1 | 1324 | // change thread state |
aoqi@1 | 1325 | __ move(t, _thread_in_Java); |
aoqi@1 | 1326 | __ sw(t, thread, in_bytes(JavaThread::thread_state_offset())); |
fujie@9171 | 1327 | __ reset_last_Java_frame(thread, true); |
aoqi@1 | 1328 | |
aoqi@1 | 1329 | // reset handle block |
aoqi@6880 | 1330 | __ ld(t, thread, in_bytes(JavaThread::active_handles_offset())); |
aoqi@1 | 1331 | __ sw(R0, t, JNIHandleBlock::top_offset_in_bytes()); |
aoqi@1 | 1332 | |
aoqi@1 | 1333 | // If result was an oop then unbox and save it in the frame |
aoqi@1 | 1334 | { Label L; |
aoqi@1 | 1335 | Label no_oop, store_result; |
aoqi@6880 | 1336 | //FIXME, addi only support 16-bit imeditate |
aoqi@6880 | 1337 | __ ld(AT, FP, frame::interpreter_frame_result_handler_offset*wordSize); |
aoqi@6880 | 1338 | __ li(T0, AbstractInterpreter::result_handler(T_OBJECT)); |
aoqi@6880 | 1339 | __ bne(AT, T0, no_oop); |
aoqi@6880 | 1340 | __ delayed()->nop(); |
aoqi@6880 | 1341 | __ move(V0, S1); |
aoqi@6880 | 1342 | __ beq(V0, R0, store_result); |
aoqi@6880 | 1343 | __ delayed()->nop(); |
aoqi@1 | 1344 | // unbox |
aoqi@6880 | 1345 | __ ld(V0, V0, 0); |
aoqi@1 | 1346 | __ bind(store_result); |
aoqi@6880 | 1347 | __ sd(V0, FP, (frame::interpreter_frame_oop_temp_offset)*wordSize); |
aoqi@1 | 1348 | // keep stack depth as expected by pushing oop which will eventually be discarded |
aoqi@1 | 1349 | __ bind(no_oop); |
aoqi@1 | 1350 | } |
aoqi@1 | 1351 | { |
aoqi@1 | 1352 | Label no_reguard; |
aoqi@1 | 1353 | __ lw(t, thread, in_bytes(JavaThread::stack_guard_state_offset())); |
aoqi@6880 | 1354 | __ move(AT,(int) JavaThread::stack_guard_yellow_disabled); |
aoqi@1 | 1355 | __ bne(t, AT, no_reguard); |
aoqi@1 | 1356 | __ delayed()->nop(); |
aoqi@6880 | 1357 | __ pushad(); |
fujie@9160 | 1358 | __ move(S5_heapbase, SP); |
fujie@9160 | 1359 | __ move(AT, -StackAlignmentInBytes); |
fujie@9160 | 1360 | __ andr(SP, SP, AT); |
aoqi@6880 | 1361 | __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), relocInfo::runtime_call_type); |
aoqi@1 | 1362 | __ delayed()->nop(); |
fujie@9160 | 1363 | __ move(SP, S5_heapbase); |
aoqi@6880 | 1364 | __ popad(); |
aoqi@1 | 1365 | //add for compressedoops |
aoqi@1 | 1366 | __ reinit_heapbase(); |
aoqi@1 | 1367 | __ bind(no_reguard); |
aoqi@1 | 1368 | } |
aoqi@6880 | 1369 | // restore esi to have legal interpreter frame, |
aoqi@1 | 1370 | // i.e., bci == 0 <=> esi == code_base() |
aoqi@1 | 1371 | // Can't call_VM until bcp is within reasonable. |
aoqi@1 | 1372 | __ get_method(method); // method is junk from thread_in_native to now. |
aoqi@1 | 1373 | __ verify_oop(method); |
aoqi@6880 | 1374 | __ ld(BCP, method, in_bytes(Method::const_offset())); |
aoqi@1 | 1375 | __ lea(BCP, Address(BCP, in_bytes(ConstMethod::codes_offset()))); |
aoqi@1 | 1376 | // handle exceptions (exception handling will handle unlocking!) |
aoqi@6880 | 1377 | { |
aoqi@1 | 1378 | Label L; |
aoqi@1 | 1379 | __ lw(t, thread, in_bytes(Thread::pending_exception_offset())); |
aoqi@1 | 1380 | __ beq(t, R0, L); |
aoqi@1 | 1381 | __ delayed()->nop(); |
aoqi@6880 | 1382 | // Note: At some point we may want to unify this with the code used in |
aoqi@1 | 1383 | // call_VM_base(); |
aoqi@1 | 1384 | // i.e., we should use the StubRoutines::forward_exception code. For now this |
aoqi@1 | 1385 | // doesn't work here because the esp is not correctly set at this point. |
aoqi@6880 | 1386 | __ MacroAssembler::call_VM(noreg, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 1387 | InterpreterRuntime::throw_pending_exception)); |
aoqi@1 | 1388 | __ should_not_reach_here(); |
aoqi@1 | 1389 | __ bind(L); |
aoqi@1 | 1390 | } |
aoqi@1 | 1391 | |
aoqi@1 | 1392 | // do unlocking if necessary |
aoqi@6880 | 1393 | { |
aoqi@6880 | 1394 | Label L; |
aoqi@1 | 1395 | __ lw(t, method, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1396 | __ andi(t, t, JVM_ACC_SYNCHRONIZED); |
aoqi@1 | 1397 | __ beq(t, R0, L); |
aoqi@1 | 1398 | // the code below should be shared with interpreter macro assembler implementation |
aoqi@6880 | 1399 | { |
aoqi@6880 | 1400 | Label unlock; |
aoqi@1 | 1401 | // BasicObjectLock will be first in list, |
aoqi@1 | 1402 | // since this is a synchronized method. However, need |
aoqi@6880 | 1403 | // to check that the object has not been unlocked by |
aoqi@6880 | 1404 | // an explicit monitorexit bytecode. |
aoqi@6880 | 1405 | __ delayed()->daddi(c_rarg0, FP, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); |
aoqi@1 | 1406 | // address of first monitor |
aoqi@1 | 1407 | |
aoqi@1 | 1408 | __ ld(t, c_rarg0, BasicObjectLock::obj_offset_in_bytes()); |
aoqi@1 | 1409 | __ bne(t, R0, unlock); |
aoqi@1 | 1410 | __ delayed()->nop(); |
aoqi@1 | 1411 | |
aoqi@1 | 1412 | // Entry already unlocked, need to throw exception |
aoqi@6880 | 1413 | __ MacroAssembler::call_VM(NOREG, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 1414 | InterpreterRuntime::throw_illegal_monitor_state_exception)); |
aoqi@1 | 1415 | __ should_not_reach_here(); |
aoqi@1 | 1416 | |
aoqi@6880 | 1417 | __ bind(unlock); |
aoqi@6880 | 1418 | __ unlock_object(c_rarg0); |
aoqi@1 | 1419 | } |
aoqi@1 | 1420 | __ bind(L); |
aoqi@6880 | 1421 | } |
aoqi@1 | 1422 | |
aoqi@1 | 1423 | // jvmti/jvmpi support |
aoqi@1 | 1424 | // Note: This must happen _after_ handling/throwing any exceptions since |
aoqi@1 | 1425 | // the exception handler code notifies the runtime of method exits |
aoqi@1 | 1426 | // too. If this happens before, method entry/exit notifications are |
aoqi@1 | 1427 | // not properly paired (was bug - gri 11/22/99). |
aoqi@1 | 1428 | __ notify_method_exit(false, vtos, InterpreterMacroAssembler::NotifyJVMTI ); |
aoqi@1 | 1429 | |
aoqi@6880 | 1430 | // restore potential result in V0:V1, |
aoqi@1 | 1431 | // call result handler to restore potential result in ST0 & handle result |
aoqi@1 | 1432 | //__ lw(V0, SP, 3 * wordSize); |
aoqi@1 | 1433 | //__ lw(V1, SP, 2 * wordSize); |
aoqi@1 | 1434 | //__ lwc1(F0, SP, 1 * wordSize); |
aoqi@1 | 1435 | //__ lwc1(F1, SP, 0 * wordSize); |
aoqi@1 | 1436 | //__ addi(SP, SP, 4 * wordSize); |
aoqi@1 | 1437 | __ move(V0, S1); |
aoqi@1 | 1438 | __ move(V1, S3); |
aoqi@1 | 1439 | __ dmtc1(S4, F0); |
aoqi@1 | 1440 | __ dmtc1(S2, F1); |
aoqi@1 | 1441 | __ ld(t, FP, (frame::interpreter_frame_result_handler_offset) * wordSize); |
aoqi@1 | 1442 | __ jalr(t); |
aoqi@1 | 1443 | __ delayed()->nop(); |
aoqi@1 | 1444 | |
aoqi@1 | 1445 | |
aoqi@1 | 1446 | // remove activation |
aoqi@1 | 1447 | __ ld(SP, FP, frame::interpreter_frame_sender_sp_offset * wordSize); // get sender sp |
aoqi@1 | 1448 | __ ld(RA, FP, frame::interpreter_frame_return_addr_offset * wordSize); // get return address |
aoqi@1 | 1449 | __ ld(FP, FP, frame::interpreter_frame_sender_fp_offset * wordSize); // restore sender's fp |
aoqi@1 | 1450 | __ jr(RA); |
aoqi@1 | 1451 | __ delayed()->nop(); |
aoqi@1 | 1452 | |
aoqi@1 | 1453 | #ifndef CORE |
aoqi@1 | 1454 | if (inc_counter) { |
aoqi@1 | 1455 | // Handle overflow of counter and compile method |
aoqi@1 | 1456 | __ bind(invocation_counter_overflow); |
aoqi@1 | 1457 | generate_counter_overflow(&continue_after_compile); |
aoqi@1 | 1458 | // entry_point is the beginning of this |
aoqi@1 | 1459 | // function and checks again for compiled code |
aoqi@1 | 1460 | } |
aoqi@1 | 1461 | #endif |
aoqi@1 | 1462 | return entry_point; |
aoqi@1 | 1463 | } |
aoqi@1 | 1464 | |
aoqi@1 | 1465 | // |
aoqi@1 | 1466 | // Generic interpreted method entry to (asm) interpreter |
aoqi@1 | 1467 | // |
aoqi@1 | 1468 | // Layout of frame just at the entry |
aoqi@1 | 1469 | // |
aoqi@6880 | 1470 | // [ argument word n-1 ] <--- sp |
aoqi@1 | 1471 | // ... |
aoqi@6880 | 1472 | // [ argument word 0 ] |
aoqi@6880 | 1473 | // assume Method* in Rmethod before call this method. |
aoqi@1 | 1474 | // prerequisites to the generated stub : the callee Method* in Rmethod |
aoqi@1 | 1475 | // note you must save the caller bcp before call the generated stub |
aoqi@1 | 1476 | // |
aoqi@1 | 1477 | address InterpreterGenerator::generate_normal_entry(bool synchronized) { |
aoqi@1 | 1478 | // determine code generation flags |
aoqi@1 | 1479 | bool inc_counter = UseCompiler || CountCompiledCalls; |
aoqi@1 | 1480 | |
aoqi@1 | 1481 | // Rmethod: Method* |
aoqi@6880 | 1482 | // Rsender: sender 's sp |
aoqi@1 | 1483 | address entry_point = __ pc(); |
fujie@6895 | 1484 | |
aoqi@6880 | 1485 | const Address invocation_counter(Rmethod, |
aoqi@6880 | 1486 | in_bytes(MethodCounters::invocation_counter_offset() + InvocationCounter::counter_offset())); |
aoqi@1 | 1487 | |
aoqi@1 | 1488 | // get parameter size (always needed) |
aoqi@6880 | 1489 | __ ld(T3, Rmethod, in_bytes(Method::const_offset())); //T3 --> Rmethod._constMethod |
aoqi@1 | 1490 | __ lhu(V0, T3, in_bytes(ConstMethod::size_of_parameters_offset())); |
aoqi@1 | 1491 | |
aoqi@1 | 1492 | // Rmethod: Method* |
aoqi@1 | 1493 | // V0: size of parameters |
aoqi@6880 | 1494 | // Rsender: sender 's sp ,could be different frome sp+ wordSize if we call via c2i |
aoqi@1 | 1495 | // get size of locals in words to T2 |
aoqi@6880 | 1496 | __ lhu(T2, T3, in_bytes(ConstMethod::size_of_locals_offset())); |
aoqi@1 | 1497 | // T2 = no. of additional locals, locals include parameters |
aoqi@6880 | 1498 | __ dsub(T2, T2, V0); |
aoqi@1 | 1499 | |
aoqi@1 | 1500 | // see if we've got enough room on the stack for locals plus overhead. |
aoqi@1 | 1501 | // Layout of frame at this point |
aoqi@1 | 1502 | // |
aoqi@1 | 1503 | // [ argument word n-1 ] <--- sp |
aoqi@1 | 1504 | // ... |
aoqi@6880 | 1505 | // [ argument word 0 ] |
aoqi@1 | 1506 | generate_stack_overflow_check(); |
aoqi@1 | 1507 | // after this function, the layout of frame does not change |
aoqi@1 | 1508 | |
aoqi@1 | 1509 | // compute beginning of parameters (LVP) |
aoqi@1 | 1510 | __ dsll(LVP, V0, LogBytesPerWord); |
aoqi@1 | 1511 | __ daddiu(LVP, LVP, (-1) * wordSize); |
aoqi@1 | 1512 | __ dadd(LVP, LVP, SP); |
aoqi@1 | 1513 | |
aoqi@1 | 1514 | // T2 - # of additional locals |
aoqi@1 | 1515 | // allocate space for locals |
aoqi@1 | 1516 | // explicitly initialize locals |
aoqi@1 | 1517 | { |
aoqi@1 | 1518 | Label exit, loop; |
aoqi@1 | 1519 | __ beq(T2, R0, exit); |
aoqi@1 | 1520 | __ delayed()->nop(); |
fujie@6895 | 1521 | |
aoqi@1 | 1522 | __ bind(loop); |
aoqi@1 | 1523 | __ sd(R0, SP, -1 * wordSize); // initialize local variables |
aoqi@1 | 1524 | __ daddiu(T2, T2, -1); // until everything initialized |
aoqi@1 | 1525 | __ bne(T2, R0, loop); |
aoqi@1 | 1526 | __ delayed(); |
fujie@6895 | 1527 | |
aoqi@1 | 1528 | __ daddiu(SP, SP, (-1) * wordSize); //fill delay slot |
fujie@6895 | 1529 | |
aoqi@1 | 1530 | __ bind(exit); |
aoqi@1 | 1531 | } |
aoqi@1 | 1532 | |
aoqi@6880 | 1533 | // |
aoqi@6880 | 1534 | // [ local var m-1 ] <--- sp |
aoqi@1 | 1535 | // ... |
aoqi@6880 | 1536 | // [ local var 0 ] |
aoqi@6880 | 1537 | // [ argument word n-1 ] <--- T0? |
aoqi@1 | 1538 | // ... |
aoqi@6880 | 1539 | // [ argument word 0 ] <--- LVP |
aoqi@1 | 1540 | |
aoqi@1 | 1541 | // initialize fixed part of activation frame |
aoqi@1 | 1542 | |
aoqi@1 | 1543 | generate_fixed_frame(false); |
aoqi@1 | 1544 | |
aoqi@1 | 1545 | |
aoqi@1 | 1546 | // after this function, the layout of frame is as following |
aoqi@6880 | 1547 | // |
aoqi@1 | 1548 | // [ monitor block top ] <--- sp ( the top monitor entry ) |
aoqi@1 | 1549 | // [ byte code pointer ] (if native, bcp = 0) |
aoqi@1 | 1550 | // [ constant pool cache ] |
aoqi@1 | 1551 | // [ Method* ] |
aoqi@6880 | 1552 | // [ locals offset ] |
aoqi@1 | 1553 | // [ sender's sp ] |
aoqi@1 | 1554 | // [ sender's fp ] <--- fp |
aoqi@6880 | 1555 | // [ return address ] |
aoqi@1 | 1556 | // [ local var m-1 ] |
aoqi@1 | 1557 | // ... |
aoqi@1 | 1558 | // [ local var 0 ] |
aoqi@1 | 1559 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@1 | 1560 | // ... |
aoqi@1 | 1561 | // [ argument word 0 ] <--- LVP |
aoqi@1 | 1562 | |
aoqi@1 | 1563 | |
aoqi@1 | 1564 | // make sure method is not native & not abstract |
aoqi@1 | 1565 | #ifdef ASSERT |
aoqi@1 | 1566 | __ ld(AT, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1567 | { |
aoqi@1 | 1568 | Label L; |
aoqi@1 | 1569 | __ andi(T2, AT, JVM_ACC_NATIVE); |
aoqi@1 | 1570 | __ beq(T2, R0, L); |
aoqi@1 | 1571 | __ delayed()->nop(); |
aoqi@1 | 1572 | __ stop("tried to execute native method as non-native"); |
aoqi@1 | 1573 | __ bind(L); |
aoqi@1 | 1574 | } |
aoqi@6880 | 1575 | { |
aoqi@6880 | 1576 | Label L; |
aoqi@1 | 1577 | __ andi(T2, AT, JVM_ACC_ABSTRACT); |
aoqi@1 | 1578 | __ beq(T2, R0, L); |
aoqi@1 | 1579 | __ delayed()->nop(); |
aoqi@1 | 1580 | __ stop("tried to execute abstract method in interpreter"); |
aoqi@1 | 1581 | __ bind(L); |
aoqi@1 | 1582 | } |
aoqi@1 | 1583 | #endif |
aoqi@1 | 1584 | |
aoqi@1 | 1585 | // Since at this point in the method invocation the exception handler |
aoqi@1 | 1586 | // would try to exit the monitor of synchronized methods which hasn't |
aoqi@1 | 1587 | // been entered yet, we set the thread local variable |
aoqi@1 | 1588 | // _do_not_unlock_if_synchronized to true. The remove_activation will |
aoqi@1 | 1589 | // check this flag. |
aoqi@1 | 1590 | |
aoqi@1 | 1591 | #ifndef OPT_THREAD |
aoqi@1 | 1592 | Register thread = T8; |
aoqi@1 | 1593 | __ get_thread(thread); |
aoqi@1 | 1594 | #else |
aoqi@1 | 1595 | Register thread = TREG; |
aoqi@1 | 1596 | #endif |
aoqi@1 | 1597 | __ move(AT, (int)true); |
aoqi@1 | 1598 | __ sb(AT, thread, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
aoqi@1 | 1599 | |
aoqi@1 | 1600 | #ifndef CORE |
aoqi@1 | 1601 | |
aoqi@1 | 1602 | // 2014/11/24 Fu |
aoqi@1 | 1603 | // mdp : T8 |
aoqi@1 | 1604 | // tmp1: T9 |
aoqi@6880 | 1605 | // tmp2: T2 |
aoqi@1 | 1606 | __ profile_parameters_type(T8, T9, T2); |
aoqi@1 | 1607 | |
aoqi@1 | 1608 | // increment invocation count & check for overflow |
aoqi@1 | 1609 | Label invocation_counter_overflow; |
aoqi@1 | 1610 | Label profile_method; |
aoqi@1 | 1611 | Label profile_method_continue; |
aoqi@1 | 1612 | if (inc_counter) { |
aoqi@6880 | 1613 | generate_counter_incr(&invocation_counter_overflow, |
aoqi@6880 | 1614 | &profile_method, |
aoqi@6880 | 1615 | &profile_method_continue); |
aoqi@1 | 1616 | if (ProfileInterpreter) { |
aoqi@1 | 1617 | __ bind(profile_method_continue); |
aoqi@1 | 1618 | } |
aoqi@1 | 1619 | } |
aoqi@1 | 1620 | |
aoqi@1 | 1621 | Label continue_after_compile; |
aoqi@1 | 1622 | __ bind(continue_after_compile); |
aoqi@1 | 1623 | |
aoqi@1 | 1624 | #endif // CORE |
aoqi@1 | 1625 | |
aoqi@1 | 1626 | bang_stack_shadow_pages(false); |
aoqi@1 | 1627 | |
aoqi@1 | 1628 | // reset the _do_not_unlock_if_synchronized flag |
aoqi@1 | 1629 | #ifndef OPT_THREAD |
aoqi@1 | 1630 | __ get_thread(thread); |
aoqi@1 | 1631 | #endif |
aoqi@1 | 1632 | __ sb(R0, thread, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); |
aoqi@1 | 1633 | |
aoqi@1 | 1634 | // check for synchronized methods |
aoqi@1 | 1635 | // Must happen AFTER invocation_counter check and stack overflow check, |
aoqi@1 | 1636 | // so method is not locked if overflows. |
aoqi@1 | 1637 | // |
aoqi@1 | 1638 | if (synchronized) { |
aoqi@1 | 1639 | // Allocate monitor and lock method |
aoqi@1 | 1640 | lock_method(); |
aoqi@1 | 1641 | } else { |
aoqi@1 | 1642 | // no synchronization necessary |
aoqi@1 | 1643 | #ifdef ASSERT |
aoqi@1 | 1644 | { Label L; |
aoqi@1 | 1645 | __ lw(AT, Rmethod, in_bytes(Method::access_flags_offset())); |
aoqi@1 | 1646 | __ andi(T2, AT, JVM_ACC_SYNCHRONIZED); |
aoqi@1 | 1647 | __ beq(T2, R0, L); |
aoqi@1 | 1648 | __ delayed()->nop(); |
aoqi@1 | 1649 | __ stop("method needs synchronization"); |
aoqi@1 | 1650 | __ bind(L); |
aoqi@1 | 1651 | } |
aoqi@1 | 1652 | #endif |
aoqi@1 | 1653 | } |
aoqi@1 | 1654 | |
aoqi@1 | 1655 | // layout of frame after lock_method |
aoqi@6880 | 1656 | // [ monitor entry ] <--- sp |
aoqi@1 | 1657 | // ... |
aoqi@6880 | 1658 | // [ monitor entry ] |
aoqi@1 | 1659 | // [ monitor block top ] ( the top monitor entry ) |
aoqi@1 | 1660 | // [ byte code pointer ] (if native, bcp = 0) |
aoqi@1 | 1661 | // [ constant pool cache ] |
aoqi@1 | 1662 | // [ Method* ] |
aoqi@6880 | 1663 | // [ locals offset ] |
aoqi@1 | 1664 | // [ sender's sp ] |
aoqi@1 | 1665 | // [ sender's fp ] |
aoqi@1 | 1666 | // [ return address ] <--- fp |
aoqi@1 | 1667 | // [ local var m-1 ] |
aoqi@1 | 1668 | // ... |
aoqi@1 | 1669 | // [ local var 0 ] |
aoqi@1 | 1670 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@1 | 1671 | // ... |
aoqi@1 | 1672 | // [ argument word 0 ] <--- LVP |
aoqi@1 | 1673 | |
aoqi@1 | 1674 | |
aoqi@1 | 1675 | // start execution |
aoqi@1 | 1676 | #ifdef ASSERT |
aoqi@6880 | 1677 | { |
aoqi@6880 | 1678 | Label L; |
aoqi@1 | 1679 | __ ld(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); |
aoqi@1 | 1680 | __ beq(AT, SP, L); |
aoqi@1 | 1681 | __ delayed()->nop(); |
aoqi@1 | 1682 | __ stop("broken stack frame setup in interpreter in native"); |
aoqi@1 | 1683 | __ bind(L); |
aoqi@1 | 1684 | } |
aoqi@1 | 1685 | #endif |
aoqi@1 | 1686 | |
aoqi@1 | 1687 | // jvmti/jvmpi support |
aoqi@1 | 1688 | __ notify_method_entry(); |
aoqi@1 | 1689 | |
aoqi@1 | 1690 | __ dispatch_next(vtos); |
aoqi@1 | 1691 | |
aoqi@1 | 1692 | // invocation counter overflow |
aoqi@1 | 1693 | if (inc_counter) { |
aoqi@1 | 1694 | if (ProfileInterpreter) { |
aoqi@1 | 1695 | // We have decided to profile this method in the interpreter |
aoqi@1 | 1696 | __ bind(profile_method); |
aoqi@6880 | 1697 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
aoqi@6880 | 1698 | InterpreterRuntime::profile_method)); |
aoqi@1 | 1699 | __ set_method_data_pointer_for_bcp(); |
aoqi@1 | 1700 | __ get_method(Rmethod); |
aoqi@1 | 1701 | __ b(profile_method_continue); |
aoqi@1 | 1702 | __ delayed()->nop(); |
aoqi@1 | 1703 | } |
aoqi@1 | 1704 | // Handle overflow of counter and compile method |
aoqi@1 | 1705 | __ bind(invocation_counter_overflow); |
aoqi@6880 | 1706 | generate_counter_overflow(&continue_after_compile); |
aoqi@1 | 1707 | } |
aoqi@1 | 1708 | |
aoqi@1 | 1709 | return entry_point; |
aoqi@1 | 1710 | } |
aoqi@1 | 1711 | |
aoqi@1 | 1712 | // Entry points |
aoqi@1 | 1713 | // |
aoqi@1 | 1714 | // Here we generate the various kind of entries into the interpreter. |
aoqi@1 | 1715 | // The two main entry type are generic bytecode methods and native |
aoqi@1 | 1716 | // call method. These both come in synchronized and non-synchronized |
aoqi@1 | 1717 | // versions but the frame layout they create is very similar. The |
aoqi@1 | 1718 | // other method entry types are really just special purpose entries |
aoqi@1 | 1719 | // that are really entry and interpretation all in one. These are for |
aoqi@1 | 1720 | // trivial methods like accessor, empty, or special math methods. |
aoqi@1 | 1721 | // |
aoqi@1 | 1722 | // When control flow reaches any of the entry types for the interpreter |
aoqi@1 | 1723 | // the following holds -> |
aoqi@1 | 1724 | // |
aoqi@1 | 1725 | // Arguments: |
aoqi@1 | 1726 | // |
aoqi@1 | 1727 | // Rmethod: Method* |
aoqi@1 | 1728 | // V0: receiver |
aoqi@1 | 1729 | // |
aoqi@1 | 1730 | // |
aoqi@1 | 1731 | // Stack layout immediately at entry |
aoqi@1 | 1732 | // |
aoqi@1 | 1733 | // [ parameter n-1 ] <--- sp |
aoqi@1 | 1734 | // ... |
aoqi@1 | 1735 | // [ parameter 0 ] |
aoqi@1 | 1736 | // [ expression stack ] (caller's java expression stack) |
aoqi@1 | 1737 | |
aoqi@1 | 1738 | // Assuming that we don't go to one of the trivial specialized entries |
aoqi@1 | 1739 | // the stack will look like below when we are ready to execute the |
aoqi@1 | 1740 | // first bytecode (or call the native routine). The register usage |
aoqi@1 | 1741 | // will be as the template based interpreter expects (see |
aoqi@1 | 1742 | // interpreter_amd64.hpp). |
aoqi@1 | 1743 | // |
aoqi@1 | 1744 | // local variables follow incoming parameters immediately; i.e. |
aoqi@1 | 1745 | // the return address is moved to the end of the locals). |
aoqi@1 | 1746 | // |
aoqi@6880 | 1747 | // [ monitor entry ] <--- sp |
aoqi@1 | 1748 | // ... |
aoqi@6880 | 1749 | // [ monitor entry ] |
aoqi@1 | 1750 | // [ monitor block top ] ( the top monitor entry ) |
aoqi@1 | 1751 | // [ byte code pointer ] (if native, bcp = 0) |
aoqi@1 | 1752 | // [ constant pool cache ] |
aoqi@1 | 1753 | // [ Method* ] |
aoqi@6880 | 1754 | // [ locals offset ] |
aoqi@1 | 1755 | // [ sender's sp ] |
aoqi@1 | 1756 | // [ sender's fp ] |
aoqi@1 | 1757 | // [ return address ] <--- fp |
aoqi@1 | 1758 | // [ local var m-1 ] |
aoqi@1 | 1759 | // ... |
aoqi@1 | 1760 | // [ local var 0 ] |
aoqi@1 | 1761 | // [ argumnet word n-1 ] <--- ( sender's sp ) |
aoqi@1 | 1762 | // ... |
aoqi@1 | 1763 | // [ argument word 0 ] <--- S7 |
aoqi@1 | 1764 | |
aoqi@1 | 1765 | address AbstractInterpreterGenerator::generate_method_entry( |
aoqi@1 | 1766 | AbstractInterpreter::MethodKind kind) { |
aoqi@1 | 1767 | // determine code generation flags |
aoqi@1 | 1768 | bool synchronized = false; |
aoqi@1 | 1769 | address entry_point = NULL; |
aoqi@6880 | 1770 | switch (kind) { |
aoqi@6880 | 1771 | case Interpreter::zerolocals : |
aoqi@6880 | 1772 | break; |
aoqi@6880 | 1773 | case Interpreter::zerolocals_synchronized: |
aoqi@6880 | 1774 | synchronized = true; |
aoqi@6880 | 1775 | break; |
aoqi@6880 | 1776 | case Interpreter::native : |
aoqi@6880 | 1777 | entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); |
aoqi@6880 | 1778 | break; |
aoqi@6880 | 1779 | case Interpreter::native_synchronized : |
aoqi@6880 | 1780 | entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); |
aoqi@6880 | 1781 | break; |
aoqi@6880 | 1782 | case Interpreter::empty : |
aoqi@6880 | 1783 | entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); |
aoqi@6880 | 1784 | break; |
aoqi@6880 | 1785 | case Interpreter::accessor : |
aoqi@6880 | 1786 | entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); |
aoqi@6880 | 1787 | break; |
aoqi@6880 | 1788 | case Interpreter::abstract : |
aoqi@6880 | 1789 | entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); |
aoqi@6880 | 1790 | break; |
aoqi@1 | 1791 | |
aoqi@6880 | 1792 | case Interpreter::java_lang_math_sin : // fall thru |
aoqi@6880 | 1793 | case Interpreter::java_lang_math_cos : // fall thru |
aoqi@6880 | 1794 | case Interpreter::java_lang_math_tan : // fall thru |
aoqi@6880 | 1795 | case Interpreter::java_lang_math_log : // fall thru |
aoqi@6880 | 1796 | case Interpreter::java_lang_math_log10 : // fall thru |
aoqi@6880 | 1797 | case Interpreter::java_lang_math_pow : // fall thru |
aoqi@6880 | 1798 | case Interpreter::java_lang_math_exp : break; |
aoqi@6880 | 1799 | case Interpreter::java_lang_math_abs : // fall thru |
aoqi@6880 | 1800 | case Interpreter::java_lang_math_sqrt : |
aoqi@6880 | 1801 | entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break; |
aoqi@6880 | 1802 | case Interpreter::java_lang_ref_reference_get: |
aoqi@6880 | 1803 | entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; |
aoqi@6880 | 1804 | default: |
aoqi@6880 | 1805 | fatal(err_msg("unexpected method kind: %d", kind)); |
aoqi@6880 | 1806 | break; |
aoqi@6880 | 1807 | } |
aoqi@6880 | 1808 | if (entry_point) return entry_point; |
aoqi@1 | 1809 | |
aoqi@6880 | 1810 | return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized); |
aoqi@1 | 1811 | } |
aoqi@1 | 1812 | |
aoqi@1 | 1813 | // These should never be compiled since the interpreter will prefer |
aoqi@6880 | 1814 | // the compiled version to the intrinsic version. |
aoqi@1 | 1815 | bool AbstractInterpreter::can_be_compiled(methodHandle m) { |
aoqi@1 | 1816 | switch (method_kind(m)) { |
aoqi@1 | 1817 | case Interpreter::java_lang_math_sin : // fall thru |
aoqi@1 | 1818 | case Interpreter::java_lang_math_cos : // fall thru |
aoqi@1 | 1819 | case Interpreter::java_lang_math_tan : // fall thru |
aoqi@1 | 1820 | case Interpreter::java_lang_math_abs : // fall thru |
aoqi@1 | 1821 | case Interpreter::java_lang_math_log : // fall thru |
aoqi@1 | 1822 | case Interpreter::java_lang_math_log10 : // fall thru |
aoqi@1 | 1823 | case Interpreter::java_lang_math_sqrt : // fall thru |
aoqi@1 | 1824 | case Interpreter::java_lang_math_pow : // fall thru |
aoqi@1 | 1825 | case Interpreter::java_lang_math_exp : |
aoqi@1 | 1826 | return false; |
aoqi@1 | 1827 | default: |
aoqi@1 | 1828 | return true; |
aoqi@1 | 1829 | } |
aoqi@1 | 1830 | } |
aoqi@1 | 1831 | |
aoqi@1 | 1832 | // How much stack a method activation needs in words. |
aoqi@1 | 1833 | int AbstractInterpreter::size_top_interpreter_activation(Method* method) { |
aoqi@1 | 1834 | |
aoqi@6880 | 1835 | const int entry_size = frame::interpreter_frame_monitor_size(); |
aoqi@1 | 1836 | |
aoqi@6880 | 1837 | // total overhead size: entry_size + (saved ebp thru expr stack bottom). |
aoqi@6880 | 1838 | // be sure to change this if you add/subtract anything to/from the overhead area |
aoqi@6880 | 1839 | const int overhead_size = -(frame::interpreter_frame_initial_sp_offset) + entry_size; |
aoqi@1 | 1840 | |
aoqi@6880 | 1841 | const int stub_code = 6; // see generate_call_stub |
aoqi@6880 | 1842 | // return overhead_size + method->max_locals() + method->max_stack() + stub_code; |
aoqi@6880 | 1843 | const int method_stack = (method->max_locals() + method->max_stack()) * |
aoqi@6880 | 1844 | Interpreter::stackElementWords; |
aoqi@6880 | 1845 | return overhead_size + method_stack + stub_code; |
aoqi@1 | 1846 | } |
aoqi@1 | 1847 | |
aoqi@1 | 1848 | void AbstractInterpreter::layout_activation(Method* method, |
aoqi@1 | 1849 | int tempcount, |
aoqi@1 | 1850 | int popframe_extra_args, |
aoqi@1 | 1851 | int moncount, |
aoqi@1 | 1852 | int caller_actual_parameters, |
aoqi@1 | 1853 | int callee_param_count, |
aoqi@1 | 1854 | int callee_locals, |
aoqi@1 | 1855 | frame* caller, |
aoqi@1 | 1856 | frame* interpreter_frame, |
aoqi@1 | 1857 | bool is_top_frame, |
aoqi@1 | 1858 | bool is_bottom_frame) { |
aoqi@1 | 1859 | // Note: This calculation must exactly parallel the frame setup |
aoqi@1 | 1860 | // in AbstractInterpreterGenerator::generate_method_entry. |
aoqi@1 | 1861 | // If interpreter_frame!=NULL, set up the method, locals, and monitors. |
aoqi@1 | 1862 | // The frame interpreter_frame, if not NULL, is guaranteed to be the |
aoqi@1 | 1863 | // right size, as determined by a previous call to this method. |
aoqi@1 | 1864 | // It is also guaranteed to be walkable even though it is in a skeletal state |
aoqi@1 | 1865 | |
aoqi@1 | 1866 | // fixed size of an interpreter frame: |
aoqi@6880 | 1867 | |
aoqi@6880 | 1868 | int max_locals = method->max_locals() * Interpreter::stackElementWords; |
aoqi@6880 | 1869 | int extra_locals = (method->max_locals() - method->size_of_parameters()) * Interpreter::stackElementWords; |
aoqi@1 | 1870 | |
aoqi@1 | 1871 | #ifdef ASSERT |
aoqi@1 | 1872 | if (!EnableInvokeDynamic) { |
aoqi@1 | 1873 | // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? |
aoqi@1 | 1874 | // Probably, since deoptimization doesn't work yet. |
aoqi@1 | 1875 | assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); |
aoqi@1 | 1876 | } |
aoqi@1 | 1877 | assert(caller->sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable(2)"); |
aoqi@1 | 1878 | #endif |
aoqi@1 | 1879 | |
aoqi@1 | 1880 | interpreter_frame->interpreter_frame_set_method(method); |
aoqi@1 | 1881 | // NOTE the difference in using sender_sp and interpreter_frame_sender_sp |
aoqi@1 | 1882 | // interpreter_frame_sender_sp is the original sp of the caller (the unextended_sp) |
aoqi@1 | 1883 | // and sender_sp is fp+8 |
aoqi@1 | 1884 | intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1; |
aoqi@1 | 1885 | |
aoqi@1 | 1886 | #ifdef ASSERT |
aoqi@1 | 1887 | if (caller->is_interpreted_frame()) { |
aoqi@1 | 1888 | assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement"); |
aoqi@1 | 1889 | } |
aoqi@1 | 1890 | #endif |
aoqi@1 | 1891 | |
aoqi@6880 | 1892 | interpreter_frame->interpreter_frame_set_locals(locals); |
aoqi@6880 | 1893 | BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin(); |
aoqi@6880 | 1894 | BasicObjectLock* monbot = montop - moncount; |
aoqi@6880 | 1895 | interpreter_frame->interpreter_frame_set_monitor_end(montop - moncount); |
aoqi@1 | 1896 | |
aoqi@6880 | 1897 | //set last sp; |
aoqi@6880 | 1898 | intptr_t* esp = (intptr_t*) monbot - tempcount*Interpreter::stackElementWords - |
aoqi@6880 | 1899 | popframe_extra_args; |
aoqi@6880 | 1900 | interpreter_frame->interpreter_frame_set_last_sp(esp); |
aoqi@6880 | 1901 | // All frames but the initial interpreter frame we fill in have a |
aoqi@6880 | 1902 | // value for sender_sp that allows walking the stack but isn't |
aoqi@6880 | 1903 | // truly correct. Correct the value here. |
aoqi@6880 | 1904 | // |
aoqi@6880 | 1905 | if (extra_locals != 0 && |
aoqi@6880 | 1906 | interpreter_frame->sender_sp() == interpreter_frame->interpreter_frame_sender_sp() ) { |
aoqi@1 | 1907 | interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() + extra_locals); |
aoqi@1 | 1908 | } |
aoqi@6880 | 1909 | *interpreter_frame->interpreter_frame_cache_addr() = method->constants()->cache(); |
aoqi@1 | 1910 | } |
aoqi@1 | 1911 | |
aoqi@1 | 1912 | //----------------------------------------------------------------------------- |
aoqi@1 | 1913 | // Exceptions |
aoqi@1 | 1914 | |
aoqi@1 | 1915 | void TemplateInterpreterGenerator::generate_throw_exception() { |
aoqi@1 | 1916 | // Entry point in previous activation (i.e., if the caller was |
aoqi@1 | 1917 | // interpreted) |
aoqi@1 | 1918 | Interpreter::_rethrow_exception_entry = __ pc(); |
aoqi@1 | 1919 | // Restore sp to interpreter_frame_last_sp even though we are going |
aoqi@1 | 1920 | // to empty the expression stack for the exception processing. |
aoqi@6880 | 1921 | __ sd(R0,FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 1922 | |
aoqi@1 | 1923 | // V0: exception |
aoqi@1 | 1924 | // V1: return address/pc that threw exception |
aoqi@1 | 1925 | __ restore_bcp(); // esi points to call/send |
aoqi@1 | 1926 | __ restore_locals(); |
aoqi@1 | 1927 | |
aoqi@1 | 1928 | //add for compressedoops |
aoqi@1 | 1929 | __ reinit_heapbase(); |
aoqi@1 | 1930 | // Entry point for exceptions thrown within interpreter code |
aoqi@6880 | 1931 | Interpreter::_throw_exception_entry = __ pc(); |
aoqi@1 | 1932 | // expression stack is undefined here |
aoqi@1 | 1933 | // V0: exception |
aoqi@1 | 1934 | // BCP: exception bcp |
aoqi@1 | 1935 | __ verify_oop(V0); |
aoqi@1 | 1936 | |
aoqi@1 | 1937 | // expression stack must be empty before entering the VM in case of an exception |
aoqi@1 | 1938 | __ empty_expression_stack(); |
aoqi@1 | 1939 | // find exception handler address and preserve exception oop |
aoqi@1 | 1940 | __ move(A1, V0); |
aoqi@1 | 1941 | __ call_VM(V1, CAST_FROM_FN_PTR(address, InterpreterRuntime::exception_handler_for_exception), A1); |
aoqi@1 | 1942 | // V0: exception handler entry point |
aoqi@1 | 1943 | // V1: preserved exception oop |
aoqi@1 | 1944 | // S0: bcp for exception handler |
aoqi@1 | 1945 | __ daddi(SP, SP, (-1) * wordSize); |
aoqi@1 | 1946 | __ sd(V1, SP, 0); // push exception which is now the only value on the stack |
aoqi@1 | 1947 | __ jr(V0); // jump to exception handler (may be _remove_activation_entry!) |
aoqi@1 | 1948 | __ delayed()->nop(); |
aoqi@1 | 1949 | |
aoqi@1 | 1950 | // If the exception is not handled in the current frame the frame is removed and |
aoqi@1 | 1951 | // the exception is rethrown (i.e. exception continuation is _rethrow_exception). |
aoqi@1 | 1952 | // |
aoqi@1 | 1953 | // Note: At this point the bci is still the bxi for the instruction which caused |
aoqi@1 | 1954 | // the exception and the expression stack is empty. Thus, for any VM calls |
aoqi@1 | 1955 | // at this point, GC will find a legal oop map (with empty expression stack). |
aoqi@1 | 1956 | |
aoqi@1 | 1957 | // In current activation |
aoqi@1 | 1958 | // V0: exception |
aoqi@1 | 1959 | // BCP: exception bcp |
aoqi@1 | 1960 | |
aoqi@1 | 1961 | // |
aoqi@1 | 1962 | // JVMTI PopFrame support |
aoqi@1 | 1963 | // |
aoqi@1 | 1964 | |
aoqi@1 | 1965 | Interpreter::_remove_activation_preserving_args_entry = __ pc(); |
aoqi@1 | 1966 | __ empty_expression_stack(); |
aoqi@1 | 1967 | // Set the popframe_processing bit in pending_popframe_condition indicating that we are |
aoqi@1 | 1968 | // currently handling popframe, so that call_VMs that may happen later do not trigger new |
aoqi@1 | 1969 | // popframe handling cycles. |
aoqi@1 | 1970 | #ifndef OPT_THREAD |
aoqi@1 | 1971 | Register thread = T2; |
aoqi@1 | 1972 | __ get_thread(T2); |
aoqi@1 | 1973 | #else |
aoqi@1 | 1974 | Register thread = TREG; |
aoqi@1 | 1975 | #endif |
aoqi@1 | 1976 | __ lw(T3, thread, in_bytes(JavaThread::popframe_condition_offset())); |
aoqi@1 | 1977 | __ ori(T3, T3, JavaThread::popframe_processing_bit); |
aoqi@1 | 1978 | __ sw(T3, thread, in_bytes(JavaThread::popframe_condition_offset())); |
aoqi@1 | 1979 | |
aoqi@1 | 1980 | #ifndef CORE |
aoqi@1 | 1981 | { |
aoqi@1 | 1982 | // Check to see whether we are returning to a deoptimized frame. |
aoqi@1 | 1983 | // (The PopFrame call ensures that the caller of the popped frame is |
aoqi@1 | 1984 | // either interpreted or compiled and deoptimizes it if compiled.) |
aoqi@1 | 1985 | // In this case, we can't call dispatch_next() after the frame is |
aoqi@1 | 1986 | // popped, but instead must save the incoming arguments and restore |
aoqi@1 | 1987 | // them after deoptimization has occurred. |
aoqi@1 | 1988 | // |
aoqi@1 | 1989 | // Note that we don't compare the return PC against the |
aoqi@1 | 1990 | // deoptimization blob's unpack entry because of the presence of |
aoqi@1 | 1991 | // adapter frames in C2. |
aoqi@1 | 1992 | Label caller_not_deoptimized; |
aoqi@1 | 1993 | __ ld(A0, FP, frame::return_addr_offset * wordSize); |
aoqi@1 | 1994 | __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::interpreter_contains), A0); |
aoqi@1 | 1995 | __ bne(V0, R0, caller_not_deoptimized); |
aoqi@1 | 1996 | __ delayed()->nop(); |
aoqi@1 | 1997 | |
aoqi@1 | 1998 | // Compute size of arguments for saving when returning to deoptimized caller |
aoqi@1 | 1999 | __ get_method(A1); |
aoqi@6880 | 2000 | __ verify_oop(A1); |
wanghaomin@9254 | 2001 | __ ld(A1, A1, in_bytes(Method::const_offset())); |
aoqi@1 | 2002 | __ lhu(A1, A1, in_bytes(ConstMethod::size_of_parameters_offset())); |
aoqi@1 | 2003 | __ shl(A1, Interpreter::logStackElementSize); |
aoqi@1 | 2004 | __ restore_locals(); |
wanghaomin@9254 | 2005 | __ dsub(A2, LVP, A1); |
aoqi@1 | 2006 | __ daddiu(A2, A2, wordSize); |
aoqi@1 | 2007 | // Save these arguments |
aoqi@1 | 2008 | #ifndef OPT_THREAD |
aoqi@1 | 2009 | __ get_thread(A0); |
aoqi@1 | 2010 | #else |
aoqi@1 | 2011 | __ move(A0, TREG); |
aoqi@1 | 2012 | #endif |
aoqi@1 | 2013 | __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), A0, A1, A2); |
aoqi@1 | 2014 | |
aoqi@1 | 2015 | __ remove_activation(vtos, T9, false, false, false); |
aoqi@1 | 2016 | |
aoqi@1 | 2017 | // Inform deoptimization that it is responsible for restoring these arguments |
aoqi@1 | 2018 | #ifndef OPT_THREAD |
aoqi@1 | 2019 | __ get_thread(thread); |
aoqi@1 | 2020 | #endif |
aoqi@1 | 2021 | __ move(AT, JavaThread::popframe_force_deopt_reexecution_bit); |
aoqi@1 | 2022 | __ sw(AT, thread, in_bytes(JavaThread::popframe_condition_offset())); |
aoqi@1 | 2023 | // Continue in deoptimization handler |
aoqi@1 | 2024 | __ jr(T9); |
aoqi@1 | 2025 | __ delayed()->nop(); |
aoqi@1 | 2026 | |
aoqi@1 | 2027 | __ bind(caller_not_deoptimized); |
aoqi@1 | 2028 | } |
aoqi@1 | 2029 | #endif /* !CORE */ |
aoqi@1 | 2030 | |
aoqi@6880 | 2031 | __ remove_activation(vtos, T3, |
aoqi@6880 | 2032 | /* throw_monitor_exception */ false, |
aoqi@6880 | 2033 | /* install_monitor_exception */ false, |
aoqi@6880 | 2034 | /* notify_jvmdi */ false); |
aoqi@1 | 2035 | |
aoqi@1 | 2036 | // Clear the popframe condition flag |
aoqi@1 | 2037 | // Finish with popframe handling |
aoqi@1 | 2038 | // A previous I2C followed by a deoptimization might have moved the |
aoqi@1 | 2039 | // outgoing arguments further up the stack. PopFrame expects the |
aoqi@1 | 2040 | // mutations to those outgoing arguments to be preserved and other |
aoqi@1 | 2041 | // constraints basically require this frame to look exactly as |
aoqi@1 | 2042 | // though it had previously invoked an interpreted activation with |
aoqi@1 | 2043 | // no space between the top of the expression stack (current |
aoqi@1 | 2044 | // last_sp) and the top of stack. Rather than force deopt to |
aoqi@1 | 2045 | // maintain this kind of invariant all the time we call a small |
aoqi@1 | 2046 | // fixup routine to move the mutated arguments onto the top of our |
aoqi@1 | 2047 | // expression stack if necessary. |
aoqi@1 | 2048 | __ move(T8, SP); |
aoqi@1 | 2049 | __ ld(A2, FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 2050 | #ifndef OPT_THREAD |
aoqi@1 | 2051 | __ get_thread(thread); |
aoqi@1 | 2052 | #endif |
aoqi@1 | 2053 | // PC must point into interpreter here |
aoqi@1 | 2054 | __ set_last_Java_frame(thread, noreg, FP, __ pc()); |
aoqi@1 | 2055 | __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), thread, T8, A2); |
fujie@9171 | 2056 | __ reset_last_Java_frame(thread, true); |
aoqi@1 | 2057 | // Restore the last_sp and null it out |
aoqi@1 | 2058 | __ ld(SP, FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 2059 | __ sd(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); |
aoqi@1 | 2060 | |
aoqi@1 | 2061 | |
aoqi@1 | 2062 | |
aoqi@6880 | 2063 | __ move(AT, JavaThread::popframe_inactive); |
aoqi@1 | 2064 | __ sw(AT, thread, in_bytes(JavaThread::popframe_condition_offset())); |
aoqi@1 | 2065 | |
aoqi@1 | 2066 | // Finish with popframe handling |
aoqi@1 | 2067 | __ restore_bcp(); |
aoqi@1 | 2068 | __ restore_locals(); |
aoqi@1 | 2069 | #ifndef CORE |
aoqi@1 | 2070 | // The method data pointer was incremented already during |
aoqi@1 | 2071 | // call profiling. We have to restore the mdp for the current bcp. |
aoqi@1 | 2072 | if (ProfileInterpreter) { |
aoqi@1 | 2073 | __ set_method_data_pointer_for_bcp(); |
aoqi@1 | 2074 | } |
aoqi@1 | 2075 | #endif // !CORE |
aoqi@1 | 2076 | // Clear the popframe condition flag |
aoqi@1 | 2077 | #ifndef OPT_THREAD |
aoqi@1 | 2078 | __ get_thread(thread); |
aoqi@6880 | 2079 | #endif |
aoqi@6880 | 2080 | __ move(AT, JavaThread::popframe_inactive); |
aoqi@6880 | 2081 | __ sw(AT, thread, in_bytes(JavaThread::popframe_condition_offset())); |
aoqi@1 | 2082 | __ dispatch_next(vtos); |
aoqi@1 | 2083 | // end of PopFrame support |
aoqi@1 | 2084 | |
aoqi@1 | 2085 | Interpreter::_remove_activation_entry = __ pc(); |
aoqi@1 | 2086 | |
aoqi@1 | 2087 | // preserve exception over this code sequence |
aoqi@1 | 2088 | __ ld(T0, SP, 0); |
aoqi@1 | 2089 | __ daddi(SP, SP, wordSize); |
aoqi@1 | 2090 | #ifndef OPT_THREAD |
aoqi@1 | 2091 | __ get_thread(thread); |
aoqi@1 | 2092 | #endif |
aoqi@1 | 2093 | __ sd(T0, thread, in_bytes(JavaThread::vm_result_offset())); |
aoqi@1 | 2094 | // remove the activation (without doing throws on illegalMonitorExceptions) |
aoqi@1 | 2095 | __ remove_activation(vtos, T3, false, true, false); |
aoqi@1 | 2096 | // restore exception |
aoqi@1 | 2097 | __ get_vm_result(T0, thread); |
aoqi@1 | 2098 | __ verify_oop(T0); |
aoqi@1 | 2099 | |
aoqi@1 | 2100 | // Inbetween activations - previous activation type unknown yet |
aoqi@1 | 2101 | // compute continuation point - the continuation point expects |
aoqi@1 | 2102 | // the following registers set up: |
aoqi@1 | 2103 | // |
aoqi@6880 | 2104 | // T0: exception eax |
aoqi@6880 | 2105 | // T1: return address/pc that threw exception edx |
aoqi@6880 | 2106 | // SP: expression stack of caller esp |
aoqi@6880 | 2107 | // FP: ebp of caller ebp |
aoqi@1 | 2108 | __ daddi(SP, SP, (-2) * wordSize); |
aoqi@6880 | 2109 | __ sd(T0, SP, wordSize); // save exception |
aoqi@1 | 2110 | __ sd(T3, SP, 0); // save return address |
aoqi@1 | 2111 | __ move(A1, T3); |
aoqi@1 | 2112 | __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, A1); |
aoqi@1 | 2113 | __ move(T9, V0); // save exception handler |
aoqi@6880 | 2114 | __ ld(V0, SP, wordSize); // restore exception |
aoqi@1 | 2115 | __ ld(V1, SP, 0); // restore return address |
aoqi@1 | 2116 | __ daddi(SP, SP, 2 * wordSize); |
aoqi@1 | 2117 | |
aoqi@1 | 2118 | // Note that an "issuing PC" is actually the next PC after the call |
aoqi@1 | 2119 | __ jr(T9); // jump to exception handler of caller |
aoqi@1 | 2120 | __ delayed()->nop(); |
aoqi@1 | 2121 | } |
aoqi@1 | 2122 | |
aoqi@1 | 2123 | |
aoqi@1 | 2124 | // |
aoqi@1 | 2125 | // JVMTI ForceEarlyReturn support |
aoqi@1 | 2126 | // |
aoqi@1 | 2127 | address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) { |
aoqi@1 | 2128 | address entry = __ pc(); |
aoqi@1 | 2129 | __ restore_bcp(); |
aoqi@1 | 2130 | __ restore_locals(); |
aoqi@1 | 2131 | __ empty_expression_stack(); |
aoqi@1 | 2132 | __ empty_FPU_stack(); |
aoqi@1 | 2133 | __ load_earlyret_value(state); |
aoqi@1 | 2134 | |
aoqi@1 | 2135 | #ifndef OPT_THREAD |
aoqi@1 | 2136 | __ get_thread(TREG); |
aoqi@1 | 2137 | #endif |
aoqi@1 | 2138 | __ ld_ptr(T9, TREG, in_bytes(JavaThread::jvmti_thread_state_offset())); |
aoqi@1 | 2139 | //const Address cond_addr(ecx, JvmtiThreadState::earlyret_state_offset()); |
aoqi@1 | 2140 | const Address cond_addr(T9, in_bytes(JvmtiThreadState::earlyret_state_offset())); |
aoqi@1 | 2141 | // Clear the earlyret state |
aoqi@1 | 2142 | __ move(AT,JvmtiThreadState::earlyret_inactive); |
aoqi@6880 | 2143 | __ sw(AT,cond_addr); |
fujie@33 | 2144 | __ sync(); |
aoqi@1 | 2145 | |
aoqi@1 | 2146 | |
aoqi@1 | 2147 | __ remove_activation(state, T0, |
aoqi@6880 | 2148 | false, /* throw_monitor_exception */ |
aoqi@6880 | 2149 | false, /* install_monitor_exception */ |
aoqi@6880 | 2150 | true); /* notify_jvmdi */ |
fujie@32 | 2151 | __ sync(); |
aoqi@6880 | 2152 | __ jr(T0); |
aoqi@6880 | 2153 | __ delayed()->nop(); |
aoqi@1 | 2154 | return entry; |
aoqi@1 | 2155 | } // end of ForceEarlyReturn support |
aoqi@1 | 2156 | |
aoqi@1 | 2157 | |
aoqi@1 | 2158 | //----------------------------------------------------------------------------- |
aoqi@1 | 2159 | // Helper for vtos entry point generation |
aoqi@1 | 2160 | |
aoqi@1 | 2161 | void TemplateInterpreterGenerator::set_vtos_entry_points(Template* t, |
aoqi@1 | 2162 | address& bep, |
aoqi@1 | 2163 | address& cep, |
aoqi@1 | 2164 | address& sep, |
aoqi@1 | 2165 | address& aep, |
aoqi@1 | 2166 | address& iep, |
aoqi@1 | 2167 | address& lep, |
aoqi@1 | 2168 | address& fep, |
aoqi@1 | 2169 | address& dep, |
aoqi@1 | 2170 | address& vep) { |
aoqi@1 | 2171 | assert(t->is_valid() && t->tos_in() == vtos, "illegal template"); |
aoqi@1 | 2172 | Label L; |
aoqi@1 | 2173 | fep = __ pc(); __ push(ftos); __ b(L); __ delayed()->nop(); |
aoqi@1 | 2174 | dep = __ pc(); __ push(dtos); __ b(L); __ delayed()->nop(); |
aoqi@1 | 2175 | lep = __ pc(); __ push(ltos); __ b(L); __ delayed()->nop(); |
aoqi@1 | 2176 | aep =__ pc(); __ push(atos); __ b(L); __ delayed()->nop(); |
aoqi@6880 | 2177 | bep = cep = sep = |
aoqi@6880 | 2178 | iep = __ pc(); __ push(itos); |
aoqi@6880 | 2179 | vep = __ pc(); |
aoqi@6880 | 2180 | __ bind(L); |
aoqi@1 | 2181 | generate_and_dispatch(t); |
aoqi@1 | 2182 | } |
aoqi@1 | 2183 | |
aoqi@1 | 2184 | |
aoqi@1 | 2185 | //----------------------------------------------------------------------------- |
aoqi@1 | 2186 | // Generation of individual instructions |
aoqi@1 | 2187 | |
aoqi@1 | 2188 | // helpers for generate_and_dispatch |
aoqi@1 | 2189 | |
aoqi@1 | 2190 | |
aoqi@1 | 2191 | InterpreterGenerator::InterpreterGenerator(StubQueue* code) |
aoqi@1 | 2192 | : TemplateInterpreterGenerator(code) { |
aoqi@1 | 2193 | generate_all(); // down here so it can be "virtual" |
aoqi@1 | 2194 | } |
aoqi@1 | 2195 | |
aoqi@1 | 2196 | //----------------------------------------------------------------------------- |
aoqi@1 | 2197 | |
aoqi@1 | 2198 | // Non-product code |
aoqi@1 | 2199 | #ifndef PRODUCT |
aoqi@1 | 2200 | address TemplateInterpreterGenerator::generate_trace_code(TosState state) { |
aoqi@1 | 2201 | address entry = __ pc(); |
aoqi@1 | 2202 | |
aoqi@1 | 2203 | // prepare expression stack |
aoqi@1 | 2204 | __ push(state); // save tosca |
aoqi@1 | 2205 | |
aoqi@9228 | 2206 | // tos & tos2 |
aoqi@1 | 2207 | // trace_bytecode need actually 4 args, the last two is tos&tos2 |
aoqi@1 | 2208 | // this work fine for x86. but mips o32 call convention will store A2-A3 |
aoqi@1 | 2209 | // to the stack position it think is the tos&tos2 |
aoqi@1 | 2210 | // when the expression stack have no more than 2 data, error occur. |
aoqi@1 | 2211 | __ ld(A2, SP, 0); |
aoqi@1 | 2212 | __ ld(A3, SP, 1 * wordSize); |
aoqi@1 | 2213 | |
aoqi@1 | 2214 | // pass arguments & call tracer |
aoqi@1 | 2215 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), RA, A2, A3); |
aoqi@1 | 2216 | __ move(RA, V0); // make sure return address is not destroyed by pop(state) |
aoqi@1 | 2217 | |
aoqi@1 | 2218 | // restore expression stack |
aoqi@1 | 2219 | __ pop(state); // restore tosca |
aoqi@1 | 2220 | |
aoqi@1 | 2221 | // return |
aoqi@1 | 2222 | __ jr(RA); |
aoqi@1 | 2223 | __ delayed()->nop(); |
aoqi@1 | 2224 | |
aoqi@1 | 2225 | return entry; |
aoqi@1 | 2226 | } |
aoqi@1 | 2227 | |
aoqi@1 | 2228 | void TemplateInterpreterGenerator::count_bytecode() { |
aoqi@1 | 2229 | __ li(T8, (long)&BytecodeCounter::_counter_value); |
aoqi@1 | 2230 | __ lw(AT, T8, 0); |
aoqi@1 | 2231 | __ daddi(AT, AT, 1); |
aoqi@1 | 2232 | __ sw(AT, T8, 0); |
aoqi@1 | 2233 | } |
aoqi@1 | 2234 | |
aoqi@1 | 2235 | void TemplateInterpreterGenerator::histogram_bytecode(Template* t) { |
aoqi@6880 | 2236 | __ li(T8, (long)&BytecodeHistogram::_counters[t->bytecode()]); |
aoqi@6880 | 2237 | __ lw(AT, T8, 0); |
aoqi@6880 | 2238 | __ daddi(AT, AT, 1); |
aoqi@6880 | 2239 | __ sw(AT, T8, 0); |
aoqi@1 | 2240 | } |
aoqi@1 | 2241 | |
aoqi@1 | 2242 | void TemplateInterpreterGenerator::histogram_bytecode_pair(Template* t) { |
aoqi@6880 | 2243 | __ li(T8, (long)&BytecodePairHistogram::_index); |
aoqi@6880 | 2244 | __ lw(T9, T8, 0); |
aoqi@6880 | 2245 | __ dsrl(T9, T9, BytecodePairHistogram::log2_number_of_codes); |
aoqi@6880 | 2246 | __ li(T8, ((long)t->bytecode()) << BytecodePairHistogram::log2_number_of_codes); |
aoqi@6880 | 2247 | __ orr(T9, T9, T8); |
aoqi@6880 | 2248 | __ li(T8, (long)&BytecodePairHistogram::_index); |
aoqi@6880 | 2249 | __ sw(T9, T8, 0); |
aoqi@6880 | 2250 | __ dsll(T9, T9, 2); |
aoqi@6880 | 2251 | __ li(T8, (long)BytecodePairHistogram::_counters); |
aoqi@6880 | 2252 | __ dadd(T8, T8, T9); |
aoqi@6880 | 2253 | __ lw(AT, T8, 0); |
aoqi@6880 | 2254 | __ daddi(AT, AT, 1); |
aoqi@6880 | 2255 | __ sw(AT, T8, 0); |
aoqi@1 | 2256 | } |
aoqi@1 | 2257 | |
aoqi@1 | 2258 | |
aoqi@1 | 2259 | void TemplateInterpreterGenerator::trace_bytecode(Template* t) { |
aoqi@1 | 2260 | // Call a little run-time stub to avoid blow-up for each bytecode. |
aoqi@1 | 2261 | // The run-time runtime saves the right registers, depending on |
aoqi@1 | 2262 | // the tosca in-state for the given template. |
aoqi@1 | 2263 | |
aoqi@6880 | 2264 | address entry = Interpreter::trace_code(t->tos_in()); |
aoqi@6880 | 2265 | assert(entry != NULL, "entry must have been generated"); |
aoqi@6880 | 2266 | __ call(entry, relocInfo::none); |
aoqi@6880 | 2267 | __ delayed()->nop(); |
aoqi@6880 | 2268 | //add for compressedoops |
aoqi@6880 | 2269 | __ reinit_heapbase(); |
aoqi@1 | 2270 | } |
aoqi@1 | 2271 | |
aoqi@1 | 2272 | |
aoqi@1 | 2273 | void TemplateInterpreterGenerator::stop_interpreter_at() { |
aoqi@1 | 2274 | Label L; |
aoqi@6880 | 2275 | __ li(T8, long(&BytecodeCounter::_counter_value)); |
aoqi@6880 | 2276 | __ lw(T8, T8, 0); |
aoqi@6880 | 2277 | __ move(AT, StopInterpreterAt); |
aoqi@6880 | 2278 | __ bne(T8, AT, L); |
aoqi@6880 | 2279 | __ delayed()->nop(); |
aoqi@6880 | 2280 | __ call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); |
aoqi@6880 | 2281 | __ delayed()->nop(); |
aoqi@6880 | 2282 | __ bind(L); |
aoqi@1 | 2283 | } |
aoqi@1 | 2284 | #endif // !PRODUCT |
aoqi@1 | 2285 | #endif // ! CC_INTERP |