< prev index next >

src/hotspot/share/oops/method.cpp

Print this page

        

@@ -48,10 +48,11 @@
 #include "oops/methodData.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
+#include "oops/valueKlass.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/methodHandles.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/compilationPolicy.hpp"

@@ -107,11 +108,10 @@
 
   if (access_flags.is_native()) {
     clear_native_function();
     set_signature_handler(NULL);
   }
-
   NOT_PRODUCT(set_compiled_invocation_count(0);)
 }
 
 // Release Method*.  The nmethod will be gone when we get here because
 // we've walked the code cache.

@@ -139,15 +139,25 @@
 address Method::get_c2i_entry() {
   assert(adapter() != NULL, "must have");
   return adapter()->get_c2i_entry();
 }
 
+address Method::get_c2i_value_entry() {
+  assert(adapter() != NULL, "must have");
+  return adapter()->get_c2i_value_entry();
+}
+
 address Method::get_c2i_unverified_entry() {
   assert(adapter() != NULL, "must have");
   return adapter()->get_c2i_unverified_entry();
 }
 
+address Method::get_c2i_unverified_value_entry() {
+  assert(adapter() != NULL, "must have");
+  return adapter()->get_c2i_unverified_value_entry();
+}
+
 char* Method::name_and_sig_as_C_string() const {
   return name_and_sig_as_C_string(constants()->pool_holder(), name(), signature());
 }
 
 char* Method::name_and_sig_as_C_string(char* buf, int size) const {

@@ -493,10 +503,28 @@
 BasicType Method::result_type() const {
   ResultTypeFinder rtf(signature());
   return rtf.type();
 }
 
+// ValueKlass the method is declared to return. This must not
+// safepoint as it is called with references live on the stack at
+// locations the GC is unaware of.
+ValueKlass* Method::returned_value_type(Thread* thread) const {
+  SignatureStream ss(signature());
+  while (!ss.at_return_type()) {
+    ss.next();
+  }
+  Handle class_loader(thread, method_holder()->class_loader());
+  Handle protection_domain(thread, method_holder()->protection_domain());
+  Klass* k = NULL;
+  {
+    NoSafepointVerifier nsv;
+    k = ss.as_klass(class_loader, protection_domain, SignatureStream::ReturnNull, thread);
+  }
+  assert(k != NULL && !thread->has_pending_exception(), "can't resolve klass");
+  return ValueKlass::cast(k);
+}
 
 bool Method::is_empty_method() const {
   return  code_size() == 1
       && *code_base() == Bytecodes::_return;
 }

@@ -681,29 +709,31 @@
           Bytecodes::is_const(java_code_at(0)) &&
           Bytecodes::length_for(java_code_at(0)) == last_index &&
           Bytecodes::is_return(java_code_at(last_index)));
 }
 
