mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-04 10:46:27 +00:00
8192025: Less referential references
Reviewed-by: coleenp, eosterlund, mchung, ahgross, rhalade
This commit is contained in:
parent
9714f829c9
commit
1ac19a3166
@ -3556,6 +3556,34 @@ void java_lang_ref_SoftReference::set_clock(jlong value) {
|
||||
base->long_field_put(static_clock_offset, value);
|
||||
}
|
||||
|
||||
// Support for java_lang_ref_ReferenceQueue
|
||||
|
||||
oop java_lang_ref_ReferenceQueue::NULL_queue() {
|
||||
InstanceKlass* ik = SystemDictionary::ReferenceQueue_klass();
|
||||
oop mirror = ik->java_mirror();
|
||||
return mirror->obj_field(static_NULL_queue_offset);
|
||||
}
|
||||
|
||||
oop java_lang_ref_ReferenceQueue::ENQUEUED_queue() {
|
||||
InstanceKlass* ik = SystemDictionary::ReferenceQueue_klass();
|
||||
oop mirror = ik->java_mirror();
|
||||
return mirror->obj_field(static_ENQUEUED_queue_offset);
|
||||
}
|
||||
|
||||
void java_lang_ref_ReferenceQueue::compute_offsets() {
|
||||
InstanceKlass* k = SystemDictionary::ReferenceQueue_klass();
|
||||
compute_offset(static_NULL_queue_offset,
|
||||
k,
|
||||
vmSymbols::referencequeue_null_name(),
|
||||
vmSymbols::referencequeue_signature(),
|
||||
true /* is_static */);
|
||||
compute_offset(static_ENQUEUED_queue_offset,
|
||||
k,
|
||||
vmSymbols::referencequeue_enqueued_name(),
|
||||
vmSymbols::referencequeue_signature(),
|
||||
true /* is_static */);
|
||||
}
|
||||
|
||||
// Support for java_lang_invoke_DirectMethodHandle
|
||||
|
||||
int java_lang_invoke_DirectMethodHandle::_member_offset;
|
||||
@ -4193,6 +4221,8 @@ int java_lang_ref_Reference::referent_offset;
|
||||
int java_lang_ref_Reference::queue_offset;
|
||||
int java_lang_ref_Reference::next_offset;
|
||||
int java_lang_ref_Reference::discovered_offset;
|
||||
int java_lang_ref_ReferenceQueue::static_NULL_queue_offset;
|
||||
int java_lang_ref_ReferenceQueue::static_ENQUEUED_queue_offset;
|
||||
int java_lang_ref_SoftReference::timestamp_offset;
|
||||
int java_lang_ref_SoftReference::static_clock_offset;
|
||||
int java_lang_ClassLoader::parent_offset;
|
||||
@ -4437,6 +4467,7 @@ void JavaClasses::compute_offsets() {
|
||||
java_lang_StackTraceElement::compute_offsets();
|
||||
java_lang_StackFrameInfo::compute_offsets();
|
||||
java_lang_LiveStackFrameInfo::compute_offsets();
|
||||
java_lang_ref_ReferenceQueue::compute_offsets();
|
||||
|
||||
// generated interpreter code wants to know about the offsets we just computed:
|
||||
AbstractAssembler::update_delayed_values();
|
||||
|
||||
@ -921,6 +921,8 @@ class java_lang_ref_Reference: AllStatic {
|
||||
static inline void set_discovered(oop ref, oop value);
|
||||
static inline void set_discovered_raw(oop ref, oop value);
|
||||
static inline HeapWord* discovered_addr_raw(oop ref);
|
||||
static inline oop queue(oop ref);
|
||||
static inline void set_queue(oop ref, oop value);
|
||||
static bool is_referent_field(oop obj, ptrdiff_t offset);
|
||||
static inline bool is_phantom(oop ref);
|
||||
};
|
||||
@ -944,6 +946,20 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
// Interface to java.lang.ref.ReferenceQueue objects
|
||||
|
||||
class java_lang_ref_ReferenceQueue: public AllStatic {
|
||||
public:
|
||||
static int static_NULL_queue_offset;
|
||||
static int static_ENQUEUED_queue_offset;
|
||||
|
||||
// Accessors
|
||||
static oop NULL_queue();
|
||||
static oop ENQUEUED_queue();
|
||||
|
||||
static void compute_offsets();
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.MethodHandle objects
|
||||
|
||||
class MethodHandleEntry;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -127,6 +127,12 @@ void java_lang_ref_Reference::set_discovered_raw(oop ref, oop value) {
|
||||
HeapWord* java_lang_ref_Reference::discovered_addr_raw(oop ref) {
|
||||
return ref->obj_field_addr_raw<HeapWord>(discovered_offset);
|
||||
}
|
||||
oop java_lang_ref_Reference::queue(oop ref) {
|
||||
return ref->obj_field(queue_offset);
|
||||
}
|
||||
void java_lang_ref_Reference::set_queue(oop ref, oop value) {
|
||||
return ref->obj_field_put(queue_offset, value);
|
||||
}
|
||||
bool java_lang_ref_Reference::is_phantom(oop ref) {
|
||||
return InstanceKlass::cast(ref->klass())->reference_type() == REF_PHANTOM;
|
||||
}
|
||||
|
||||
@ -2113,6 +2113,8 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
|
||||
InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
|
||||
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(ReferenceQueue_klass), scan, CHECK);
|
||||
|
||||
// JSR 292 classes
|
||||
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
||||
WKID jsr292_group_end = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
|
||||
|
||||
@ -136,6 +136,7 @@ class OopStorage;
|
||||
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
|
||||
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
|
||||
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
|
||||
do_klass(ReferenceQueue_klass, java_lang_ref_ReferenceQueue, Pre ) \
|
||||
\
|
||||
do_klass(Thread_klass, java_lang_Thread, Pre ) \
|
||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \
|
||||
|
||||
@ -86,6 +86,7 @@
|
||||
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
|
||||
template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \
|
||||
template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \
|
||||
template(java_lang_ref_ReferenceQueue, "java/lang/ref/ReferenceQueue") \
|
||||
template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
|
||||
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
|
||||
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
|
||||
@ -438,6 +439,8 @@
|
||||
template(module_entry_name, "module_entry") \
|
||||
template(resolved_references_name, "<resolved_references>") \
|
||||
template(init_lock_name, "<init_lock>") \
|
||||
template(referencequeue_null_name, "NULL") \
|
||||
template(referencequeue_enqueued_name, "ENQUEUED") \
|
||||
\
|
||||
/* name symbols needed by intrinsics */ \
|
||||
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
|
||||
@ -531,6 +534,7 @@
|
||||
template(string_signature, "Ljava/lang/String;") \
|
||||
template(string_array_signature, "[Ljava/lang/String;") \
|
||||
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
||||
template(referencequeue_signature, "Ljava/lang/ref/ReferenceQueue;") \
|
||||
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
|
||||
template(executable_signature, "Ljava/lang/reflect/Executable;") \
|
||||
template(module_signature, "Ljava/lang/Module;") \
|
||||
|
||||
@ -62,11 +62,13 @@ bool Klass::is_cloneable() const {
|
||||
}
|
||||
|
||||
void Klass::set_is_cloneable() {
|
||||
if (name() != vmSymbols::java_lang_invoke_MemberName()) {
|
||||
_access_flags.set_is_cloneable_fast();
|
||||
} else {
|
||||
if (name() == vmSymbols::java_lang_invoke_MemberName()) {
|
||||
assert(is_final(), "no subclasses allowed");
|
||||
// MemberName cloning should not be intrinsified and always happen in JVM_Clone.
|
||||
} else if (is_instance_klass() && InstanceKlass::cast(this)->reference_type() != REF_NONE) {
|
||||
// Reference cloning should not be intrinsified and always happen in JVM_Clone.
|
||||
} else {
|
||||
_access_flags.set_is_cloneable_fast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "gc/shared/collectedHeap.inline.hpp"
|
||||
#include "interpreter/bytecode.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/referenceType.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/access.inline.hpp"
|
||||
@ -629,6 +630,35 @@ JVM_ENTRY(void, JVM_MonitorNotifyAll(JNIEnv* env, jobject handle))
|
||||
JVM_END
|
||||
|
||||
|
||||
template<DecoratorSet decorators>
|
||||
static void fixup_clone_referent(oop src, oop new_obj) {
|
||||
typedef HeapAccess<decorators> RefAccess;
|
||||
const int ref_offset = java_lang_ref_Reference::referent_offset;
|
||||
oop referent = RefAccess::oop_load_at(src, ref_offset);
|
||||
RefAccess::oop_store_at(new_obj, ref_offset, referent);
|
||||
}
|
||||
|
||||
static void fixup_cloned_reference(ReferenceType ref_type, oop src, oop clone) {
|
||||
// Kludge: After unbarriered clone, re-copy the referent with
|
||||
// correct barriers. This works for current collectors, but won't
|
||||
// work for ZGC and maybe other future collectors or variants of
|
||||
// existing ones (like G1 with concurrent reference processing).
|
||||
if (ref_type == REF_PHANTOM) {
|
||||
fixup_clone_referent<ON_PHANTOM_OOP_REF>(src, clone);
|
||||
} else {
|
||||
fixup_clone_referent<ON_WEAK_OOP_REF>(src, clone);
|
||||
}
|
||||
if ((java_lang_ref_Reference::next(clone) != NULL) ||
|
||||
(java_lang_ref_Reference::queue(clone) == java_lang_ref_ReferenceQueue::ENQUEUED_queue())) {
|
||||
// If the source has been enqueued or is being enqueued, don't
|
||||
// register the clone with a queue.
|
||||
java_lang_ref_Reference::set_queue(clone, java_lang_ref_ReferenceQueue::NULL_queue());
|
||||
}
|
||||
// discovered and next are list links; the clone is not in those lists.
|
||||
java_lang_ref_Reference::set_discovered(clone, NULL);
|
||||
java_lang_ref_Reference::set_next(clone, NULL);
|
||||
}
|
||||
|
||||
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
|
||||
JVMWrapper("JVM_Clone");
|
||||
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
|
||||
@ -654,17 +684,28 @@ JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
|
||||
}
|
||||
|
||||
// Make shallow object copy
|
||||
ReferenceType ref_type = REF_NONE;
|
||||
const int size = obj->size();
|
||||
oop new_obj_oop = NULL;
|
||||
if (obj->is_array()) {
|
||||
const int length = ((arrayOop)obj())->length();
|
||||
new_obj_oop = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
|
||||
} else {
|
||||
ref_type = InstanceKlass::cast(klass)->reference_type();
|
||||
assert((ref_type == REF_NONE) ==
|
||||
!klass->is_subclass_of(SystemDictionary::Reference_klass()),
|
||||
"invariant");
|
||||
new_obj_oop = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
|
||||
}
|
||||
|
||||
HeapAccess<>::clone(obj(), new_obj_oop, size);
|
||||
|
||||
// If cloning a Reference, set Reference fields to a safe state.
|
||||
// Fixup must be completed before any safepoint.
|
||||
if (ref_type != REF_NONE) {
|
||||
fixup_cloned_reference(ref_type, obj(), new_obj_oop);
|
||||
}
|
||||
|
||||
Handle new_obj(THREAD, new_obj_oop);
|
||||
// Caution: this involves a java upcall, so the clone should be
|
||||
// "gc-robust" by this stage.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user