< prev index next >

src/hotspot/share/prims/jvm.cpp

Print this page
*** 55,10 ***
--- 55,11 ---
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/access.inline.hpp"
  #include "oops/constantPool.hpp"
  #include "oops/fieldStreams.inline.hpp"
+ #include "oops/flatArrayKlass.hpp"
  #include "oops/instanceKlass.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/method.hpp"
  #include "oops/recordComponent.hpp"
  #include "oops/objArrayKlass.hpp"

*** 425,10 ***
--- 426,36 ---
    const char* temp_dir = os::get_temp_directory();
    Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL);
    return (jstring) JNIHandles::make_local(THREAD, h());
  JVM_END
  
+ JVM_ENTRY(jarray, JVM_NewNullRestrictedArray(JNIEnv *env, jclass elmClass, jint len))
+   if (len < 0) {
+     THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Array length is negative");
+   }
+   oop mirror = JNIHandles::resolve_non_null(elmClass);
+   Klass* klass = java_lang_Class::as_Klass(mirror);
+   klass->initialize(CHECK_NULL);
+   if (klass->is_identity_class()) {
+     THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is not a value class");
+   }
+   if (klass->is_abstract()) {
+     THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is abstract");
+   }
+   InlineKlass* vk = InlineKlass::cast(klass);
+   if (!vk->is_implicitly_constructible()) {
+     THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Element class is not implicitly constructible");
+   }
+   oop array = oopFactory::new_valueArray(vk, len, CHECK_NULL);
+   return (jarray) JNIHandles::make_local(THREAD, array);
+ JVM_END
+ 
+ 
+ JVM_ENTRY(jboolean, JVM_IsNullRestrictedArray(JNIEnv *env, jobject obj))
+   arrayOop oop = arrayOop(JNIHandles::resolve_non_null(obj));
+   return oop->is_null_free_array();
+ JVM_END
  
  // java.lang.Runtime /////////////////////////////////////////////////////////////////////////
  
  extern volatile jint vm_created;
  

*** 633,12 ***
  // java.lang.Object ///////////////////////////////////////////////
  
  
  JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
    // as implemented in the classic virtual machine; return 0 if object is null
!   return handle == nullptr ? 0 :
!          checked_cast<jint>(ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)));
  JVM_END
  
  
  JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
    Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
--- 660,32 ---
  // java.lang.Object ///////////////////////////////////////////////
  
  
  JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
    // as implemented in the classic virtual machine; return 0 if object is null
!   if (handle == nullptr) {
!     return 0;
+   }
+   oop obj = JNIHandles::resolve_non_null(handle);
+   if (EnableValhalla && obj->klass()->is_inline_klass()) {
+       JavaValue result(T_INT);
+       JavaCallArguments args;
+       Handle ho(THREAD, obj);
+       args.push_oop(ho);
+       methodHandle method(THREAD, Universe::value_object_hash_code_method());
+       JavaCalls::call(&result, method, &args, THREAD);
+       if (HAS_PENDING_EXCEPTION) {
+         if (!PENDING_EXCEPTION->is_a(vmClasses::Error_klass())) {
+           Handle e(THREAD, PENDING_EXCEPTION);
+           CLEAR_PENDING_EXCEPTION;
+           THROW_MSG_CAUSE_(vmSymbols::java_lang_InternalError(), "Internal error in hashCode", e, false);
+         }
+       }
+       return result.get_jint();
+   } else {
+     return checked_cast<jint>(ObjectSynchronizer::FastHashCode(THREAD, obj));
+   }
  JVM_END
  
  
  JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
    Handle obj(THREAD, JNIHandles::resolve_non_null(handle));

