# HG changeset patch # User amurillo # Date 1417542633 28800 # Node ID fc1f9b67fd8c5d5cd94ecc03569d93e7ce7fb574 # Parent 3562db849018867411898f4d0131ad0c0863051a# Parent 01de5cfa06c14ccb664d1c9d13b6f9c68eaa3d7c Merge diff -r 3562db849018 -r fc1f9b67fd8c .hgtags --- a/.hgtags Wed Nov 26 13:58:01 2014 -0800 +++ b/.hgtags Tue Dec 02 09:50:33 2014 -0800 @@ -557,3 +557,4 @@ 3a8a0fd171c5876023112941b1c7254262f9adfc hs25.40-b19 aa2442f89230dc46147c721812f3b3bd4c612e83 hs25.40-b20 5ea68fb91139081304357f9b937f32c5fdfeca6d jdk8u40-b16 +6bf89bfe8185747a57193efb6cec1f17ccc80414 hs25.40-b21 diff -r 3562db849018 -r fc1f9b67fd8c make/hotspot_version --- a/make/hotspot_version Wed Nov 26 13:58:01 2014 -0800 +++ b/make/hotspot_version Tue Dec 02 09:50:33 2014 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=40 -HS_BUILD_NUMBER=20 +HS_BUILD_NUMBER=21 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 3562db849018 -r fc1f9b67fd8c src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/ci/ciMethod.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -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 @@ // 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/ci/ciMethod.hpp Tue Dec 02 09:50:33 2014 -0800 @@ -90,7 +90,7 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/ci/ciObjectFactory.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -239,7 +239,7 @@ 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 @@ } // ------------------------------------------------------------------ -// 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 @@ } #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 @@ } // ------------------------------------------------------------------ -// 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 @@ } } 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 @@ // 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/ci/ciObjectFactory.hpp --- a/src/share/vm/ci/ciObjectFactory.hpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/ci/ciObjectFactory.hpp Tue Dec 02 09:50:33 2014 -0800 @@ -73,7 +73,7 @@ void insert(int index, ciMetadata* obj, GrowableArray* 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/ci/ciTypeFlow.cpp --- a/src/share/vm/ci/ciTypeFlow.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/ci/ciTypeFlow.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -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 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/classfile/classLoaderExt.hpp --- a/src/share/vm/classfile/classLoaderExt.hpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/classfile/classLoaderExt.hpp Tue Dec 02 09:50:33 2014 -0800 @@ -63,6 +63,9 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/code/dependencies.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -879,6 +879,8 @@ bool is_witness(Klass* k) { if (doing_subtype_search()) { return Dependencies::is_concrete_klass(k); + } else if (!k->oop_is_instance()) { + return false; // no methods to find in an array type } else { Method* m = InstanceKlass::cast(k)->find_method(_name, _signature); if (m == NULL || !Dependencies::is_concrete_method(m)) return false; @@ -1085,7 +1087,7 @@ Klass* chain; // scratch variable #define ADD_SUBCLASS_CHAIN(k) { \ assert(chaini < CHAINMAX, "oob"); \ - chain = InstanceKlass::cast(k)->subklass(); \ + chain = k->subklass(); \ if (chain != NULL) chains[chaini++] = chain; } // Look for non-abstract subclasses. @@ -1096,35 +1098,37 @@ // (Their subclasses are additional indirect implementors. // See InstanceKlass::add_implementor.) // (Note: nof_implementors is always zero for non-interfaces.) - int nof_impls = InstanceKlass::cast(context_type)->nof_implementors(); - if (nof_impls > 1) { - // Avoid this case: *I.m > { A.m, C }; B.m > C - // Here, I.m has 2 concrete implementations, but m appears unique - // as A.m, because the search misses B.m when checking C. - // The inherited method B.m was getting missed by the walker - // when interface 'I' was the starting point. - // %%% Until this is fixed more systematically, bail out. - // (Old CHA had the same limitation.) - return context_type; - } - if (nof_impls > 0) { - Klass* impl = InstanceKlass::cast(context_type)->implementor(); - assert(impl != NULL, "just checking"); - // If impl is the same as the context_type, then more than one - // implementor has seen. No exact info in this case. - if (impl == context_type) { - return context_type; // report an inexact witness to this sad affair + if (top_level_call) { + int nof_impls = InstanceKlass::cast(context_type)->nof_implementors(); + if (nof_impls > 1) { + // Avoid this case: *I.m > { A.m, C }; B.m > C + // Here, I.m has 2 concrete implementations, but m appears unique + // as A.m, because the search misses B.m when checking C. + // The inherited method B.m was getting missed by the walker + // when interface 'I' was the starting point. + // %%% Until this is fixed more systematically, bail out. + // (Old CHA had the same limitation.) + return context_type; } - if (do_counts) - { NOT_PRODUCT(deps_find_witness_steps++); } - if (is_participant(impl)) { - if (!participants_hide_witnesses) { + if (nof_impls > 0) { + Klass* impl = InstanceKlass::cast(context_type)->implementor(); + assert(impl != NULL, "just checking"); + // If impl is the same as the context_type, then more than one + // implementor has seen. No exact info in this case. + if (impl == context_type) { + return context_type; // report an inexact witness to this sad affair + } + if (do_counts) + { NOT_PRODUCT(deps_find_witness_steps++); } + if (is_participant(impl)) { + if (!participants_hide_witnesses) { + ADD_SUBCLASS_CHAIN(impl); + } + } else if (is_witness(impl) && !ignore_witness(impl)) { + return impl; + } else { ADD_SUBCLASS_CHAIN(impl); } - } else if (is_witness(impl) && !ignore_witness(impl)) { - return impl; - } else { - ADD_SUBCLASS_CHAIN(impl); } } diff -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/c2_globals.hpp --- a/src/share/vm/opto/c2_globals.hpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/c2_globals.hpp Tue Dec 02 09:50:33 2014 -0800 @@ -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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/compile.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -679,7 +679,8 @@ _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 @@ _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 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/compile.hpp Tue Dec 02 09:50:33 2014 -0800 @@ -290,6 +290,7 @@ 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 @@ 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 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/doCall.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -410,6 +410,11 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/escape.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -2409,7 +2409,7 @@ } } } - 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/loopTransform.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -269,10 +269,9 @@ 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 @@ 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 @@ // 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/loopUnswitch.cpp --- a/src/share/vm/opto/loopUnswitch.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/loopUnswitch.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -59,8 +59,8 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/loopopts.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -734,7 +734,7 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/memnode.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -1255,6 +1255,16 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/opto/node.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -69,7 +69,7 @@ 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 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/prims/jvmtiEnv.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -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 @@ 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 -r 3562db849018 -r fc1f9b67fd8c src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Wed Nov 26 13:58:01 2014 -0800 +++ b/src/share/vm/prims/whitebox.cpp Tue Dec 02 09:50:33 2014 -0800 @@ -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 @@ 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 @@ 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 }, diff -r 3562db849018 -r fc1f9b67fd8c test/compiler/EliminateAutoBox/UnsignedLoads.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/EliminateAutoBox/UnsignedLoads.java Tue Dec 02 09:50:33 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @run main/othervm -Xbatch -XX:+EliminateAutoBox + * -XX:CompileOnly=::valueOf,::byteValue,::shortValue,::testUnsignedByte,::testUnsignedShort + * UnsignedLoads + */ +import static com.oracle.java.testlibrary.Asserts.assertEQ; + +public class UnsignedLoads { + public static int testUnsignedByte() { + byte[] bytes = new byte[] {-1}; + int res = 0; + for (int i = 0; i < 100000; i++) { + for (Byte b : bytes) { + res = b & 0xff; + } + } + return res; + } + + public static int testUnsignedShort() { + int res = 0; + short[] shorts = new short[] {-1}; + for (int i = 0; i < 100000; i++) { + for (Short s : shorts) { + res = s & 0xffff; + } + } + return res; + } + + public static void main(String[] args) { + assertEQ(testUnsignedByte(), 255); + assertEQ(testUnsignedShort(), 65535); + System.out.println("TEST PASSED"); + } +} diff -r 3562db849018 -r fc1f9b67fd8c test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java Tue Dec 02 09:50:33 2014 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; + +import com.oracle.java.testlibrary.*; + +/* + * @test + * @bug 8050079 + * @summary Compiles a monomorphic call to finalizeObject() on a modified java.lang.Object to test C1 CHA. + * @library /testlibrary + * @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java + * @run main TestMonomorphicObjectCall + */ +public class TestMonomorphicObjectCall { + final static String testClasses = System.getProperty("test.classes") + File.separator; + + private static void callFinalize(Object object) throws Throwable { + // Call modified version of java.lang.Object::finalize() that is + // not overridden by any subclass. C1 CHA should mark the call site + // as monomorphic and inline the method. + object.finalizeObject(); + } + + public static void main(String[] args) throws Throwable { + if (args.length == 0) { + // Execute new instance with modified java.lang.Object + executeTestJvm(); + } else { + // Trigger compilation of 'callFinalize' + callFinalize(new Object()); + } + } + + public static void executeTestJvm() throws Throwable { + // Execute test with modified version of java.lang.Object + // in -Xbootclasspath. + String[] vmOpts = new String[] { + "-Xbootclasspath/p:" + testClasses, + "-Xcomp", + "-XX:-VerifyDependencies", + "-XX:CompileOnly=TestMonomorphicObjectCall::callFinalize", + "-XX:CompileOnly=Object::finalizeObject", + "-XX:TieredStopAtLevel=1", + TestMonomorphicObjectCall.class.getName(), + "true"}; + OutputAnalyzer output = ProcessTools.executeTestJvm(vmOpts); + output.shouldHaveExitValue(0); + } +} diff -r 3562db849018 -r fc1f9b67fd8c test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java Tue Dec 02 09:50:33 2014 -0800 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Slightly modified version of java.lang.Object that replaces + * finalize() by finalizeObject() to avoid overriding in subclasses. + */ +public class Object { + + private static native void registerNatives(); + static { + registerNatives(); + } + + public final native Class getClass(); + + public native int hashCode(); + + public boolean equals(Object obj) { + return (this == obj); + } + + protected native Object clone() throws CloneNotSupportedException; + + public String toString() { + return getClass().getName() + "@" + Integer.toHexString(hashCode()); + } + + public final native void notify(); + + public final native void notifyAll(); + + public final native void wait(long timeout) throws InterruptedException; + + public final void wait(long timeout, int nanos) throws InterruptedException { + if (timeout < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException( + "nanosecond timeout value out of range"); + } + + if (nanos >= 500000 || (nanos != 0 && timeout == 0)) { + timeout++; + } + + wait(timeout); + } + + public final void wait() throws InterruptedException { + wait(0); + } + + /** + * Replaces original finalize() method and is therefore not + * overridden by any subclasses of Object. + * @throws Throwable + */ + // protected void finalize() throws Throwable { } + public void finalizeObject() throws Throwable { } +} diff -r 3562db849018 -r fc1f9b67fd8c test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Nov 26 13:58:01 2014 -0800 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Dec 02 09:50:33 2014 -0800 @@ -90,6 +90,10 @@ public native URL[] getLookupCacheURLs(ClassLoader loader); public native int[] getLookupCacheMatches(ClassLoader loader, String name); + // JVMTI + public native void addToBootstrapClassLoaderSearch(String segment); + public native void addToSystemClassLoaderSearch(String segment); + // G1 public native boolean g1InConcurrentMark(); public native boolean g1IsHumongous(Object o);