< prev index next > src/hotspot/share/runtime/sharedRuntime.cpp
Print this page
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
+ #include "cds/archiveBuilder.hpp"
+ #include "cds/archiveUtils.inline.hpp"
+ #include "cds/cdsConfig.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
+ #include "code/SCCache.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/nmethod.inline.hpp"
#include "code/scopeDesc.hpp"
#include "code/vtableStubs.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
! #include "runtime/perfData.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stackWatermarkSet.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/copy.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/resourceHash.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
! #include "runtime/perfData.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stackWatermarkSet.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vm_version.hpp"
+ #include "services/management.hpp"
#include "utilities/copy.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/resourceHash.hpp"
SHARED_STUBS_DO(SHARED_STUB_FIELD_DEFINE)
#undef SHARED_STUB_FIELD_DEFINE
nmethod* SharedRuntime::_cont_doYield_stub;
+ PerfTickCounters* SharedRuntime::_perf_resolve_opt_virtual_total_time = nullptr;
+ PerfTickCounters* SharedRuntime::_perf_resolve_virtual_total_time = nullptr;
+ PerfTickCounters* SharedRuntime::_perf_resolve_static_total_time = nullptr;
+ PerfTickCounters* SharedRuntime::_perf_handle_wrong_method_total_time = nullptr;
+ PerfTickCounters* SharedRuntime::_perf_ic_miss_total_time = nullptr;
+
#define SHARED_STUB_NAME_DECLARE(name, type) "Shared Runtime " # name "_blob",
const char *SharedRuntime::_stub_names[] = {
SHARED_STUBS_DO(SHARED_STUB_NAME_DECLARE)
};
_throw_NullPointerException_at_call_blob =
generate_throw_exception(SharedStubId::throw_NullPointerException_at_call_id,
CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
- AdapterHandlerLibrary::initialize();
-
#if COMPILER2_OR_JVMCI
// Vectors are generated only by C2 and JVMCI.
bool support_wide = is_wide_vector(MaxVectorSize);
if (support_wide) {
_polling_page_vectors_safepoint_handler_blob =
_polling_page_return_handler_blob =
generate_handler_blob(SharedStubId::polling_page_return_handler_id,
CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception));
generate_deopt_blob();
+
+ if (UsePerfData) {
+ EXCEPTION_MARK;
+ NEWPERFTICKCOUNTERS(_perf_resolve_opt_virtual_total_time, SUN_CI, "resovle_opt_virtual_call");
+ NEWPERFTICKCOUNTERS(_perf_resolve_virtual_total_time, SUN_CI, "resovle_virtual_call");
+ NEWPERFTICKCOUNTERS(_perf_resolve_static_total_time, SUN_CI, "resovle_static_call");
+ NEWPERFTICKCOUNTERS(_perf_handle_wrong_method_total_time, SUN_CI, "handle_wrong_method");
+ NEWPERFTICKCOUNTERS(_perf_ic_miss_total_time , SUN_CI, "ic_miss");
+ if (HAS_PENDING_EXCEPTION) {
+ vm_exit_during_initialization("SharedRuntime::generate_stubs() failed unexpectedly");
+ }
+ }
+ }
+
+ void SharedRuntime::init_adapter_library() {
+ AdapterHandlerLibrary::initialize();
+ }
+
+ static void print_counter_on(outputStream* st, const char* name, PerfTickCounters* counter, uint cnt) {
+ st->print(" %-28s " JLONG_FORMAT_W(6) "us", name, counter->elapsed_counter_value_us());
+ if (TraceThreadTime) {
+ st->print(" (elapsed) " JLONG_FORMAT_W(6) "us (thread)", counter->thread_counter_value_us());
+ }
+ st->print(" / %5d events", cnt);
+ st->cr();
+ }
+
+ void SharedRuntime::print_counters_on(outputStream* st) {
+ st->print_cr("SharedRuntime:");
+ if (UsePerfData) {
+ print_counter_on(st, "resolve_opt_virtual_call:", _perf_resolve_opt_virtual_total_time, _resolve_opt_virtual_ctr);
+ print_counter_on(st, "resolve_virtual_call:", _perf_resolve_virtual_total_time, _resolve_virtual_ctr);
+ print_counter_on(st, "resolve_static_call:", _perf_resolve_static_total_time, _resolve_static_ctr);
+ print_counter_on(st, "handle_wrong_method:", _perf_handle_wrong_method_total_time, _wrong_method_ctr);
+ print_counter_on(st, "ic_miss:", _perf_ic_miss_total_time, _ic_miss_ctr);
+
+ jlong total_elapsed_time_us = Management::ticks_to_us(_perf_resolve_opt_virtual_total_time->elapsed_counter_value() +
+ _perf_resolve_virtual_total_time->elapsed_counter_value() +
+ _perf_resolve_static_total_time->elapsed_counter_value() +
+ _perf_handle_wrong_method_total_time->elapsed_counter_value() +
+ _perf_ic_miss_total_time->elapsed_counter_value());
+ st->print("Total: " JLONG_FORMAT_W(5) "us", total_elapsed_time_us);
+ if (TraceThreadTime) {
+ jlong total_thread_time_us = Management::ticks_to_us(_perf_resolve_opt_virtual_total_time->thread_counter_value() +
+ _perf_resolve_virtual_total_time->thread_counter_value() +
+ _perf_resolve_static_total_time->thread_counter_value() +
+ _perf_handle_wrong_method_total_time->thread_counter_value() +
+ _perf_ic_miss_total_time->thread_counter_value());
+ st->print(" (elapsed) " JLONG_FORMAT_W(5) "us (thread)", total_thread_time_us);
+
+ }
+ st->cr();
+ } else {
+ st->print_cr(" no data (UsePerfData is turned off)");
+ }
}
#if INCLUDE_JFR
//------------------------------generate jfr runtime stubs ------
void SharedRuntime::generate_jfr_stubs() {
#include <math.h>
// Implementation of SharedRuntime
- #ifndef PRODUCT
// For statistics
uint SharedRuntime::_ic_miss_ctr = 0;
uint SharedRuntime::_wrong_method_ctr = 0;
uint SharedRuntime::_resolve_static_ctr = 0;
uint SharedRuntime::_resolve_virtual_ctr = 0;
uint SharedRuntime::_resolve_opt_virtual_ctr = 0;
uint SharedRuntime::_implicit_null_throws = 0;
uint SharedRuntime::_implicit_div0_throws = 0;
int64_t SharedRuntime::_nof_normal_calls = 0;
int64_t SharedRuntime::_nof_inlined_calls = 0;
#include <math.h>
// Implementation of SharedRuntime
// For statistics
uint SharedRuntime::_ic_miss_ctr = 0;
uint SharedRuntime::_wrong_method_ctr = 0;
uint SharedRuntime::_resolve_static_ctr = 0;
uint SharedRuntime::_resolve_virtual_ctr = 0;
uint SharedRuntime::_resolve_opt_virtual_ctr = 0;
+
+ #ifndef PRODUCT
uint SharedRuntime::_implicit_null_throws = 0;
uint SharedRuntime::_implicit_div0_throws = 0;
int64_t SharedRuntime::_nof_normal_calls = 0;
int64_t SharedRuntime::_nof_inlined_calls = 0;
if (_ICmiss_index >= maxICmiss_count) _ICmiss_index = maxICmiss_count - 1;
_ICmiss_at[index] = at;
_ICmiss_count[index] = 1;
}
! void SharedRuntime::print_ic_miss_histogram() {
if (ICMissHistogram) {
! tty->print_cr("IC Miss Histogram:");
int tot_misses = 0;
for (int i = 0; i < _ICmiss_index; i++) {
! tty->print_cr(" at: " INTPTR_FORMAT " nof: %d", p2i(_ICmiss_at[i]), _ICmiss_count[i]);
tot_misses += _ICmiss_count[i];
}
! tty->print_cr("Total IC misses: %7d", tot_misses);
}
}
! #endif // PRODUCT
JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x))
return x * y;
JRT_END
if (_ICmiss_index >= maxICmiss_count) _ICmiss_index = maxICmiss_count - 1;
_ICmiss_at[index] = at;
_ICmiss_count[index] = 1;
}
! void SharedRuntime::print_ic_miss_histogram_on(outputStream* st) {
if (ICMissHistogram) {
! st->print_cr("IC Miss Histogram:");
int tot_misses = 0;
for (int i = 0; i < _ICmiss_index; i++) {
! st->print_cr(" at: " INTPTR_FORMAT " nof: %d", p2i(_ICmiss_at[i]), _ICmiss_count[i]);
tot_misses += _ICmiss_count[i];
}
! st->print_cr("Total IC misses: %7d", tot_misses);
}
}
! #endif // !PRODUCT
JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x))
return x * y;
JRT_END
// an error. Our method could have been redefined just after we
// fetched the Method* from the constant pool.
ResourceMark rm;
log_trace(redefine, class, obsolete)("calling obsolete method '%s'", method->name_and_sig_as_C_string());
}
+
+ LogStreamHandle(Trace, interpreter, bytecode) log;
+ if (log.is_enabled()) {
+ ResourceMark rm;
+ log.print("method entry: " INTPTR_FORMAT " %s %s%s%s%s",
+ p2i(thread),
+ (method->is_static() ? "static" : "virtual"),
+ method->name_and_sig_as_C_string(),
+ (method->is_native() ? " native" : ""),
+ (thread->class_being_initialized() != nullptr ? " clinit" : ""),
+ (method->method_holder()->is_initialized() ? "" : " being_initialized"));
+ }
return 0;
JRT_END
// ret_pc points into caller; we are returning caller's exception handler
// for given exception
(!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
assert(!caller_nm->is_unloading(), "It should not be unloading");
- #ifndef PRODUCT
// tracing/debugging/statistics
uint *addr = (is_optimized) ? (&_resolve_opt_virtual_ctr) :
(is_virtual) ? (&_resolve_virtual_ctr) :
(&_resolve_static_ctr);
Atomic::inc(addr);
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("resolving %s%s (%s) call to",
(is_optimized) ? "optimized " : "", (is_virtual) ? "virtual" : "static",
Bytecodes::name(invoke_code));
(!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
assert(!caller_nm->is_unloading(), "It should not be unloading");
// tracing/debugging/statistics
uint *addr = (is_optimized) ? (&_resolve_opt_virtual_ctr) :
(is_virtual) ? (&_resolve_virtual_ctr) :
(&_resolve_static_ctr);
Atomic::inc(addr);
+ #ifndef PRODUCT
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("resolving %s%s (%s) call to",
(is_optimized) ? "optimized " : "", (is_virtual) ? "virtual" : "static",
Bytecodes::name(invoke_code));
return callee_method;
}
// Inline caches exist only in compiled code
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_ic_miss(JavaThread* current))
+ PerfTraceTime timer(_perf_ic_miss_total_time);
+
#ifdef ASSERT
RegisterMap reg_map(current,
RegisterMap::UpdateMap::skip,
RegisterMap::ProcessFrames::include,
RegisterMap::WalkContinuation::skip);
JRT_END
// Handle call site that has been made non-entrant
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* current))
+ PerfTraceTime timer(_perf_handle_wrong_method_total_time);
+
// 6243940 We might end up in here if the callee is deoptimized
// as we race to call it. We don't want to take a safepoint if
// the caller was interpreted because the caller frame will look
// interpreted to the stack walkers and arguments are now
// "compiled" so it is much better to make this transition
return get_resolved_entry(current, callee_method);
JRT_END
// Handle abstract method call
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_abstract(JavaThread* current))
+ PerfTraceTime timer(_perf_handle_wrong_method_total_time);
+
// Verbose error message for AbstractMethodError.
// Get the called method from the invoke bytecode.
vframeStream vfst(current, true);
assert(!vfst.at_end(), "Java frame must exist");
methodHandle caller(current, vfst.method());
return callee_method->verified_code_entry();
}
// resolve a static call and patch code
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_static_call_C(JavaThread* current ))
+ PerfTraceTime timer(_perf_resolve_static_total_time);
+
methodHandle callee_method;
bool enter_special = false;
JRT_BLOCK
callee_method = SharedRuntime::resolve_helper(false, false, CHECK_NULL);
current->set_vm_result_2(callee_method());
return get_resolved_entry(current, callee_method);
JRT_END
// resolve virtual call and update inline cache to monomorphic
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_virtual_call_C(JavaThread* current))
+ PerfTraceTime timer(_perf_resolve_virtual_total_time);
+
methodHandle callee_method;
JRT_BLOCK
callee_method = SharedRuntime::resolve_helper(true, false, CHECK_NULL);
current->set_vm_result_2(callee_method());
JRT_BLOCK_END
// Resolve a virtual call that can be statically bound (e.g., always
// monomorphic, so it has no inline cache). Patch code to resolved target.
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_opt_virtual_call_C(JavaThread* current))
+ PerfTraceTime timer(_perf_resolve_opt_virtual_total_time);
+
methodHandle callee_method;
JRT_BLOCK
callee_method = SharedRuntime::resolve_helper(true, true, CHECK_NULL);
current->set_vm_result_2(callee_method());
JRT_BLOCK_END
// receivers for non-static calls
Handle receiver = find_callee_info(bc, call_info, CHECK_(methodHandle()));
methodHandle callee_method(current, call_info.selected_method());
- #ifndef PRODUCT
Atomic::inc(&_ic_miss_ctr);
// Statistics & Tracing
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("IC miss (%s) call to", Bytecodes::name(bc));
callee_method->print_short_name(tty);
// receivers for non-static calls
Handle receiver = find_callee_info(bc, call_info, CHECK_(methodHandle()));
methodHandle callee_method(current, call_info.selected_method());
Atomic::inc(&_ic_miss_ctr);
+ #ifndef PRODUCT
// Statistics & Tracing
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("IC miss (%s) call to", Bytecodes::name(bc));
callee_method->print_short_name(tty);
}
}
methodHandle callee_method = find_callee_method(CHECK_(methodHandle()));
-
- #ifndef PRODUCT
Atomic::inc(&_wrong_method_ctr);
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("handle_wrong_method reresolving call to");
callee_method->print_short_name(tty);
tty->print_cr(" code: " INTPTR_FORMAT, p2i(callee_method->code()));
}
}
methodHandle callee_method = find_callee_method(CHECK_(methodHandle()));
Atomic::inc(&_wrong_method_ctr);
+ #ifndef PRODUCT
if (TraceCallFixup) {
ResourceMark rm(current);
tty->print("handle_wrong_method reresolving call to");
callee_method->print_short_name(tty);
tty->print_cr(" code: " INTPTR_FORMAT, p2i(callee_method->code()));
void SharedRuntime::print_statistics() {
ttyLocker ttyl;
if (xtty != nullptr) xtty->head("statistics type='SharedRuntime'");
! SharedRuntime::print_ic_miss_histogram();
!
! // Dump the JRT_ENTRY counters
- if (_new_instance_ctr) tty->print_cr("%5u new instance requires GC", _new_instance_ctr);
- if (_new_array_ctr) tty->print_cr("%5u new array requires GC", _new_array_ctr);
- if (_multi2_ctr) tty->print_cr("%5u multianewarray 2 dim", _multi2_ctr);
- if (_multi3_ctr) tty->print_cr("%5u multianewarray 3 dim", _multi3_ctr);
- if (_multi4_ctr) tty->print_cr("%5u multianewarray 4 dim", _multi4_ctr);
- if (_multi5_ctr) tty->print_cr("%5u multianewarray 5 dim", _multi5_ctr);
-
- tty->print_cr("%5u inline cache miss in compiled", _ic_miss_ctr);
- tty->print_cr("%5u wrong method", _wrong_method_ctr);
- tty->print_cr("%5u unresolved static call site", _resolve_static_ctr);
- tty->print_cr("%5u unresolved virtual call site", _resolve_virtual_ctr);
- tty->print_cr("%5u unresolved opt virtual call site", _resolve_opt_virtual_ctr);
-
- if (_mon_enter_stub_ctr) tty->print_cr("%5u monitor enter stub", _mon_enter_stub_ctr);
- if (_mon_exit_stub_ctr) tty->print_cr("%5u monitor exit stub", _mon_exit_stub_ctr);
- if (_mon_enter_ctr) tty->print_cr("%5u monitor enter slow", _mon_enter_ctr);
- if (_mon_exit_ctr) tty->print_cr("%5u monitor exit slow", _mon_exit_ctr);
- if (_partial_subtype_ctr) tty->print_cr("%5u slow partial subtype", _partial_subtype_ctr);
- if (_jbyte_array_copy_ctr) tty->print_cr("%5u byte array copies", _jbyte_array_copy_ctr);
- if (_jshort_array_copy_ctr) tty->print_cr("%5u short array copies", _jshort_array_copy_ctr);
- if (_jint_array_copy_ctr) tty->print_cr("%5u int array copies", _jint_array_copy_ctr);
- if (_jlong_array_copy_ctr) tty->print_cr("%5u long array copies", _jlong_array_copy_ctr);
- if (_oop_array_copy_ctr) tty->print_cr("%5u oop array copies", _oop_array_copy_ctr);
- if (_checkcast_array_copy_ctr) tty->print_cr("%5u checkcast array copies", _checkcast_array_copy_ctr);
- if (_unsafe_array_copy_ctr) tty->print_cr("%5u unsafe array copies", _unsafe_array_copy_ctr);
- if (_generic_array_copy_ctr) tty->print_cr("%5u generic array copies", _generic_array_copy_ctr);
- if (_slow_array_copy_ctr) tty->print_cr("%5u slow array copies", _slow_array_copy_ctr);
- if (_find_handler_ctr) tty->print_cr("%5u find exception handler", _find_handler_ctr);
- if (_rethrow_ctr) tty->print_cr("%5u rethrow handler", _rethrow_ctr);
- if (_unsafe_set_memory_ctr) tty->print_cr("%5u unsafe set memorys", _unsafe_set_memory_ctr);
-
- AdapterHandlerLibrary::print_statistics();
if (xtty != nullptr) xtty->tail("statistics");
}
inline double percent(int64_t x, int64_t y) {
return 100.0 * (double)x / (double)MAX2(y, (int64_t)1);
}
class MethodArityHistogram {
void SharedRuntime::print_statistics() {
ttyLocker ttyl;
if (xtty != nullptr) xtty->head("statistics type='SharedRuntime'");
! SharedRuntime::print_ic_miss_histogram_on(tty);
! SharedRuntime::print_counters_on(tty);
! AdapterHandlerLibrary::print_statistics_on(tty);
if (xtty != nullptr) xtty->tail("statistics");
}
+ //void SharedRuntime::print_counters_on(outputStream* st) {
+ // // Dump the JRT_ENTRY counters
+ // if (_new_instance_ctr) st->print_cr("%5u new instance requires GC", _new_instance_ctr);
+ // if (_new_array_ctr) st->print_cr("%5u new array requires GC", _new_array_ctr);
+ // if (_multi2_ctr) st->print_cr("%5u multianewarray 2 dim", _multi2_ctr);
+ // if (_multi3_ctr) st->print_cr("%5u multianewarray 3 dim", _multi3_ctr);
+ // if (_multi4_ctr) st->print_cr("%5u multianewarray 4 dim", _multi4_ctr);
+ // if (_multi5_ctr) st->print_cr("%5u multianewarray 5 dim", _multi5_ctr);
+ //
+ // st->print_cr("%5u inline cache miss in compiled", _ic_miss_ctr);
+ // st->print_cr("%5u wrong method", _wrong_method_ctr);
+ // st->print_cr("%5u unresolved static call site", _resolve_static_ctr);
+ // st->print_cr("%5u unresolved virtual call site", _resolve_virtual_ctr);
+ // st->print_cr("%5u unresolved opt virtual call site", _resolve_opt_virtual_ctr);
+ //
+ // if (_mon_enter_stub_ctr) st->print_cr("%5u monitor enter stub", _mon_enter_stub_ctr);
+ // if (_mon_exit_stub_ctr) st->print_cr("%5u monitor exit stub", _mon_exit_stub_ctr);
+ // if (_mon_enter_ctr) st->print_cr("%5u monitor enter slow", _mon_enter_ctr);
+ // if (_mon_exit_ctr) st->print_cr("%5u monitor exit slow", _mon_exit_ctr);
+ // if (_partial_subtype_ctr) st->print_cr("%5u slow partial subtype", _partial_subtype_ctr);
+ // if (_jbyte_array_copy_ctr) st->print_cr("%5u byte array copies", _jbyte_array_copy_ctr);
+ // if (_jshort_array_copy_ctr) st->print_cr("%5u short array copies", _jshort_array_copy_ctr);
+ // if (_jint_array_copy_ctr) st->print_cr("%5u int array copies", _jint_array_copy_ctr);
+ // if (_jlong_array_copy_ctr) st->print_cr("%5u long array copies", _jlong_array_copy_ctr);
+ // if (_oop_array_copy_ctr) st->print_cr("%5u oop array copies", _oop_array_copy_ctr);
+ // if (_checkcast_array_copy_ctr) st->print_cr("%5u checkcast array copies", _checkcast_array_copy_ctr);
+ // if (_unsafe_array_copy_ctr) st->print_cr("%5u unsafe array copies", _unsafe_array_copy_ctr);
+ // if (_generic_array_copy_ctr) st->print_cr("%5u generic array copies", _generic_array_copy_ctr);
+ // if (_slow_array_copy_ctr) st->print_cr("%5u slow array copies", _slow_array_copy_ctr);
+ // if (_find_handler_ctr) st->print_cr("%5u find exception handler", _find_handler_ctr);
+ // if (_rethrow_ctr) st->print_cr("%5u rethrow handler", _rethrow_ctr);
+ // if (_unsafe_set_memory_ctr) tty->print_cr("%5u unsafe set memorys", _unsafe_set_memory_ctr);
+ //}
+
inline double percent(int64_t x, int64_t y) {
return 100.0 * (double)x / (double)MAX2(y, (int64_t)1);
}
class MethodArityHistogram {
uint64_t MethodArityHistogram::_total_compiled_calls;
uint64_t MethodArityHistogram::_max_compiled_calls_per_method;
int MethodArityHistogram::_max_arity;
int MethodArityHistogram::_max_size;
! void SharedRuntime::print_call_statistics(uint64_t comp_total) {
tty->print_cr("Calls from compiled code:");
int64_t total = _nof_normal_calls + _nof_interface_calls + _nof_static_calls;
int64_t mono_c = _nof_normal_calls - _nof_megamorphic_calls;
int64_t mono_i = _nof_interface_calls;
tty->print_cr("\t" INT64_FORMAT_W(12) " (100%%) total non-inlined ", total);
uint64_t MethodArityHistogram::_total_compiled_calls;
uint64_t MethodArityHistogram::_max_compiled_calls_per_method;
int MethodArityHistogram::_max_arity;
int MethodArityHistogram::_max_size;
! void SharedRuntime::print_call_statistics_on(outputStream* st) {
tty->print_cr("Calls from compiled code:");
int64_t total = _nof_normal_calls + _nof_interface_calls + _nof_static_calls;
int64_t mono_c = _nof_normal_calls - _nof_megamorphic_calls;
int64_t mono_i = _nof_interface_calls;
tty->print_cr("\t" INT64_FORMAT_W(12) " (100%%) total non-inlined ", total);
#endif
#ifndef PRODUCT
static int _lookups; // number of calls to lookup
static int _equals; // number of buckets checked with matching hash
! static int _hits; // number of successful lookups
static int _compact; // number of equals calls with compact signature
#endif
// A simple wrapper class around the calling convention information
// that allows sharing of adapters for the same calling convention.
! class AdapterFingerPrint : public CHeapObj<mtCode> {
private:
enum {
_basic_type_bits = 4,
_basic_type_mask = right_n_bits(_basic_type_bits),
_basic_types_per_int = BitsPerInt / _basic_type_bits,
_compact_int_count = 3
};
// TO DO: Consider integrating this with a more global scheme for compressing signatures.
// For now, 4 bits per components (plus T_VOID gaps after double/long) is not excessive.
! union {
! int _compact[_compact_int_count];
! int* _fingerprint;
! } _value;
! int _length; // A negative length indicates the fingerprint is in the compact form,
! // Otherwise _value._fingerprint is the array.
// Remap BasicTypes that are handled equivalently by the adapters.
// These are correct for the current system but someday it might be
// necessary to make this mapping platform dependent.
static int adapter_encoding(BasicType in) {
#endif
#ifndef PRODUCT
static int _lookups; // number of calls to lookup
static int _equals; // number of buckets checked with matching hash
! static int _archived_hits; // number of successful lookups in archived table
+ static int _runtime_hits; // number of successful lookups in runtime table
static int _compact; // number of equals calls with compact signature
#endif
// A simple wrapper class around the calling convention information
// that allows sharing of adapters for the same calling convention.
! class AdapterFingerPrint : public MetaspaceObj {
private:
enum {
_basic_type_bits = 4,
_basic_type_mask = right_n_bits(_basic_type_bits),
_basic_types_per_int = BitsPerInt / _basic_type_bits,
_compact_int_count = 3
};
// TO DO: Consider integrating this with a more global scheme for compressing signatures.
// For now, 4 bits per components (plus T_VOID gaps after double/long) is not excessive.
! int _length;
! int _value[_compact_int_count];
!
! // Private construtor. Use allocate() to get an instance.
! AdapterFingerPrint(int total_args_passed, BasicType* sig_bt) {
! // Pack the BasicTypes with 8 per int
+ _length = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
+ int sig_index = 0;
+ for (int index = 0; index < _length; index++) {
+ int value = 0;
+ for (int byte = 0; sig_index < total_args_passed && byte < _basic_types_per_int; byte++) {
+ int bt = adapter_encoding(sig_bt[sig_index++]);
+ assert((bt & _basic_type_mask) == bt, "must fit in 4 bits");
+ value = (value << _basic_type_bits) | bt;
+ }
+ _value[index] = value;
+ }
+ }
+
+ // Call deallocate instead
+ ~AdapterFingerPrint() {
+ FreeHeap(this);
+ }
// Remap BasicTypes that are handled equivalently by the adapters.
// These are correct for the current system but someday it might be
// necessary to make this mapping platform dependent.
static int adapter_encoding(BasicType in) {
ShouldNotReachHere();
return T_CONFLICT;
}
}
! public:
! AdapterFingerPrint(int total_args_passed, BasicType* sig_bt) {
! // The fingerprint is based on the BasicType signature encoded
! // into an array of ints with eight entries per int.
! int* ptr;
! int len = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
- if (len <= _compact_int_count) {
- assert(_compact_int_count == 3, "else change next line");
- _value._compact[0] = _value._compact[1] = _value._compact[2] = 0;
- // Storing the signature encoded as signed chars hits about 98%
- // of the time.
- _length = -len;
- ptr = _value._compact;
- } else {
- _length = len;
- _value._fingerprint = NEW_C_HEAP_ARRAY(int, _length, mtCode);
- ptr = _value._fingerprint;
- }
! // Now pack the BasicTypes with 8 per int
! int sig_index = 0;
! for (int index = 0; index < len; index++) {
! int value = 0;
! for (int byte = 0; sig_index < total_args_passed && byte < _basic_types_per_int; byte++) {
! int bt = adapter_encoding(sig_bt[sig_index++]);
! assert((bt & _basic_type_mask) == bt, "must fit in 4 bits");
! value = (value << _basic_type_bits) | bt;
}
- ptr[index] = value;
}
}
! ~AdapterFingerPrint() {
! if (_length > 0) {
! FREE_C_HEAP_ARRAY(int, _value._fingerprint);
! }
}
int value(int index) {
! if (_length < 0) {
- return _value._compact[index];
- }
- return _value._fingerprint[index];
}
int length() {
if (_length < 0) return -_length;
return _length;
}
bool is_compact() {
! return _length <= 0;
}
unsigned int compute_hash() {
int hash = 0;
for (int i = 0; i < length(); i++) {
int v = value(i);
! hash = (hash << 8) ^ v ^ (hash >> 5);
}
return (unsigned int)hash;
}
const char* as_string() {
ShouldNotReachHere();
return T_CONFLICT;
}
}
! void* operator new(size_t size, size_t fp_size) throw() {
! assert(fp_size >= size, "sanity check");
! void* p = AllocateHeap(fp_size, mtCode);
! memset(p, 0, fp_size);
! return p;
! }
! template<typename Function>
! void iterate_args(Function function) {
! for (int i = 0; i < length(); i++) {
! unsigned val = (unsigned)value(i);
! // args are packed so that first/lower arguments are in the highest
! // bits of each int value, so iterate from highest to the lowest
! for (int j = 32 - _basic_type_bits; j >= 0; j -= _basic_type_bits) {
! unsigned v = (val >> j) & _basic_type_mask;
+ if (v == 0) {
+ continue;
+ }
+ function(v);
}
}
}
! public:
! static int allocation_size(int total_args_passed, BasicType* sig_bt) {
! int len = (total_args_passed + (_basic_types_per_int-1)) / _basic_types_per_int;
! return sizeof(AdapterFingerPrint) + (len > _compact_int_count ? (len - _compact_int_count) * sizeof(int) : 0);
+ }
+
+ static AdapterFingerPrint* allocate(int total_args_passed, BasicType* sig_bt) {
+ int size_in_bytes = allocation_size(total_args_passed, sig_bt);
+ return new (size_in_bytes) AdapterFingerPrint(total_args_passed, sig_bt);
+ }
+
+ static void deallocate(AdapterFingerPrint* fp) {
+ fp->~AdapterFingerPrint();
}
int value(int index) {
! return _value[index];
}
+
int length() {
if (_length < 0) return -_length;
return _length;
}
bool is_compact() {
! return _length <= _compact_int_count;
}
unsigned int compute_hash() {
int hash = 0;
for (int i = 0; i < length(); i++) {
int v = value(i);
! //Add arithmetic operation to the hash, like +3 to improve hashing
+ hash = ((hash << 8) ^ v ^ (hash >> 5)) + 3;
}
return (unsigned int)hash;
}
const char* as_string() {
st.print("%x", value(i));
}
return st.as_string();
}
- #ifndef PRODUCT
- // Reconstitutes the basic type arguments from the fingerprint,
- // producing strings like LIJDF
const char* as_basic_args_string() {
stringStream st;
bool long_prev = false;
! for (int i = 0; i < length(); i++) {
! unsigned val = (unsigned)value(i);
! // args are packed so that first/lower arguments are in the highest
! // bits of each int value, so iterate from highest to the lowest
! for (int j = 32 - _basic_type_bits; j >= 0; j -= _basic_type_bits) {
! unsigned v = (val >> j) & _basic_type_mask;
! if (v == 0) {
- assert(i == length() - 1, "Only expect zeroes in the last word");
- continue;
- }
- if (long_prev) {
- long_prev = false;
- if (v == T_VOID) {
- st.print("J");
- } else {
- st.print("L");
- }
- }
- switch (v) {
- case T_INT: st.print("I"); break;
- case T_LONG: long_prev = true; break;
- case T_FLOAT: st.print("F"); break;
- case T_DOUBLE: st.print("D"); break;
- case T_VOID: break;
- default: ShouldNotReachHere();
}
}
! }
if (long_prev) {
st.print("L");
}
return st.as_string();
}
! #endif // !product
bool equals(AdapterFingerPrint* other) {
if (other->_length != _length) {
return false;
- }
- if (_length < 0) {
- assert(_compact_int_count == 3, "else change next line");
- return _value._compact[0] == other->_value._compact[0] &&
- _value._compact[1] == other->_value._compact[1] &&
- _value._compact[2] == other->_value._compact[2];
} else {
for (int i = 0; i < _length; i++) {
! if (_value._fingerprint[i] != other->_value._fingerprint[i]) {
return false;
}
}
}
return true;
}
static bool equals(AdapterFingerPrint* const& fp1, AdapterFingerPrint* const& fp2) {
NOT_PRODUCT(_equals++);
return fp1->equals(fp2);
}
static unsigned int compute_hash(AdapterFingerPrint* const& fp) {
return fp->compute_hash();
}
};
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
using AdapterHandlerTable = ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293,
AnyObj::C_HEAP, mtCode,
AdapterFingerPrint::compute_hash,
AdapterFingerPrint::equals>;
static AdapterHandlerTable* _adapter_handler_table;
// Find a entry with the same fingerprint if it exists
! static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
NOT_PRODUCT(_lookups++);
assert_lock_strong(AdapterHandlerLibrary_lock);
! AdapterFingerPrint fp(total_args_passed, sig_bt);
! AdapterHandlerEntry** entry = _adapter_handler_table->get(&fp);
! if (entry != nullptr) {
#ifndef PRODUCT
! if (fp.is_compact()) _compact++;
! _hits++;
#endif
! return *entry;
}
return nullptr;
}
#ifndef PRODUCT
! static void print_table_statistics() {
auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
return sizeof(*key) + sizeof(*a);
};
TableStatistics ts = _adapter_handler_table->statistics_calculate(size);
! ts.print(tty, "AdapterHandlerTable");
! tty->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)",
! _adapter_handler_table->table_size(), _adapter_handler_table->number_of_entries());
! tty->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d compact %d",
! _lookups, _equals, _hits, _compact);
}
! #endif
// ---------------------------------------------------------------------------
// Implementation of AdapterHandlerLibrary
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_no_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_int_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_int_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_obj_arg_handler = nullptr;
const int AdapterHandlerLibrary_size = 16*K;
BufferBlob* AdapterHandlerLibrary::_buffer = nullptr;
BufferBlob* AdapterHandlerLibrary::buffer_blob() {
return _buffer;
st.print("%x", value(i));
}
return st.as_string();
}
const char* as_basic_args_string() {
stringStream st;
bool long_prev = false;
! iterate_args([&] (int arg) {
! if (long_prev) {
! long_prev = false;
! if (arg == T_VOID) {
! st.print("J");
! } else {
! st.print("L");
}
}
! switch (arg) {
+ case T_INT: st.print("I"); break;
+ case T_LONG: long_prev = true; break;
+ case T_FLOAT: st.print("F"); break;
+ case T_DOUBLE: st.print("D"); break;
+ case T_VOID: break;
+ default: ShouldNotReachHere();
+ }
+ });
if (long_prev) {
st.print("L");
}
return st.as_string();
}
!
+ BasicType* as_basic_type(int& nargs) {
+ nargs = 0;
+ GrowableArray<BasicType> btarray;
+ bool long_prev = false;
+
+ iterate_args([&] (int arg) {
+ if (long_prev) {
+ long_prev = false;
+ if (arg == T_VOID) {
+ btarray.append(T_LONG);
+ } else {
+ btarray.append(T_OBJECT); // it could be T_ARRAY; it shouldn't matter
+ }
+ }
+ switch (arg) {
+ case T_INT: // fallthrough
+ case T_FLOAT: // fallthrough
+ case T_DOUBLE:
+ case T_VOID:
+ btarray.append((BasicType)arg);
+ break;
+ case T_LONG:
+ long_prev = true;
+ break;
+ default: ShouldNotReachHere();
+ }
+ });
+
+ if (long_prev) {
+ btarray.append(T_OBJECT);
+ }
+
+ nargs = btarray.length();
+ BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nargs);
+ int index = 0;
+ GrowableArrayIterator<BasicType> iter = btarray.begin();
+ while (iter != btarray.end()) {
+ sig_bt[index++] = *iter;
+ ++iter;
+ }
+ assert(index == btarray.length(), "sanity check");
+ #ifdef ASSERT
+ {
+ AdapterFingerPrint* compare_fp = AdapterFingerPrint::allocate(nargs, sig_bt);
+ assert(this->equals(compare_fp), "sanity check");
+ AdapterFingerPrint::deallocate(compare_fp);
+ }
+ #endif
+ return sig_bt;
+ }
bool equals(AdapterFingerPrint* other) {
if (other->_length != _length) {
return false;
} else {
for (int i = 0; i < _length; i++) {
! if (_value[i] != other->_value[i]) {
return false;
}
}
}
return true;
}
+ // methods required by virtue of being a MetaspaceObj
+ void metaspace_pointers_do(MetaspaceClosure* it) { return; /* nothing to do here */ }
+ int size() const { return (int)heap_word_size(sizeof(AdapterFingerPrint) + (_length > _compact_int_count ? (_length - _compact_int_count) * sizeof(int) : 0)); }
+ MetaspaceObj::Type type() const { return AdapterFingerPrintType; }
+
static bool equals(AdapterFingerPrint* const& fp1, AdapterFingerPrint* const& fp2) {
NOT_PRODUCT(_equals++);
return fp1->equals(fp2);
}
static unsigned int compute_hash(AdapterFingerPrint* const& fp) {
return fp->compute_hash();
}
};
+ #if INCLUDE_CDS
+ static inline bool adapter_fp_equals_compact_hashtable_entry(AdapterHandlerEntry* entry, AdapterFingerPrint* fp, int len_unused) {
+ return AdapterFingerPrint::equals(entry->fingerprint(), fp);
+ }
+
+ class ArchivedAdapterTable : public OffsetCompactHashtable<
+ AdapterFingerPrint*,
+ AdapterHandlerEntry*,
+ adapter_fp_equals_compact_hashtable_entry> {};
+ #endif // INCLUDE_CDS
+
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
using AdapterHandlerTable = ResourceHashtable<AdapterFingerPrint*, AdapterHandlerEntry*, 293,
AnyObj::C_HEAP, mtCode,
AdapterFingerPrint::compute_hash,
AdapterFingerPrint::equals>;
static AdapterHandlerTable* _adapter_handler_table;
+ static GrowableArray<AdapterHandlerEntry*>* _adapter_handler_list = nullptr;
// Find a entry with the same fingerprint if it exists
! AdapterHandlerEntry* AdapterHandlerLibrary::lookup(AdapterFingerPrint* fp) {
NOT_PRODUCT(_lookups++);
+ AdapterHandlerEntry* entry = nullptr;
+ #if INCLUDE_CDS
+ // if we are building the archive then the archived adapter table is
+ // not valid and we need to use the ones added to the runtime table
+ if (!CDSConfig::is_dumping_adapters()) {
+ // Search archived table first. It is read-only table so can be searched without lock
+ entry = _archived_adapter_handler_table.lookup(fp, fp->compute_hash(), 0 /* unused */);
+ if (entry != nullptr) {
+ #ifndef PRODUCT
+ if (fp->is_compact()) {
+ _compact++;
+ }
+ _archived_hits++;
+ #endif
+ return entry;
+ }
+ }
+ #endif // INCLUDE_CDS
assert_lock_strong(AdapterHandlerLibrary_lock);
! AdapterHandlerEntry** entry_p = _adapter_handler_table->get(fp);
! if (entry_p != nullptr) {
! entry = *entry_p;
+ assert(entry->fingerprint()->equals(fp), "fingerprint mismatch key fp %s %s (hash=%d) != found fp %s %s (hash=%d)",
+ entry->fingerprint()->as_basic_args_string(), entry->fingerprint()->as_string(), entry->fingerprint()->compute_hash(),
+ fp->as_basic_args_string(), fp->as_string(), fp->compute_hash());
#ifndef PRODUCT
! if (fp->is_compact()) _compact++;
! _runtime_hits++;
#endif
! return entry;
}
return nullptr;
}
#ifndef PRODUCT
! void AdapterHandlerLibrary::print_statistics_on(outputStream* st) {
auto size = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
return sizeof(*key) + sizeof(*a);
};
TableStatistics ts = _adapter_handler_table->statistics_calculate(size);
! ts.print(st, "AdapterHandlerTable");
! st->print_cr("AdapterHandlerTable (table_size=%d, entries=%d)",
! _adapter_handler_table->table_size(), _adapter_handler_table->number_of_entries());
! int total_hits = _archived_hits + _runtime_hits;
! st->print_cr("AdapterHandlerTable: lookups %d equals %d hits %d (archived=%d+runtime=%d) compact %d",
+ _lookups, _equals, total_hits, _archived_hits, _runtime_hits, _compact);
}
! #endif // !PRODUCT
// ---------------------------------------------------------------------------
// Implementation of AdapterHandlerLibrary
AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_no_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_int_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_int_arg_handler = nullptr;
AdapterHandlerEntry* AdapterHandlerLibrary::_obj_obj_arg_handler = nullptr;
+ #if INCLUDE_CDS
+ ArchivedAdapterTable AdapterHandlerLibrary::_archived_adapter_handler_table;
+ #endif // INCLUDE_CDS
const int AdapterHandlerLibrary_size = 16*K;
BufferBlob* AdapterHandlerLibrary::_buffer = nullptr;
BufferBlob* AdapterHandlerLibrary::buffer_blob() {
return _buffer;
// are never compiled so an i2c entry is somewhat meaningless, but
// throw AbstractMethodError just in case.
// Pass wrong_method_abstract for the c2i transitions to return
// AbstractMethodError for invalid invocations.
address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub();
! _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, nullptr),
SharedRuntime::throw_AbstractMethodError_entry(),
wrong_method_abstract, wrong_method_abstract);
_buffer = BufferBlob::create("adapters", AdapterHandlerLibrary_size);
! _no_arg_handler = create_adapter(no_arg_blob, 0, nullptr, true);
BasicType obj_args[] = { T_OBJECT };
! _obj_arg_handler = create_adapter(obj_arg_blob, 1, obj_args, true);
BasicType int_args[] = { T_INT };
! _int_arg_handler = create_adapter(int_arg_blob, 1, int_args, true);
BasicType obj_int_args[] = { T_OBJECT, T_INT };
! _obj_int_arg_handler = create_adapter(obj_int_arg_blob, 2, obj_int_args, true);
BasicType obj_obj_args[] = { T_OBJECT, T_OBJECT };
! _obj_obj_arg_handler = create_adapter(obj_obj_arg_blob, 2, obj_obj_args, true);
assert(no_arg_blob != nullptr &&
! obj_arg_blob != nullptr &&
! int_arg_blob != nullptr &&
! obj_int_arg_blob != nullptr &&
! obj_obj_arg_blob != nullptr, "Initial adapters must be properly created");
}
// Outside of the lock
post_adapter_creation(no_arg_blob, _no_arg_handler);
post_adapter_creation(obj_arg_blob, _obj_arg_handler);
post_adapter_creation(int_arg_blob, _int_arg_handler);
post_adapter_creation(obj_int_arg_blob, _obj_int_arg_handler);
post_adapter_creation(obj_obj_arg_blob, _obj_obj_arg_handler);
}
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
address c2i_unverified_entry,
address c2i_no_clinit_check_entry) {
// Insert an entry into the table
! return new AdapterHandlerEntry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry,
! c2i_no_clinit_check_entry);
}
AdapterHandlerEntry* AdapterHandlerLibrary::get_simple_adapter(const methodHandle& method) {
if (method->is_abstract()) {
return _abstract_method_handler;
// are never compiled so an i2c entry is somewhat meaningless, but
// throw AbstractMethodError just in case.
// Pass wrong_method_abstract for the c2i transitions to return
// AbstractMethodError for invalid invocations.
address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub();
! _abstract_method_handler = AdapterHandlerLibrary::new_entry(AdapterFingerPrint::allocate(0, nullptr),
SharedRuntime::throw_AbstractMethodError_entry(),
wrong_method_abstract, wrong_method_abstract);
_buffer = BufferBlob::create("adapters", AdapterHandlerLibrary_size);
! _no_arg_handler = create_simple_adapter(no_arg_blob, 0, nullptr);
BasicType obj_args[] = { T_OBJECT };
! _obj_arg_handler = create_simple_adapter(obj_arg_blob, 1, obj_args);
BasicType int_args[] = { T_INT };
! _int_arg_handler = create_simple_adapter(int_arg_blob, 1, int_args);
BasicType obj_int_args[] = { T_OBJECT, T_INT };
! _obj_int_arg_handler = create_simple_adapter(obj_int_arg_blob, 2, obj_int_args);
BasicType obj_obj_args[] = { T_OBJECT, T_OBJECT };
! _obj_obj_arg_handler = create_simple_adapter(obj_obj_arg_blob, 2, obj_obj_args);
assert(no_arg_blob != nullptr &&
! obj_arg_blob != nullptr &&
! int_arg_blob != nullptr &&
! obj_int_arg_blob != nullptr &&
! obj_obj_arg_blob != nullptr, "Initial adapters must be properly created");
}
// Outside of the lock
post_adapter_creation(no_arg_blob, _no_arg_handler);
post_adapter_creation(obj_arg_blob, _obj_arg_handler);
post_adapter_creation(int_arg_blob, _int_arg_handler);
post_adapter_creation(obj_int_arg_blob, _obj_int_arg_handler);
post_adapter_creation(obj_obj_arg_blob, _obj_obj_arg_handler);
}
+ AdapterHandlerEntry* AdapterHandlerLibrary::create_simple_adapter(AdapterBlob*& adapter_blob,
+ int total_args_passed,
+ BasicType* sig_bt) {
+ AdapterFingerPrint* fp = AdapterFingerPrint::allocate(total_args_passed, sig_bt);
+ // We may find the adapter in the table if it is loaded from the AOT cache
+ AdapterHandlerEntry* entry = lookup(fp);
+ if (entry != nullptr) {
+ assert(entry->is_shared() && !entry->is_linked(), "Non null AdapterHandlerEntry should be in the AOT cache in unlinked state");
+ if (!link_adapter_handler(entry, adapter_blob)) {
+ if (!generate_adapter_code(adapter_blob, entry, total_args_passed, sig_bt, /* is_transient */ false)) {
+ return nullptr;
+ }
+ }
+ // AdapterFingerPrint is already in the cache, no need to keep this one
+ AdapterFingerPrint::deallocate(fp);
+ } else {
+ entry = create_adapter(adapter_blob, fp, total_args_passed, sig_bt, /* is_transient */ false);
+ }
+ return entry;
+ }
+
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
address c2i_unverified_entry,
address c2i_no_clinit_check_entry) {
// Insert an entry into the table
! return AdapterHandlerEntry::allocate(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry,
! c2i_no_clinit_check_entry);
}
AdapterHandlerEntry* AdapterHandlerLibrary::get_simple_adapter(const methodHandle& method) {
if (method->is_abstract()) {
return _abstract_method_handler;
BasicType* sig_bt = si.basic_types();
{
MutexLocker mu(AdapterHandlerLibrary_lock);
// Lookup method signature's fingerprint
! entry = lookup(total_args_passed, sig_bt);
if (entry != nullptr) {
#ifdef ASSERT
if (VerifyAdapterSharing) {
AdapterBlob* comparison_blob = nullptr;
! AdapterHandlerEntry* comparison_entry = create_adapter(comparison_blob, total_args_passed, sig_bt, false);
assert(comparison_blob == nullptr, "no blob should be created when creating an adapter for comparison");
assert(comparison_entry->compare_code(entry), "code must match");
// Release the one just created and return the original
! delete comparison_entry;
}
#endif
return entry;
}
! entry = create_adapter(new_adapter, total_args_passed, sig_bt, /* allocate_code_blob */ true);
}
// Outside of the lock
if (new_adapter != nullptr) {
post_adapter_creation(new_adapter, entry);
}
return entry;
}
! AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_adapter,
! int total_args_passed,
! BasicType* sig_bt,
! bool allocate_code_blob) {
! if (log_is_enabled(Info, perf, class, link)) {
! ClassLoader::perf_method_adapters_count()->inc();
}
! // StubRoutines::_final_stubs_code is initialized after this function can be called. As a result,
! // VerifyAdapterCalls and VerifyAdapterSharing can fail if we re-use code that generated prior
! // to all StubRoutines::_final_stubs_code being set. Checks refer to runtime range checks generated
! // in an I2C stub that ensure that an I2C stub is called from an interpreter frame or stubs.
! bool contains_all_checks = StubRoutines::final_stubs_code() != nullptr;
! VMRegPair stack_regs[16];
! VMRegPair* regs = (total_args_passed <= 16) ? stack_regs : NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
- // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
- int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed);
BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
CodeBuffer buffer(buf);
short buffer_locs[20];
buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs,
! sizeof(buffer_locs)/sizeof(relocInfo));
!
! // Make a C heap allocated version of the fingerprint to store in the adapter
! AdapterFingerPrint* fingerprint = new AdapterFingerPrint(total_args_passed, sig_bt);
- MacroAssembler _masm(&buffer);
- AdapterHandlerEntry* entry = SharedRuntime::generate_i2c2i_adapters(&_masm,
- total_args_passed,
- comp_args_on_stack,
- sig_bt,
- regs,
- fingerprint);
#ifdef ASSERT
if (VerifyAdapterSharing) {
! entry->save_code(buf->code_begin(), buffer.insts_size());
! if (!allocate_code_blob) {
! return entry;
}
}
#endif
! new_adapter = AdapterBlob::create(&buffer);
! NOT_PRODUCT(int insts_size = buffer.insts_size());
- if (new_adapter == nullptr) {
// CodeCache is full, disable compilation
// Ought to log this but compile log is only per compile thread
// and we're some non descript Java thread.
! return nullptr;
}
! entry->relocate(new_adapter->content_begin());
#ifndef PRODUCT
// debugging support
if (PrintAdapterHandlers || PrintStubCode) {
! ttyLocker ttyl;
- entry->print_adapter_on(tty);
- tty->print_cr("i2c argument handler #%d for: %s %s (%d bytes generated)",
- _adapter_handler_table->number_of_entries(), fingerprint->as_basic_args_string(),
- fingerprint->as_string(), insts_size);
- tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(entry->get_c2i_entry()));
- if (Verbose || PrintStubCode) {
- address first_pc = entry->base_address();
- if (first_pc != nullptr) {
- Disassembler::decode(first_pc, first_pc + insts_size, tty
- NOT_PRODUCT(COMMA &new_adapter->asm_remarks()));
- tty->cr();
- }
- }
}
#endif
! // Add the entry only if the entry contains all required checks (see sharedRuntime_xxx.cpp)
! // The checks are inserted only if -XX:+VerifyAdapterCalls is specified.
! if (contains_all_checks || !VerifyAdapterCalls) {
assert_lock_strong(AdapterHandlerLibrary_lock);
! _adapter_handler_table->put(fingerprint, entry);
}
! return entry;
}
address AdapterHandlerEntry::base_address() {
address base = _i2c_entry;
if (base == nullptr) base = _c2i_entry;
assert(base <= _c2i_entry || _c2i_entry == nullptr, "");
BasicType* sig_bt = si.basic_types();
{
MutexLocker mu(AdapterHandlerLibrary_lock);
// Lookup method signature's fingerprint
! AdapterFingerPrint *fp = AdapterFingerPrint::allocate(total_args_passed, sig_bt);
+ entry = lookup(fp);
if (entry != nullptr) {
#ifdef ASSERT
if (VerifyAdapterSharing) {
AdapterBlob* comparison_blob = nullptr;
! AdapterFingerPrint* comparison_fp = AdapterFingerPrint::allocate(total_args_passed, sig_bt);
+ AdapterHandlerEntry* comparison_entry = create_adapter(comparison_blob, comparison_fp, total_args_passed, sig_bt, true);
assert(comparison_blob == nullptr, "no blob should be created when creating an adapter for comparison");
assert(comparison_entry->compare_code(entry), "code must match");
+ AdapterFingerPrint::deallocate(comparison_fp);
// Release the one just created and return the original
! AdapterHandlerEntry::deallocate(comparison_entry);
}
#endif
+ AdapterFingerPrint::deallocate(fp);
return entry;
}
! entry = create_adapter(new_adapter, fp, total_args_passed, sig_bt, /* is_transient */ false);
}
// Outside of the lock
if (new_adapter != nullptr) {
post_adapter_creation(new_adapter, entry);
}
return entry;
}
! bool AdapterHandlerLibrary::lookup_aot_cache(AdapterHandlerEntry* handler, CodeBuffer* buffer) {
! ResourceMark rm;
! const char* name = AdapterHandlerLibrary::name(handler->fingerprint());
! const uint32_t id = AdapterHandlerLibrary::id(handler->fingerprint());
! uint32_t offsets[4];
! if (SCCache::load_adapter(buffer, id, name, offsets)) {
+ address i2c_entry = buffer->insts_begin();
+ assert(offsets[0] == 0, "sanity check");
+ handler->set_entry_points(i2c_entry, i2c_entry + offsets[1], i2c_entry + offsets[2], i2c_entry + offsets[3]);
+ return true;
}
+ return false;
+ }
! #ifndef PRODUCT
! void AdapterHandlerLibrary::print_adapter_handler_info(AdapterHandlerEntry* handler, AdapterBlob* adapter_blob) {
! ttyLocker ttyl;
! ResourceMark rm;
! int insts_size = adapter_blob->code_size();
+ handler->print_adapter_on(tty);
+ tty->print_cr("i2c argument handler for: %s %s (%d bytes generated)",
+ handler->fingerprint()->as_basic_args_string(),
+ handler->fingerprint()->as_string(), insts_size);
+ tty->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(handler->get_c2i_entry()));
+ if (Verbose || PrintStubCode) {
+ address first_pc = handler->base_address();
+ if (first_pc != nullptr) {
+ Disassembler::decode(first_pc, first_pc + insts_size, tty, &adapter_blob->asm_remarks());
+ tty->cr();
+ }
+ }
+ }
+ #endif // PRODUCT
! bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
! AdapterHandlerEntry* handler,
+ int total_args_passed,
+ BasicType* sig_bt,
+ bool is_transient) {
+ if (log_is_enabled(Info, perf, class, link)) {
+ ClassLoader::perf_method_adapters_count()->inc();
+ }
BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
CodeBuffer buffer(buf);
short buffer_locs[20];
buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs,
! sizeof(buffer_locs)/sizeof(relocInfo));
! MacroAssembler masm(&buffer);
! VMRegPair stack_regs[16];
! VMRegPair* regs = (total_args_passed <= 16) ? stack_regs : NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
+ // Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
+ int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed);
+ SharedRuntime::generate_i2c2i_adapters(&masm,
+ total_args_passed,
+ comp_args_on_stack,
+ sig_bt,
+ regs,
+ handler);
+ if (CDSConfig::is_dumping_adapters()) {
+ // try to save generated code
+ const char* name = AdapterHandlerLibrary::name(handler->fingerprint());
+ const uint32_t id = AdapterHandlerLibrary::id(handler->fingerprint());
+ uint32_t offsets[4];
+ offsets[0] = 0;
+ offsets[1] = handler->get_c2i_entry() - handler->get_i2c_entry();
+ offsets[2] = handler->get_c2i_unverified_entry() - handler->get_i2c_entry();
+ offsets[3] = handler->get_c2i_no_clinit_check_entry() - handler->get_i2c_entry();
+ SCCache::store_adapter(&buffer, id, name, offsets);
+ }
#ifdef ASSERT
if (VerifyAdapterSharing) {
! handler->save_code(buf->code_begin(), buffer.insts_size());
! if (is_transient) {
! return true;
}
}
#endif
! adapter_blob = AdapterBlob::create(&buffer);
! if (adapter_blob == nullptr) {
// CodeCache is full, disable compilation
// Ought to log this but compile log is only per compile thread
// and we're some non descript Java thread.
! return false;
}
! handler->relocate(adapter_blob->content_begin());
#ifndef PRODUCT
// debugging support
if (PrintAdapterHandlers || PrintStubCode) {
! print_adapter_handler_info(handler, adapter_blob);
}
#endif
+ return true;
+ }
! AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& adapter_blob,
! AdapterFingerPrint* fingerprint,
! int total_args_passed,
+ BasicType* sig_bt,
+ bool is_transient) {
+ AdapterHandlerEntry* handler = AdapterHandlerLibrary::new_entry(fingerprint);
+ if (!generate_adapter_code(adapter_blob, handler, total_args_passed, sig_bt, is_transient)) {
+ return nullptr;
+ }
+ if (!is_transient) {
assert_lock_strong(AdapterHandlerLibrary_lock);
! _adapter_handler_table->put(fingerprint, handler);
}
! return handler;
+ }
+
+ #if INCLUDE_CDS
+ bool AdapterHandlerLibrary::link_adapter_handler(AdapterHandlerEntry* handler, AdapterBlob*& adapter_blob) {
+ #ifndef PRODUCT
+ if (TestAdapterLinkFailure) {
+ return false;
+ }
+ #endif
+ BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
+ CodeBuffer buffer(buf);
+ short buffer_locs[20];
+ buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs,
+ sizeof(buffer_locs)/sizeof(relocInfo));
+
+ if (!lookup_aot_cache(handler, &buffer)) {
+ return false;
+ }
+ adapter_blob = AdapterBlob::create(&buffer);
+ if (adapter_blob == nullptr) {
+ // CodeCache is full, disable compilation
+ // Ought to log this but compile log is only per compile thread
+ // and we're some non descript Java thread.
+ return false;
+ }
+ handler->relocate(adapter_blob->content_begin());
+ #ifndef PRODUCT
+ // debugging support
+ if (PrintAdapterHandlers || PrintStubCode) {
+ print_adapter_handler_info(handler, adapter_blob);
+ }
+ #endif
+ return true;
+ }
+
+ class CopyAdapterTableToArchive : StackObj {
+ private:
+ CompactHashtableWriter* _writer;
+ ArchiveBuilder* _builder;
+ public:
+ CopyAdapterTableToArchive(CompactHashtableWriter* writer) : _writer(writer),
+ _builder(ArchiveBuilder::current())
+ {}
+
+ bool do_entry(AdapterFingerPrint* fp, AdapterHandlerEntry* entry) {
+ LogStreamHandle(Trace, cds) lsh;
+ if (ArchiveBuilder::current()->has_been_archived((address)entry)) {
+ assert(ArchiveBuilder::current()->has_been_archived((address)fp), "must be");
+ AdapterFingerPrint* buffered_fp = ArchiveBuilder::current()->get_buffered_addr(fp);
+ assert(buffered_fp != nullptr,"sanity check");
+ AdapterHandlerEntry* buffered_entry = ArchiveBuilder::current()->get_buffered_addr(entry);
+ assert(buffered_entry != nullptr,"sanity check");
+
+ uint hash = fp->compute_hash();
+ u4 delta = _builder->buffer_to_offset_u4((address)buffered_entry);
+ _writer->add(hash, delta);
+ if (lsh.is_enabled()) {
+ address fp_runtime_addr = (address)buffered_fp + ArchiveBuilder::current()->buffer_to_requested_delta();
+ address entry_runtime_addr = (address)buffered_entry + ArchiveBuilder::current()->buffer_to_requested_delta();
+ log_trace(cds)("Added fp=%p (%s), entry=%p to the archived adater table", buffered_fp, buffered_fp->as_basic_args_string(), buffered_entry);
+ }
+ } else {
+ if (lsh.is_enabled()) {
+ log_trace(cds)("Skipping adapter handler %p (fp=%s) as it is not archived", entry, fp->as_basic_args_string());
+ }
+ }
+ return true;
+ }
+ };
+
+ size_t AdapterHandlerLibrary::estimate_size_for_archive() {
+ return CompactHashtableWriter::estimate_size(_adapter_handler_table->number_of_entries());
+ }
+
+ void AdapterHandlerLibrary::archive_adapter_table() {
+ CompactHashtableStats stats;
+ CompactHashtableWriter writer(_adapter_handler_table->number_of_entries(), &stats);
+ CopyAdapterTableToArchive copy(&writer);
+ _adapter_handler_table->iterate(©);
+ writer.dump(&_archived_adapter_handler_table, "archived adapter table");
+ }
+
+ void AdapterHandlerLibrary::serialize_shared_table_header(SerializeClosure* soc) {
+ _archived_adapter_handler_table.serialize_header(soc);
}
+ #endif // INCLUDE_CDS
address AdapterHandlerEntry::base_address() {
address base = _i2c_entry;
if (base == nullptr) base = _c2i_entry;
assert(base <= _c2i_entry || _c2i_entry == nullptr, "");
if (_c2i_no_clinit_check_entry != nullptr)
_c2i_no_clinit_check_entry += delta;
assert(base_address() == new_base, "");
}
AdapterHandlerEntry::~AdapterHandlerEntry() {
- delete _fingerprint;
#ifdef ASSERT
FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
#endif
}
#ifdef ASSERT
// Capture the code before relocation so that it can be compared
if (_c2i_no_clinit_check_entry != nullptr)
_c2i_no_clinit_check_entry += delta;
assert(base_address() == new_base, "");
}
+ void AdapterHandlerEntry::metaspace_pointers_do(MetaspaceClosure* it) {
+ LogStreamHandle(Trace, cds) lsh;
+ if (lsh.is_enabled()) {
+ lsh.print("Iter(AdapterHandlerEntry): %p(%s)", this, _fingerprint->as_basic_args_string());
+ lsh.cr();
+ }
+ it->push(&_fingerprint);
+ }
+
+ #if INCLUDE_CDS
+ void AdapterHandlerEntry::remove_unshareable_info() {
+ set_entry_points(nullptr, nullptr, nullptr, nullptr, false);
+ }
+
+ void AdapterHandlerEntry::restore_unshareable_info(TRAPS) {
+ PerfTraceElapsedTime timer(ClassLoader::perf_method_adapters_time());
+ // A fixed set of simple adapters are eagerly linked during JVM initialization
+ // in AdapterHandlerTable::initialize().
+ // Others may already have been linked because they are shared by other methods.
+ if (is_linked()) {
+ return;
+ }
+ AdapterBlob* adapter_blob = nullptr;
+ {
+ MutexLocker mu(AdapterHandlerLibrary_lock);
+ assert(_fingerprint != nullptr, "_fingerprint must not be null");
+ #ifdef ASSERT
+ AdapterHandlerEntry* entry = AdapterHandlerLibrary::lookup(_fingerprint);
+ assert(entry == this, "sanity check");
+ #endif
+ if (!AdapterHandlerLibrary::link_adapter_handler(this, adapter_blob)) {
+ ResourceMark rm;
+ log_warning(cds)("Failed to link AdapterHandlerEntry to its code in the AOT code cache");
+ int nargs;
+ BasicType* bt = _fingerprint->as_basic_type(nargs);
+ if (!AdapterHandlerLibrary::generate_adapter_code(adapter_blob, this, nargs, bt, /* is_transient */ false)) {
+ if (!is_init_completed()) {
+ // Don't throw exceptions during VM initialization because java.lang.* classes
+ // might not have been initialized, causing problems when constructing the
+ // Java exception object.
+ vm_exit_during_initialization("Out of space in CodeCache for adapters");
+ } else {
+ THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Out of space in CodeCache for adapters");
+ }
+ }
+ }
+ }
+ // Outside of the lock
+ if (adapter_blob != nullptr) {
+ post_adapter_creation(adapter_blob, this);
+ }
+ assert(_linked, "AdapterHandlerEntry must now be linked");
+ }
+ #endif // INCLUDE_CDS
AdapterHandlerEntry::~AdapterHandlerEntry() {
#ifdef ASSERT
FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
#endif
+ FreeHeap(this);
}
#ifdef ASSERT
// Capture the code before relocation so that it can be compared
FREE_C_HEAP_ARRAY(intptr_t, buf);
JRT_END
bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
bool found = false;
! auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
! return (found = (b == CodeCache::find_blob(a->get_i2c_entry())));
};
! assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
! _adapter_handler_table->iterate(findblob);
return found;
}
void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
bool found = false;
! auto findblob = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
! if (b == CodeCache::find_blob(a->get_i2c_entry())) {
found = true;
st->print("Adapter for signature: ");
! a->print_adapter_on(st);
return true;
} else {
return false; // keep looking
}
};
! assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
! _adapter_handler_table->iterate(findblob);
assert(found, "Should have found handler");
}
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
st->print("AHE@" INTPTR_FORMAT ": %s", p2i(this), fingerprint()->as_string());
FREE_C_HEAP_ARRAY(intptr_t, buf);
JRT_END
bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
bool found = false;
! #if INCLUDE_CDS
! auto findblob_archived_table = [&] (AdapterHandlerEntry* handler) {
+ return (found = (b == CodeCache::find_blob(handler->get_i2c_entry())));
};
! _archived_adapter_handler_table.iterate(findblob_archived_table);
! #endif // INCLUDE_CDS
+ if (!found) {
+ auto findblob_runtime_table = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
+ return (found = (b == CodeCache::find_blob(a->get_i2c_entry())));
+ };
+ assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
+ _adapter_handler_table->iterate(findblob_runtime_table);
+ }
return found;
}
+ const char* AdapterHandlerLibrary::name(AdapterFingerPrint* fingerprint) {
+ return fingerprint->as_basic_args_string();
+ }
+
+ uint32_t AdapterHandlerLibrary::id(AdapterFingerPrint* fingerprint) {
+ unsigned int hash = fingerprint->compute_hash();
+ return hash;
+ }
+
void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
bool found = false;
! #if INCLUDE_CDS
! auto findblob_archived_table = [&] (AdapterHandlerEntry* handler) {
+ if (b == CodeCache::find_blob(handler->get_i2c_entry())) {
found = true;
st->print("Adapter for signature: ");
! handler->print_adapter_on(st);
return true;
} else {
return false; // keep looking
+
}
};
! _archived_adapter_handler_table.iterate(findblob_archived_table);
! #endif // INCLUDE_CDS
+ if (!found) {
+ auto findblob_runtime_table = [&] (AdapterFingerPrint* key, AdapterHandlerEntry* a) {
+ if (b == CodeCache::find_blob(a->get_i2c_entry())) {
+ found = true;
+ st->print("Adapter for signature: ");
+ a->print_adapter_on(st);
+ return true;
+ } else {
+ return false; // keep looking
+ }
+ };
+ assert_locked_or_safepoint(AdapterHandlerLibrary_lock);
+ _adapter_handler_table->iterate(findblob_runtime_table);
+ }
assert(found, "Should have found handler");
}
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
st->print("AHE@" INTPTR_FORMAT ": %s", p2i(this), fingerprint()->as_string());
st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
}
st->cr();
}
! #ifndef PRODUCT
!
! void AdapterHandlerLibrary::print_statistics() {
! print_table_statistics();
}
- #endif /* PRODUCT */
-
JRT_LEAF(void, SharedRuntime::enable_stack_reserved_zone(JavaThread* current))
assert(current == JavaThread::current(), "pre-condition");
StackOverflow* overflow_state = current->stack_overflow_state();
overflow_state->enable_stack_reserved_zone(/*check_if_disabled*/true);
overflow_state->set_reserved_stack_activation(current->stack_base());
st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
}
st->cr();
}
! bool AdapterHandlerLibrary::is_abstract_method_adapter(AdapterHandlerEntry* entry) {
! if (entry == _abstract_method_handler) {
! return true;
! }
+ return false;
}
JRT_LEAF(void, SharedRuntime::enable_stack_reserved_zone(JavaThread* current))
assert(current == JavaThread::current(), "pre-condition");
StackOverflow* overflow_state = current->stack_overflow_state();
overflow_state->enable_stack_reserved_zone(/*check_if_disabled*/true);
overflow_state->set_reserved_stack_activation(current->stack_base());
< prev index next >