--- a/src/hotspot/share/classfile/javaClasses.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/classfile/javaClasses.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -64,6 +64,7 @@
#include "runtime/safepointVerifiers.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vframe.inline.hpp"
+#include "runtime/vm_version.hpp"
#include "utilities/align.hpp"
#include "utilities/preserveException.hpp"
#include "utilities/utf8.hpp"
@@ -198,7 +199,7 @@
#if INCLUDE_CDS
void java_lang_String::serialize_offsets(SerializeClosure* f) {
STRING_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
- f->do_u4((u4*)&initialized);
+ f->do_bool(&initialized);
}
#endif
@@ -376,20 +377,24 @@
if (_to_java_string_fn == NULL) {
void *lib_handle = os::native_java_library();
- _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "NewStringPlatform"));
+ _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "JNU_NewStringPlatform"));
if (_to_java_string_fn == NULL) {
fatal("NewStringPlatform missing");
}
}
jstring js = NULL;
- { JavaThread* thread = (JavaThread*)THREAD;
- assert(thread->is_Java_thread(), "must be java thread");
+ {
+ assert(THREAD->is_Java_thread(), "must be java thread");
+ JavaThread* thread = (JavaThread*)THREAD;
HandleMark hm(thread);
ThreadToNativeFromVM ttn(thread);
js = (_to_java_string_fn)(thread->jni_environment(), str);
}
- return Handle(THREAD, JNIHandles::resolve(js));
+
+ Handle native_platform_string(THREAD, JNIHandles::resolve(js));
+ JNIHandles::destroy_local(js); // destroy local JNIHandle.
+ return native_platform_string;
}
// Converts a Java String to a native C string that can be used for
@@ -877,7 +882,7 @@
} else {
assert(Universe::is_module_initialized() ||
(ModuleEntryTable::javabase_defined() &&
- (oopDesc::equals(module(), ModuleEntryTable::javabase_moduleEntry()->module()))),
+ (module() == ModuleEntryTable::javabase_moduleEntry()->module())),
"Incorrect java.lang.Module specification while creating mirror");
set_module(mirror(), module());
}
@@ -954,7 +959,7 @@
}
// set the classLoader field in the java_lang_Class instance
- assert(oopDesc::equals(class_loader(), k->class_loader()), "should be same");
+ assert(class_loader() == k->class_loader(), "should be same");
set_class_loader(mirror(), class_loader());
// Setup indirection from klass->mirror
@@ -1509,9 +1514,9 @@
// Note: create_basic_type_mirror above initializes ak to a non-null value.
type = ArrayKlass::cast(ak)->element_type();
} else {
- assert(oopDesc::equals(java_class, Universe::void_mirror()), "only valid non-array primitive");
+ assert(java_class == Universe::void_mirror(), "only valid non-array primitive");
}
- assert(oopDesc::equals(Universe::java_mirror(type), java_class), "must be consistent");
+ assert(Universe::java_mirror(type) == java_class, "must be consistent");
return type;
}
@@ -1540,7 +1545,7 @@
int java_lang_Class::classRedefinedCount_offset = -1;
#define CLASS_FIELDS_DO(macro) \
- macro(classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false) ; \
+ macro(classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false); \
macro(_class_loader_offset, k, "classLoader", classloader_signature, false); \
macro(_component_mirror_offset, k, "componentType", class_signature, false); \
macro(_module_offset, k, "module", module_signature, false); \
@@ -1566,7 +1571,7 @@
#if INCLUDE_CDS
void java_lang_Class::serialize_offsets(SerializeClosure* f) {
- f->do_u4((u4*)&offsets_computed);
+ f->do_bool(&offsets_computed);
f->do_u4((u4*)&_init_lock_offset);
CLASS_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
@@ -1933,7 +1938,6 @@
return method != NULL && (method->constants()->version() == version);
}
-
// This class provides a simple wrapper over the internal structure of
// exception backtrace to insulate users of the backtrace from needing
// to know what it looks like.
@@ -1945,7 +1949,11 @@
typeArrayOop _methods;
typeArrayOop _bcis;
objArrayOop _mirrors;
- typeArrayOop _names; // needed to insulate method name against redefinition
+ typeArrayOop _names; // Needed to insulate method name against redefinition.
+ // This is set to a java.lang.Boolean(true) if the top frame
+ // of the backtrace is omitted because it shall be hidden.
+ // Else it is null.
+ oop _has_hidden_top_frame;
int _index;
NoSafepointVerifier _nsv;
@@ -1955,6 +1963,7 @@
trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
trace_names_offset = java_lang_Throwable::trace_names_offset,
trace_next_offset = java_lang_Throwable::trace_next_offset,
+ trace_hidden_offset = java_lang_Throwable::trace_hidden_offset,
trace_size = java_lang_Throwable::trace_size,
trace_chunk_size = java_lang_Throwable::trace_chunk_size
};
@@ -1980,11 +1989,15 @@
assert(names != NULL, "names array should be initialized in backtrace");
return names;
}
+ static oop get_has_hidden_top_frame(objArrayHandle chunk) {
+ oop hidden = chunk->obj_at(trace_hidden_offset);
+ return hidden;
+ }
public:
// constructor for new backtrace
- BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL) {
+ BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL), _has_hidden_top_frame(NULL) {
expand(CHECK);
_backtrace = Handle(THREAD, _head);
_index = 0;
@@ -1995,6 +2008,7 @@
_bcis = get_bcis(backtrace);
_mirrors = get_mirrors(backtrace);
_names = get_names(backtrace);
+ _has_hidden_top_frame = get_has_hidden_top_frame(backtrace);
assert(_methods->length() == _bcis->length() &&
_methods->length() == _mirrors->length() &&
_mirrors->length() == _names->length(),
@@ -2032,6 +2046,7 @@
new_head->obj_at_put(trace_bcis_offset, new_bcis());
new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
new_head->obj_at_put(trace_names_offset, new_names());
+ new_head->obj_at_put(trace_hidden_offset, NULL);
_head = new_head();
_methods = new_methods();
@@ -2072,6 +2087,16 @@
_index++;
}
+ void set_has_hidden_top_frame(TRAPS) {
+ if (_has_hidden_top_frame == NULL) {
+ jvalue prim;
+ prim.z = 1;
+ PauseNoSafepointVerifier pnsv(&_nsv);
+ _has_hidden_top_frame = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK);
+ _head->obj_at_put(trace_hidden_offset, _has_hidden_top_frame);
+ }
+ }
+
};
struct BacktraceElement : public StackObj {
@@ -2401,7 +2426,13 @@
}
}
if (method->is_hidden()) {
- if (skip_hidden) continue;
+ if (skip_hidden) {
+ if (total_count == 0) {
+ // The top frame will be hidden from the stack trace.
+ bt.set_has_hidden_top_frame(CHECK);
+ }
+ continue;
+ }
}
bt.push(method, bci, CHECK);
total_count++;
@@ -2518,6 +2549,37 @@
}
}
+bool java_lang_Throwable::get_top_method_and_bci(oop throwable, Method** method, int* bci) {
+ Thread* THREAD = Thread::current();
+ objArrayHandle result(THREAD, objArrayOop(backtrace(throwable)));
+ BacktraceIterator iter(result, THREAD);
+ // No backtrace available.
+ if (!iter.repeat()) return false;
+
+ // If the exception happened in a frame that has been hidden, i.e.,
+ // omitted from the back trace, we can not compute the message.
+ oop hidden = ((objArrayOop)backtrace(throwable))->obj_at(trace_hidden_offset);
+ if (hidden != NULL) {
+ return false;
+ }
+
+ // Get first backtrace element.
+ BacktraceElement bte = iter.next(THREAD);
+
+ InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(bte._mirror()));
+ assert(holder != NULL, "first element should be non-null");
+ Method* m = holder->method_with_orig_idnum(bte._method_id, bte._version);
+
+ // Original version is no longer available.
+ if (m == NULL || !version_matches(m, bte._version)) {
+ return false;
+ }
+
+ *method = m;
+ *bci = bte._bci;
+ return true;
+}
+
oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) {
// Allocate java.lang.StackTraceElement instance
InstanceKlass* k = SystemDictionary::StackTraceElement_klass();
@@ -2593,10 +2655,6 @@
source_file = NULL;
java_lang_Class::set_source_file(java_class(), source_file);
}
- if (ShowHiddenFrames) {
- source = vmSymbols::unknown_class_name();
- source_file = StringTable::intern(source, CHECK);
- }
}
java_lang_StackTraceElement::set_fileName(element(), source_file);
@@ -2634,11 +2692,7 @@
// via the previous versions list.
holder = holder->get_klass_version(version);
assert(holder != NULL, "sanity check");
- Symbol* source = holder->source_file_name();
- if (ShowHiddenFrames && source == NULL) {
- source = vmSymbols::unknown_class_name();
- }
- filename = source;
+ filename = holder->source_file_name();
line_number = Backtrace::get_line_number(method, bci);
}
}
@@ -2677,14 +2731,14 @@
Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
short version = stackFrame->short_field(_version_offset);
- short bci = stackFrame->short_field(_bci_offset);
+ int bci = stackFrame->int_field(_bci_offset);
Symbol* name = method->name();
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK);
}
#define STACKFRAMEINFO_FIELDS_DO(macro) \
macro(_memberName_offset, k, "memberName", object_signature, false); \
- macro(_bci_offset, k, "bci", short_signature, false)
+ macro(_bci_offset, k, "bci", int_signature, false)
void java_lang_StackFrameInfo::compute_offsets() {
InstanceKlass* k = SystemDictionary::StackFrameInfo_klass();
@@ -3719,14 +3773,14 @@
}
bool java_lang_invoke_MethodType::equals(oop mt1, oop mt2) {
- if (oopDesc::equals(mt1, mt2))
+ if (mt1 == mt2)
return true;
- if (!oopDesc::equals(rtype(mt1), rtype(mt2)))
+ if (rtype(mt1) != rtype(mt2))
return false;
if (ptype_count(mt1) != ptype_count(mt2))
return false;
for (int i = ptype_count(mt1) - 1; i >= 0; i--) {
- if (!oopDesc::equals(ptype(mt1, i), ptype(mt2, i)))
+ if (ptype(mt1, i) != ptype(mt2, i))
return false;
}
return true;
@@ -3940,7 +3994,7 @@
// This loop taken verbatim from ClassLoader.java:
do {
acl = parent(acl);
- if (oopDesc::equals(cl, acl)) {
+ if (cl == acl) {
return true;
}
assert(++loop_count > 0, "loop_count overflow");
@@ -3970,7 +4024,7 @@
oop cl = SystemDictionary::java_system_loader();
while(cl != NULL) {
- if (oopDesc::equals(cl, loader)) return true;
+ if (cl == loader) return true;
cl = parent(cl);
}
return false;
@@ -4034,6 +4088,7 @@
int _page_size;
bool _big_endian;
bool _use_unaligned_access;
+ int _data_cache_line_flush_size;
public:
UnsafeConstantsFixup() {
// round up values for all static final fields
@@ -4041,6 +4096,7 @@
_page_size = os::vm_page_size();
_big_endian = LITTLE_ENDIAN_ONLY(false) BIG_ENDIAN_ONLY(true);
_use_unaligned_access = UseUnalignedAccesses;
+ _data_cache_line_flush_size = (int)VM_Version::data_cache_line_flush_size();
}
void do_field(fieldDescriptor* fd) {
@@ -4057,6 +4113,8 @@
mirror->bool_field_put(fd->offset(), _big_endian);
} else if (fd->name() == vmSymbols::use_unaligned_access_name()) {
mirror->bool_field_put(fd->offset(), _use_unaligned_access);
+ } else if (fd->name() == vmSymbols::data_cache_line_flush_size_name()) {
+ mirror->int_field_put(fd->offset(), _data_cache_line_flush_size);
} else {
assert(false, "unexpected UnsafeConstants field");
}
@@ -4155,6 +4213,14 @@
int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset;
int reflect_ConstantPool::_oop_offset;
int reflect_UnsafeStaticFieldAccessorImpl::_base_offset;
+int java_lang_Integer_IntegerCache::_static_cache_offset;
+int java_lang_Long_LongCache::_static_cache_offset;
+int java_lang_Character_CharacterCache::_static_cache_offset;
+int java_lang_Short_ShortCache::_static_cache_offset;
+int java_lang_Byte_ByteCache::_static_cache_offset;
+int java_lang_Boolean::_static_TRUE_offset;
+int java_lang_Boolean::_static_FALSE_offset;
+
#define STACKTRACEELEMENT_FIELDS_DO(macro) \
@@ -4216,6 +4282,7 @@
}
void java_lang_StackFrameInfo::set_bci(oop element, int value) {
+ assert(value >= 0 && value < max_jushort, "must be a valid bci value");
element->int_field_put(_bci_offset, value);
}
@@ -4314,6 +4381,192 @@
}
#endif
+#define INTEGER_CACHE_FIELDS_DO(macro) \
+ macro(_static_cache_offset, k, "cache", java_lang_Integer_array_signature, true)
+
+void java_lang_Integer_IntegerCache::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ INTEGER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+objArrayOop java_lang_Integer_IntegerCache::cache(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return objArrayOop(base->obj_field(_static_cache_offset));
+}
+
+Symbol* java_lang_Integer_IntegerCache::symbol() {
+ return vmSymbols::java_lang_Integer_IntegerCache();
+}
+
+#if INCLUDE_CDS
+void java_lang_Integer_IntegerCache::serialize_offsets(SerializeClosure* f) {
+ INTEGER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef INTEGER_CACHE_FIELDS_DO
+
+jint java_lang_Integer::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.i;
+}
+
+#define LONG_CACHE_FIELDS_DO(macro) \
+ macro(_static_cache_offset, k, "cache", java_lang_Long_array_signature, true)
+
+void java_lang_Long_LongCache::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ LONG_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+objArrayOop java_lang_Long_LongCache::cache(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return objArrayOop(base->obj_field(_static_cache_offset));
+}
+
+Symbol* java_lang_Long_LongCache::symbol() {
+ return vmSymbols::java_lang_Long_LongCache();
+}
+
+#if INCLUDE_CDS
+void java_lang_Long_LongCache::serialize_offsets(SerializeClosure* f) {
+ LONG_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef LONG_CACHE_FIELDS_DO
+
+jlong java_lang_Long::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.j;
+}
+
+#define CHARACTER_CACHE_FIELDS_DO(macro) \
+ macro(_static_cache_offset, k, "cache", java_lang_Character_array_signature, true)
+
+void java_lang_Character_CharacterCache::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ CHARACTER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+objArrayOop java_lang_Character_CharacterCache::cache(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return objArrayOop(base->obj_field(_static_cache_offset));
+}
+
+Symbol* java_lang_Character_CharacterCache::symbol() {
+ return vmSymbols::java_lang_Character_CharacterCache();
+}
+
+#if INCLUDE_CDS
+void java_lang_Character_CharacterCache::serialize_offsets(SerializeClosure* f) {
+ CHARACTER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef CHARACTER_CACHE_FIELDS_DO
+
+jchar java_lang_Character::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.c;
+}
+
+#define SHORT_CACHE_FIELDS_DO(macro) \
+ macro(_static_cache_offset, k, "cache", java_lang_Short_array_signature, true)
+
+void java_lang_Short_ShortCache::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ SHORT_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+objArrayOop java_lang_Short_ShortCache::cache(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return objArrayOop(base->obj_field(_static_cache_offset));
+}
+
+Symbol* java_lang_Short_ShortCache::symbol() {
+ return vmSymbols::java_lang_Short_ShortCache();
+}
+
+#if INCLUDE_CDS
+void java_lang_Short_ShortCache::serialize_offsets(SerializeClosure* f) {
+ SHORT_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef SHORT_CACHE_FIELDS_DO
+
+jshort java_lang_Short::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.s;
+}
+
+#define BYTE_CACHE_FIELDS_DO(macro) \
+ macro(_static_cache_offset, k, "cache", java_lang_Byte_array_signature, true)
+
+void java_lang_Byte_ByteCache::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ BYTE_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+objArrayOop java_lang_Byte_ByteCache::cache(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return objArrayOop(base->obj_field(_static_cache_offset));
+}
+
+Symbol* java_lang_Byte_ByteCache::symbol() {
+ return vmSymbols::java_lang_Byte_ByteCache();
+}
+
+#if INCLUDE_CDS
+void java_lang_Byte_ByteCache::serialize_offsets(SerializeClosure* f) {
+ BYTE_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef BYTE_CACHE_FIELDS_DO
+
+jbyte java_lang_Byte::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.b;
+}
+#define BOOLEAN_FIELDS_DO(macro) \
+ macro(_static_TRUE_offset, k, "TRUE", java_lang_Boolean_signature, true); \
+ macro(_static_FALSE_offset, k, "FALSE", java_lang_Boolean_signature, true)
+
+
+void java_lang_Boolean::compute_offsets(InstanceKlass *k) {
+ guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized");
+ BOOLEAN_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+oop java_lang_Boolean::get_TRUE(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return base->obj_field(_static_TRUE_offset);
+}
+
+oop java_lang_Boolean::get_FALSE(InstanceKlass *ik) {
+ oop base = ik->static_field_base_raw();
+ return base->obj_field(_static_FALSE_offset);
+}
+
+Symbol* java_lang_Boolean::symbol() {
+ return vmSymbols::java_lang_Boolean();
+}
+
+#if INCLUDE_CDS
+void java_lang_Boolean::serialize_offsets(SerializeClosure* f) {
+ BOOLEAN_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+#undef BOOLEAN_CACHE_FIELDS_DO
+
+jboolean java_lang_Boolean::value(oop obj) {
+ jvalue v;
+ java_lang_boxing_object::get_value(obj, &v);
+ return v.z;
+}
+
static int member_offset(int hardcoded_offset) {
return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes();
}
@@ -4353,9 +4606,6 @@
// BASIC_JAVA_CLASSES_DO_PART1 classes (java_lang_String and java_lang_Class)
// earlier inside SystemDictionary::resolve_well_known_classes()
BASIC_JAVA_CLASSES_DO_PART2(DO_COMPUTE_OFFSETS);
-
- // generated interpreter code wants to know about the offsets we just computed:
- AbstractAssembler::update_delayed_values();
}
#if INCLUDE_CDS