*** 692,10 ***
--- 739,16 ---
         InstanceKlass::cast(klass)->reference_type() != REF_NONE)) {
      ResourceMark rm(THREAD);
      THROW_MSG_NULL(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
    }
  
+   if (klass->is_inline_klass()) {
+     // Value instances have no identity, so return the current instance instead of allocating a new one
+     // Value classes cannot have finalizers, so the method can return immediately
+     return JNIHandles::make_local(THREAD, obj());
+   }
+ 
    // Make shallow object copy
    const size_t size = obj->size();
    oop new_obj_oop = nullptr;
    if (obj->is_array()) {
      const int length = ((arrayOop)obj())->length();

*** 1202,24 ***
  
    Klass* klass = java_lang_Class::as_Klass(mirror);
    // Figure size of result array
    int size;
    if (klass->is_instance_klass()) {
!     size = InstanceKlass::cast(klass)->local_interfaces()->length();
    } else {
!     assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass");
      size = 2;
    }
  
    // Allocate result array
    objArrayOop r = oopFactory::new_objArray(vmClasses::Class_klass(), size, CHECK_NULL);
    objArrayHandle result (THREAD, r);
    // Fill in result
    if (klass->is_instance_klass()) {
      // Regular instance klass, fill in all local interfaces
      for (int index = 0; index < size; index++) {
!       Klass* k = InstanceKlass::cast(klass)->local_interfaces()->at(index);
        result->obj_at_put(index, k->java_mirror());
      }
    } else {
      // All arrays implement java.lang.Cloneable and java.io.Serializable
      result->obj_at_put(0, vmClasses::Cloneable_klass()->java_mirror());
--- 1255,26 ---
  
    Klass* klass = java_lang_Class::as_Klass(mirror);
    // Figure size of result array
    int size;
    if (klass->is_instance_klass()) {
!     InstanceKlass* ik = InstanceKlass::cast(klass);
+     size = ik->local_interfaces()->length();
    } else {
!     assert(klass->is_objArray_klass() || klass->is_typeArray_klass() || klass->is_flatArray_klass(), "Illegal mirror klass");
      size = 2;
    }
  
    // Allocate result array
    objArrayOop r = oopFactory::new_objArray(vmClasses::Class_klass(), size, CHECK_NULL);
    objArrayHandle result (THREAD, r);
    // Fill in result
    if (klass->is_instance_klass()) {
      // Regular instance klass, fill in all local interfaces
      for (int index = 0; index < size; index++) {
!       InstanceKlass* ik = InstanceKlass::cast(klass);
+       Klass* k = ik->local_interfaces()->at(index);
        result->obj_at_put(index, k->java_mirror());
      }
    } else {
      // All arrays implement java.lang.Cloneable and java.io.Serializable
      result->obj_at_put(0, vmClasses::Cloneable_klass()->java_mirror());

*** 1250,10 ***
--- 1305,29 ---
    }
    Klass* k = java_lang_Class::as_Klass(mirror);
    return k->is_hidden();
  JVM_END
  
+ JVM_ENTRY(jboolean, JVM_IsIdentityClass(JNIEnv *env, jclass cls))
+   oop mirror = JNIHandles::resolve_non_null(cls);
+   if (java_lang_Class::is_primitive(mirror)) {
+     return JNI_FALSE;
+   }
+   Klass* k = java_lang_Class::as_Klass(mirror);
+   if (EnableValhalla) {
+     return k->is_array_klass() || k->is_identity_class();
+   } else {
+     return k->is_interface() ? JNI_FALSE : JNI_TRUE;
+   }
+ JVM_END
+ 
+ JVM_ENTRY(jboolean, JVM_IsImplicitlyConstructibleClass(JNIEnv *env, jclass cls))
+   oop mirror = JNIHandles::resolve_non_null(cls);
+   InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
+   return ik->is_implicitly_constructible();
+ JVM_END
+ 
  
  JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls))
    oop mirror = JNIHandles::resolve_non_null(cls);
    if (mirror == nullptr) {
      THROW_(vmSymbols::java_lang_NullPointerException(), nullptr);

*** 1859,15 ***
    int num_methods = 0;
  
    // Select methods matching the criteria.
    for (int i = 0; i < methods_length; i++) {
      Method* method = methods->at(i);
!     if (want_constructor && !method->is_object_initializer()) {
        continue;
      }
      if (!want_constructor &&
!         (method->is_object_initializer() || method->is_static_initializer() ||
           method->is_overpass())) {
        continue;
      }
      if (publicOnly && !method->is_public()) {
        continue;
--- 1933,15 ---
    int num_methods = 0;
  
    // Select methods matching the criteria.
    for (int i = 0; i < methods_length; i++) {
      Method* method = methods->at(i);
!     if (want_constructor && !method->is_object_constructor()) {
        continue;
      }
      if (!want_constructor &&
!         (method->is_object_constructor() || method->is_class_initializer() ||
           method->is_overpass())) {
        continue;
      }
      if (publicOnly && !method->is_public()) {
        continue;

*** 1891,10 ***
--- 1965,11 ---
        // Otherwise should probably put a method that throws NSME
        result->obj_at_put(i, nullptr);
      } else {
        oop m;
        if (want_constructor) {
+         assert(method->is_object_constructor(), "must be");
          m = Reflection::new_constructor(method, CHECK_NULL);
        } else {
          m = Reflection::new_method(method, false, CHECK_NULL);
        }
        result->obj_at_put(i, m);

*** 2173,14 ***
    methodHandle m (THREAD, k->find_method(name, sig));
    if (m.is_null()) {
      THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
    }
    oop method;
!   if (m->is_object_initializer()) {
      method = Reflection::new_constructor(m, CHECK_NULL);
    } else {
-     // new_method accepts <clinit> as Method here
      method = Reflection::new_method(m, true, CHECK_NULL);
    }
    return JNIHandles::make_local(THREAD, method);
  }
  
--- 2248,13 ---
    methodHandle m (THREAD, k->find_method(name, sig));
    if (m.is_null()) {
      THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
    }
    oop method;
!   if (m->is_object_constructor()) {
      method = Reflection::new_constructor(m, CHECK_NULL);
    } else {
      method = Reflection::new_method(m, true, CHECK_NULL);
    }
    return JNIHandles::make_local(THREAD, method);
  }
  

*** 2448,10 ***
--- 2522,47 ---
    JvmtiVMObjectAllocEventCollector oam;
    oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL);
    return JNIHandles::make_local(THREAD, asd);
  JVM_END
  
+ // Arrays support /////////////////////////////////////////////////////////////
+ 
+ JVM_ENTRY(jboolean, JVM_ArrayIsAccessAtomic(JNIEnv *env, jclass unused, jobject array))
+   oop o = JNIHandles::resolve(array);
+   Klass* k = o->klass();
+   if ((o == nullptr) || (!k->is_array_klass())) {
+     THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+   }
+   return ArrayKlass::cast(k)->element_access_must_be_atomic();
+ JVM_END
+ 
+ JVM_ENTRY(jobject, JVM_ArrayEnsureAccessAtomic(JNIEnv *env, jclass unused, jobject array))
+   oop o = JNIHandles::resolve(array);
+   Klass* k = o->klass();
+   if ((o == nullptr) || (!k->is_array_klass())) {
+     THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+   }
+   if (k->is_flatArray_klass()) {
+     FlatArrayKlass* vk = FlatArrayKlass::cast(k);
+     if (!vk->element_access_must_be_atomic()) {
+       /**
+        * Need to decide how to implement:
+        *
+        * 1) Change to objArrayOop layout, therefore oop->klass() differs so
+        * then "<atomic>[Qfoo;" klass needs to subclass "[Qfoo;" to pass through
+        * "checkcast" & "instanceof"
+        *
+        * 2) Use extra header in the flatArrayOop to flag atomicity required and
+        * possibly per instance lock structure. Said info, could be placed in
+        * "trailer" rather than disturb the current arrayOop
+        */
+       Unimplemented();
+     }
+   }
+   return array;
+ JVM_END
+ 
  // Verification ////////////////////////////////////////////////////////////////////////////////
  
  // Reflection for the verifier /////////////////////////////////////////////////////////////////
  
  // RedefineClasses support: bug 6214132 caused verification to fail.

*** 2577,11 ***
  
  
  JVM_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index))
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
    k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
!   return InstanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS;
  JVM_END
  
  
  JVM_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index))
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
--- 2688,11 ---
  
  
  JVM_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index))
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
    k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
