aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm
diff options
context:
space:
mode:
authorcoleenp <none@none>2014-12-01 09:38:52 -0500
committercoleenp <none@none>2014-12-01 09:38:52 -0500
commit8103c474e75ae3daa81d881f849bca9d7877ba8b (patch)
tree2dd66fb3929c734a22c1013d730d03c8a6634473 /src/share/vm
parentbd86ef9fc2bf6afce4f6829067676bcd50d6ed06 (diff)
parent7d8d2d5c79a82221c34a2b97c30dd800a208cc1b (diff)
downloadjdk8u_hotspot-8103c474e75ae3daa81d881f849bca9d7877ba8b.tar.gz
Merge
Diffstat (limited to 'src/share/vm')
-rw-r--r--src/share/vm/ci/ciMethod.cpp6
-rw-r--r--src/share/vm/ci/ciMethod.hpp2
-rw-r--r--src/share/vm/ci/ciObjectFactory.cpp43
-rw-r--r--src/share/vm/ci/ciObjectFactory.hpp2
-rw-r--r--src/share/vm/ci/ciTypeFlow.cpp3
-rw-r--r--src/share/vm/classfile/classLoaderExt.hpp3
-rw-r--r--src/share/vm/opto/c2_globals.hpp2
-rw-r--r--src/share/vm/opto/compile.cpp7
-rw-r--r--src/share/vm/opto/compile.hpp6
-rw-r--r--src/share/vm/opto/doCall.cpp5
-rw-r--r--src/share/vm/opto/escape.cpp2
-rw-r--r--src/share/vm/opto/loopTransform.cpp9
-rw-r--r--src/share/vm/opto/loopUnswitch.cpp4
-rw-r--r--src/share/vm/opto/loopopts.cpp2
-rw-r--r--src/share/vm/opto/memnode.cpp10
-rw-r--r--src/share/vm/opto/node.cpp4
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp3
-rw-r--r--src/share/vm/prims/whitebox.cpp28
18 files changed, 106 insertions, 35 deletions
diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp
index 476ae145e..ae5dd763a 100644
--- a/src/share/vm/ci/ciMethod.cpp
+++ b/src/share/vm/ci/ciMethod.cpp
@@ -68,7 +68,10 @@
// ciMethod::ciMethod
//
// Loaded method.
-ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
+ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
+ ciMetadata(h_m()),
+ _holder(holder)
+{
assert(h_m() != NULL, "no null method");
// These fields are always filled in in loaded methods.
@@ -124,7 +127,6 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
// generating _signature may allow GC and therefore move m.
// These fields are always filled in.
_name = env->get_symbol(h_m()->name());
- _holder = env->get_instance_klass(h_m()->method_holder());
ciSymbol* sig_symbol = env->get_symbol(h_m()->signature());
constantPoolHandle cpool = h_m()->constants();
_signature = new (env->arena()) ciSignature(_holder, cpool, sig_symbol);
diff --git a/src/share/vm/ci/ciMethod.hpp b/src/share/vm/ci/ciMethod.hpp
index 24eec2ad9..59d2cdff1 100644
--- a/src/share/vm/ci/ciMethod.hpp
+++ b/src/share/vm/ci/ciMethod.hpp
@@ -90,7 +90,7 @@ class ciMethod : public ciMetadata {
BCEscapeAnalyzer* _bcea;
#endif
- ciMethod(methodHandle h_m);
+ ciMethod(methodHandle h_m, ciInstanceKlass* holder);
ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor);
Method* get_Method() const {
diff --git a/src/share/vm/ci/ciObjectFactory.cpp b/src/share/vm/ci/ciObjectFactory.cpp
index aaa607ff1..c7415310a 100644
--- a/src/share/vm/ci/ciObjectFactory.cpp
+++ b/src/share/vm/ci/ciObjectFactory.cpp
@@ -239,7 +239,7 @@ void ciObjectFactory::remove_symbols() {
ciObject* ciObjectFactory::get(oop key) {
ASSERT_IN_VM;
- assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be");
+ assert(Universe::heap()->is_in_reserved(key), "must be");
NonPermObject* &bucket = find_non_perm(key);
if (bucket != NULL) {
@@ -260,10 +260,10 @@ ciObject* ciObjectFactory::get(oop key) {
}
// ------------------------------------------------------------------
-// ciObjectFactory::get
+// ciObjectFactory::get_metadata
//
-// Get the ciObject corresponding to some oop. If the ciObject has
-// already been created, it is returned. Otherwise, a new ciObject
+// Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
+// already been created, it is returned. Otherwise, a new ciMetadata
// is created.
ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
ASSERT_IN_VM;
@@ -290,9 +290,9 @@ ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
}
#endif
if (!is_found_at(index, key, _ci_metadata)) {
- // The ciObject does not yet exist. Create it and insert it
+ // The ciMetadata does not yet exist. Create it and insert it
// into the cache.
- ciMetadata* new_object = create_new_object(key);
+ ciMetadata* new_object = create_new_metadata(key);
init_ident_of(new_object);
assert(new_object->is_metadata(), "must be");
@@ -344,15 +344,28 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
}
// ------------------------------------------------------------------
-// ciObjectFactory::create_new_object
+// ciObjectFactory::create_new_metadata
//
-// Create a new ciObject from a Metadata*.
+// Create a new ciMetadata from a Metadata*.
//
-// Implementation note: this functionality could be virtual behavior
-// of the oop itself. For now, we explicitly marshal the object.
-ciMetadata* ciObjectFactory::create_new_object(Metadata* o) {
+// Implementation note: in order to keep Metadata live, an auxiliary ciObject
+// is used, which points to it's holder.
+ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) {
EXCEPTION_CONTEXT;
+ // Hold metadata from unloading by keeping it's holder alive.
+ if (_initialized && o->is_klass()) {
+ Klass* holder = ((Klass*)o);
+ if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) {
+ // Though ciInstanceKlass records class loader oop, it's not enough to keep
+ // VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
+ // It is enough to record a ciObject, since cached elements are never removed
+ // during ciObjectFactory lifetime. ciObjectFactory itself is created for
+ // every compilation and lives for the whole duration of the compilation.
+ ciObject* h = get(holder->klass_holder());
+ }
+ }
+
if (o->is_klass()) {
KlassHandle h_k(THREAD, (Klass*)o);
Klass* k = (Klass*)o;
@@ -365,14 +378,16 @@ ciMetadata* ciObjectFactory::create_new_object(Metadata* o) {
}
} else if (o->is_method()) {
methodHandle h_m(THREAD, (Method*)o);
- return new (arena()) ciMethod(h_m);
+ ciEnv *env = CURRENT_THREAD_ENV;
+ ciInstanceKlass* holder = env->get_instance_klass(h_m()->method_holder());
+ return new (arena()) ciMethod(h_m, holder);
} else if (o->is_methodData()) {
// Hold methodHandle alive - might not be necessary ???
methodHandle h_m(THREAD, ((MethodData*)o)->method());
return new (arena()) ciMethodData((MethodData*)o);
}
- // The oop is of some type not supported by the compiler interface.
+ // The Metadata* is of some type not supported by the compiler interface.
ShouldNotReachHere();
return NULL;
}
@@ -701,7 +716,7 @@ static ciObjectFactory::NonPermObject* emptyBucket = NULL;
// If there is no entry in the cache corresponding to this oop, return
// the null tail of the bucket into which the oop should be inserted.
ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
- assert(Universe::heap()->is_in_reserved_or_null(key), "must be");
+ assert(Universe::heap()->is_in_reserved(key), "must be");
ciMetadata* klass = get_metadata(key->klass());
NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) {
diff --git a/src/share/vm/ci/ciObjectFactory.hpp b/src/share/vm/ci/ciObjectFactory.hpp
index 6c228e09d..4cdcc69be 100644
--- a/src/share/vm/ci/ciObjectFactory.hpp
+++ b/src/share/vm/ci/ciObjectFactory.hpp
@@ -73,7 +73,7 @@ private:
void insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects);
ciObject* create_new_object(oop o);
- ciMetadata* create_new_object(Metadata* o);
+ ciMetadata* create_new_metadata(Metadata* o);
void ensure_metadata_alive(ciMetadata* m);
diff --git a/src/share/vm/ci/ciTypeFlow.cpp b/src/share/vm/ci/ciTypeFlow.cpp
index 834f71be5..d78eb1456 100644
--- a/src/share/vm/ci/ciTypeFlow.cpp
+++ b/src/share/vm/ci/ciTypeFlow.cpp
@@ -35,6 +35,7 @@
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp"
+#include "opto/compile.hpp"
#include "runtime/deoptimization.hpp"
#include "utilities/growableArray.hpp"
@@ -2646,7 +2647,7 @@ void ciTypeFlow::df_flow_types(Block* start,
assert (!blk->has_pre_order(), "");
blk->set_next_pre_order();
- if (_next_pre_order >= MaxNodeLimit / 2) {
+ if (_next_pre_order >= (int)Compile::current()->max_node_limit() / 2) {
// Too many basic blocks. Bail out.
// This can happen when try/finally constructs are nested to depth N,
// and there is O(2**N) cloning of jsr bodies. See bug 4697245!
diff --git a/src/share/vm/classfile/classLoaderExt.hpp b/src/share/vm/classfile/classLoaderExt.hpp
index 677242594..7b2360af9 100644
--- a/src/share/vm/classfile/classLoaderExt.hpp
+++ b/src/share/vm/classfile/classLoaderExt.hpp
@@ -63,6 +63,9 @@ public:
ClassPathEntry* new_entry) {
ClassLoader::add_to_list(new_entry);
}
+ static void append_boot_classpath(ClassPathEntry* new_entry) {
+ ClassLoader::add_to_list(new_entry);
+ }
static void setup_search_paths() {}
static void init_lookup_cache(TRAPS) {}
diff --git a/src/share/vm/opto/c2_globals.hpp b/src/share/vm/opto/c2_globals.hpp
index 8b0b752f0..adeee7a83 100644
--- a/src/share/vm/opto/c2_globals.hpp
+++ b/src/share/vm/opto/c2_globals.hpp
@@ -647,7 +647,7 @@
develop(bool, AlwaysIncrementalInline, false, \
"do all inlining incrementally") \
\
- product(intx, LiveNodeCountInliningCutoff, 20000, \
+ product(intx, LiveNodeCountInliningCutoff, 40000, \
"max number of live nodes in a method") \
\
diagnostic(bool, OptimizeExpensiveOps, true, \
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index 53515c142..4d2050c5a 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -679,7 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_inlining_incrementally(false),
_print_inlining_list(NULL),
_print_inlining_idx(0),
- _interpreter_frame_size(0) {
+ _interpreter_frame_size(0),
+ _max_node_limit(MaxNodeLimit) {
C = this;
CompileWrapper cw(this);
@@ -990,7 +991,8 @@ Compile::Compile( ciEnv* ci_env,
_print_inlining_list(NULL),
_print_inlining_idx(0),
_allowed_reasons(0),
- _interpreter_frame_size(0) {
+ _interpreter_frame_size(0),
+ _max_node_limit(MaxNodeLimit) {
C = this;
#ifndef PRODUCT
@@ -1100,6 +1102,7 @@ void Compile::Init(int aliaslevel) {
set_do_count_invocations(false);
set_do_method_data_update(false);
set_rtm_state(NoRTM); // No RTM lock eliding by default
+ method_has_option_value("MaxNodeLimit", _max_node_limit);
#if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state();
diff --git a/src/share/vm/opto/compile.hpp b/src/share/vm/opto/compile.hpp
index c7be16ee1..2cc3c811c 100644
--- a/src/share/vm/opto/compile.hpp
+++ b/src/share/vm/opto/compile.hpp
@@ -290,6 +290,7 @@ class Compile : public Phase {
int _freq_inline_size; // Max hot method inline size for this compilation
int _fixed_slots; // count of frame slots not allocated by the register
// allocator i.e. locks, original deopt pc, etc.
+ uintx _max_node_limit; // Max unique node count during a single compilation.
// For deopt
int _orig_pc_slot;
int _orig_pc_slot_offset_in_bytes;
@@ -594,6 +595,9 @@ class Compile : public Phase {
void set_rtm_state(RTMState s) { _rtm_state = s; }
bool use_rtm() const { return (_rtm_state & NoRTM) == 0; }
bool profile_rtm() const { return _rtm_state == ProfileRTM; }
+ uint max_node_limit() const { return (uint)_max_node_limit; }
+ void set_max_node_limit(uint n) { _max_node_limit = n; }
+
// check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);
@@ -723,7 +727,7 @@ class Compile : public Phase {
record_method_not_compilable(reason, true);
}
bool check_node_count(uint margin, const char* reason) {
- if (live_nodes() + margin > (uint)MaxNodeLimit) {
+ if (live_nodes() + margin > max_node_limit()) {
record_method_not_compilable(reason);
return true;
} else {
diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
index a1ba7f792..960e61aaa 100644
--- a/src/share/vm/opto/doCall.cpp
+++ b/src/share/vm/opto/doCall.cpp
@@ -410,6 +410,11 @@ void Parse::do_call() {
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
assert(declared_signature != NULL, "cannot be null");
+ // Bump max node limit for JSR292 users
+ if (bc() == Bytecodes::_invokedynamic || orig_callee->is_method_handle_intrinsic()) {
+ C->set_max_node_limit(3*MaxNodeLimit);
+ }
+
// uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation
if (!will_link || can_not_compile_call_site(orig_callee, klass)) {
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index 515c9fe97..4af344928 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -2409,7 +2409,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
}
}
}
- if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) {
+ if (C->live_nodes() + 2*NodeLimitFudgeFactor > C->max_node_limit()) {
if (C->do_escape_analysis() == true && !C->failing()) {
// Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick"
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index 16e5e8c1e..695c9f8a8 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -269,10 +269,9 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
Node *test = ((IdealLoopTree*)this)->tail();
int body_size = ((IdealLoopTree*)this)->_body.size();
- int live_node_count = phase->C->live_nodes();
// Peeling does loop cloning which can result in O(N^2) node construction
if( body_size > 255 /* Prevent overflow for large body_size */
- || (body_size * body_size + live_node_count > MaxNodeLimit) ) {
+ || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) {
return false; // too large to safely clone
}
while( test != _head ) { // Scan till run off top of loop
@@ -601,7 +600,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
return false;
if (new_body_size > unroll_limit ||
// Unrolling can result in a large amount of node construction
- new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) {
+ new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) {
return false;
}
@@ -2287,8 +2286,8 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
// Skip next optimizations if running low on nodes. Note that
// policy_unswitching and policy_maximally_unroll have this check.
- uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes();
- if ((2 * _body.size()) > nodes_left) {
+ int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
+ if ((int)(2 * _body.size()) > nodes_left) {
return true;
}
diff --git a/src/share/vm/opto/loopUnswitch.cpp b/src/share/vm/opto/loopUnswitch.cpp
index 047c00e80..c750fd683 100644
--- a/src/share/vm/opto/loopUnswitch.cpp
+++ b/src/share/vm/opto/loopUnswitch.cpp
@@ -59,8 +59,8 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
if (!_head->is_Loop()) {
return false;
}
- uint nodes_left = MaxNodeLimit - phase->C->live_nodes();
- if (2 * _body.size() > nodes_left) {
+ int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
+ if ((int)(2 * _body.size()) > nodes_left) {
return false; // Too speculative if running low on nodes.
}
LoopNode* head = _head->as_Loop();
diff --git a/src/share/vm/opto/loopopts.cpp b/src/share/vm/opto/loopopts.cpp
index 258b4bc17..8b00a9af9 100644
--- a/src/share/vm/opto/loopopts.cpp
+++ b/src/share/vm/opto/loopopts.cpp
@@ -734,7 +734,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) {
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
weight += region->fast_out(i)->outcnt();
}
- int nodes_left = MaxNodeLimit - C->live_nodes();
+ int nodes_left = C->max_node_limit() - C->live_nodes();
if (weight * 8 > nodes_left) {
#ifndef PRODUCT
if (PrintOpto)
diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp
index 104c50b8c..46c2d4765 100644
--- a/src/share/vm/opto/memnode.cpp
+++ b/src/share/vm/opto/memnode.cpp
@@ -1255,6 +1255,16 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
result = new (phase->C) ConvI2LNode(phase->transform(result));
}
#endif
+ // Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair).
+ // Need to preserve unboxing load type if it is unsigned.
+ switch(this->Opcode()) {
+ case Op_LoadUB:
+ result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFF));
+ break;
+ case Op_LoadUS:
+ result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFFFF));
+ break;
+ }
return result;
}
}
diff --git a/src/share/vm/opto/node.cpp b/src/share/vm/opto/node.cpp
index 328f6c837..dd3c07915 100644
--- a/src/share/vm/opto/node.cpp
+++ b/src/share/vm/opto/node.cpp
@@ -69,7 +69,7 @@ void Node::verify_construction() {
Compile::set_debug_idx(new_debug_idx);
set_debug_idx( new_debug_idx );
assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX");
- assert(Compile::current()->live_nodes() < (uint)MaxNodeLimit, "Live Node limit exceeded limit");
+ assert(Compile::current()->live_nodes() < Compile::current()->max_node_limit(), "Live Node limit exceeded limit");
if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) {
tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx);
BREAKPOINT;
@@ -326,7 +326,7 @@ inline int Node::Init(int req, Compile* C) {
Node::Node(uint req)
: _idx(IDX_INIT(req))
{
- assert( req < (uint)(MaxNodeLimit - NodeLimitFudgeFactor), "Input limit exceeded" );
+ assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" );
debug_only( verify_construction() );
NOT_PRODUCT(nodes_created++);
if (req == 0) {
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index b5b3b8a63..c9d53cff4 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderExt.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecodeStream.hpp"
@@ -475,7 +476,7 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {
if (TraceClassLoading) {
tty->print_cr("[Opened %s]", zip_entry->name());
}
- ClassLoader::add_to_list(zip_entry);
+ ClassLoaderExt::append_boot_classpath(zip_entry);
return JVMTI_ERROR_NONE;
} else {
return JVMTI_ERROR_WRONG_PHASE;
diff --git a/src/share/vm/prims/whitebox.cpp b/src/share/vm/prims/whitebox.cpp
index fda11b709..0132cb13e 100644
--- a/src/share/vm/prims/whitebox.cpp
+++ b/src/share/vm/prims/whitebox.cpp
@@ -56,6 +56,7 @@
#endif // INCLUDE_NMT
#include "compiler/compileBroker.hpp"
+#include "jvmtifiles/jvmtiEnv.hpp"
#include "runtime/compilationPolicy.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@@ -126,6 +127,29 @@ WB_ENTRY(jintArray, WB_GetLookupCacheMatches(JNIEnv* env, jobject o, jobject loa
return result;
WB_END
+WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
+#if INCLUDE_JVMTI
+ ResourceMark rm;
+ const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
+ JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
+ jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
+ assert(err == JVMTI_ERROR_NONE, "must not fail");
+#endif
+}
+WB_END
+
+WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
+#if INCLUDE_JVMTI
+ ResourceMark rm;
+ const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
+ JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
+ jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
+ assert(err == JVMTI_ERROR_NONE, "must not fail");
+#endif
+}
+WB_END
+
+
WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
return (jlong)Arguments::max_heap_for_compressed_oops();
}
@@ -958,6 +982,10 @@ static JNINativeMethod methods[] = {
CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
(void*) &WB_ParseCommandLine
},
+ {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
+ (void*)&WB_AddToBootstrapClassLoaderSearch},
+ {CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V",
+ (void*)&WB_AddToSystemClassLoaderSearch},
{CC"getCompressedOopsMaxHeapSize", CC"()J",
(void*)&WB_GetCompressedOopsMaxHeapSize},
{CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },