Mercurial > hg > graal-compiler
diff src/share/vm/interpreter/bytecodeInterpreter.cpp @ 14909:4ca6dc0799b6
Backout jdk9 merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Tue, 01 Apr 2014 13:57:07 +0200 |
parents | 1e820011ee5f |
children | 89152779163c |
line wrap: on
line diff
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Apr 01 14:09:03 2014 +0200 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Apr 01 13:57:07 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,16 +28,14 @@ #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/bytecodeInterpreter.inline.hpp" -#include "interpreter/bytecodeInterpreterProfiling.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "memory/cardTableModRefBS.hpp" #include "memory/resourceArea.hpp" #include "oops/methodCounters.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" -#include "prims/jvmtiThreadState.hpp" -#include "runtime/biasedLocking.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.hpp" @@ -68,9 +66,6 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif -#ifdef TARGET_OS_ARCH_aix_ppc -# include "orderAccess_aix_ppc.inline.hpp" -#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "orderAccess_bsd_x86.inline.hpp" #endif @@ -143,20 +138,19 @@ * is no entry point to do the transition to vm so we just * do it by hand here. */ -#define VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap) \ +#define VM_JAVA_ERROR_NO_JUMP(name, msg) \ DECACHE_STATE(); \ SET_LAST_JAVA_FRAME(); \ { \ - InterpreterRuntime::note_a_trap(THREAD, istate->method(), BCI()); \ ThreadInVMfromJava trans(THREAD); \ Exceptions::_throw_msg(THREAD, __FILE__, __LINE__, name, msg); \ } \ RESET_LAST_JAVA_FRAME(); \ CACHE_STATE(); -// Normal throw of a java error. -#define VM_JAVA_ERROR(name, msg, note_a_trap) \ - VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap) \ +// Normal throw of a java error +#define VM_JAVA_ERROR(name, msg) \ + VM_JAVA_ERROR_NO_JUMP(name, msg) \ goto handle_exception; #ifdef PRODUCT @@ -203,10 +197,6 @@ !THREAD->pop_frame_in_process()) { \ goto handle_Pop_Frame; \ } \ - if (THREAD->jvmti_thread_state() && \ - THREAD->jvmti_thread_state()->is_earlyret_pending()) { \ - goto handle_Early_Return; \ - } \ opcode = *pc; \ } \ } \ @@ -342,30 +332,12 @@ if (UseLoopCounter) { \ bool do_OSR = UseOnStackReplacement; \ mcs->backedge_counter()->increment(); \ - if (ProfileInterpreter) { \ - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); \ - /* Check for overflow against MDO count. */ \ - do_OSR = do_OSR \ - && (mdo_last_branch_taken_count >= (uint)InvocationCounter::InterpreterBackwardBranchLimit)\ - /* When ProfileInterpreter is on, the backedge_count comes */ \ - /* from the methodDataOop, which value does not get reset on */ \ - /* the call to frequency_counter_overflow(). To avoid */ \ - /* excessive calls to the overflow routine while the method is */ \ - /* being compiled, add a second test to make sure the overflow */ \ - /* function is called only once every overflow_frequency. */ \ - && (!(mdo_last_branch_taken_count & 1023)); \ - } else { \ - /* check for overflow of backedge counter */ \ - do_OSR = do_OSR \ - && mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter()); \ - } \ + if (do_OSR) do_OSR = mcs->backedge_counter()->reached_InvocationLimit(); \ if (do_OSR) { \ - nmethod* osr_nmethod; \ + nmethod* osr_nmethod; \ OSR_REQUEST(osr_nmethod, branch_pc); \ if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \ - intptr_t* buf; \ - /* Call OSR migration with last java frame only, no checks. */ \ - CALL_VM_NAKED_LJF(buf=SharedRuntime::OSR_migration_begin(THREAD)); \ + intptr_t* buf = SharedRuntime::OSR_migration_begin(THREAD); \ istate->set_msg(do_osr); \ istate->set_osr_buf((address)buf); \ istate->set_osr_entry(osr_nmethod->osr_entry()); \ @@ -373,6 +345,7 @@ } \ } \ } /* UseCompiler ... */ \ + mcs->invocation_counter()->increment(); \ SAFEPOINT; \ } @@ -405,21 +378,17 @@ #undef CACHE_FRAME #define CACHE_FRAME() -// BCI() returns the current bytecode-index. -#undef BCI -#define BCI() ((int)(intptr_t)(pc - (intptr_t)istate->method()->code_base())) - /* * CHECK_NULL - Macro for throwing a NullPointerException if the object * passed is a null ref. * On some architectures/platforms it should be possible to do this implicitly */ #undef CHECK_NULL -#define CHECK_NULL(obj_) \ - if ((obj_) == NULL) { \ - VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), NULL, note_nullCheck_trap); \ - } \ - VERIFY_OOP(obj_) +#define CHECK_NULL(obj_) \ + if ((obj_) == NULL) { \ + VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), ""); \ + } \ + VERIFY_OOP(obj_) #define VMdoubleConstZero() 0.0 #define VMdoubleConstOne() 1.0 @@ -441,30 +410,22 @@ CACHE_CP(); \ CACHE_LOCALS(); -// Call the VM with last java frame only. -#define CALL_VM_NAKED_LJF(func) \ - DECACHE_STATE(); \ - SET_LAST_JAVA_FRAME(); \ - func; \ - RESET_LAST_JAVA_FRAME(); \ - CACHE_STATE(); - -// Call the VM. Don't check for pending exceptions. -#define CALL_VM_NOCHECK(func) \ - CALL_VM_NAKED_LJF(func) \ - if (THREAD->pop_frame_pending() && \ - !THREAD->pop_frame_in_process()) { \ - goto handle_Pop_Frame; \ - } \ - if (THREAD->jvmti_thread_state() && \ - THREAD->jvmti_thread_state()->is_earlyret_pending()) { \ - goto handle_Early_Return; \ - } +// Call the VM don't check for pending exceptions +#define CALL_VM_NOCHECK(func) \ + DECACHE_STATE(); \ + SET_LAST_JAVA_FRAME(); \ + func; \ + RESET_LAST_JAVA_FRAME(); \ + CACHE_STATE(); \ + if (THREAD->pop_frame_pending() && \ + !THREAD->pop_frame_in_process()) { \ + goto handle_Pop_Frame; \ + } // Call the VM and check for pending exceptions -#define CALL_VM(func, label) { \ - CALL_VM_NOCHECK(func); \ - if (THREAD->has_pending_exception()) goto label; \ +#define CALL_VM(func, label) { \ + CALL_VM_NOCHECK(func); \ + if (THREAD->has_pending_exception()) goto label; \ } /* @@ -541,6 +502,8 @@ interpreterState orig = istate; #endif + static volatile jbyte* _byte_map_base; // adjusted card table base for oop store barrier + register intptr_t* topOfStack = (intptr_t *)istate->stack(); /* access with STACK macros */ register address pc = istate->bcp(); register jubyte opcode; @@ -548,9 +511,12 @@ register ConstantPoolCache* cp = istate->constants(); // method()->constants()->cache() #ifdef LOTS_OF_REGS register JavaThread* THREAD = istate->thread(); + register volatile jbyte* BYTE_MAP_BASE = _byte_map_base; #else #undef THREAD #define THREAD istate->thread() +#undef BYTE_MAP_BASE +#define BYTE_MAP_BASE _byte_map_base #endif #ifdef USELABELS @@ -656,20 +622,16 @@ topOfStack < istate->stack_base(), "Stack top out of range"); -#ifdef CC_INTERP_PROFILE - // MethodData's last branch taken count. - uint mdo_last_branch_taken_count = 0; -#else - const uint mdo_last_branch_taken_count = 0; -#endif - switch (istate->msg()) { case initialize: { - if (initialized++) ShouldNotReachHere(); // Only one initialize call. + if (initialized++) ShouldNotReachHere(); // Only one initialize call _compiling = (UseCompiler || CountCompiledCalls); #ifdef VM_JVMTI _jvmti_interp_events = JvmtiExport::can_post_interpreter_events(); #endif + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); + _byte_map_base = (volatile jbyte*)(((CardTableModRefBS*)bs)->byte_map_base); return; } break; @@ -684,12 +646,15 @@ METHOD->increment_interpreter_invocation_count(THREAD); } mcs->invocation_counter()->increment(); - if (mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter())) { - CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception); - // We no longer retry on a counter overflow. + if (mcs->invocation_counter()->reached_InvocationLimit()) { + CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception); + + // We no longer retry on a counter overflow + + // istate->set_msg(retry_method); + // THREAD->clr_do_not_unlock(); + // return; } - // Get or create profile data. Check for pending (async) exceptions. - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); SAFEPOINT; } @@ -711,99 +676,117 @@ } #endif // HACK - // Lock method if synchronized. + + // lock method if synchronized if (METHOD->is_synchronized()) { - // oop rcvr = locals[0].j.r; - oop rcvr; - if (METHOD->is_static()) { - rcvr = METHOD->constants()->pool_holder()->java_mirror(); - } else { - rcvr = LOCALS_OBJECT(0); - VERIFY_OOP(rcvr); - } - // The initial monitor is ours for the taking. - // Monitor not filled in frame manager any longer as this caused race condition with biased locking. - BasicObjectLock* mon = &istate->monitor_base()[-1]; - mon->set_obj(rcvr); - bool success = false; - uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; - markOop mark = rcvr->mark(); - intptr_t hash = (intptr_t) markOopDesc::no_hash; - // Implies UseBiasedLocking. - if (mark->has_bias_pattern()) { - uintptr_t thread_ident; - uintptr_t anticipated_bias_locking_value; - thread_ident = (uintptr_t)istate->thread(); - anticipated_bias_locking_value = - (((uintptr_t)rcvr->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & - ~((uintptr_t) markOopDesc::age_mask_in_place); - - if (anticipated_bias_locking_value == 0) { - // Already biased towards this thread, nothing to do. - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::biased_lock_entry_count_addr())++; - } - success = true; - } else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { - // Try to revoke bias. - markOop header = rcvr->klass()->prototype_header(); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) - (*BiasedLocking::revoked_lock_entry_count_addr())++; - } - } else if ((anticipated_bias_locking_value & epoch_mask_in_place) != 0) { - // Try to rebias. - markOop new_header = (markOop) ( (intptr_t) rcvr->klass()->prototype_header() | thread_ident); - if (hash != markOopDesc::no_hash) { - new_header = new_header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::rebiased_lock_entry_count_addr())++; + // oop rcvr = locals[0].j.r; + oop rcvr; + if (METHOD->is_static()) { + rcvr = METHOD->constants()->pool_holder()->java_mirror(); + } else { + rcvr = LOCALS_OBJECT(0); + VERIFY_OOP(rcvr); + } + // The initial monitor is ours for the taking + BasicObjectLock* mon = &istate->monitor_base()[-1]; + oop monobj = mon->obj(); + assert(mon->obj() == rcvr, "method monitor mis-initialized"); + + bool success = UseBiasedLocking; + if (UseBiasedLocking) { + markOop mark = rcvr->mark(); + if (mark->has_bias_pattern()) { + // The bias pattern is present in the object's header. Need to check + // whether the bias owner and the epoch are both still current. + intptr_t xx = ((intptr_t) THREAD) ^ (intptr_t) mark; + xx = (intptr_t) rcvr->klass()->prototype_header() ^ xx; + intptr_t yy = (xx & ~((int) markOopDesc::age_mask_in_place)); + if (yy != 0 ) { + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + + if (yy & markOopDesc::biased_lock_mask_in_place == 0 ) { + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + if (yy & markOopDesc::epoch_mask_in_place == 0) { + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + intptr_t unbiased = (intptr_t) mark & (markOopDesc::biased_lock_mask_in_place | + markOopDesc::age_mask_in_place | + markOopDesc::epoch_mask_in_place); + if (Atomic::cmpxchg_ptr((intptr_t)THREAD | unbiased, (intptr_t*) rcvr->mark_addr(), unbiased) != unbiased) { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + } + } else { + try_rebias: + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD; + if (Atomic::cmpxchg_ptr((intptr_t)THREAD | (intptr_t) rcvr->klass()->prototype_header(), + (intptr_t*) rcvr->mark_addr(), + (intptr_t) mark) != (intptr_t) mark) { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + } + } + } else { + try_revoke_bias: + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + // + xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD; + if (Atomic::cmpxchg_ptr(rcvr->klass()->prototype_header(), + (intptr_t*) rcvr->mark_addr(), + mark) == mark) { + // (*counters->revoked_lock_entry_count_addr())++; + success = false; + } + } } } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); - } - success = true; - } else { - // Try to bias towards thread in case object is anonymously biased. - markOop header = (markOop) ((uintptr_t) mark & - ((uintptr_t)markOopDesc::biased_lock_mask_in_place | - (uintptr_t)markOopDesc::age_mask_in_place | epoch_mask_in_place)); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - markOop new_header = (markOop) ((uintptr_t) header | thread_ident); - // Debugging hint. - DEBUG_ONLY(mon->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) - if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), header) == header) { - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; - } - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); - } - success = true; - } - } - - // Traditional lightweight locking. - if (!success) { - markOop displaced = rcvr->mark()->set_unlocked(); - mon->lock()->set_displaced_header(displaced); - bool call_vm = UseHeavyMonitors; - if (call_vm || Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - mon->lock()->set_displaced_header(NULL); - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + cas_label: + success = false; } } - } + if (!success) { + markOop displaced = rcvr->mark()->set_unlocked(); + mon->lock()->set_displaced_header(displaced); + if (Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + mon->lock()->set_displaced_header(NULL); + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + } + } + } } THREAD->clr_do_not_unlock(); @@ -825,14 +808,9 @@ case popping_frame: { // returned from a java call to pop the frame, restart the call // clear the message so we don't confuse ourselves later + ShouldNotReachHere(); // we don't return this. assert(THREAD->pop_frame_in_process(), "wrong frame pop state"); istate->set_msg(no_request); - if (_compiling) { - // Set MDX back to the ProfileData of the invoke bytecode that will be - // restarted. - SET_MDX(NULL); - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); - } THREAD->clr_pop_frame_in_process(); goto run; } @@ -858,19 +836,10 @@ if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) { goto handle_Pop_Frame; } - if (THREAD->jvmti_thread_state() && - THREAD->jvmti_thread_state()->is_earlyret_pending()) { - goto handle_Early_Return; - } if (THREAD->has_pending_exception()) goto handle_exception; // Update the pc by the saved amount of the invoke bytecode size UPDATE_PC(istate->bcp_advance()); - - if (_compiling) { - // Get or create profile data. Check for pending (async) exceptions. - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); - } goto run; } @@ -878,11 +847,6 @@ // Returned from an opcode that will reexecute. Deopt was // a result of a PopFrame request. // - - if (_compiling) { - // Get or create profile data. Check for pending (async) exceptions. - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); - } goto run; } @@ -905,11 +869,6 @@ } UPDATE_PC(Bytecodes::length_at(METHOD, pc)); if (THREAD->has_pending_exception()) goto handle_exception; - - if (_compiling) { - // Get or create profile data. Check for pending (async) exceptions. - BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); - } goto run; } case got_monitors: { @@ -922,84 +881,15 @@ BasicObjectLock* entry = (BasicObjectLock*) istate->stack_base(); assert(entry->obj() == NULL, "Frame manager didn't allocate the monitor"); entry->set_obj(lockee); - bool success = false; - uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; - - markOop mark = lockee->mark(); - intptr_t hash = (intptr_t) markOopDesc::no_hash; - // implies UseBiasedLocking - if (mark->has_bias_pattern()) { - uintptr_t thread_ident; - uintptr_t anticipated_bias_locking_value; - thread_ident = (uintptr_t)istate->thread(); - anticipated_bias_locking_value = - (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & - ~((uintptr_t) markOopDesc::age_mask_in_place); - - if (anticipated_bias_locking_value == 0) { - // already biased towards this thread, nothing to do - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::biased_lock_entry_count_addr())++; - } - success = true; - } else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { - // try revoke bias - markOop header = lockee->klass()->prototype_header(); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) { - (*BiasedLocking::revoked_lock_entry_count_addr())++; - } - } - } else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) { - // try rebias - markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident); - if (hash != markOopDesc::no_hash) { - new_header = new_header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::rebiased_lock_entry_count_addr())++; - } - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - success = true; + + markOop displaced = lockee->mark()->set_unlocked(); + entry->lock()->set_displaced_header(displaced); + if (Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + entry->lock()->set_displaced_header(NULL); } else { - // try to bias towards thread in case object is anonymously biased - markOop header = (markOop) ((uintptr_t) mark & ((uintptr_t)markOopDesc::biased_lock_mask_in_place | - (uintptr_t)markOopDesc::age_mask_in_place | epoch_mask_in_place)); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - markOop new_header = (markOop) ((uintptr_t) header | thread_ident); - // debugging hint - DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) - if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) { - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; - } - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - success = true; - } - } - - // traditional lightweight locking - if (!success) { - markOop displaced = lockee->mark()->set_unlocked(); - entry->lock()->set_displaced_header(displaced); - bool call_vm = UseHeavyMonitors; - if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - entry->lock()->set_displaced_header(NULL); - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); } } UPDATE_PC_AND_TOS(1, -1); @@ -1160,11 +1050,6 @@ uint16_t reg = Bytes::get_Java_u2(pc + 2); opcode = pc[1]; - - // Wide and it's sub-bytecode are counted as separate instructions. If we - // don't account for this here, the bytecode trace skips the next bytecode. - DO_UPDATE_INSTRUCTION_COUNT(opcode); - switch(opcode) { case Bytecodes::_aload: VERIFY_OOP(LOCALS_OBJECT(reg)); @@ -1208,13 +1093,10 @@ UPDATE_PC_AND_CONTINUE(6); } case Bytecodes::_ret: - // Profile ret. - BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(reg)))); - // Now, update the pc. pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(reg)); UPDATE_PC_AND_CONTINUE(0); default: - VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode", note_no_trap); + VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode"); } } @@ -1295,7 +1177,7 @@ CASE(_i##opcname): \ if (test && (STACK_INT(-1) == 0)) { \ VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \ - "/ by zero", note_div0Check_trap); \ + "/ by zero"); \ } \ SET_STACK_INT(VMint##opname(STACK_INT(-2), \ STACK_INT(-1)), \ @@ -1307,7 +1189,7 @@ jlong l1 = STACK_LONG(-1); \ if (VMlongEqz(l1)) { \ VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \ - "/ by long zero", note_div0Check_trap); \ + "/ by long zero"); \ } \ } \ /* First long at (-1,-2) next long at (-3,-4) */ \ @@ -1520,23 +1402,17 @@ #define COMPARISON_OP(name, comparison) \ CASE(_if_icmp##name): { \ - const bool cmp = (STACK_INT(-2) comparison STACK_INT(-1)); \ - int skip = cmp \ + int skip = (STACK_INT(-2) comparison STACK_INT(-1)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ - /* Profile branch. */ \ - BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -2); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ } \ CASE(_if##name): { \ - const bool cmp = (STACK_INT(-1) comparison 0); \ - int skip = cmp \ + int skip = (STACK_INT(-1) comparison 0) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ - /* Profile branch. */ \ - BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1545,12 +1421,9 @@ #define COMPARISON_OP2(name, comparison) \ COMPARISON_OP(name, comparison) \ CASE(_if_acmp##name): { \ - const bool cmp = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1)); \ - int skip = cmp \ + int skip = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ - /* Profile branch. */ \ - BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -2); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1558,12 +1431,9 @@ #define NULL_COMPARISON_NOT_OP(name) \ CASE(_if##name): { \ - const bool cmp = (!(STACK_OBJECT(-1) == NULL)); \ - int skip = cmp \ + int skip = (!(STACK_OBJECT(-1) == NULL)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ - /* Profile branch. */ \ - BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1571,12 +1441,9 @@ #define NULL_COMPARISON_OP(name) \ CASE(_if##name): { \ - const bool cmp = ((STACK_OBJECT(-1) == NULL)); \ - int skip = cmp \ + int skip = ((STACK_OBJECT(-1) == NULL)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ - /* Profile branch. */ \ - BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1599,42 +1466,30 @@ int32_t high = Bytes::get_Java_u4((address)&lpc[2]); int32_t skip; key -= low; - if (((uint32_t) key > (uint32_t)(high - low))) { - key = -1; - skip = Bytes::get_Java_u4((address)&lpc[0]); - } else { - skip = Bytes::get_Java_u4((address)&lpc[key + 3]); - } - // Profile switch. - BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/key); - // Does this really need a full backedge check (osr)? + skip = ((uint32_t) key > (uint32_t)(high - low)) + ? Bytes::get_Java_u4((address)&lpc[0]) + : Bytes::get_Java_u4((address)&lpc[key + 3]); + // Does this really need a full backedge check (osr?) address branch_pc = pc; UPDATE_PC_AND_TOS(skip, -1); DO_BACKEDGE_CHECKS(skip, branch_pc); CONTINUE; } - /* Goto pc whose table entry matches specified key. */ + /* Goto pc whose table entry matches specified key */ CASE(_lookupswitch): { jint* lpc = (jint*)VMalignWordUp(pc+1); int32_t key = STACK_INT(-1); int32_t skip = Bytes::get_Java_u4((address) lpc); /* default amount */ - // Remember index. - int index = -1; - int newindex = 0; int32_t npairs = Bytes::get_Java_u4((address) &lpc[1]); while (--npairs >= 0) { - lpc += 2; - if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) { - skip = Bytes::get_Java_u4((address)&lpc[1]); - index = newindex; - break; - } - newindex += 1; + lpc += 2; + if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) { + skip = Bytes::get_Java_u4((address)&lpc[1]); + break; + } } - // Profile switch. - BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/index); address branch_pc = pc; UPDATE_PC_AND_TOS(skip, -1); DO_BACKEDGE_CHECKS(skip, branch_pc); @@ -1719,7 +1574,7 @@ if ((uint32_t)index >= (uint32_t)arrObj->length()) { \ sprintf(message, "%d", index); \ VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \ - message, note_rangeCheck_trap); \ + message); \ } /* 32-bit loads. These handle conversion from < 32-bit types */ @@ -1745,11 +1600,8 @@ ARRAY_LOADTO32(T_INT, jint, "%d", STACK_INT, 0); CASE(_faload): ARRAY_LOADTO32(T_FLOAT, jfloat, "%f", STACK_FLOAT, 0); - CASE(_aaload): { - ARRAY_INTRO(-2); - SET_STACK_OBJECT(((objArrayOop) arrObj)->obj_at(index), -2); - UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); - } + CASE(_aaload): + ARRAY_LOADTO32(T_OBJECT, oop, INTPTR_FORMAT, STACK_OBJECT, 0); CASE(_baload): ARRAY_LOADTO32(T_BYTE, jbyte, "%d", STACK_INT, 0); CASE(_caload): @@ -1793,24 +1645,21 @@ // arrObj, index are set if (rhsObject != NULL) { /* Check assignability of rhsObject into arrObj */ - Klass* rhsKlass = rhsObject->klass(); // EBX (subclass) - Klass* elemKlass = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX + Klass* rhsKlassOop = rhsObject->klass(); // EBX (subclass) + Klass* elemKlassOop = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX // // Check for compatibilty. This check must not GC!! // Seems way more expensive now that we must dispatch // - if (rhsKlass != elemKlass && !rhsKlass->is_subtype_of(elemKlass)) { // ebx->is... - // Decrement counter if subtype check failed. - BI_PROFILE_SUBTYPECHECK_FAILED(rhsKlass); - VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "", note_arrayCheck_trap); + if (rhsKlassOop != elemKlassOop && !rhsKlassOop->is_subtype_of(elemKlassOop)) { // ebx->is... + VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), ""); } - // Profile checkcast with null_seen and receiver. - BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, rhsKlass); - } else { - // Profile checkcast with null_seen and receiver. - BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL); } - ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); + oop* elem_loc = (oop*)(((address) arrObj->base(T_OBJECT)) + index * sizeof(oop)); + // *(oop*)(((address) arrObj->base(T_OBJECT)) + index * sizeof(oop)) = rhsObject; + *elem_loc = rhsObject; + // Mark the card + OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)elem_loc >> CardTableModRefBS::card_shift], 0); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } CASE(_bastore): @@ -1851,87 +1700,14 @@ } if (entry != NULL) { entry->set_obj(lockee); - int success = false; - uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; - - markOop mark = lockee->mark(); - intptr_t hash = (intptr_t) markOopDesc::no_hash; - // implies UseBiasedLocking - if (mark->has_bias_pattern()) { - uintptr_t thread_ident; - uintptr_t anticipated_bias_locking_value; - thread_ident = (uintptr_t)istate->thread(); - anticipated_bias_locking_value = - (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & - ~((uintptr_t) markOopDesc::age_mask_in_place); - - if (anticipated_bias_locking_value == 0) { - // already biased towards this thread, nothing to do - if (PrintBiasedLockingStatistics) { - (* BiasedLocking::biased_lock_entry_count_addr())++; - } - success = true; - } - else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { - // try revoke bias - markOop header = lockee->klass()->prototype_header(); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) - (*BiasedLocking::revoked_lock_entry_count_addr())++; - } - } - else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) { - // try rebias - markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident); - if (hash != markOopDesc::no_hash) { - new_header = new_header->copy_set_hash(hash); - } - if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) { - if (PrintBiasedLockingStatistics) - (* BiasedLocking::rebiased_lock_entry_count_addr())++; - } - else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - success = true; - } - else { - // try to bias towards thread in case object is anonymously biased - markOop header = (markOop) ((uintptr_t) mark & ((uintptr_t)markOopDesc::biased_lock_mask_in_place | - (uintptr_t)markOopDesc::age_mask_in_place | - epoch_mask_in_place)); - if (hash != markOopDesc::no_hash) { - header = header->copy_set_hash(hash); - } - markOop new_header = (markOop) ((uintptr_t) header | thread_ident); - // debugging hint - DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) - if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) { - if (PrintBiasedLockingStatistics) - (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; - } - else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - success = true; - } - } - - // traditional lightweight locking - if (!success) { - markOop displaced = lockee->mark()->set_unlocked(); - entry->lock()->set_displaced_header(displaced); - bool call_vm = UseHeavyMonitors; - if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - entry->lock()->set_displaced_header(NULL); - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } + markOop displaced = lockee->mark()->set_unlocked(); + entry->lock()->set_displaced_header(displaced); + if (Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + entry->lock()->set_displaced_header(NULL); + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); } } UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); @@ -1953,15 +1729,12 @@ BasicLock* lock = most_recent->lock(); markOop header = lock->displaced_header(); most_recent->set_obj(NULL); - if (!lockee->mark()->has_bias_pattern()) { - bool call_vm = UseHeavyMonitors; - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL || call_vm) { - if (call_vm || Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { - // restore object for the slow case - most_recent->set_obj(lockee); - CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception); - } + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL) { + if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { + // restore object for the slow case + most_recent->set_obj(lockee); + CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception); } } UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); @@ -2034,9 +1807,6 @@ TosState tos_type = cache->flag_state(); int field_offset = cache->f2_as_index(); if (cache->is_volatile()) { - if (support_IRIW_for_not_multiple_copy_atomic_cpu) { - OrderAccess::fence(); - } if (tos_type == atos) { VERIFY_OOP(obj->obj_field_acquire(field_offset)); SET_STACK_OBJECT(obj->obj_field_acquire(field_offset), -1); @@ -2153,6 +1923,7 @@ } else if (tos_type == atos) { VERIFY_OOP(STACK_OBJECT(-1)); obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); + OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)obj >> CardTableModRefBS::card_shift], 0); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); } else if (tos_type == ltos) { @@ -2173,6 +1944,7 @@ } else if (tos_type == atos) { VERIFY_OOP(STACK_OBJECT(-1)); obj->obj_field_put(field_offset, STACK_OBJECT(-1)); + OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)obj >> CardTableModRefBS::card_shift], 0); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); } else if (tos_type == ltos) { @@ -2209,14 +1981,10 @@ if (UseTLAB) { result = (oop) THREAD->tlab().allocate(obj_size); } - // Disable non-TLAB-based fast-path, because profiling requires that all - // allocations go through InterpreterRuntime::_new() if THREAD->tlab().allocate - // returns NULL. -#ifndef CC_INTERP_PROFILE if (result == NULL) { need_zero = true; // Try allocate in shared eden - retry: + retry: HeapWord* compare_to = *Universe::heap()->top_addr(); HeapWord* new_top = compare_to + obj_size; if (new_top <= *Universe::heap()->end_addr()) { @@ -2226,7 +1994,6 @@ result = (oop) compare_to; } } -#endif if (result != NULL) { // Initialize object (if nonzero size and need) and then the header if (need_zero ) { @@ -2243,9 +2010,6 @@ } result->set_klass_gap(0); result->set_klass(k_entry); - // Must prevent reordering of stores for object initialization - // with stores that publish the new object. - OrderAccess::storestore(); SET_STACK_OBJECT(result, 0); UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1); } @@ -2254,9 +2018,6 @@ // Slow case allocation CALL_VM(InterpreterRuntime::_new(THREAD, METHOD->constants(), index), handle_exception); - // Must prevent reordering of stores for object initialization - // with stores that publish the new object. - OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), 0); THREAD->set_vm_result(NULL); UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1); @@ -2266,9 +2027,6 @@ jint size = STACK_INT(-1); CALL_VM(InterpreterRuntime::anewarray(THREAD, METHOD->constants(), index, size), handle_exception); - // Must prevent reordering of stores for object initialization - // with stores that publish the new object. - OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -1); THREAD->set_vm_result(NULL); UPDATE_PC_AND_CONTINUE(3); @@ -2283,9 +2041,6 @@ //adjust pointer to start of stack element CALL_VM(InterpreterRuntime::multianewarray(THREAD, dimarray), handle_exception); - // Must prevent reordering of stores for object initialization - // with stores that publish the new object. - OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -dims); THREAD->set_vm_result(NULL); UPDATE_PC_AND_TOS_AND_CONTINUE(4, -(dims-1)); @@ -2294,63 +2049,61 @@ if (STACK_OBJECT(-1) != NULL) { VERIFY_OOP(STACK_OBJECT(-1)); u2 index = Bytes::get_Java_u2(pc+1); + if (ProfileInterpreter) { + // needs Profile_checkcast QQQ + ShouldNotReachHere(); + } // Constant pool may have actual klass or unresolved klass. If it is - // unresolved we must resolve it. + // unresolved we must resolve it if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass(); - Klass* objKlass = STACK_OBJECT(-1)->klass(); // ebx + Klass* objKlassOop = STACK_OBJECT(-1)->klass(); //ebx // // Check for compatibilty. This check must not GC!! - // Seems way more expensive now that we must dispatch. + // Seems way more expensive now that we must dispatch // - if (objKlass != klassOf && !objKlass->is_subtype_of(klassOf)) { - // Decrement counter at checkcast. - BI_PROFILE_SUBTYPECHECK_FAILED(objKlass); + if (objKlassOop != klassOf && + !objKlassOop->is_subtype_of(klassOf)) { ResourceMark rm(THREAD); - const char* objName = objKlass->external_name(); + const char* objName = objKlassOop->external_name(); const char* klassName = klassOf->external_name(); char* message = SharedRuntime::generate_class_cast_message( objName, klassName); - VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap); + VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message); } - // Profile checkcast with null_seen and receiver. - BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, objKlass); } else { - // Profile checkcast with null_seen and receiver. - BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL); + if (UncommonNullCast) { +// istate->method()->set_null_cast_seen(); +// [RGV] Not sure what to do here! + + } } UPDATE_PC_AND_CONTINUE(3); CASE(_instanceof): if (STACK_OBJECT(-1) == NULL) { SET_STACK_INT(0, -1); - // Profile instanceof with null_seen and receiver. - BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/true, NULL); } else { VERIFY_OOP(STACK_OBJECT(-1)); u2 index = Bytes::get_Java_u2(pc+1); // Constant pool may have actual klass or unresolved klass. If it is - // unresolved we must resolve it. + // unresolved we must resolve it if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass(); - Klass* objKlass = STACK_OBJECT(-1)->klass(); + Klass* objKlassOop = STACK_OBJECT(-1)->klass(); // // Check for compatibilty. This check must not GC!! - // Seems way more expensive now that we must dispatch. + // Seems way more expensive now that we must dispatch // - if ( objKlass == klassOf || objKlass->is_subtype_of(klassOf)) { + if ( objKlassOop == klassOf || objKlassOop->is_subtype_of(klassOf)) { SET_STACK_INT(1, -1); } else { SET_STACK_INT(0, -1); - // Decrement counter at checkcast. - BI_PROFILE_SUBTYPECHECK_FAILED(objKlass); } - // Profile instanceof with null_seen and receiver. - BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/false, objKlass); } UPDATE_PC_AND_CONTINUE(3); @@ -2493,9 +2246,6 @@ istate->set_callee_entry_point(method->from_interpreted_entry()); istate->set_bcp_advance(5); - // Invokedynamic has got a call counter, just like an invokestatic -> increment! - BI_PROFILE_UPDATE_CALL(); - UPDATE_PC_AND_RETURN(0); // I'll be back... } @@ -2528,9 +2278,6 @@ istate->set_callee_entry_point(method->from_interpreted_entry()); istate->set_bcp_advance(3); - // Invokehandle has got a call counter, just like a final call -> increment! - BI_PROFILE_UPDATE_FINALCALL(); - UPDATE_PC_AND_RETURN(0); // I'll be back... } @@ -2558,18 +2305,14 @@ CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); if (cache->is_vfinal()) { callee = cache->f2_as_vfinal_method(); - // Profile 'special case of invokeinterface' final call. - BI_PROFILE_UPDATE_FINALCALL(); } else { - // Get receiver. + // get receiver int parms = cache->parameter_size(); - // Same comments as invokevirtual apply here. - oop rcvr = STACK_OBJECT(-parms); - VERIFY_OOP(rcvr); - InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); + // Same comments as invokevirtual apply here + VERIFY_OOP(STACK_OBJECT(-parms)); + InstanceKlass* rcvrKlass = (InstanceKlass*) + STACK_OBJECT(-parms)->klass(); callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; - // Profile 'special case of invokeinterface' virtual call. - BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); } istate->set_callee(callee); istate->set_callee_entry_point(callee->from_interpreted_entry()); @@ -2600,18 +2343,15 @@ // interface. The link resolver checks this but only for the first // time this interface is called. if (i == int2->itable_length()) { - VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap); + VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), ""); } int mindex = cache->f2_as_index(); itableMethodEntry* im = ki->first_method_entry(rcvr->klass()); callee = im[mindex].method(); if (callee == NULL) { - VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), "", note_no_trap); + VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), ""); } - // Profile virtual call. - BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); - istate->set_callee(callee); istate->set_callee_entry_point(callee->from_interpreted_entry()); #ifdef VM_JVMTI @@ -2643,11 +2383,8 @@ Method* callee; if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) { CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); - if (cache->is_vfinal()) { - callee = cache->f2_as_vfinal_method(); - // Profile final call. - BI_PROFILE_UPDATE_FINALCALL(); - } else { + if (cache->is_vfinal()) callee = cache->f2_as_vfinal_method(); + else { // get receiver int parms = cache->parameter_size(); // this works but needs a resourcemark and seems to create a vtable on every call: @@ -2656,9 +2393,8 @@ // this fails with an assert // InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass()); // but this works - oop rcvr = STACK_OBJECT(-parms); - VERIFY_OOP(rcvr); - InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); + VERIFY_OOP(STACK_OBJECT(-parms)); + InstanceKlass* rcvrKlass = (InstanceKlass*) STACK_OBJECT(-parms)->klass(); /* Executing this code in java.lang.String: public String(char value[]) { @@ -2676,17 +2412,12 @@ */ callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; - // Profile virtual call. - BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); } } else { if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) { CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); } callee = cache->f1_as_method(); - - // Profile call. - BI_PROFILE_UPDATE_CALL(); } istate->set_callee(callee); @@ -2708,9 +2439,6 @@ jint size = STACK_INT(-1); CALL_VM(InterpreterRuntime::newarray(THREAD, atype, size), handle_exception); - // Must prevent reordering of stores for object initialization - // with stores that publish the new object. - OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -1); THREAD->set_vm_result(NULL); @@ -2741,8 +2469,6 @@ CASE(_goto): { int16_t offset = (int16_t)Bytes::get_Java_u2(pc + 1); - // Profile jump. - BI_PROFILE_UPDATE_JUMP(); address branch_pc = pc; UPDATE_PC(offset); DO_BACKEDGE_CHECKS(offset, branch_pc); @@ -2759,8 +2485,6 @@ CASE(_goto_w): { int32_t offset = Bytes::get_Java_u4(pc + 1); - // Profile jump. - BI_PROFILE_UPDATE_JUMP(); address branch_pc = pc; UPDATE_PC(offset); DO_BACKEDGE_CHECKS(offset, branch_pc); @@ -2770,9 +2494,6 @@ /* return from a jsr or jsr_w */ CASE(_ret): { - // Profile ret. - BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(pc[1])))); - // Now, update the pc. pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(pc[1])); UPDATE_PC_AND_CONTINUE(0); } @@ -2846,26 +2567,23 @@ if (TraceExceptions) { ttyLocker ttyl; ResourceMark rm; - tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, continuing at %d for thread " INTPTR_FORMAT, - istate->bcp() - (intptr_t)METHOD->code_base(), + pc - (intptr_t)METHOD->code_base(), continuation_bci, THREAD); } // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort(except_oop)); - - // Update profiling data. - BI_PROFILE_ALIGN_TO_CURRENT_BCI(); goto run; } if (TraceExceptions) { ttyLocker ttyl; ResourceMark rm; - tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, unwinding for thread " INTPTR_FORMAT, - istate->bcp() - (intptr_t)METHOD->code_base(), + pc - (intptr_t) METHOD->code_base(), THREAD); } // for AbortVMOnException flag @@ -2873,87 +2591,32 @@ // No handler in this activation, unwind and try again THREAD->set_pending_exception(except_oop(), NULL, 0); goto handle_return; - } // handle_exception: + } /* handle_exception: */ + + // Return from an interpreter invocation with the result of the interpretation // on the top of the Java Stack (or a pending exception) - handle_Pop_Frame: { - - // We don't really do anything special here except we must be aware - // that we can get here without ever locking the method (if sync). - // Also we skip the notification of the exit. - - istate->set_msg(popping_frame); - // Clear pending so while the pop is in process - // we don't start another one if a call_vm is done. - THREAD->clr_pop_frame_pending(); - // Let interpreter (only) see the we're in the process of popping a frame - THREAD->set_pop_frame_in_process(); - - goto handle_return; - - } // handle_Pop_Frame - - // ForceEarlyReturn ends a method, and returns to the caller with a return value - // given by the invoker of the early return. - handle_Early_Return: { - - istate->set_msg(early_return); - - // Clear expression stack. - topOfStack = istate->stack_base() - Interpreter::stackElementWords; - - JvmtiThreadState *ts = THREAD->jvmti_thread_state(); - - // Push the value to be returned. - switch (istate->method()->result_type()) { - case T_BOOLEAN: - case T_SHORT: - case T_BYTE: - case T_CHAR: - case T_INT: - SET_STACK_INT(ts->earlyret_value().i, 0); - MORE_STACK(1); - break; - case T_LONG: - SET_STACK_LONG(ts->earlyret_value().j, 1); - MORE_STACK(2); - break; - case T_FLOAT: - SET_STACK_FLOAT(ts->earlyret_value().f, 0); - MORE_STACK(1); - break; - case T_DOUBLE: - SET_STACK_DOUBLE(ts->earlyret_value().d, 1); - MORE_STACK(2); - break; - case T_ARRAY: - case T_OBJECT: - SET_STACK_OBJECT(ts->earlyret_oop(), 0); - MORE_STACK(1); - break; - } - - ts->clr_earlyret_value(); - ts->set_earlyret_oop(NULL); - ts->clr_earlyret_pending(); - - // Fall through to handle_return. - - } // handle_Early_Return - - handle_return: { - // A storestore barrier is required to order initialization of - // final fields with publishing the reference to the object that - // holds the field. Without the barrier the value of final fields - // can be observed to change. - OrderAccess::storestore(); - +handle_Pop_Frame: + + // We don't really do anything special here except we must be aware + // that we can get here without ever locking the method (if sync). + // Also we skip the notification of the exit. + + istate->set_msg(popping_frame); + // Clear pending so while the pop is in process + // we don't start another one if a call_vm is done. + THREAD->clr_pop_frame_pending(); + // Let interpreter (only) see the we're in the process of popping a frame + THREAD->set_pop_frame_in_process(); + +handle_return: + { DECACHE_STATE(); - bool suppress_error = istate->msg() == popping_frame || istate->msg() == early_return; - bool suppress_exit_event = THREAD->has_pending_exception() || istate->msg() == popping_frame; + bool suppress_error = istate->msg() == popping_frame; + bool suppress_exit_event = THREAD->has_pending_exception() || suppress_error; Handle original_exception(THREAD, THREAD->pending_exception()); Handle illegal_state_oop(THREAD, NULL); @@ -3014,18 +2677,15 @@ BasicLock* lock = end->lock(); markOop header = lock->displaced_header(); end->set_obj(NULL); - - if (!lockee->mark()->has_bias_pattern()) { - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL) { - if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { - // restore object for the slow case - end->set_obj(lockee); - { - // Prevent any HandleMarkCleaner from freeing our live handles - HandleMark __hm(THREAD); - CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, end)); - } + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL) { + if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { + // restore object for the slow case + end->set_obj(lockee); + { + // Prevent any HandleMarkCleaner from freeing our live handles + HandleMark __hm(THREAD); + CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, end)); } } } @@ -3070,41 +2730,27 @@ oop rcvr = base->obj(); if (rcvr == NULL) { if (!suppress_error) { - VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap); + VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), ""); illegal_state_oop = THREAD->pending_exception(); THREAD->clear_pending_exception(); } - } else if (UseHeavyMonitors) { - { - // Prevent any HandleMarkCleaner from freeing our live handles. - HandleMark __hm(THREAD); - CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); - } - if (THREAD->has_pending_exception()) { - if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); - THREAD->clear_pending_exception(); - } } else { BasicLock* lock = base->lock(); markOop header = lock->displaced_header(); base->set_obj(NULL); - - if (!rcvr->mark()->has_bias_pattern()) { - base->set_obj(NULL); - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL) { - if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) { - // restore object for the slow case - base->set_obj(rcvr); - { - // Prevent any HandleMarkCleaner from freeing our live handles - HandleMark __hm(THREAD); - CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); - } - if (THREAD->has_pending_exception()) { - if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); - THREAD->clear_pending_exception(); - } + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL) { + if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) { + // restore object for the slow case + base->set_obj(rcvr); + { + // Prevent any HandleMarkCleaner from freeing our live handles + HandleMark __hm(THREAD); + CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); + } + if (THREAD->has_pending_exception()) { + if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); + THREAD->clear_pending_exception(); } } } @@ -3112,8 +2758,6 @@ } } } - // Clear the do_not_unlock flag now. - THREAD->clr_do_not_unlock(); // // Notify jvmti/jvmdi @@ -3158,14 +2802,15 @@ // A pending exception that was pending prior to a possible popping frame // overrides the popping frame. // - assert(!suppress_error || (suppress_error && illegal_state_oop() == NULL), "Error was not suppressed"); + assert(!suppress_error || suppress_error && illegal_state_oop() == NULL, "Error was not suppressed"); if (illegal_state_oop() != NULL || original_exception() != NULL) { - // Inform the frame manager we have no result. + // inform the frame manager we have no result istate->set_msg(throwing_exception); if (illegal_state_oop() != NULL) THREAD->set_pending_exception(illegal_state_oop(), NULL, 0); else THREAD->set_pending_exception(original_exception(), NULL, 0); + istate->set_return_kind((Bytecodes::Code)opcode); UPDATE_PC_AND_RETURN(0); } @@ -3184,12 +2829,13 @@ LOCALS_SLOT(METHOD->size_of_parameters() - 1)); THREAD->set_popframe_condition_bit(JavaThread::popframe_force_deopt_reexecution_bit); } - } else { - istate->set_msg(return_from_method); + THREAD->clr_pop_frame_in_process(); } // Normal return // Advance the pc and return to frame manager + istate->set_msg(return_from_method); + istate->set_return_kind((Bytecodes::Code)opcode); UPDATE_PC_AND_RETURN(1); } /* handle_return: */ @@ -3237,7 +2883,7 @@ } oop BytecodeInterpreter::stack_object(intptr_t *tos, int offset) { - return cast_to_oop(tos [Interpreter::expr_index_at(-offset)]); + return (oop)tos [Interpreter::expr_index_at(-offset)]; } jdouble BytecodeInterpreter::stack_double(intptr_t *tos, int offset) { @@ -3306,7 +2952,7 @@ return (jfloat)locals[Interpreter::local_index_at(-offset)]; } oop BytecodeInterpreter::locals_object(intptr_t* locals, int offset) { - return cast_to_oop(locals[Interpreter::local_index_at(-offset)]); + return (oop)locals[Interpreter::local_index_at(-offset)]; } jdouble BytecodeInterpreter::locals_double(intptr_t* locals, int offset) { return ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->d; @@ -3464,8 +3110,9 @@ tty->print_cr("result_to_call._bcp_advance: %d ", this->_result._to_call._bcp_advance); tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf); tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry); + tty->print_cr("result_return_kind 0x%x ", (int) this->_result._return_kind); tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link); - tty->print_cr("native_mirror: " INTPTR_FORMAT, (void*) this->_oop_temp); + tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp); tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base); tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit); tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base); @@ -3482,9 +3129,9 @@ } extern "C" { - void PI(uintptr_t arg) { - ((BytecodeInterpreter*)arg)->print(); - } + void PI(uintptr_t arg) { + ((BytecodeInterpreter*)arg)->print(); + } } #endif // PRODUCT