mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
943 lines
44 KiB
Diff
943 lines
44 KiB
Diff
From 297f564f6af79fb824f5b4e9119f1d3d0c827fb0 Mon Sep 17 00:00:00 2001
|
|
From: Vladimir Dvorak <vladimir.dvorak@jetbrains.com>
|
|
Date: Mon, 16 Nov 2020 20:20:12 +0100
|
|
Subject: [PATCH 19/34] dcevm15 - fix java15 patch compilation issues
|
|
|
|
---
|
|
.../share/classfile/classFileParser.hpp | 8 +-
|
|
.../share/classfile/classLoaderData.cpp | 2 +-
|
|
src/hotspot/share/classfile/dictionary.hpp | 10 +-
|
|
src/hotspot/share/classfile/javaClasses.hpp | 2 +
|
|
.../share/gc/g1/g1FullGCCompactTask.cpp | 4 +-
|
|
.../share/gc/g1/g1FullGCCompactionPoint.cpp | 8 +-
|
|
.../share/gc/g1/g1FullGCPrepareTask.cpp | 4 +-
|
|
src/hotspot/share/gc/shared/dcevmSharedGC.cpp | 14 +-
|
|
src/hotspot/share/gc/shared/dcevmSharedGC.hpp | 2 +-
|
|
src/hotspot/share/gc/shared/gcConfig.cpp | 2 +-
|
|
src/hotspot/share/gc/shared/space.cpp | 4 +-
|
|
.../share/interpreter/linkResolver.cpp | 2 +-
|
|
src/hotspot/share/oops/instanceKlass.cpp | 17 ++-
|
|
src/hotspot/share/oops/instanceKlass.hpp | 1 +
|
|
src/hotspot/share/oops/klass.cpp | 8 +-
|
|
src/hotspot/share/prims/jvm.cpp | 2 +
|
|
.../prims/jvmtiEnhancedRedefineClasses.cpp | 129 +++++++++---------
|
|
.../prims/jvmtiEnhancedRedefineClasses.hpp | 14 +-
|
|
src/hotspot/share/prims/jvmtiEnv.cpp | 11 +-
|
|
.../share/prims/jvmtiRedefineClasses.cpp | 1 +
|
|
src/hotspot/share/prims/methodHandles.hpp | 3 +
|
|
src/hotspot/share/runtime/arguments.cpp | 22 +--
|
|
src/hotspot/share/runtime/mutexLocker.cpp | 2 +-
|
|
23 files changed, 159 insertions(+), 113 deletions(-)
|
|
|
|
diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp
|
|
index e5761e61767..0d266b9047e 100644
|
|
--- a/src/hotspot/share/classfile/classFileParser.hpp
|
|
+++ b/src/hotspot/share/classfile/classFileParser.hpp
|
|
@@ -150,9 +150,6 @@ class ClassFileParser {
|
|
const intArray* _method_ordering;
|
|
GrowableArray<Method*>* _all_mirandas;
|
|
|
|
- // Enhanced class redefinition
|
|
- const bool _pick_newest;
|
|
-
|
|
enum { fixed_buffer_size = 128 };
|
|
u_char _linenumbertable_buffer[fixed_buffer_size];
|
|
|
|
@@ -206,6 +203,9 @@ class ClassFileParser {
|
|
bool _has_vanilla_constructor;
|
|
int _max_bootstrap_specifier_index; // detects BSS values
|
|
|
|
+ // (DCEVM) Enhanced class redefinition
|
|
+ const bool _pick_newest;
|
|
+
|
|
void parse_stream(const ClassFileStream* const stream, TRAPS);
|
|
|
|
void mangle_hidden_class_name(InstanceKlass* const ik);
|
|
@@ -582,7 +582,7 @@ class ClassFileParser {
|
|
ClassLoaderData* loader_data() const { return _loader_data; }
|
|
const Symbol* class_name() const { return _class_name; }
|
|
const InstanceKlass* super_klass() const { return _super_klass; }
|
|
- Array<Klass*>* local_interfaces() const { return _local_interfaces; }
|
|
+ Array<InstanceKlass*>* local_interfaces() const { return _local_interfaces; }
|
|
|
|
ReferenceType reference_type() const { return _rt; }
|
|
AccessFlags access_flags() const { return _access_flags; }
|
|
diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp
|
|
index 4d64c6b454a..aadcd50ef4a 100644
|
|
--- a/src/hotspot/share/classfile/classLoaderData.cpp
|
|
+++ b/src/hotspot/share/classfile/classLoaderData.cpp
|
|
@@ -597,7 +597,7 @@ void ClassLoaderData::exchange_holders(ClassLoaderData* cld) {
|
|
oop holder_oop = _holder.peek();
|
|
_holder.replace(cld->_holder.peek());
|
|
cld->_holder.replace(holder_oop);
|
|
- WeakHandle<vm_class_loader_data> exchange = _holder;
|
|
+ WeakHandle<vm_weak_data> exchange = _holder;
|
|
_holder = cld->_holder;
|
|
cld->_holder = exchange;
|
|
}
|
|
diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp
|
|
index 114a983e783..a50f4ff84d2 100644
|
|
--- a/src/hotspot/share/classfile/dictionary.hpp
|
|
+++ b/src/hotspot/share/classfile/dictionary.hpp
|
|
@@ -84,6 +84,11 @@ public:
|
|
void print_on(outputStream* st) const;
|
|
void verify();
|
|
|
|
+ // (DCEVM) Enhanced class redefinition
|
|
+ bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass);
|
|
+
|
|
+ void rollback_redefinition();
|
|
+
|
|
private:
|
|
DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass);
|
|
|
|
@@ -106,11 +111,6 @@ public:
|
|
|
|
void free_entry(DictionaryEntry* entry);
|
|
|
|
- // Enhanced class redefinition
|
|
- bool update_klass(unsigned int hash, Symbol* name, ClassLoaderData* loader_data, InstanceKlass* k, InstanceKlass* old_klass);
|
|
-
|
|
- void rollback_redefinition();
|
|
-
|
|
// (DCEVM) return old class if redefining in AllowEnhancedClassRedefinition, otherwise return "k"
|
|
static InstanceKlass* old_if_redefined(InstanceKlass* k) {
|
|
return (k != NULL && k->is_redefining()) ? ((InstanceKlass* )k->old_version()) : k;
|
|
diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp
|
|
index a68c5139151..9abf2e1d105 100644
|
|
--- a/src/hotspot/share/classfile/javaClasses.hpp
|
|
+++ b/src/hotspot/share/classfile/javaClasses.hpp
|
|
@@ -255,7 +255,9 @@ class java_lang_Class : AllStatic {
|
|
static void set_init_lock(oop java_class, oop init_lock);
|
|
static void set_protection_domain(oop java_class, oop protection_domain);
|
|
static void set_class_loader(oop java_class, oop class_loader);
|
|
+ public: // DCEVM
|
|
static void set_component_mirror(oop java_class, oop comp_mirror);
|
|
+ private:
|
|
static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain,
|
|
Handle classData, TRAPS);
|
|
static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS);
|
|
diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
|
index f70f4606dc8..a22ed48560d 100644
|
|
--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
|
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp
|
|
@@ -157,14 +157,14 @@ void G1FullGCCompactTask::serial_compaction_dcevm() {
|
|
|
|
size_t G1FullGCCompactTask::G1CompactRegionClosureDcevm::apply(oop obj) {
|
|
size_t size = obj->size();
|
|
- HeapWord* destination = (HeapWord*)obj->forwardee();
|
|
+ HeapWord* destination = cast_from_oop<HeapWord*>(obj->forwardee());
|
|
if (destination == NULL) {
|
|
// Object not moving
|
|
return size;
|
|
}
|
|
|
|
// copy object and reinit its mark
|
|
- HeapWord* obj_addr = (HeapWord*) obj;
|
|
+ HeapWord* obj_addr = cast_from_oop<HeapWord*>(obj);
|
|
|
|
if (!_rescue_oops_it->at_end() && **_rescue_oops_it == obj_addr) {
|
|
++(*_rescue_oops_it);
|
|
diff --git a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
|
index 1e49571c999..755935a2c91 100644
|
|
--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
|
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp
|
|
@@ -174,7 +174,7 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_
|
|
assert(_current_region != NULL, "Must have been initialized");
|
|
|
|
// Store a forwarding pointer if the object should be moved.
|
|
- if ((HeapWord*)object != _compaction_top || force_forward) {
|
|
+ if (cast_from_oop<HeapWord*>(object) != _compaction_top || force_forward) {
|
|
object->forward_to(oop(_compaction_top));
|
|
} else {
|
|
if (object->forwardee() != NULL) {
|
|
@@ -188,11 +188,11 @@ void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_
|
|
} else {
|
|
// Make sure object has the correct mark-word set or that it will be
|
|
// fixed when restoring the preserved marks.
|
|
- assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark
|
|
- object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet
|
|
+ assert(object->mark_raw() == markWord::prototype_for_klass(object->klass()) || // Correct mark
|
|
+ object->mark_must_be_preserved() || // Will be restored by PreservedMarksSet
|
|
(UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking
|
|
"should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT,
|
|
- p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object)));
|
|
+ p2i(object), object->mark_raw().value(), markWord::prototype_for_klass(object->klass()).value());
|
|
}
|
|
assert(object->forwardee() == NULL, "should be forwarded to NULL");
|
|
}
|
|
diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
|
index a45681b60cf..2f06b9617e4 100644
|
|
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
|
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
|
|
@@ -269,7 +269,7 @@ size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::apply(oop object)
|
|
HeapWord* compact_top = _cp->forward_compact_top(forward_size);
|
|
|
|
if (compact_top == NULL || must_rescue(object, oop(compact_top))) {
|
|
- _cp->rescued_oops()->append((HeapWord*)object);
|
|
+ _cp->rescued_oops()->append(cast_from_oop<HeapWord*>(object));
|
|
} else {
|
|
_cp->forward_dcevm(object, forward_size, (size != forward_size));
|
|
}
|
|
@@ -295,7 +295,7 @@ bool G1FullGCPrepareTask::G1PrepareCompactLiveClosureDcevm::must_rescue(oop old_
|
|
int new_size = old_obj->size_given_klass(oop(old_obj)->klass()->new_version());
|
|
int original_size = old_obj->size();
|
|
|
|
- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size);
|
|
+ bool overlap = (cast_from_oop<HeapWord*>(old_obj) + original_size < cast_from_oop<HeapWord*>(new_obj) + new_size);
|
|
|
|
return overlap;
|
|
}
|
|
diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
|
index 803e645f843..3dee097f1d3 100644
|
|
--- a/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
|
+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.cpp
|
|
@@ -58,10 +58,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_
|
|
DcevmSharedGC::update_fields(rescued_obj, new_obj);
|
|
} else {
|
|
rescued_obj->set_klass(new_klass);
|
|
- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size);
|
|
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(new_obj), size);
|
|
}
|
|
} else {
|
|
- Copy::aligned_disjoint_words((HeapWord*)rescued_obj, (HeapWord*)new_obj, size);
|
|
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(rescued_obj), cast_from_oop<HeapWord*>(new_obj), size);
|
|
}
|
|
|
|
new_obj->init_mark_raw();
|
|
@@ -111,11 +111,11 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
|
|
|
// Save object somewhere, there is an overlap in fields
|
|
if (new_klass_oop->is_copying_backwards()) {
|
|
- if (((HeapWord *)q >= (HeapWord *)new_location && (HeapWord *)q < (HeapWord *)new_location + new_size) ||
|
|
- ((HeapWord *)new_location >= (HeapWord *)q && (HeapWord *)new_location < (HeapWord *)q + size)) {
|
|
+ if ((cast_from_oop<HeapWord*>(q) >= cast_from_oop<HeapWord*>(new_location) && cast_from_oop<HeapWord*>(q) < cast_from_oop<HeapWord*>(new_location) + new_size) ||
|
|
+ (cast_from_oop<HeapWord*>(new_location) >= cast_from_oop<HeapWord*>(q) && cast_from_oop<HeapWord*>(new_location) < cast_from_oop<HeapWord*>(q) + size)) {
|
|
tmp = NEW_RESOURCE_ARRAY(HeapWord, size);
|
|
q = (oop) tmp;
|
|
- Copy::aligned_disjoint_words((HeapWord*)tmp_obj, (HeapWord*)q, size);
|
|
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(tmp_obj), cast_from_oop<HeapWord*>(q), size);
|
|
}
|
|
}
|
|
|
|
@@ -131,13 +131,13 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
|
|
|
void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) {
|
|
assert(cur != NULL, "just checking");
|
|
- char* to = (char*)(HeapWord*)new_location;
|
|
+ char* to = (char*)cast_from_oop<HeapWord*>(new_location);
|
|
while (*cur != 0) {
|
|
int size = *cur;
|
|
if (size > 0) {
|
|
cur++;
|
|
int offset = *cur;
|
|
- HeapWord* from = (HeapWord*)(((char *)(HeapWord*)tmp_obj) + offset);
|
|
+ HeapWord* from = (HeapWord*)(((char *)cast_from_oop<HeapWord*>(tmp_obj)) + offset);
|
|
if (size == HeapWordSize) {
|
|
*((HeapWord*)to) = *from;
|
|
} else if (size == HeapWordSize * 2) {
|
|
diff --git a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
|
index e2ef0171fb2..a4e27e00280 100644
|
|
--- a/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
|
+++ b/src/hotspot/share/gc/shared/dcevmSharedGC.hpp
|
|
@@ -29,7 +29,7 @@
|
|
#include "gc/shared/genOopClosures.hpp"
|
|
#include "gc/shared/taskqueue.hpp"
|
|
#include "memory/iterator.hpp"
|
|
-#include "oops/markOop.hpp"
|
|
+#include "oops/markWord.hpp"
|
|
#include "oops/oop.hpp"
|
|
#include "runtime/timer.hpp"
|
|
#include "utilities/growableArray.hpp"
|
|
diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp
|
|
index f01d64d1434..5c1a09390f1 100644
|
|
--- a/src/hotspot/share/gc/shared/gcConfig.cpp
|
|
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp
|
|
@@ -100,7 +100,7 @@ void GCConfig::fail_if_non_included_gc_is_selected() {
|
|
void GCConfig::select_gc_ergonomically() {
|
|
if (AllowEnhancedClassRedefinition && !UseG1GC) {
|
|
// Enhanced class redefinition only supports serial GC at the moment
|
|
- FLAG_SET_ERGO(bool, UseSerialGC, true);
|
|
+ FLAG_SET_ERGO(UseSerialGC, true);
|
|
} else if (os::is_server_class_machine()) {
|
|
#if INCLUDE_G1GC
|
|
FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true);
|
|
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
|
|
index 9772c32c42e..e8e3d7884c2 100644
|
|
--- a/src/hotspot/share/gc/shared/space.cpp
|
|
+++ b/src/hotspot/share/gc/shared/space.cpp
|
|
@@ -440,7 +440,7 @@ int CompactibleSpace::space_index(oop obj) {
|
|
index++;
|
|
}
|
|
|
|
- tty->print_cr("could not compute space_index for %08xh", (HeapWord*)obj);
|
|
+ tty->print_cr("could not compute space_index for %08xh", cast_from_oop<HeapWord*>(obj));
|
|
index = 0;
|
|
|
|
Generation* gen = heap->old_gen();
|
|
@@ -485,7 +485,7 @@ bool CompactibleSpace::must_rescue(oop old_obj, oop new_obj) {
|
|
bool new_in_tenured = tenured_gen->is_in_reserved(new_obj);
|
|
if (old_in_tenured == new_in_tenured) {
|
|
// Rescue if object may overlap with a higher memory address.
|
|
- bool overlap = ((HeapWord*)old_obj + original_size < (HeapWord*)new_obj + new_size);
|
|
+ bool overlap = (cast_from_oop<HeapWord*>(old_obj) + original_size < cast_from_oop<HeapWord*>(new_obj) + new_size);
|
|
if (old_in_tenured) {
|
|
// Old and new address are in same space, so just compare the address.
|
|
// Must rescue if object moves towards the top of the space.
|
|
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
|
|
index b2f24ddbeda..9daeeb70b34 100644
|
|
--- a/src/hotspot/share/interpreter/linkResolver.cpp
|
|
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
|
|
@@ -1031,7 +1031,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
|
assert(m != NULL, "information about the current method must be available for 'put' bytecodes");
|
|
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
|
|
fd.is_static() &&
|
|
- !(m()->is_static_initializer() || m()->name() == vmSymbols::ha_class_initializer_name()));
|
|
+ !(m->is_static_initializer() || m->name() == vmSymbols::ha_class_initializer_name()));
|
|
bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
|
|
!fd.is_static() &&
|
|
!m->is_object_initializer());
|
|
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
|
index f8e60941046..5e40d78a87e 100644
|
|
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
|
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
|
@@ -1316,7 +1316,7 @@ void InstanceKlass::init_implementor() {
|
|
// (DCEVM) - init_implementor() for dcevm
|
|
void InstanceKlass::init_implementor_from_redefine() {
|
|
assert(is_interface(), "not interface");
|
|
- Klass** addr = adr_implementor();
|
|
+ Klass* volatile* addr = adr_implementor();
|
|
assert(addr != NULL, "null addr");
|
|
if (addr != NULL) {
|
|
*addr = NULL;
|
|
@@ -1659,6 +1659,21 @@ void InstanceKlass::methods_do(void f(Method* method)) {
|
|
}
|
|
}
|
|
|
|
+void InstanceKlass::methods_do(void f(Method* method, TRAPS), TRAPS) {
|
|
+ // Methods aren't stable until they are loaded. This can be read outside
|
|
+ // a lock through the ClassLoaderData for profiling
|
|
+ if (!is_loaded()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int len = methods()->length();
|
|
+ for (int index = 0; index < len; index++) {
|
|
+ Method* m = methods()->at(index);
|
|
+ assert(m->is_method(), "must be method");
|
|
+ f(m, CHECK);
|
|
+ }
|
|
+}
|
|
+
|
|
// (DCEVM) Update information contains mapping of fields from old class to the new class.
|
|
// Info is stored on HEAP, you need to call clear_update_information to free the space.
|
|
void InstanceKlass::store_update_information(GrowableArray<int> &values) {
|
|
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
|
|
index 6ead9426728..b56d42cb177 100644
|
|
--- a/src/hotspot/share/oops/instanceKlass.hpp
|
|
+++ b/src/hotspot/share/oops/instanceKlass.hpp
|
|
@@ -1069,6 +1069,7 @@ public:
|
|
void clear_update_information();
|
|
|
|
void methods_do(void f(Method* method));
|
|
+ void methods_do(void f(Method* method, TRAPS), TRAPS);
|
|
void array_klasses_do(void f(Klass* k));
|
|
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
|
|
|
|
diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp
|
|
index 352d8f84631..88f5ec9ba4a 100644
|
|
--- a/src/hotspot/share/oops/klass.cpp
|
|
+++ b/src/hotspot/share/oops/klass.cpp
|
|
@@ -200,13 +200,13 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word
|
|
Klass::Klass(KlassID id) : _id(id),
|
|
_java_mirror(NULL),
|
|
_prototype_header(markWord::prototype()),
|
|
- _shared_class_path_index(-1),
|
|
- _new_version(NULL),
|
|
_old_version(NULL),
|
|
+ _new_version(NULL),
|
|
+ _redefinition_flags(Klass::NoRedefinition),
|
|
_is_redefining(false),
|
|
+ _update_information(NULL),
|
|
_is_copying_backwards(false),
|
|
- _redefinition_flags(Klass::NoRedefinition),
|
|
- _update_information(NULL) {
|
|
+ _shared_class_path_index(-1) {
|
|
CDS_ONLY(_shared_class_flags = 0;)
|
|
CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;)
|
|
_primary_supers[0] = this;
|
|
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
|
|
index 333b65ccfc1..13bcac352fb 100644
|
|
--- a/src/hotspot/share/prims/jvm.cpp
|
|
+++ b/src/hotspot/share/prims/jvm.cpp
|
|
@@ -1054,6 +1054,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na
|
|
class_loader,
|
|
protection_domain,
|
|
&st,
|
|
+ NULL,
|
|
CHECK_NULL);
|
|
|
|
if (log_is_enabled(Debug, class, resolve) && defined_k != NULL) {
|
|
@@ -1074,6 +1075,7 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na
|
|
class_loader,
|
|
&st,
|
|
cl_info,
|
|
+ NULL,
|
|
CHECK_NULL);
|
|
if (defined_k == NULL) {
|
|
THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a hidden class");
|
|
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
|
index 1da6661dd3e..619e3988e3a 100644
|
|
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
|
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
|
|
@@ -24,11 +24,14 @@
|
|
|
|
#include "precompiled.hpp"
|
|
#include "aot/aotLoader.hpp"
|
|
+#include "classfile/classFileParser.hpp"
|
|
#include "classfile/classFileStream.hpp"
|
|
#include "classfile/metadataOnStackMark.hpp"
|
|
#include "classfile/systemDictionary.hpp"
|
|
#include "classfile/verifier.hpp"
|
|
#include "classfile/dictionary.hpp"
|
|
+#include "classfile/classLoaderDataGraph.hpp"
|
|
+#include "interpreter/linkResolver.hpp"
|
|
#include "interpreter/oopMapCache.hpp"
|
|
#include "interpreter/rewriter.hpp"
|
|
#include "logging/logStream.hpp"
|
|
@@ -37,17 +40,22 @@
|
|
#include "memory/resourceArea.hpp"
|
|
#include "memory/iterator.inline.hpp"
|
|
#include "oops/fieldStreams.hpp"
|
|
+#include "oops/fieldStreams.inline.hpp"
|
|
#include "oops/klassVtable.hpp"
|
|
#include "oops/oop.inline.hpp"
|
|
#include "oops/constantPool.inline.hpp"
|
|
+#include "oops/metadata.hpp"
|
|
+#include "oops/methodData.hpp"
|
|
#include "prims/jvmtiImpl.hpp"
|
|
#include "prims/jvmtiClassFileReconstituter.hpp"
|
|
#include "prims/jvmtiEnhancedRedefineClasses.hpp"
|
|
#include "prims/methodComparator.hpp"
|
|
#include "prims/resolvedMethodTable.hpp"
|
|
+#include "prims/methodHandles.hpp"
|
|
#include "runtime/deoptimization.hpp"
|
|
#include "runtime/jniHandles.inline.hpp"
|
|
#include "runtime/relocator.hpp"
|
|
+#include "runtime/fieldDescriptor.hpp"
|
|
#include "runtime/fieldDescriptor.inline.hpp"
|
|
#include "utilities/bitMap.inline.hpp"
|
|
#include "prims/jvmtiThreadState.inline.hpp"
|
|
@@ -55,6 +63,8 @@
|
|
#include "oops/constantPool.inline.hpp"
|
|
#include "gc/g1/g1CollectedHeap.hpp"
|
|
#include "gc/shared/dcevmSharedGC.hpp"
|
|
+#include "gc/shared/scavengableNMethods.hpp"
|
|
+#include "ci/ciObjectFactory.hpp"
|
|
|
|
Array<Method*>* VM_EnhancedRedefineClasses::_old_methods = NULL;
|
|
Array<Method*>* VM_EnhancedRedefineClasses::_new_methods = NULL;
|
|
@@ -66,6 +76,7 @@ int VM_EnhancedRedefineClasses::_matching_methods_length = 0;
|
|
int VM_EnhancedRedefineClasses::_deleted_methods_length = 0;
|
|
int VM_EnhancedRedefineClasses::_added_methods_length = 0;
|
|
Klass* VM_EnhancedRedefineClasses::_the_class_oop = NULL;
|
|
+u8 VM_EnhancedRedefineClasses::_id_counter = 0;
|
|
|
|
//
|
|
// Create new instance of enhanced class redefiner.
|
|
@@ -88,6 +99,7 @@ VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const j
|
|
_class_load_kind = class_load_kind;
|
|
_res = JVMTI_ERROR_NONE;
|
|
_any_class_has_resolved_methods = false;
|
|
+ _id = next_id();
|
|
}
|
|
|
|
static inline InstanceKlass* get_ik(jclass def) {
|
|
@@ -211,9 +223,7 @@ class FieldCopier : public FieldClosure {
|
|
|
|
// TODO: review...
|
|
void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
|
- if (!nm->on_scavenge_root_list()) {
|
|
- CodeCache::add_scavenge_root_nmethod(nm);
|
|
- }
|
|
+ ScavengableNMethods::register_nmethod(nm);
|
|
}
|
|
|
|
void VM_EnhancedRedefineClasses::unregister_nmethod_g1(nmethod* nm) {
|
|
@@ -414,7 +424,7 @@ public:
|
|
_tmp_obj_size = size;
|
|
_tmp_obj = (oop)resource_allocate_bytes(size * HeapWordSize);
|
|
}
|
|
- Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size);
|
|
+ Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(o), cast_from_oop<HeapWord*>(_tmp_obj), size);
|
|
}
|
|
|
|
virtual void do_object(oop obj) {
|
|
@@ -505,9 +515,6 @@ void VM_EnhancedRedefineClasses::doit() {
|
|
ClearCpoolCacheAndUnpatch clear_cpool_cache(thread);
|
|
ClassLoaderDataGraph::classes_do(&clear_cpool_cache);
|
|
|
|
-
|
|
- // SystemDictionary::methods_do(fix_invoke_method);
|
|
-
|
|
// JSR-292 support
|
|
if (_any_class_has_resolved_methods) {
|
|
bool trace_name_printed = false;
|
|
@@ -564,8 +571,8 @@ void VM_EnhancedRedefineClasses::doit() {
|
|
InstanceKlass* old = InstanceKlass::cast(cur->old_version());
|
|
|
|
// Swap marks to have same hashcodes
|
|
- markOop cur_mark = cur->prototype_header();
|
|
- markOop old_mark = old->prototype_header();
|
|
+ markWord cur_mark = cur->prototype_header();
|
|
+ markWord old_mark = old->prototype_header();
|
|
cur->set_prototype_header(old_mark);
|
|
old->set_prototype_header(cur_mark);
|
|
|
|
@@ -579,14 +586,14 @@ void VM_EnhancedRedefineClasses::doit() {
|
|
// Revert pool holder for old version of klass (it was updated by one of ours closure!)
|
|
old->constants()->set_pool_holder(old);
|
|
|
|
- Klass* array_klasses = old->array_klasses();
|
|
+ ObjArrayKlass* array_klasses = old->array_klasses();
|
|
if (array_klasses != NULL) {
|
|
assert(cur->array_klasses() == NULL, "just checking");
|
|
|
|
// Transfer the array classes, otherwise we might get cast exceptions when casting array types.
|
|
// Also, set array klasses element klass.
|
|
cur->set_array_klasses(array_klasses);
|
|
- ObjArrayKlass::cast(array_klasses)->set_element_klass(cur);
|
|
+ array_klasses->set_element_klass(cur);
|
|
java_lang_Class::release_set_array_klass(cur->java_mirror(), array_klasses);
|
|
java_lang_Class::set_component_mirror(array_klasses->java_mirror(), cur->java_mirror());
|
|
}
|
|
@@ -641,11 +648,15 @@ void VM_EnhancedRedefineClasses::doit() {
|
|
//ClassLoaderDataGraph::classes_do(&clean_weak_method_links);
|
|
|
|
// Disable any dependent concurrent compilations
|
|
- SystemDictionary::notice_modification();
|
|
+ // SystemDictionary::notice_modification();
|
|
+
|
|
+ JvmtiExport::increment_redefinition_count();
|
|
|
|
// Set flag indicating that some invariants are no longer true.
|
|
// See jvmtiExport.hpp for detailed explanation.
|
|
- JvmtiExport::set_has_redefined_a_class();
|
|
+
|
|
+ // dcevm15: handled by _redefinition_count
|
|
+ // JvmtiExport::set_has_redefined_a_class();
|
|
|
|
#ifdef PRODUCT
|
|
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
|
@@ -718,7 +729,7 @@ bool VM_EnhancedRedefineClasses::is_modifiable_class(oop klass_mirror) {
|
|
}
|
|
|
|
// Cannot redefine or retransform an anonymous class.
|
|
- if (InstanceKlass::cast(k)->is_anonymous()) {
|
|
+ if (InstanceKlass::cast(k)->is_unsafe_anonymous()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
@@ -804,22 +815,30 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
|
|
|
InstanceKlass* k;
|
|
|
|
- if (InstanceKlass::cast(the_class)->is_anonymous()) {
|
|
- const InstanceKlass* host_class = the_class->host_klass();
|
|
+ if (InstanceKlass::cast(the_class)->is_unsafe_anonymous()) {
|
|
+ const InstanceKlass* host_class = the_class->unsafe_anonymous_host();
|
|
|
|
// Make sure it's the real host class, not another anonymous class.
|
|
- while (host_class != NULL && host_class->is_anonymous()) {
|
|
- host_class = host_class->host_klass();
|
|
+ while (host_class != NULL && host_class->is_unsafe_anonymous()) {
|
|
+ host_class = host_class->unsafe_anonymous_host();
|
|
}
|
|
|
|
+ ClassLoadInfo cl_info(protection_domain,
|
|
+ host_class,
|
|
+ NULL, // dynamic_nest_host
|
|
+ NULL, // cp_patches
|
|
+ Handle(), // classData
|
|
+ false, // is_hidden
|
|
+ false, // is_strong_hidden
|
|
+ true); // FIXME: check if correct. can_access_vm_annotations
|
|
+
|
|
k = SystemDictionary::parse_stream(the_class_sym,
|
|
the_class_loader,
|
|
- protection_domain,
|
|
&st,
|
|
- host_class,
|
|
+ cl_info,
|
|
the_class,
|
|
- NULL,
|
|
THREAD);
|
|
+
|
|
k->class_loader_data()->exchange_holders(the_class->class_loader_data());
|
|
the_class->class_loader_data()->inc_keep_alive();
|
|
} else {
|
|
@@ -966,7 +985,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
|
// Check interfaces
|
|
|
|
// Interfaces removed?
|
|
- Array<Klass*>* old_interfaces = the_class->transitive_interfaces();
|
|
+ Array<InstanceKlass*>* old_interfaces = the_class->transitive_interfaces();
|
|
for (i = 0; i < old_interfaces->length(); i++) {
|
|
InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i));
|
|
if (!new_class->implements_interface_any_version(old_interface)) {
|
|
@@ -976,7 +995,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
|
}
|
|
|
|
// Interfaces added?
|
|
- Array<Klass*>* new_interfaces = new_class->transitive_interfaces();
|
|
+ Array<InstanceKlass*>* new_interfaces = new_class->transitive_interfaces();
|
|
for (i = 0; i<new_interfaces->length(); i++) {
|
|
if (!the_class->implements_interface_any_version(new_interfaces->at(i))) {
|
|
result = result | Klass::ModifyClass;
|
|
@@ -1389,8 +1408,8 @@ void VM_EnhancedRedefineClasses::rollback() {
|
|
// Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp
|
|
// The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not
|
|
// do that, they assume that cache entry is resolved already.
|
|
-void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method) {
|
|
- RawBytecodeStream bcs(method);
|
|
+void VM_EnhancedRedefineClasses::unpatch_bytecode(Method* method, TRAPS) {
|
|
+ RawBytecodeStream bcs(methodHandle(THREAD, method));
|
|
Bytecodes::Code code;
|
|
Bytecodes::Code java_code;
|
|
while (!bcs.is_last_bytecode()) {
|
|
@@ -1454,11 +1473,11 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
|
HandleMark hm(_thread);
|
|
InstanceKlass *ik = InstanceKlass::cast(k);
|
|
|
|
- constantPoolHandle other_cp = constantPoolHandle(ik->constants());
|
|
+ constantPoolHandle other_cp = constantPoolHandle(_thread, ik->constants());
|
|
|
|
// Update host klass of anonymous classes (for example, produced by lambdas) to newest version.
|
|
- if (ik->is_anonymous() && ik->host_klass()->new_version() != NULL) {
|
|
- ik->set_host_klass(InstanceKlass::cast(ik->host_klass()->newest_version()));
|
|
+ if (ik->is_unsafe_anonymous() && ik->unsafe_anonymous_host()->new_version() != NULL) {
|
|
+ ik->set_unsafe_anonymous_host(InstanceKlass::cast(ik->unsafe_anonymous_host()->newest_version()));
|
|
}
|
|
|
|
// Update implementor if there is only one, in this case implementor() can reference old class
|
|
@@ -1492,7 +1511,18 @@ void VM_EnhancedRedefineClasses::ClearCpoolCacheAndUnpatch::do_klass(Klass* k) {
|
|
|
|
// If bytecode rewriting is enabled, we also need to unpatch bytecode to force resolution of zeroed entries
|
|
if (RewriteBytecodes) {
|
|
- ik->methods_do(unpatch_bytecode);
|
|
+ ik->methods_do(unpatch_bytecode, _thread);
|
|
+ }
|
|
+}
|
|
+
|
|
+u8 VM_EnhancedRedefineClasses::next_id() {
|
|
+ while (true) {
|
|
+ u8 id = _id_counter;
|
|
+ u8 next_id = id + 1;
|
|
+ u8 result = Atomic::cmpxchg(&_id_counter, id, next_id);
|
|
+ if (result == id) {
|
|
+ return next_id;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -1512,31 +1542,8 @@ void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
|
|
}
|
|
}
|
|
|
|
-void VM_EnhancedRedefineClasses::fix_invoke_method(Method* method) {
|
|
-
|
|
- constantPoolHandle other_cp = constantPoolHandle(method->constants());
|
|
-
|
|
- for (int i = 0; i < other_cp->length(); i++) {
|
|
- if (other_cp->tag_at(i).is_klass()) {
|
|
- Klass* klass = other_cp->resolved_klass_at(i);
|
|
- if (klass->new_version() != NULL) {
|
|
- // Constant pool entry points to redefined class -- update to the new version
|
|
- other_cp->klass_at_put(i, klass->newest_version());
|
|
- }
|
|
- assert(other_cp->resolved_klass_at(i)->new_version() == NULL, "Must be new klass!");
|
|
- }
|
|
- }
|
|
-
|
|
- ConstantPoolCache* cp_cache = other_cp->cache();
|
|
- if (cp_cache != NULL) {
|
|
- cp_cache->clear_entries();
|
|
- }
|
|
-
|
|
-}
|
|
-
|
|
|
|
-
|
|
-void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
|
+void VM_EnhancedRedefineClasses::update_jmethod_ids(TRAPS) {
|
|
for (int j = 0; j < _matching_methods_length; ++j) {
|
|
Method* old_method = _matching_old_methods[j];
|
|
jmethodID jmid = old_method->find_jmethod_id_or_null();
|
|
@@ -1547,10 +1554,10 @@ void VM_EnhancedRedefineClasses::update_jmethod_ids() {
|
|
|
|
if (jmid != NULL) {
|
|
// There is a jmethodID, change it to point to the new method
|
|
- methodHandle new_method_h(_matching_new_methods[j]);
|
|
+ methodHandle new_method_h(THREAD, _matching_new_methods[j]);
|
|
|
|
if (old_method->new_version() == NULL) {
|
|
- methodHandle old_method_h(_matching_old_methods[j]);
|
|
+ methodHandle old_method_h(THREAD, _matching_old_methods[j]);
|
|
jmethodID new_jmethod_id = Method::make_jmethod_id(old_method_h->method_holder()->class_loader_data(), old_method_h());
|
|
bool result = InstanceKlass::cast(old_method_h->method_holder())->update_jmethod_id(old_method_h(), new_jmethod_id);
|
|
} else {
|
|
@@ -1887,7 +1894,7 @@ void VM_EnhancedRedefineClasses::redefine_single_class(InstanceKlass* new_class_
|
|
|
|
// track number of methods that are EMCP for add_previous_version() call below
|
|
check_methods_and_mark_as_obsolete();
|
|
- update_jmethod_ids();
|
|
+ update_jmethod_ids(THREAD);
|
|
|
|
_any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods;
|
|
|
|
@@ -2119,12 +2126,12 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
|
|
|
Handle protection_domain(THREAD, klass->protection_domain());
|
|
|
|
+ ClassLoadInfo cl_info(protection_domain);
|
|
+
|
|
ClassFileParser parser(&st,
|
|
klass->name(),
|
|
klass->class_loader_data(),
|
|
- protection_domain,
|
|
- NULL, // host_klass
|
|
- NULL, // cp_patches
|
|
+ &cl_info,
|
|
ClassFileParser::INTERNAL, // publicity level
|
|
true,
|
|
THREAD);
|
|
@@ -2134,7 +2141,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
|
links.append(KlassPair(super_klass, klass));
|
|
}
|
|
|
|
- Array<Klass*>* local_interfaces = parser.local_interfaces();
|
|
+ Array<InstanceKlass*>* local_interfaces = parser.local_interfaces();
|
|
for (int j = 0; j < local_interfaces->length(); j++) {
|
|
Klass* iface = local_interfaces->at(j);
|
|
if (iface != NULL && _affected_klasses->contains(iface)) {
|
|
@@ -2157,7 +2164,7 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
|
links.append(KlassPair(super_klass, klass));
|
|
}
|
|
|
|
- Array<Klass*>* local_interfaces = klass->local_interfaces();
|
|
+ Array<InstanceKlass*>* local_interfaces = klass->local_interfaces();
|
|
for (int j = 0; j < local_interfaces->length(); j++) {
|
|
Klass* interfaceKlass = local_interfaces->at(j);
|
|
if (_affected_klasses->contains(interfaceKlass)) {
|
|
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
|
index 4c0412d343d..0066088b3b0 100644
|
|
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
|
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.hpp
|
|
@@ -32,7 +32,7 @@
|
|
#include "memory/resourceArea.hpp"
|
|
#include "oops/objArrayKlass.hpp"
|
|
#include "oops/objArrayOop.hpp"
|
|
-#include "gc/shared/vmGCOperations.hpp"
|
|
+#include "gc/shared/gcVMOperations.hpp"
|
|
#include "../../../java.base/unix/native/include/jni_md.h"
|
|
|
|
//
|
|
@@ -59,6 +59,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
|
static int _deleted_methods_length;
|
|
static int _added_methods_length;
|
|
static Klass* _the_class_oop;
|
|
+ static u8 _id_counter;
|
|
|
|
// The instance fields are used to pass information from
|
|
// doit_prologue() to doit() and doit_epilogue().
|
|
@@ -91,6 +92,9 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
|
elapsedTimer _timer_heap_iterate;
|
|
elapsedTimer _timer_heap_full_gc;
|
|
|
|
+ // Redefinition id used by JFR
|
|
+ u8 _id;
|
|
+
|
|
// These routines are roughly in call order unless otherwise noted.
|
|
|
|
// Load and link new classes (either redefined or affected by redefinition - subclass, ...)
|
|
@@ -118,15 +122,14 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
|
static void mark_as_scavengable(nmethod* nm);
|
|
static void unregister_nmethod_g1(nmethod* nm);
|
|
static void register_nmethod_g1(nmethod* nm);
|
|
- static void unpatch_bytecode(Method* method);
|
|
- static void fix_invoke_method(Method* method);
|
|
+ static void unpatch_bytecode(Method* method, TRAPS);
|
|
|
|
// Figure out which new methods match old methods in name and signature,
|
|
// which methods have been added, and which are no longer present
|
|
void compute_added_deleted_matching_methods();
|
|
|
|
// Change jmethodIDs to point to the new methods
|
|
- void update_jmethod_ids();
|
|
+ void update_jmethod_ids(TRAPS);
|
|
|
|
// marking methods as old and/or obsolete
|
|
void check_methods_and_mark_as_obsolete();
|
|
@@ -141,6 +144,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
|
|
|
void flush_dependent_code(InstanceKlass* k_h, TRAPS);
|
|
|
|
+ u8 next_id();
|
|
+
|
|
static void check_class(InstanceKlass* k_oop, TRAPS);
|
|
|
|
static void dump_methods();
|
|
@@ -181,6 +186,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
|
|
|
bool allow_nested_vm_operations() const { return true; }
|
|
jvmtiError check_error() { return _res; }
|
|
+ u8 id() { return _id; }
|
|
|
|
// Modifiable test must be shared between IsModifiableClass query
|
|
// and redefine implementation
|
|
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
|
|
index b6838ac034d..fba0f48abd7 100644
|
|
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
|
|
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
|
|
@@ -456,20 +456,23 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
|
|
|
|
EventRetransformClasses event;
|
|
jvmtiError error;
|
|
+ u8 op_id;
|
|
|
|
if (AllowEnhancedClassRedefinition) {
|
|
MutexLocker sd_mutex(EnhancedRedefineClasses_lock);
|
|
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
|
|
VMThread::execute(&op);
|
|
+ op_id = op.id();
|
|
error = (op.check_error());
|
|
} else {
|
|
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
|
|
VMThread::execute(&op);
|
|
+ op_id = op.id();
|
|
error = op.check_error();
|
|
}
|
|
if (error == JVMTI_ERROR_NONE) {
|
|
event.set_classCount(class_count);
|
|
- event.set_redefinitionId(op.id());
|
|
+ event.set_redefinitionId(op_id);
|
|
event.commit();
|
|
}
|
|
return error;
|
|
@@ -484,19 +487,23 @@ JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_de
|
|
EventRedefineClasses event;
|
|
jvmtiError error;
|
|
|
|
+ u8 op_id;
|
|
+
|
|
if (AllowEnhancedClassRedefinition) {
|
|
MutexLocker sd_mutex(EnhancedRedefineClasses_lock);
|
|
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
|
VMThread::execute(&op);
|
|
+ op_id = op.id();
|
|
error = (op.check_error());
|
|
} else {
|
|
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
|
|
VMThread::execute(&op);
|
|
+ op_id = op.id();
|
|
error = op.check_error();
|
|
}
|
|
if (error == JVMTI_ERROR_NONE) {
|
|
event.set_classCount(class_count);
|
|
- event.set_redefinitionId(op.id());
|
|
+ event.set_redefinitionId(op_id);
|
|
event.commit();
|
|
}
|
|
return error;
|
|
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
index a7840848e10..346eac7c431 100644
|
|
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
@@ -1271,6 +1271,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
|
|
the_class_loader,
|
|
&st,
|
|
cl_info,
|
|
+ NULL,
|
|
THREAD);
|
|
// Clear class_being_redefined just to be sure.
|
|
state->clear_class_being_redefined();
|
|
diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp
|
|
index 54f36202a5f..917d31efd77 100644
|
|
--- a/src/hotspot/share/prims/methodHandles.hpp
|
|
+++ b/src/hotspot/share/prims/methodHandles.hpp
|
|
@@ -180,6 +180,9 @@ public:
|
|
assert(ref_kind_is_valid(ref_kind), "");
|
|
return (ref_kind & 1) != 0;
|
|
}
|
|
+ static bool ref_kind_is_static(int ref_kind) {
|
|
+ return !ref_kind_has_receiver(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial);
|
|
+ }
|
|
|
|
static int ref_kind_to_flags(int ref_kind);
|
|
|
|
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
|
index d05a2893498..3a92b8869dc 100644
|
|
--- a/src/hotspot/share/runtime/arguments.cpp
|
|
+++ b/src/hotspot/share/runtime/arguments.cpp
|
|
@@ -2128,13 +2128,15 @@ bool Arguments::check_gc_consistency() {
|
|
// of collectors.
|
|
uint i = 0;
|
|
if (UseSerialGC) i++;
|
|
- if (UseConcMarkSweepGC) i++;
|
|
- if (UseParallelGC || UseParallelOldGC) i++;
|
|
+ if (UseParallelGC) i++;
|
|
if (UseG1GC) i++;
|
|
+ if (UseEpsilonGC) i++;
|
|
+ if (UseZGC) i++;
|
|
+ if (UseShenandoahGC) i++;
|
|
if (AllowEnhancedClassRedefinition) {
|
|
// Must use serial GC. This limitation applies because the instance size changing GC modifications
|
|
// are only built into the mark and compact algorithm.
|
|
- if ((!UseSerialGC && !UseG1GC) && i >= 1) {
|
|
+ if (!UseSerialGC && !UseG1GC && i >= 1) {
|
|
jio_fprintf(defaultStream::error_stream(),
|
|
"Must use the Serial or G1 GC with enhanced class redefinition.\n");
|
|
return false;
|
|
@@ -4494,18 +4496,18 @@ void Arguments::setup_hotswap_agent() {
|
|
|
|
// TODO: open it only for org.hotswap.agent module
|
|
// Use to access java.lang.reflect.Proxy/proxyCache
|
|
- create_numbered_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.base/java.lang=ALL-UNNAMED", addopens_count++);
|
|
// Class of field java.lang.reflect.Proxy/proxyCache
|
|
- create_numbered_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.base/jdk.internal.loader=ALL-UNNAMED", addopens_count++);
|
|
// Use to access java.io.Reader, java.io.InputStream, java.io.FileInputStream
|
|
- create_numbered_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.base/java.io=ALL-UNNAMED", addopens_count++);
|
|
// java.beans.Introspector access
|
|
- create_numbered_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.desktop/java.beans=ALL-UNNAMED", addopens_count++);
|
|
// java.beans.Introspector access
|
|
- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans=ALL-UNNAMED", addopens_count++);
|
|
// com.sun.beans.introspect.ClassInfo access
|
|
- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.introspect=ALL-UNNAMED", addopens_count++);
|
|
// com.sun.beans.introspect.util.Cache access
|
|
- create_numbered_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++);
|
|
+ create_numbered_module_property("jdk.module.addopens", "java.desktop/com.sun.beans.util=ALL-UNNAMED", addopens_count++);
|
|
|
|
}
|
|
diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp
|
|
index 6f982072909..14a3ed730fe 100644
|
|
--- a/src/hotspot/share/runtime/mutexLocker.cpp
|
|
+++ b/src/hotspot/share/runtime/mutexLocker.cpp
|
|
@@ -287,7 +287,7 @@ void mutex_init() {
|
|
def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never);
|
|
def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never);
|
|
def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always);
|
|
- def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, Monitor::_safepoint_check_always); // for ensuring that class redefinition is not done in parallel
|
|
+ def(EnhancedRedefineClasses_lock , PaddedMutex , nonleaf+7, false, _safepoint_check_always); // for ensuring that class redefinition is not done in parallel
|
|
def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions
|
|
def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always);
|
|
|
|
--
|
|
2.23.0
|
|
|