# HG changeset patch # User jrose # Date 1248220566 25200 # Node ID 75596850f863069c0ff81626332b46133ae32295 # Parent 606c988ff684d21dd74fd736ba524467e188c2a3 6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics Summary: remove useless lazy evaluation of intrinsics; add LAST_COMPILER_INLINE to help categorize them Reviewed-by: kvn diff -r 606c988ff684 -r 75596850f863 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -3231,6 +3231,16 @@ this_klass->set_minor_version(minor_version); this_klass->set_major_version(major_version); + // Set up methodOop::intrinsic_id as soon as we know the names of methods. + // (We used to do this lazily, but now we query it in Rewriter, + // which is eagerly done for every method, so we might as well do it now, + // when everything is fresh in memory.) + if (methodOopDesc::klass_id_for_intrinsics(this_klass->as_klassOop()) != vmSymbols::NO_SID) { + for (int j = 0; j < methods->length(); j++) { + ((methodOop)methods->obj_at(j))->init_intrinsic_id(); + } + } + if (cached_class_file_bytes != NULL) { // JVMTI: we have an instanceKlass now, tell it about the cached bytes this_klass->set_cached_class_file(cached_class_file_bytes, diff -r 606c988ff684 -r 75596850f863 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Jul 21 16:56:06 2009 -0700 @@ -513,9 +513,6 @@ // // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ - do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ - /* (symbol object_initializer_name defined above) */ \ - \ do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ do_name( hashCode_name, "hashCode") \ do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ @@ -635,9 +632,6 @@ do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ do_signature(equalsC_signature, "([C[C)Z") \ \ - do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ - /* (symbols invoke_name and invoke_signature defined above) */ \ - \ do_intrinsic(_compareTo, java_lang_String, compareTo_name, string_int_signature, F_R) \ do_name( compareTo_name, "compareTo") \ do_intrinsic(_indexOf, java_lang_String, indexOf_name, string_int_signature, F_R) \ @@ -656,8 +650,6 @@ do_name( attemptUpdate_name, "attemptUpdate") \ do_signature(attemptUpdate_signature, "(JJ)Z") \ \ - do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ - \ /* support for sun.misc.Unsafe */ \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ \ @@ -819,10 +811,22 @@ do_name( prefetchReadStatic_name, "prefetchReadStatic") \ do_intrinsic(_prefetchWriteStatic, sun_misc_Unsafe, prefetchWriteStatic_name, prefetch_signature, F_SN) \ do_name( prefetchWriteStatic_name, "prefetchWriteStatic") \ + /*== LAST_COMPILER_INLINE*/ \ + /*the compiler does have special inlining code for these; bytecode inline is just fine */ \ + \ + do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ + \ + do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ + /* (symbol object_initializer_name defined above) */ \ + \ + do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ + /* (symbols invoke_name and invoke_signature defined above) */ \ + \ /*end*/ + // Class vmSymbols class vmSymbols: AllStatic { @@ -935,6 +939,7 @@ #undef VM_INTRINSIC_ENUM ID_LIMIT, + LAST_COMPILER_INLINE = _prefetchWriteStatic, FIRST_ID = _none + 1 }; @@ -972,4 +977,7 @@ static Flags flags_for(ID id); static const char* short_name_as_C_string(ID id, char* buf, int size); + + // Access to intrinsic methods: + static methodOop method_for(ID id); }; diff -r 606c988ff684 -r 75596850f863 src/share/vm/interpreter/rewriter.cpp --- a/src/share/vm/interpreter/rewriter.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/interpreter/rewriter.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -273,6 +273,7 @@ compute_index_maps(); if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) { + bool did_rewrite = false; int i = _methods->length(); while (i-- > 0) { methodOop method = (methodOop)_methods->obj_at(i); @@ -281,9 +282,11 @@ // object for finalization if needed. methodHandle m(THREAD, method); rewrite_Object_init(m, CHECK); + did_rewrite = true; break; } } + assert(did_rewrite, "must find Object:: to rewrite it"); } // rewrite methods, in two passes diff -r 606c988ff684 -r 75596850f863 src/share/vm/oops/methodKlass.cpp --- a/src/share/vm/oops/methodKlass.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/oops/methodKlass.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -68,7 +68,7 @@ m->set_constants(NULL); m->set_max_stack(0); m->set_max_locals(0); - m->clear_intrinsic_id_cache(); + m->set_intrinsic_id(vmIntrinsics::_none); m->set_method_data(NULL); m->set_interpreter_throwout_count(0); m->set_vtable_index(methodOopDesc::garbage_vtable_index); diff -r 606c988ff684 -r 75596850f863 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/oops/methodOop.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -962,26 +962,39 @@ return newm; } -vmIntrinsics::ID methodOopDesc::compute_intrinsic_id() const { - assert(vmIntrinsics::_none == 0, "correct coding of default case"); - const uintptr_t max_cache_uint = right_n_bits((int)(sizeof(_intrinsic_id_cache) * BitsPerByte)); - assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_cache_uint, "else fix cache size"); +vmSymbols::SID methodOopDesc::klass_id_for_intrinsics(klassOop holder) { // if loader is not the default loader (i.e., != NULL), we can't know the intrinsics // because we are not loading from core libraries - if (instanceKlass::cast(method_holder())->class_loader() != NULL) return vmIntrinsics::_none; + if (instanceKlass::cast(holder)->class_loader() != NULL) + return vmSymbols::NO_SID; // regardless of name, no intrinsics here // see if the klass name is well-known: - symbolOop klass_name = instanceKlass::cast(method_holder())->name(); - vmSymbols::SID klass_id = vmSymbols::find_sid(klass_name); - if (klass_id == vmSymbols::NO_SID) return vmIntrinsics::_none; + symbolOop klass_name = instanceKlass::cast(holder)->name(); + return vmSymbols::find_sid(klass_name); +} + +void methodOopDesc::init_intrinsic_id() { + assert(_intrinsic_id == vmIntrinsics::_none, "do this just once"); + const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte)); + assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_id_uint, "else fix size"); + + // the klass name is well-known: + vmSymbols::SID klass_id = klass_id_for_intrinsics(method_holder()); + assert(klass_id != vmSymbols::NO_SID, "caller responsibility"); // ditto for method and signature: vmSymbols::SID name_id = vmSymbols::find_sid(name()); - if (name_id == vmSymbols::NO_SID) return vmIntrinsics::_none; + if (name_id == vmSymbols::NO_SID) return; vmSymbols::SID sig_id = vmSymbols::find_sid(signature()); - if (sig_id == vmSymbols::NO_SID) return vmIntrinsics::_none; + if (sig_id == vmSymbols::NO_SID) return; jshort flags = access_flags().as_short(); + vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); + if (id != vmIntrinsics::_none) { + set_intrinsic_id(id); + return; + } + // A few slightly irregular cases: switch (klass_id) { case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_StrictMath): @@ -992,15 +1005,18 @@ case vmSymbols::VM_SYMBOL_ENUM_NAME(sqrt_name): // pretend it is the corresponding method in the non-strict class: klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_Math); + id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); break; } } - // return intrinsic id if any - return vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); + if (id != vmIntrinsics::_none) { + // Set up its iid. It is an alias method. + set_intrinsic_id(id); + return; + } } - // These two methods are static since a GC may move the methodOopDesc bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) { bool sig_is_loaded = true; diff -r 606c988ff684 -r 75596850f863 src/share/vm/oops/methodOop.hpp --- a/src/share/vm/oops/methodOop.hpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/oops/methodOop.hpp Tue Jul 21 16:56:06 2009 -0700 @@ -104,7 +104,7 @@ u2 _max_stack; // Maximum number of entries on the expression stack u2 _max_locals; // Number of local variables used by this method u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words - u1 _intrinsic_id_cache; // Cache for intrinsic_id; 0 or 1+vmInt::ID + u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) u1 _highest_tier_compile; // Highest compile level this method has ever seen. u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting u2 _number_of_breakpoints; // fullspeed debugging support @@ -224,8 +224,6 @@ int highest_tier_compile() { return _highest_tier_compile;} void set_highest_tier_compile(int level) { _highest_tier_compile = level;} - void clear_intrinsic_id_cache() { _intrinsic_id_cache = 0; } - // Count of times method was exited via exception while interpreting void interpreter_throwout_increment() { if (_interpreter_throwout_count < 65534) { @@ -571,18 +569,12 @@ void set_cached_itable_index(int index) { instanceKlass::cast(method_holder())->set_cached_itable_index(method_idnum(), index); } // Support for inlining of intrinsic methods - vmIntrinsics::ID intrinsic_id() const { // returns zero if not an intrinsic - const u1& cache = _intrinsic_id_cache; - if (cache != 0) { - return (vmIntrinsics::ID)(cache - 1); - } else { - vmIntrinsics::ID id = compute_intrinsic_id(); - *(u1*)&cache = ((u1) id) + 1; // force the cache to be non-const - vmIntrinsics::verify_method(id, (methodOop) this); - assert((vmIntrinsics::ID)(cache - 1) == id, "proper conversion"); - return id; - } - } + vmIntrinsics::ID intrinsic_id() const { return (vmIntrinsics::ID) _intrinsic_id; } + void set_intrinsic_id(vmIntrinsics::ID id) { _intrinsic_id = (u1) id; } + + // Helper routines for intrinsic_id() and vmIntrinsics::method(). + void init_intrinsic_id(); // updates from _none if a match + static vmSymbols::SID klass_id_for_intrinsics(klassOop holder); // On-stack replacement support bool has_osr_nmethod() { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci) != NULL; } @@ -635,9 +627,6 @@ void set_size_of_parameters(int size) { _size_of_parameters = size; } private: - // Helper routine for intrinsic_id(). - vmIntrinsics::ID compute_intrinsic_id() const; - // Inlined elements address* native_function_addr() const { assert(is_native(), "must be native"); return (address*) (this+1); } address* signature_handler_addr() const { return native_function_addr() + 1; } diff -r 606c988ff684 -r 75596850f863 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/opto/compile.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -101,7 +101,8 @@ } } // Lazily create intrinsics for intrinsic IDs well-known in the runtime. - if (m->intrinsic_id() != vmIntrinsics::_none) { + if (m->intrinsic_id() != vmIntrinsics::_none && + m->intrinsic_id() <= vmIntrinsics::LAST_COMPILER_INLINE) { CallGenerator* cg = make_vm_intrinsic(m, is_virtual); if (cg != NULL) { // Save it for next time: diff -r 606c988ff684 -r 75596850f863 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Fri Jul 17 00:50:55 2009 -0700 +++ b/src/share/vm/opto/library_call.cpp Tue Jul 21 16:56:06 2009 -0700 @@ -310,11 +310,6 @@ if (!InlineAtomicLong) return NULL; break; - case vmIntrinsics::_Object_init: - case vmIntrinsics::_invoke: - // We do not intrinsify these; they are marked for other purposes. - return NULL; - case vmIntrinsics::_getCallerClass: if (!UseNewReflection) return NULL; if (!InlineReflectionGetCallerClass) return NULL; @@ -327,6 +322,8 @@ break; default: + assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); + assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); break; } @@ -394,18 +391,11 @@ } if (PrintIntrinsics) { - switch (intrinsic_id()) { - case vmIntrinsics::_invoke: - case vmIntrinsics::_Object_init: - // We do not expect to inline these, so do not produce any noise about them. - break; - default: - tty->print("Did not inline intrinsic %s%s at bci:%d in", - vmIntrinsics::name_at(intrinsic_id()), - (is_virtual() ? " (virtual)" : ""), kit.bci()); - kit.caller()->print_short_name(tty); - tty->print_cr(" (%d bytes)", kit.caller()->code_size()); - } + tty->print("Did not inline intrinsic %s%s at bci:%d in", + vmIntrinsics::name_at(intrinsic_id()), + (is_virtual() ? " (virtual)" : ""), kit.bci()); + kit.caller()->print_short_name(tty); + tty->print_cr(" (%d bytes)", kit.caller()->code_size()); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); return NULL;