!   return InstanceKlass::cast(k)->field_access_flags(field_index);
  JVM_END
  
  
  JVM_ENTRY(jint, JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index))
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));

*** 2610,11 ***
  JVM_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index))
    ResourceMark rm(THREAD);
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
    k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
    Method* method = InstanceKlass::cast(k)->methods()->at(method_index);
!   return method->name() == vmSymbols::object_initializer_name();
  JVM_END
  
  
  JVM_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index))
    ResourceMark rm(THREAD);
--- 2721,11 ---
  JVM_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index))
    ResourceMark rm(THREAD);
    Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
    k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
    Method* method = InstanceKlass::cast(k)->methods()->at(method_index);
!   return method->is_object_constructor();
  JVM_END
  
  
  JVM_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index))
    ResourceMark rm(THREAD);

*** 2767,11 ***
        Symbol* name      = cp->uncached_name_ref_at(cp_index);
        Symbol* signature = cp->uncached_signature_ref_at(cp_index);
        InstanceKlass* ik = InstanceKlass::cast(k_called);
        for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
          if (fs.name() == name && fs.signature() == signature) {
!           return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS;
          }
        }
        return -1;
      }
      default:
--- 2878,11 ---
        Symbol* name      = cp->uncached_name_ref_at(cp_index);
        Symbol* signature = cp->uncached_signature_ref_at(cp_index);
        InstanceKlass* ik = InstanceKlass::cast(k_called);
        for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
          if (fs.name() == name && fs.signature() == signature) {
!           return fs.access_flags().as_short();
          }
        }
        return -1;
      }
      default:

