diff -r 6f9be7f87b96 make/Makefile --- a/make/Makefile Fri Aug 09 01:32:48 2013 -0700 +++ b/make/Makefile Fri Aug 16 16:12:06 2013 -0700 @@ -267,11 +267,11 @@ generic_export: $(EXPORT_LIST) export_product: $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export export_fastdebug: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export export_debug: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export export_optimized: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export export_product_jdk:: $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export diff -r 6f9be7f87b96 make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Fri Aug 09 01:32:48 2013 -0700 +++ b/make/bsd/makefiles/vm.make Fri Aug 16 16:12:06 2013 -0700 @@ -341,7 +341,7 @@ include $(MAKEFILES_DIR)/saproc.make ifeq ($(OS_VENDOR), Darwin) $(LIBJVM).dSYM: $(LIBJVM) - dsymutil $(LIBJVM) +# dsymutil $(LIBJVM) # no libjvm_db for macosx build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM diff -r 6f9be7f87b96 src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/classfile/defaultMethods.cpp Fri Aug 16 16:12:06 2013 -0700 @@ -1316,7 +1316,7 @@ Method* DefaultMethods::find_super_defau return target; } -#ifndef PRODUCT +#ifdef ASSERT // Return true is broad type is a covariant return of narrow type static bool covariant_return_type(BasicType narrow, BasicType broad) { if (narrow == broad) { @@ -1327,7 +1327,7 @@ static bool covariant_return_type(BasicT } return false; } -#endif // ndef PRODUCT +#endif static int assemble_redirect( BytecodeConstantPool* cp, BytecodeBuffer* buffer, diff -r 6f9be7f87b96 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Aug 16 16:12:06 2013 -0700 @@ -2993,6 +2993,28 @@ bool java_lang_System::has_security_mana } } + +// Support for java.lang.Enum + +bool java_lang_Enum::initialized = false; +int java_lang_Enum::ordinal_offset; + +void java_lang_Enum::compute_offsets() { + assert(!initialized, "offsets should be initialized only once"); + + Klass* k = SystemDictionary::Enum_klass(); + compute_offset(ordinal_offset, k, vmSymbols::ordinal_name(), vmSymbols::int_signature()); + + initialized = true; +} + +int java_lang_Enum::ordinal(oop obj) { + assert(initialized, "must be initialized"); + assert(is_instance(obj), "obj must be oop"); + return obj->int_field(ordinal_offset); +} + + int java_lang_Class::_klass_offset; int java_lang_Class::_array_klass_offset; int java_lang_Class::_oop_size_offset; @@ -3201,6 +3223,7 @@ void JavaClasses::compute_hard_coded_off void JavaClasses::compute_offsets() { // java_lang_Class::compute_offsets was called earlier in bootstrap java_lang_ClassLoader::compute_offsets(); + java_lang_Enum::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableInvokeDynamic) { diff -r 6f9be7f87b96 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Aug 16 16:12:06 2013 -0700 @@ -1255,6 +1255,29 @@ class java_lang_System : AllStatic { }; +// Interface to java.lang.Enum objects + +class java_lang_Enum : AllStatic { + private: + static bool initialized; + static int ordinal_offset; + + public: + static void compute_offsets(); + + // Getters + static int ordinal(oop obj); + + // Testing + static bool is_instance(oop obj) { + return obj != NULL && obj->klass()->is_subclass_of(SystemDictionary::Enum_klass()); + } + + // Debugging + friend class JavaClasses; +}; + + // Interface to java.lang.StackTraceElement objects class java_lang_StackTraceElement: AllStatic { diff -r 6f9be7f87b96 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Aug 16 16:12:06 2013 -0700 @@ -101,6 +101,7 @@ class SymbolPropertyTable; do_klass(Class_klass, java_lang_Class, Pre ) \ do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \ do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \ + do_klass(Enum_klass, java_lang_Enum, Pre ) \ do_klass(Serializable_klass, java_io_Serializable, Pre ) \ do_klass(System_klass, java_lang_System, Pre ) \ do_klass(Throwable_klass, java_lang_Throwable, Pre ) \ diff -r 6f9be7f87b96 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Aug 16 16:12:06 2013 -0700 @@ -60,6 +60,7 @@ template(java_lang_ClassLoader, "java/lang/ClassLoader") \ template(java_lang_ClassLoader_NativeLibrary, "java/lang/ClassLoader\x024NativeLibrary") \ template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \ + template(java_lang_Enum, "java/lang/Enum") \ template(java_lang_Boolean, "java/lang/Boolean") \ template(java_lang_Character, "java/lang/Character") \ template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \ @@ -394,6 +395,7 @@ template(signers_name, "signers_name") \ template(loader_data_name, "loader_data") \ template(dependencies_name, "dependencies") \ + template(ordinal_name, "ordinal") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ diff -r 6f9be7f87b96 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Fri Aug 09 01:32:48 2013 -0700 +++ b/src/share/vm/prims/unsafe.cpp Fri Aug 16 16:12:06 2013 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" @@ -168,37 +169,20 @@ jint Unsafe_invocation_key_to_method_slo oop p = JNIHandles::resolve(obj); \ OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); -// Macros for oops that check UseCompressedOops - -#define GET_OOP_FIELD(obj, offset, v) \ - oop p = JNIHandles::resolve(obj); \ - oop v; \ - if (UseCompressedOops) { \ - narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \ - v = oopDesc::decode_heap_oop(n); \ - } else { \ - v = *(oop*)index_oop_from_field_offset_long(p, offset); \ - } - // Get/SetObject must be special-cased, since it works with handles. -// The xxx140 variants for backward compatibility do not allow a full-width offset. -UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) - UnsafeWrapper("Unsafe_GetObject"); - if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); - GET_OOP_FIELD(obj, offset, v) - jobject ret = JNIHandles::make_local(env, v); +static void referent_g1_barrier(jobject obj, jlong offset, jobject ret) { #if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference - // object. If G1 is enabled then we need to register a non-null + // object. If G1 is enabled then we need to register non-null // referent with the SATB barrier. if (UseG1GC) { bool needs_barrier = false; if (ret != NULL) { - if (offset == java_lang_ref_Reference::referent_offset) { - oop o = JNIHandles::resolve_non_null(obj); + if (offset == java_lang_ref_Reference::referent_offset && obj != NULL) { + oop o = JNIHandles::resolve(obj); Klass* k = o->klass(); if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); @@ -212,7 +196,25 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject14 G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // INCLUDE_ALL_GCS +#endif +} + +// The xxx140 variants for backward compatibility do not allow a full-width offset. +UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) + UnsafeWrapper("Unsafe_GetObject"); + if (obj == NULL) { + THROW_0(vmSymbols::java_lang_NullPointerException()); + } + oop p = JNIHandles::resolve(obj); + oop v; + if (UseCompressedOops) { + narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); + v = oopDesc::decode_heap_oop(n); + } else { + v = *(oop*)index_oop_from_field_offset_long(p, offset); + } + jobject ret = JNIHandles::make_local(env, v); + referent_g1_barrier(obj, offset, ret); return ret; UNSAFE_END @@ -220,7 +222,6 @@ UNSAFE_ENTRY(void, Unsafe_SetObject140(J UnsafeWrapper("Unsafe_SetObject"); if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException()); oop x = JNIHandles::resolve(x_h); - //SET_FIELD(obj, offset, oop, x); oop p = JNIHandles::resolve(obj); if (UseCompressedOops) { if (x != NULL) { @@ -245,32 +246,16 @@ UNSAFE_END // That is, it should be in the range [0, MAX_OBJECT_SIZE]. UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetObject"); - GET_OOP_FIELD(obj, offset, v) + oop p = JNIHandles::resolve(obj); + oop v; + if (UseCompressedOops) { + narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); + v = oopDesc::decode_heap_oop(n); + } else { + v = *(oop*)index_oop_from_field_offset_long(p, offset); + } jobject ret = JNIHandles::make_local(env, v); -#if INCLUDE_ALL_GCS - // We could be accessing the referent field in a reference - // object. If G1 is enabled then we need to register non-null - // referent with the SATB barrier. - if (UseG1GC) { - bool needs_barrier = false; - - if (ret != NULL) { - if (offset == java_lang_ref_Reference::referent_offset && obj != NULL) { - oop o = JNIHandles::resolve(obj); - Klass* k = o->klass(); - if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { - assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); - needs_barrier = true; - } - } - } - - if (needs_barrier) { - oop referent = JNIHandles::resolve(ret); - G1SATBCardTableModRefBS::enqueue(referent); - } - } -#endif // INCLUDE_ALL_GCS + referent_g1_barrier(obj, offset, ret); return ret; UNSAFE_END @@ -314,6 +299,129 @@ UNSAFE_ENTRY(void, Unsafe_SetObjectVolat OrderAccess::fence(); UNSAFE_END +class StorageMode { +public: + static int DEFAULT; + static int UNCOMPRESSED_OOP; + static int COMPRESSED_OOP; + static int UNCOMPRESSED_KLASS; + static int COMPRESSED_KLASS; +}; + +int StorageMode::DEFAULT = -1; +int StorageMode::UNCOMPRESSED_OOP = -1; +int StorageMode::COMPRESSED_OOP = -1; +int StorageMode::UNCOMPRESSED_KLASS = -1; +int StorageMode::COMPRESSED_KLASS = -1; + +UNSAFE_ENTRY(void, Unsafe_setStorageModeConstant(JNIEnv* env, jobject cls, jstring name_h, jint ordinal)) { + ThreadToNativeFromVM ttnfv(thread); + oop name_oop = JNIHandles::resolve(name_h); + char* name = java_lang_String::as_utf8_string(name_oop); + + if (strcmp("DEFAULT", name) == 0) { + StorageMode::DEFAULT = ordinal; + } else if (strcmp("UNCOMPRESSED_OOP", name) == 0) { + StorageMode::UNCOMPRESSED_OOP = ordinal; + } else if (strcmp("COMPRESSED_OOP", name) == 0) { + StorageMode::COMPRESSED_OOP = ordinal; + } else if (strcmp("UNCOMPRESSED_KLASS", name) == 0) { + StorageMode::UNCOMPRESSED_KLASS = ordinal; + } else if (strcmp("COMPRESSED_KLASS", name) == 0) { + StorageMode::COMPRESSED_KLASS = ordinal; + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg_res("storage mode %s", name)); + } +} +UNSAFE_END + +UNSAFE_ENTRY(jobject, Unsafe_GetObjectWithStorageMode(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jobject mode_h)) + UnsafeWrapper("Unsafe_GetObjectWithStorageMode"); + oop p = JNIHandles::resolve(obj); + oop mode_oop = JNIHandles::resolve(mode_h); + int mode = mode_oop == NULL ? -2 : java_lang_Enum::ordinal(mode_oop); + oop v; + + if (mode == StorageMode::DEFAULT) { + if (UseCompressedOops) { + narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); + v = oopDesc::decode_heap_oop(n); + } else { + v = *(oop*)index_oop_from_field_offset_long(p, offset); + } + } else if (mode == StorageMode::UNCOMPRESSED_OOP) { + v = *(oop*)index_oop_from_field_offset_long(p, offset); + } else if (mode == StorageMode::COMPRESSED_OOP) { + narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); + v = oopDesc::decode_heap_oop(n); + } else { + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), err_msg_res("storage mode %d", mode)); + } + jobject ret = JNIHandles::make_local(env, v); + + referent_g1_barrier(obj, offset, ret); + return ret; +UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetObjectWithStorageMode(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h, jobject mode_h)) + UnsafeWrapper("Unsafe_SetObjectWithStorageMode"); + oop p = JNIHandles::resolve(obj); + oop x = JNIHandles::resolve(x_h); + oop mode_oop = JNIHandles::resolve(mode_h); + int mode = mode_oop == NULL ? -2 : java_lang_Enum::ordinal(mode_oop); + + if (mode == StorageMode::DEFAULT) { + if (UseCompressedOops) { + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } + } else if (mode == StorageMode::UNCOMPRESSED_OOP) { + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } else if (mode == StorageMode::COMPRESSED_OOP) { + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg_res("storage mode %d", mode)); + } +UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_GetMetadataWithStorageMode(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jobject mode_h)) + UnsafeWrapper("Unsafe_GetMetadataWithStorageMode"); + oop p = JNIHandles::resolve(obj); + oop mode_oop = JNIHandles::resolve(mode_h); + int mode = mode_oop == NULL ? -2 : java_lang_Enum::ordinal(mode_oop); + Klass* v; + + if (mode == StorageMode::UNCOMPRESSED_KLASS) { + v = *((Klass**) index_oop_from_field_offset_long(p, offset)); + } else if (mode == StorageMode::COMPRESSED_KLASS) { + narrowOop n = *((narrowOop*) index_oop_from_field_offset_long(p, offset)); + v = oopDesc::decode_klass(n); + } else { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg_res("storage mode %d", mode)); + } + jlong ret = (jlong) v; + + return ret; +UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetMetadataWithStorageMode(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x, jobject mode_h)) + UnsafeWrapper("Unsafe_SetMetadataWithStorageMode"); + oop p = JNIHandles::resolve(obj); + oop mode_oop = JNIHandles::resolve(mode_h); + int mode = mode_oop == NULL ? -2 : java_lang_Enum::ordinal(mode_oop); + + if (mode == StorageMode::UNCOMPRESSED_KLASS) { + Klass** addr = (Klass**) index_oop_from_field_offset_long(p, offset); + *addr = (Klass*) x; + } else if (mode == StorageMode::COMPRESSED_KLASS) { + narrowOop* addr = (narrowOop*) index_oop_from_field_offset_long(p, offset); + *addr = oopDesc::encode_klass((Klass*) x); + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg_res("storage mode %d", mode)); + } +UNSAFE_END + #ifndef SUPPORTS_NATIVE_CX8 // Keep old code for platforms which may not have atomic jlong (8 bytes) instructions @@ -1649,6 +1757,14 @@ JNINativeMethod fence_methods[] = { {CC"fullFence", CC"()V", FN_PTR(Unsafe_FullFence)}, }; +static JNINativeMethod memory_access_with_storage_mode[] = { + {CC"setStorageModeConstant", CC"(Ljava/lang/String;I)V", FN_PTR(Unsafe_setStorageModeConstant)}, + {CC"getObject", CC"("OBJ"JLsun/misc/Unsafe$StorageMode;)"OBJ"", FN_PTR(Unsafe_GetObjectWithStorageMode)}, + {CC"putObject", CC"("OBJ"J"OBJ"Lsun/misc/Unsafe$StorageMode;)V", FN_PTR(Unsafe_SetObjectWithStorageMode)}, + {CC"getMetadata", CC"("OBJ"JLsun/misc/Unsafe$StorageMode;)J", FN_PTR(Unsafe_GetMetadataWithStorageMode)}, + {CC"putMetadata", CC"("OBJ"JJLsun/misc/Unsafe$StorageMode;)V", FN_PTR(Unsafe_SetMetadataWithStorageMode)}, +}; + #undef CC #undef FN_PTR @@ -1748,5 +1864,8 @@ JVM_ENTRY(void, JVM_RegisterUnsafeMethod // Fence methods register_natives("1.8 fence methods", env, unsafecls, fence_methods, sizeof(fence_methods)/sizeof(JNINativeMethod)); + + // Memory access with storage mode + register_natives("1.8 memory access with storage mode", env, unsafecls, memory_access_with_storage_mode, sizeof(memory_access_with_storage_mode)/sizeof(JNINativeMethod)); } JVM_END