-bool Method::is_initializer() const {
-  return is_object_initializer() || is_static_initializer();
+bool Method::is_object_constructor_or_class_initializer() const {
+  return (is_object_constructor() || is_class_initializer());
 }
 
-bool Method::has_valid_initializer_flags() const {
-  return (is_static() ||
-          method_holder()->major_version() < 51);
-}
-
-bool Method::is_static_initializer() const {
+bool Method::is_class_initializer() const {
   // For classfiles version 51 or greater, ensure that the clinit method is
   // static.  Non-static methods with the name "<clinit>" are not static
   // initializers. (older classfiles exempted for backward compatibility)
-  return name() == vmSymbols::class_initializer_name() &&
-         has_valid_initializer_flags();
+  return (name() == vmSymbols::class_initializer_name() &&
+          (is_static() ||
+           method_holder()->major_version() < 51));
+}
+
+// A method named <init>, if non-static, is a classic object constructor.
+bool Method::is_object_constructor() const {
+   return name() == vmSymbols::object_initializer_name() && !is_static();
 }
 
-bool Method::is_object_initializer() const {
-   return name() == vmSymbols::object_initializer_name();
+// A static method named <init> is a factory for an inline class.
+bool Method::is_static_init_factory() const {
+   return name() == vmSymbols::object_initializer_name() && is_static();
 }
 
 bool Method::needs_clinit_barrier() const {
   return is_static() && !method_holder()->is_initialized();
 }

@@ -751,11 +781,11 @@
   return best_line;
 }
 
 
 bool Method::is_klass_loaded_by_klass_index(int klass_index) const {
-  if( constants()->tag_at(klass_index).is_unresolved_klass() ) {
+  if( constants()->tag_at(klass_index).is_unresolved_klass()) {
     Thread *thread = Thread::current();
     Symbol* klass_name = constants()->klass_name_at(klass_index);
     Handle loader(thread, method_holder()->class_loader());
     Handle prot  (thread, method_holder()->protection_domain());
     return SystemDictionary::find(klass_name, loader, prot, thread) != NULL;

@@ -767,11 +797,13 @@
 
 bool Method::is_klass_loaded(int refinfo_index, bool must_be_resolved) const {
   int klass_index = constants()->klass_ref_index_at(refinfo_index);
   if (must_be_resolved) {
     // Make sure klass is resolved in constantpool.
-    if (constants()->tag_at(klass_index).is_unresolved_klass()) return false;
+    if (constants()->tag_at(klass_index).is_unresolved_klass()) {
+      return false;
+    }
   }
   return is_klass_loaded_by_klass_index(klass_index);
 }
 
 

@@ -946,12 +978,16 @@
 void Method::clear_code() {
   // this may be NULL if c2i adapters have not been made yet
   // Only should happen at allocate time.
   if (adapter() == NULL) {
     _from_compiled_entry    = NULL;
+    _from_compiled_value_entry = NULL;
+    _from_compiled_value_ro_entry = NULL;
   } else {
     _from_compiled_entry    = adapter()->get_c2i_entry();
+    _from_compiled_value_entry = adapter()->get_c2i_value_entry();
+    _from_compiled_value_ro_entry = adapter()->get_c2i_value_ro_entry();
   }
   OrderAccess::storestore();
   _from_interpreted_entry = _i2i_entry;
   OrderAccess::storestore();
   _code = NULL;

@@ -995,10 +1031,17 @@
     CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter();
     constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline());
     _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline();
     assert(*((int*)_from_compiled_entry) == 0,
            "must be NULL during dump time, to be initialized at run time");
+    _from_compiled_value_ro_entry = cds_adapter->get_c2i_entry_trampoline(); // FIXME - doesn't work if you have value args!
+    assert(*((int*)_from_compiled_value_ro_entry) == 0,
+           "must be NULL during dump time, to be initialized at run time");
+    _from_compiled_value_entry  = cds_adapter->get_c2i_entry_trampoline(); // FIXME - doesn't work if you have value args (or this is value type)!
+    assert(*((int*)_from_compiled_value_entry) == 0,
+           "must be NULL during dump time, to be initialized at run time");
+    assert(!method_holder()->is_value(), "FIXME: valuetype not supported by CDS");
   }
 
   if (is_native()) {
     *native_function_addr() = NULL;
     set_signature_handler(NULL);

@@ -1149,13 +1192,17 @@
   }
 
   if (mh->is_shared()) {
     assert(mh->adapter() == adapter, "must be");
     assert(mh->_from_compiled_entry != NULL, "must be");
+    assert(mh->_from_compiled_value_entry != NULL, "must be");
+    assert(mh->_from_compiled_value_ro_entry != NULL, "must be");
   } else {
     mh->set_adapter_entry(adapter);
     mh->_from_compiled_entry = adapter->get_c2i_entry();
+    mh->_from_compiled_value_entry = adapter->get_c2i_value_entry();
+    mh->_from_compiled_value_ro_entry = adapter->get_c2i_value_ro_entry();
   }
   return adapter->get_c2i_entry();
 }
 
 void Method::restore_unshareable_info(TRAPS) {

@@ -1167,16 +1214,26 @@
     methodHandle mh(THREAD, this);
     link_method(mh, CHECK);
   }
 }
 
-address Method::from_compiled_entry_no_trampoline() const {
+address Method::from_compiled_entry_no_trampoline(bool caller_is_c1) const {
   CompiledMethod *code = OrderAccess::load_acquire(&_code);
-  if (code) {
-    return code->verified_entry_point();
+  if (caller_is_c1) {
+    // C1 - value arguments are passed as objects
+    if (code) {
+      return code->verified_value_entry_point();
+    } else {
+      return adapter()->get_c2i_value_entry();
+    }
   } else {
-    return adapter()->get_c2i_entry();
+    // C2 - value arguments may be passed as fields
+    if (code) {
+      return code->verified_entry_point();
+    } else {
+      return adapter()->get_c2i_entry();
+    }
   }
 }
 
 // The verified_code_entry() must be called when a invoke is resolved
 // on this method.

@@ -1189,10 +1246,22 @@
   debug_only(NoSafepointVerifier nsv;)
   assert(_from_compiled_entry != NULL, "must be set");
   return _from_compiled_entry;
 }
 
+address Method::verified_value_code_entry() {
+  debug_only(NoSafepointVerifier nsv;)
+  assert(_from_compiled_value_entry != NULL, "must be set");
+  return _from_compiled_value_entry;
+}
+
+address Method::verified_value_ro_code_entry() {
+  debug_only(NoSafepointVerifier nsv;)
+  assert(_from_compiled_value_ro_entry != NULL, "must be set");
+  return _from_compiled_value_ro_entry;
+}
+
 // Check that if an nmethod ref exists, it has a backlink to this or no backlink at all
 // (could be racing a deopt).
 // Not inline to avoid circular ref.
 bool Method::check_code() const {
   // cached in a register or local.  There's a race on the value of the field.

@@ -1220,10 +1289,12 @@
     mh->set_highest_comp_level(comp_level);
   }
 
   OrderAccess::storestore();
   mh->_from_compiled_entry = code->verified_entry_point();
+  mh->_from_compiled_value_entry = code->verified_value_entry_point();
+  mh->_from_compiled_value_ro_entry = code->verified_value_ro_entry_point();
   OrderAccess::storestore();
   // Instantly compiled code can execute.
   if (!mh->is_method_handle_intrinsic())
     mh->_from_interpreted_entry = mh->get_i2c_entry();
 }

@@ -2253,10 +2324,12 @@
   if (intrinsic_id() != vmIntrinsics::_none)
     st->print_cr(" - intrinsic id:      %d %s", intrinsic_id(), vmIntrinsics::name_at(intrinsic_id()));
   if (highest_comp_level() != CompLevel_none)
     st->print_cr(" - highest level:     %d", highest_comp_level());
   st->print_cr(" - vtable index:      %d",   _vtable_index);
+  if (valid_itable_index())
+    st->print_cr(" - itable index:      %d",   itable_index());
   st->print_cr(" - i2i entry:         " INTPTR_FORMAT, p2i(interpreter_entry()));
   st->print(   " - adapters:          ");
   AdapterHandlerEntry* a = ((Method*)this)->adapter();
   if (a == NULL)
     st->print_cr(INTPTR_FORMAT, p2i(a));

@@ -2330,10 +2403,11 @@
 void Method::print_value_on(outputStream* st) const {
   assert(is_method(), "must be method");
   st->print("%s", internal_name());
   print_address_on(st);
   st->print(" ");
+  if (WizardMode) access_flags().print_on(st);
   name()->print_value_on(st);
   st->print(" ");
   signature()->print_value_on(st);
   st->print(" in ");
   method_holder()->print_value_on(st);
< prev index next >