*** 3440,10 ***
--- 3551,14 ---
  
  JVM_LEAF(jboolean, JVM_IsPreviewEnabled(void))
    return Arguments::enable_preview() ? JNI_TRUE : JNI_FALSE;
  JVM_END
  
+ JVM_LEAF(jboolean, JVM_IsValhallaEnabled(void))
+   return EnableValhalla ? JNI_TRUE : JNI_FALSE;
+ JVM_END
+ 
  JVM_LEAF(jboolean, JVM_IsContinuationsSupported(void))
    return VMContinuations ? JNI_TRUE : JNI_FALSE;
  JVM_END
  
  JVM_LEAF(jboolean, JVM_IsForeignLinkerSupported(void))

*** 3525,11 ***
  JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
    Handle method_handle;
    if (thread->stack_overflow_state()->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
      method_handle = Handle(THREAD, JNIHandles::resolve(method));
      Handle receiver(THREAD, JNIHandles::resolve(obj));
!     objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
      oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
      jobject res = JNIHandles::make_local(THREAD, result);
      if (JvmtiExport::should_post_vm_object_alloc()) {
        oop ret_type = java_lang_reflect_Method::return_type(method_handle());
        assert(ret_type != nullptr, "sanity check: ret_type oop must not be null!");
--- 3640,11 ---
  JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
    Handle method_handle;
    if (thread->stack_overflow_state()->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
      method_handle = Handle(THREAD, JNIHandles::resolve(method));
      Handle receiver(THREAD, JNIHandles::resolve(obj));
!     objArrayHandle args = oopFactory::ensure_objArray(JNIHandles::resolve(args0), CHECK_NULL);
      oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
      jobject res = JNIHandles::make_local(THREAD, result);
      if (JvmtiExport::should_post_vm_object_alloc()) {
        oop ret_type = java_lang_reflect_Method::return_type(method_handle());
        assert(ret_type != nullptr, "sanity check: ret_type oop must not be null!");

*** 3545,12 ***
    }
  JVM_END
  
  
  JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
    oop constructor_mirror = JNIHandles::resolve(c);
-   objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
    oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
    jobject res = JNIHandles::make_local(THREAD, result);
    if (JvmtiExport::should_post_vm_object_alloc()) {
      JvmtiExport::post_vm_object_alloc(thread, result);
    }
--- 3660,12 ---
    }
  JVM_END
  
  
  JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
+   objArrayHandle args = oopFactory::ensure_objArray(JNIHandles::resolve(args0), CHECK_NULL);
    oop constructor_mirror = JNIHandles::resolve(c);
    oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
    jobject res = JNIHandles::make_local(THREAD, result);
    if (JvmtiExport::should_post_vm_object_alloc()) {
      JvmtiExport::post_vm_object_alloc(thread, result);
    }
< prev index next >