提交 7c395b52 编写于 作者: N never

7013347: allow crypto functions to be called inline to enhance performance

Reviewed-by: kvn
上级 97c82f91
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -2134,6 +2134,7 @@ public:
// address pseudos: make these names unlike instruction names to avoid confusion
inline intptr_t load_pc_address( Register reg, int bytes_to_skip );
inline void load_contents(const AddressLiteral& addrlit, Register d, int offset = 0);
inline void load_bool_contents(const AddressLiteral& addrlit, Register d, int offset = 0);
inline void load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset = 0);
inline void store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0);
inline void store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0);
......@@ -2249,7 +2250,7 @@ public:
// this platform we assume byte size
inline void stbool(Register d, const Address& a) { stb(d, a); }
inline void ldbool(const Address& a, Register d) { ldsb(a, d); }
inline void ldbool(const Address& a, Register d) { ldub(a, d); }
inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); }
// klass oop manipulations if compressed
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -692,6 +692,17 @@ inline void MacroAssembler::load_contents(const AddressLiteral& addrlit, Registe
}
inline void MacroAssembler::load_bool_contents(const AddressLiteral& addrlit, Register d, int offset) {
assert_not_delayed();
if (ForceUnreachable) {
patchable_sethi(addrlit, d);
} else {
sethi(addrlit, d);
}
ldub(d, addrlit.low10() + offset, d);
}
inline void MacroAssembler::load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset) {
assert_not_delayed();
if (ForceUnreachable) {
......
......@@ -462,6 +462,7 @@ void nmethod::init_defaults() {
_speculatively_disconnected = 0;
_has_unsafe_access = 0;
_has_method_handle_invokes = 0;
_lazy_critical_native = 0;
_marked_for_deoptimization = 0;
_lock_count = 0;
_stack_traversal_mark = 0;
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -175,6 +175,7 @@ class nmethod : public CodeBlob {
// set during construction
unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
unsigned int _lazy_critical_native:1; // Lazy JNI critical native
// Protected by Patching_lock
unsigned char _state; // {alive, not_entrant, zombie, unloaded}
......@@ -432,6 +433,9 @@ class nmethod : public CodeBlob {
bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
bool is_lazy_critical_native() const { return _lazy_critical_native; }
void set_lazy_critical_native(bool z) { _lazy_critical_native = z; }
int comp_level() const { return _comp_level; }
// Support for oops in scopes and relocs:
......
......@@ -69,7 +69,7 @@ bool GC_locker::check_active_before_gc() {
_needs_gc = true;
if (PrintJNIGCStalls && PrintGCDetails) {
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
_wait_begin = tty->time_stamp().milliseconds();
_wait_begin = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
gclog_or_tty->print_cr(INT64_FORMAT ": Setting _needs_gc. Thread \"%s\" %d locked.",
_wait_begin, Thread::current()->name(), _jni_lock_count);
}
......@@ -86,7 +86,7 @@ void GC_locker::stall_until_clear() {
if (PrintJNIGCStalls && PrintGCDetails) {
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
gclog_or_tty->print_cr(INT64_FORMAT ": Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.",
tty->time_stamp().milliseconds() - _wait_begin, Thread::current()->name(), _jni_lock_count);
(os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count);
}
}
......@@ -132,7 +132,7 @@ void GC_locker::jni_unlock(JavaThread* thread) {
if (PrintJNIGCStalls && PrintGCDetails) {
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
gclog_or_tty->print_cr(INT64_FORMAT ": Thread \"%s\" is performing GC after exiting critical section, %d locked",
tty->time_stamp().milliseconds() - _wait_begin, Thread::current()->name(), _jni_lock_count);
(os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count);
}
Universe::heap()->collect(GCCause::_gc_locker);
}
......
......@@ -164,6 +164,8 @@ class GC_locker: public AllStatic {
// is set, the slow path is always taken, till _needs_gc is cleared.
static void lock_critical(JavaThread* thread);
static void unlock_critical(JavaThread* thread);
static address needs_gc_address() { return (address) &_needs_gc; }
};
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -29,6 +29,7 @@
#ifndef PRODUCT
#include "oops/arrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/globalDefinitions.hpp"
bool arrayOopDesc::check_max_length_overflow(BasicType type) {
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -596,6 +596,11 @@ void methodOopDesc::clear_native_function() {
clear_code();
}
address methodOopDesc::critical_native_function() {
methodHandle mh(this);
return NativeLookup::lookup_critical_entry(mh);
}
void methodOopDesc::set_signature_handler(address handler) {
address* signature_handler = signature_handler_addr();
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -403,6 +403,8 @@ class methodOopDesc : public oopDesc {
native_bind_event_is_interesting = true
};
address native_function() const { return *(native_function_addr()); }
address critical_native_function();
// Must specify a real function (not NULL).
// Use clear_native_function() to unregister.
void set_native_function(address function, bool post_event_flag);
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -91,6 +91,19 @@ char* NativeLookup::pure_jni_name(methodHandle method) {
}
char* NativeLookup::critical_jni_name(methodHandle method) {
stringStream st;
// Prefix
st.print("JavaCritical_");
// Klass name
mangle_name_on(&st, method->klass_name());
st.print("_");
// Method name
mangle_name_on(&st, method->name());
return st.as_string();
}
char* NativeLookup::long_jni_name(methodHandle method) {
// Signature ignore the wrapping parenteses and the trailing return type
stringStream st;
......@@ -193,6 +206,34 @@ address NativeLookup::lookup_style(methodHandle method, char* pure_name, const c
}
address NativeLookup::lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style) {
if (!method->has_native_function()) {
return NULL;
}
address current_entry = method->native_function();
char dll_name[JVM_MAXPATHLEN];
int offset;
if (os::dll_address_to_library_name(current_entry, dll_name, sizeof(dll_name), &offset)) {
char ebuf[32];
void* dll = os::dll_load(dll_name, ebuf, sizeof(ebuf));
if (dll != NULL) {
// Compute complete JNI name for style
stringStream st;
if (os_style) os::print_jni_name_prefix_on(&st, args_size);
st.print_raw(pure_name);
st.print_raw(long_name);
if (os_style) os::print_jni_name_suffix_on(&st, args_size);
char* jni_name = st.as_string();
return (address)os::dll_lookup(dll, jni_name);
}
}
return NULL;
}
// Check all the formats of native implementation name to see if there is one
// for the specified method.
address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, TRAPS) {
......@@ -228,6 +269,58 @@ address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, T
return entry; // NULL indicates not found
}
// Check all the formats of native implementation name to see if there is one
// for the specified method.
address NativeLookup::lookup_critical_entry(methodHandle method) {
if (!CriticalJNINatives) return NULL;
if (method->is_synchronized() ||
!method->is_static()) {
// Only static non-synchronized methods are allowed
return NULL;
}
ResourceMark rm;
address entry = NULL;
Symbol* signature = method->signature();
for (int end = 0; end < signature->utf8_length(); end++) {
if (signature->byte_at(end) == 'L') {
// Don't allow object types
return NULL;
}
}
// Compute critical name
char* critical_name = critical_jni_name(method);
// Compute argument size
int args_size = 1 // JNIEnv
+ (method->is_static() ? 1 : 0) // class for static methods
+ method->size_of_parameters(); // actual parameters
// 1) Try JNI short style
entry = lookup_critical_style(method, critical_name, "", args_size, true);
if (entry != NULL) return entry;
// Compute long name
char* long_name = long_jni_name(method);
// 2) Try JNI long style
entry = lookup_critical_style(method, critical_name, long_name, args_size, true);
if (entry != NULL) return entry;
// 3) Try JNI short style without os prefix/suffix
entry = lookup_critical_style(method, critical_name, "", args_size, false);
if (entry != NULL) return entry;
// 4) Try JNI long style without os prefix/suffix
entry = lookup_critical_style(method, critical_name, long_name, args_size, false);
return entry; // NULL indicates not found
}
// Check if there are any JVM TI prefixes which have been applied to the native method name.
// If any are found, remove them before attemping the look up of the
// native implementation again.
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -36,15 +36,18 @@ class NativeLookup : AllStatic {
// JNI name computation
static char* pure_jni_name(methodHandle method);
static char* long_jni_name(methodHandle method);
static char* critical_jni_name(methodHandle method);
// Style specific lookup
static address lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS);
static address lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style);
static address lookup_base (methodHandle method, bool& in_base_library, TRAPS);
static address lookup_entry(methodHandle method, bool& in_base_library, TRAPS);
static address lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS);
public:
// Lookup native function. May throw UnsatisfiedLinkError.
static address lookup(methodHandle method, bool& in_base_library, TRAPS);
static address lookup_critical_entry(methodHandle method);
// Lookup native functions in base library.
static address base_library_lookup(const char* class_name, const char* method_name, const char* signature);
......
......@@ -659,6 +659,12 @@ class CommandLineFlags {
develop(bool, SpecialArraysEquals, true, \
"special version of Arrays.equals(char[],char[])") \
\
product(bool, CriticalJNINatives, true, \
"check for critical JNI entry points") \
\
notproduct(bool, StressCriticalJNINatives, false, \
"Exercise register saving code in critical natives") \
\
product(bool, UseSSE42Intrinsics, false, \
"SSE4.2 versions of intrinsics") \
\
......
......@@ -136,7 +136,6 @@ void SafepointSynchronize::begin() {
RuntimeService::record_safepoint_begin();
{
MutexLocker mu(Safepoint_lock);
// Reset the count of active JNI critical threads
......@@ -399,7 +398,6 @@ void SafepointSynchronize::begin() {
// Record how much time spend on the above cleanup tasks
update_statistics_on_cleanup_end(os::javaTimeNanos());
}
}
}
// Wake up all threads, so they are ready to resume execution after the safepoint
......@@ -546,6 +544,42 @@ bool SafepointSynchronize::safepoint_safe(JavaThread *thread, JavaThreadState st
}
// See if the thread is running inside a lazy critical native and
// update the thread critical count if so. Also set a suspend flag to
// cause the native wrapper to return into the JVM to do the unlock
// once the native finishes.
void SafepointSynchronize::check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state) {
if (state == _thread_in_native &&
thread->has_last_Java_frame() &&
thread->frame_anchor()->walkable()) {
// This thread might be in a critical native nmethod so look at
// the top of the stack and increment the critical count if it
// is.
frame wrapper_frame = thread->last_frame();
CodeBlob* stub_cb = wrapper_frame.cb();
if (stub_cb != NULL &&
stub_cb->is_nmethod() &&
stub_cb->as_nmethod_or_null()->is_lazy_critical_native()) {
// A thread could potentially be in a critical native across
// more than one safepoint, so only update the critical state on
// the first one. When it returns it will perform the unlock.
if (!thread->do_critical_native_unlock()) {
#ifdef ASSERT
if (!thread->in_critical()) {
GC_locker::increment_debug_jni_lock_count();
}
#endif
thread->enter_critical();
// Make sure the native wrapper calls back on return to
// perform the needed critical unlock.
thread->set_critical_native_unlock();
}
}
}
}
// -------------------------------------------------------------------------------------------------------
// Implementation of Safepoint callback point
......@@ -874,6 +908,7 @@ void ThreadSafepointState::examine_state_of_thread() {
// agree and update the safepoint state here.
if (SafepointSynchronize::safepoint_safe(_thread, state)) {
roll_forward(_at_safepoint);
SafepointSynchronize::check_for_lazy_critical_native(_thread, state);
if (_thread->in_critical()) {
// Notice that this thread is in a critical section
SafepointSynchronize::increment_jni_active_count();
......
......@@ -140,6 +140,8 @@ public:
static bool safepoint_safe(JavaThread *thread, JavaThreadState state);
static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state);
// Query
inline static bool is_at_safepoint() { return _state == _synchronized; }
inline static bool is_synchronizing() { return _state == _synchronizing; }
......
......@@ -2678,6 +2678,20 @@ nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method, int c
return nm;
}
JRT_ENTRY_NO_ASYNC(void, SharedRuntime::block_for_jni_critical(JavaThread* thread))
assert(thread == JavaThread::current(), "must be");
// The code is about to enter a JNI lazy critical native method and
// _needs_gc is true, so if this thread is already in a critical
// section then just return, otherwise this thread should block
// until needs_gc has been cleared.
if (thread->in_critical()) {
return;
}
// Lock and unlock a critical section to give the system a chance to block
GC_locker::lock_critical(thread);
GC_locker::unlock_critical(thread);
JRT_END
#ifdef HAVE_DTRACE_H
// Create a dtrace nmethod for this method. The wrapper converts the
// java compiled calling convention to the native convention, makes a dummy call
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
......@@ -462,6 +462,9 @@ class SharedRuntime: AllStatic {
VMRegPair *regs,
BasicType ret_type );
// Block before entering a JNI critical method
static void block_for_jni_critical(JavaThread* thread);
#ifdef HAVE_DTRACE_H
// Generate a dtrace wrapper for a given method. The method takes arguments
// in the Java compiled code convention, marshals them to the native
......
......@@ -33,6 +33,7 @@
#include "interpreter/linkResolver.hpp"
#include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/gcLocker.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
......@@ -2278,6 +2279,26 @@ void JavaThread::check_special_condition_for_native_trans(JavaThread *thread) {
}
}
// This is a variant of the normal
// check_special_condition_for_native_trans with slightly different
// semantics for use by critical native wrappers. It does all the
// normal checks but also performs the transition back into
// thread_in_Java state. This is required so that critical natives
// can potentially block and perform a GC if they are the last thread
// exiting the GC_locker.
void JavaThread::check_special_condition_for_native_trans_and_transition(JavaThread *thread) {
check_special_condition_for_native_trans(thread);
// Finish the transition
thread->set_thread_state(_thread_in_Java);
if (thread->do_critical_native_unlock()) {
ThreadInVMfromJavaNoAsyncException tiv(thread);
GC_locker::unlock_critical(thread);
thread->clear_critical_native_unlock();
}
}
// We need to guarantee the Threads_lock here, since resumes are not
// allowed during safepoint synchronization
// Can only resume from an external suspension
......
......@@ -182,7 +182,8 @@ class Thread: public ThreadShadow {
_ext_suspended = 0x40000000U, // thread has self-suspended
_deopt_suspend = 0x10000000U, // thread needs to self suspend for deopt
_has_async_exception = 0x00000001U // there is a pending async exception
_has_async_exception = 0x00000001U, // there is a pending async exception
_critical_native_unlock = 0x00000002U // Must call back to unlock JNI critical lock
};
// various suspension related flags - atomically updated
......@@ -350,6 +351,15 @@ class Thread: public ThreadShadow {
clear_suspend_flag(_has_async_exception);
}
bool do_critical_native_unlock() const { return (_suspend_flags & _critical_native_unlock) != 0; }
void set_critical_native_unlock() {
set_suspend_flag(_critical_native_unlock);
}
void clear_critical_native_unlock() {
clear_suspend_flag(_critical_native_unlock);
}
// Support for Unhandled Oop detection
#ifdef CHECK_UNHANDLED_OOPS
private:
......@@ -1038,6 +1048,11 @@ class JavaThread: public Thread {
// Check for async exception in addition to safepoint and suspend request.
static void check_special_condition_for_native_trans(JavaThread *thread);
// Same as check_special_condition_for_native_trans but finishes the
// transition into thread_in_Java mode so that it can potentially
// block.
static void check_special_condition_for_native_trans_and_transition(JavaThread *thread);
bool is_ext_suspend_completed(bool called_by_wait, int delay, uint32_t *bits);
bool is_ext_suspend_completed_with_lock(uint32_t *bits) {
MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
......@@ -1311,8 +1326,9 @@ class JavaThread: public Thread {
// JNI critical regions. These can nest.
bool in_critical() { return _jni_active_critical > 0; }
bool in_last_critical() { return _jni_active_critical == 1; }
void enter_critical() { assert(Thread::current() == this,
"this must be current thread");
void enter_critical() { assert(Thread::current() == this ||
Thread::current()->is_VM_thread() && SafepointSynchronize::is_synchronizing(),
"this must be current thread or synchronizing");
_jni_active_critical++; }
void exit_critical() { assert(Thread::current() == this,
"this must be current thread");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册