This commit is contained in:
David Chase 2014-03-11 10:59:26 -07:00
commit a0bb00ac27
18 changed files with 621 additions and 66 deletions

View file

@ -3619,13 +3619,14 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
"possibility of dangling Thread pointer");
OSThread* osthread = thread->osthread();
bool interrupted = osthread->interrupted();
// There is no synchronization between the setting of the interrupt
// and it being cleared here. It is critical - see 6535709 - that
// we only clear the interrupt state, and reset the interrupt event,
// if we are going to report that we were indeed interrupted - else
// an interrupt can be "lost", leading to spurious wakeups or lost wakeups
// depending on the timing
// depending on the timing. By checking thread interrupt event to see
// if the thread gets real interrupt thus prevent spurious wakeup.
bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0);
if (interrupted && clear_interrupted) {
osthread->set_interrupted(false);
ResetEvent(osthread->interrupt_event());

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2014, 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
@ -273,8 +273,8 @@ class DebugInfoReadStream : public CompressedReadStream {
}
Method* read_method() {
Method* o = (Method*)(code()->metadata_at(read_int()));
assert(o == NULL ||
o->is_metaspace_object(), "meta data only");
// is_metadata() is a faster check than is_metaspace_object()
assert(o == NULL || o->is_metadata(), "meta data only");
return o;
}
ScopeValue* read_object_value();

View file

@ -1295,6 +1295,7 @@ void ConstantPool::copy_entry_to(constantPoolHandle from_cp, int from_i,
} break;
case JVM_CONSTANT_UnresolvedClass:
case JVM_CONSTANT_UnresolvedClassInError:
{
// Can be resolved after checking tag, so check the slot first.
CPSlot entry = from_cp->slot_at(from_i);

View file

@ -42,6 +42,7 @@ class Metadata : public MetaspaceObj {
// Rehashing support for tables containing pointers to this
unsigned int new_hash(juint seed) { ShouldNotReachHere(); return 0; }
virtual bool is_metadata() const volatile { return true; }
virtual bool is_klass() const volatile { return false; }
virtual bool is_method() const volatile { return false; }
virtual bool is_methodData() const volatile { return false; }

View file

@ -3180,7 +3180,8 @@ bool LibraryCallKit::inline_native_currentThread() {
// private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted);
bool LibraryCallKit::inline_native_isInterrupted() {
// Add a fast path to t.isInterrupted(clear_int):
// (t == Thread.current() && (!TLS._osthread._interrupted || !clear_int))
// (t == Thread.current() &&
// (!TLS._osthread._interrupted || WINDOWS_ONLY(false) NOT_WINDOWS(!clear_int)))
// ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int)
// So, in the common case that the interrupt bit is false,
// we avoid making a call into the VM. Even if the interrupt bit
@ -3237,6 +3238,7 @@ bool LibraryCallKit::inline_native_isInterrupted() {
// drop through to next case
set_control( _gvn.transform(new (C) IfTrueNode(iff_bit)));
#ifndef TARGET_OS_FAMILY_windows
// (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path.
Node* clr_arg = argument(1);
Node* cmp_arg = _gvn.transform(new (C) CmpINode(clr_arg, intcon(0)));
@ -3250,6 +3252,10 @@ bool LibraryCallKit::inline_native_isInterrupted() {
// drop through to next case
set_control( _gvn.transform(new (C) IfTrueNode(iff_arg)));
#else
// To return true on Windows you must read the _interrupted field
// and check the the event state i.e. take the slow path.
#endif // TARGET_OS_FAMILY_windows
// (d) Otherwise, go to the slow path.
slow_region->add_req(control());

View file

@ -4360,7 +4360,7 @@ JVM_END
JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size))
{
memset(info, 0, sizeof(info_size));
memset(info, 0, info_size);
info->jvm_version = Abstract_VM_Version::jvm_version();
info->update_version = 0; /* 0 in HotSpot Express VM */

View file

@ -1464,7 +1464,19 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) {
// It's fine to update the thread state here because no JVMTI events
// shall be posted for this PopFrame.
state->update_for_pop_top_frame();
// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a vm-safepoint-op for safety.
if (java_thread == JavaThread::current()) {
state->update_for_pop_top_frame();
} else {
VM_UpdateForPopTopFrame op(state);
VMThread::execute(&op);
jvmtiError err = op.result();
if (err != JVMTI_ERROR_NONE) {
return err;
}
}
java_thread->set_popframe_condition(JavaThread::popframe_pending_bit);
// Set pending step flag for this popframe and it is cleared when next
// step event is posted.
@ -1505,6 +1517,7 @@ JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* metho
// depth - pre-checked as non-negative
jvmtiError
JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
jvmtiError err = JVMTI_ERROR_NONE;
ResourceMark rm;
uint32_t debug_bits = 0;
@ -1532,10 +1545,17 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL");
int frame_number = state->count_frames() - depth;
state->env_thread_state(this)->set_frame_pop(frame_number);
return JVMTI_ERROR_NONE;
// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a vm-safepoint-op for safety.
if (java_thread == JavaThread::current()) {
int frame_number = state->count_frames() - depth;
state->env_thread_state(this)->set_frame_pop(frame_number);
} else {
VM_SetFramePop op(this, state, depth);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end NotifyFramePop */

View file

@ -29,6 +29,7 @@
#include "prims/jvmtiEnvThreadState.hpp"
#include "prims/jvmtiEventController.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/frame.hpp"
#include "runtime/handles.inline.hpp"
@ -334,6 +335,60 @@ class JvmtiEnvIterator : public StackObj {
JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); }
};
// VM operation to update for pop top frame.
class VM_UpdateForPopTopFrame : public VM_Operation {
private:
JvmtiThreadState* _state;
jvmtiError _result;
public:
VM_UpdateForPopTopFrame(JvmtiThreadState* state) {
_state = state;
_result = JVMTI_ERROR_NONE;
}
VMOp_Type type() const { return VMOp_UpdateForPopTopFrame; }
jvmtiError result() { return _result; }
void doit() {
JavaThread* jt = _state->get_thread();
if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
_state->update_for_pop_top_frame();
} else {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
}
}
};
// VM operation to set frame pop.
class VM_SetFramePop : public VM_Operation {
private:
JvmtiEnv *_env;
JvmtiThreadState* _state;
jint _depth;
jvmtiError _result;
public:
VM_SetFramePop(JvmtiEnv *env, JvmtiThreadState* state, jint depth) {
_env = env;
_state = state;
_depth = depth;
_result = JVMTI_ERROR_NONE;
}
// Nested operation must be allowed for the VM_EnterInterpOnlyMode that is
// called from the JvmtiEventControllerPrivate::recompute_thread_enabled.
bool allow_nested_vm_operations() const { return true; }
VMOp_Type type() const { return VMOp_SetFramePop; }
jvmtiError result() { return _result; }
void doit() {
JavaThread* jt = _state->get_thread();
if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
int frame_number = _state->count_frames() - _depth;
_state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number);
} else {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
}
}
};
// VM operation to get monitor information with stack depth.
class VM_GetOwnedMonitorInfo : public VM_Operation {

View file

@ -190,12 +190,8 @@ void JvmtiEnvThreadState::compare_and_set_current_location(Method* new_method,
JvmtiFramePops* JvmtiEnvThreadState::get_frame_pops() {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"frame pop data only accessible from same thread or while suspended");
assert(get_thread() == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"frame pop data only accessible from same thread or at safepoint");
if (_frame_pops == NULL) {
_frame_pops = new JvmtiFramePops();
assert(_frame_pops != NULL, "_frame_pops != NULL");
@ -209,44 +205,32 @@ bool JvmtiEnvThreadState::has_frame_pops() {
}
void JvmtiEnvThreadState::set_frame_pop(int frame_number) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"frame pop data only accessible from same thread or while suspended");
assert(get_thread() == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"frame pop data only accessible from same thread or at safepoint");
JvmtiFramePop fpop(frame_number);
JvmtiEventController::set_frame_pop(this, fpop);
}
void JvmtiEnvThreadState::clear_frame_pop(int frame_number) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"frame pop data only accessible from same thread or while suspended");
assert(get_thread() == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"frame pop data only accessible from same thread or at safepoint");
JvmtiFramePop fpop(frame_number);
JvmtiEventController::clear_frame_pop(this, fpop);
}
void JvmtiEnvThreadState::clear_to_frame_pop(int frame_number) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"frame pop data only accessible from same thread or while suspended");
assert(get_thread() == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"frame pop data only accessible from same thread or at safepoint");
JvmtiFramePop fpop(frame_number);
JvmtiEventController::clear_to_frame_pop(this, fpop);
}
bool JvmtiEnvThreadState::is_frame_pop(int cur_frame_number) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(get_thread() == Thread::current() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"frame pop data only accessible from same thread or while suspended");
assert(get_thread() == Thread::current() || SafepointSynchronize::is_at_safepoint(),
"frame pop data only accessible from same thread or at safepoint");
if (!get_thread()->is_interp_only_mode() || _frame_pops == NULL) {
return false;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2014, 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
@ -989,21 +989,21 @@ JvmtiEventController::set_extension_event_callback(JvmtiEnvBase *env,
void
JvmtiEventController::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
MutexLocker mu(JvmtiThreadState_lock);
MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
JvmtiEventControllerPrivate::set_frame_pop(ets, fpop);
}
void
JvmtiEventController::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
MutexLocker mu(JvmtiThreadState_lock);
MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
JvmtiEventControllerPrivate::clear_frame_pop(ets, fpop);
}
void
JvmtiEventController::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
MutexLocker mu(JvmtiThreadState_lock);
MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
JvmtiEventControllerPrivate::clear_to_frame_pop(ets, fpop);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2014, 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
@ -63,6 +63,7 @@ JvmtiThreadState::JvmtiThreadState(JavaThread* thread)
_vm_object_alloc_event_collector = NULL;
_the_class_for_redefinition_verification = NULL;
_scratch_class_for_redefinition_verification = NULL;
_cur_stack_depth = UNKNOWN_STACK_DEPTH;
// JVMTI ForceEarlyReturn support
_pending_step_for_earlyret = false;
@ -213,12 +214,9 @@ void JvmtiThreadState::leave_interp_only_mode() {
// Helper routine used in several places
int JvmtiThreadState::count_frames() {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert(SafepointSynchronize::is_at_safepoint() ||
JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"at safepoint or must be suspended");
guarantee(SafepointSynchronize::is_at_safepoint() ||
(JavaThread *)Thread::current() == get_thread(),
"must be current thread or at safepoint");
if (!get_thread()->has_last_Java_frame()) return 0; // no Java frames
@ -243,15 +241,9 @@ int JvmtiThreadState::count_frames() {
void JvmtiThreadState::invalidate_cur_stack_depth() {
Thread *cur = Thread::current();
uint32_t debug_bits = 0;
// The caller can be the VMThread at a safepoint, the current thread
// or the target thread must be suspended.
guarantee((cur->is_VM_thread() && SafepointSynchronize::is_at_safepoint()) ||
(JavaThread *)cur == get_thread() ||
JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"sanity check");
guarantee(SafepointSynchronize::is_at_safepoint() ||
(JavaThread *)Thread::current() == get_thread(),
"must be current thread or at safepoint");
_cur_stack_depth = UNKNOWN_STACK_DEPTH;
}
@ -280,10 +272,9 @@ void JvmtiThreadState::decr_cur_stack_depth() {
}
int JvmtiThreadState::cur_stack_depth() {
uint32_t debug_bits = 0;
guarantee(JavaThread::current() == get_thread() ||
JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits),
"must be current thread or suspended");
guarantee(SafepointSynchronize::is_at_safepoint() ||
(JavaThread *)Thread::current() == get_thread(),
"must be current thread or at safepoint");
if (!is_interp_only_mode() || _cur_stack_depth == UNKNOWN_STACK_DEPTH) {
_cur_stack_depth = count_frames();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2014, 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
@ -74,6 +74,8 @@
template(PopulateDumpSharedSpace) \
template(JNIFunctionTableCopier) \
template(RedefineClasses) \
template(UpdateForPopTopFrame) \
template(SetFramePop) \
template(GetOwnedMonitorInfo) \
template(GetObjectMonitorUsage) \
template(GetCurrentContendedMonitor) \