8299089: Instrument global jni handles with tag to make them distinguishable

Co-authored-by: Stefan Karlsson <stefank@openjdk.org>
Co-authored-by: Martin Doerr <mdoerr@openjdk.org>
Co-authored-by: Leslie Zhai <lzhai@openjdk.org>
Reviewed-by: eosterlund, stefank, ayang
This commit is contained in:
Axel Boldt-Christmas 2023-01-18 09:21:08 +00:00
parent 66f7387b5f
commit c7056737e3
36 changed files with 470 additions and 227 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -122,8 +122,8 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators
void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
Register obj, Register tmp, Label& slowpath) { Register obj, Register tmp, Label& slowpath) {
// If mask changes we need to ensure that the inverse is still encodable as an immediate // If mask changes we need to ensure that the inverse is still encodable as an immediate
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1); STATIC_ASSERT(JNIHandles::tag_mask == 0b11);
__ andr(obj, obj, ~JNIHandles::weak_tag_mask); __ andr(obj, obj, ~JNIHandles::tag_mask);
__ ldr(obj, Address(obj, 0)); // *obj __ ldr(obj, Address(obj, 0)); // *obj
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -2458,22 +2458,56 @@ void MacroAssembler::verify_heapbase(const char* msg) {
#endif #endif
void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) { void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
Label done, not_weak; assert_different_registers(value, tmp1, tmp2);
Label done, tagged, weak_tagged;
cbz(value, done); // Use NULL as-is. cbz(value, done); // Use NULL as-is.
tst(value, JNIHandles::tag_mask); // Test for tag.
br(Assembler::NE, tagged);
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u); // Resolve local handle
tbz(value, 0, not_weak); // Test for jweak tag. access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, value, Address(value, 0), tmp1, tmp2);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, value,
Address(value, -JNIHandles::weak_tag_value), tmp1, tmp2);
verify_oop(value); verify_oop(value);
b(done); b(done);
bind(not_weak); bind(tagged);
// Resolve (untagged) jobject. STATIC_ASSERT(JNIHandles::TypeTag::weak_global == 0b1);
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp1, tmp2); tbnz(value, 0, weak_tagged); // Test for weak tag.
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp1, tmp2);
verify_oop(value); verify_oop(value);
b(done);
bind(weak_tagged);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF,
value, Address(value, -JNIHandles::TypeTag::weak_global), tmp1, tmp2);
verify_oop(value);
bind(done);
}
void MacroAssembler::resolve_global_jobject(Register value, Register tmp1, Register tmp2) {
assert_different_registers(value, tmp1, tmp2);
Label done;
cbz(value, done); // Use NULL as-is.
#ifdef ASSERT
{
STATIC_ASSERT(JNIHandles::TypeTag::global == 0b10);
Label valid_global_tag;
tbnz(value, 1, valid_global_tag); // Test for global tag
stop("non global jobject using resolve_global_jobject");
bind(valid_global_tag);
}
#endif
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp1, tmp2);
verify_oop(value);
bind(done); bind(done);
} }

View file

@ -823,6 +823,7 @@ public:
void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
void resolve_jobject(Register value, Register tmp1, Register tmp2); void resolve_jobject(Register value, Register tmp1, Register tmp2);
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
// C 'boolean' to Java boolean: x == 0 ? 0 : 1 // C 'boolean' to Java boolean: x == 0 ? 0 : 1
void c2bool(Register x); void c2bool(Register x);

View file

@ -6923,12 +6923,7 @@ class StubGenerator: public StubCodeGenerator {
// The handle is dereferenced through a load barrier. // The handle is dereferenced through a load barrier.
static void jfr_epilogue(MacroAssembler* _masm) { static void jfr_epilogue(MacroAssembler* _masm) {
__ reset_last_Java_frame(true); __ reset_last_Java_frame(true);
Label null_jobject; __ resolve_global_jobject(r0, rscratch1, rscratch2);
__ cbz(r0, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, decorators, T_OBJECT, r0, Address(r0, 0), rscratch1, rscratch2);
__ bind(null_jobject);
} }
// For c2: c_rarg0 is junk, call to runtime to write a checkpoint. // For c2: c_rarg0 is junk, call to runtime to write a checkpoint.
@ -6943,7 +6938,7 @@ class StubGenerator: public StubCodeGenerator {
framesize // inclusive of return address framesize // inclusive of return address
}; };
int insts_size = 512; int insts_size = 1024;
int locs_size = 64; int locs_size = 64;
CodeBuffer code("jfr_write_checkpoint", insts_size, locs_size); CodeBuffer code("jfr_write_checkpoint", insts_size, locs_size);
OopMapSet* oop_maps = new OopMapSet(); OopMapSet* oop_maps = new OopMapSet();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -113,7 +113,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
__ ldr_s32(Rsafept_cnt, Address(Rsafepoint_counter_addr)); __ ldr_s32(Rsafept_cnt, Address(Rsafepoint_counter_addr));
__ tbnz(Rsafept_cnt, 0, slow_case); __ tbnz(Rsafept_cnt, 0, slow_case);
__ bic(R1, R1, JNIHandles::weak_tag_mask); __ bic(R1, R1, JNIHandles::tag_mask);
if (JvmtiExport::can_post_field_access()) { if (JvmtiExport::can_post_field_access()) {
// Using barrier to order wrt. JVMTI check and load of result. // Using barrier to order wrt. JVMTI check and load of result.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1284,20 +1284,57 @@ void MacroAssembler::resolve_jobject(Register value,
Register tmp1, Register tmp1,
Register tmp2) { Register tmp2) {
assert_different_registers(value, tmp1, tmp2); assert_different_registers(value, tmp1, tmp2);
Label done, not_weak; Label done, tagged, weak_tagged;
cbz(value, done); // Use NULL as-is.
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
tbz(value, 0, not_weak); // Test for jweak tag.
cbz(value, done); // Use NULL as-is.
tst(value, JNIHandles::tag_mask); // Test for tag.
b(tagged, ne);
// Resolve local handle
access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, Address(value, 0), value, tmp1, tmp2, noreg);
verify_oop(value);
b(done);
bind(tagged);
tst(value, JNIHandles::TypeTag::weak_global); // Test for weak tag.
b(weak_tagged, ne);
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, Address(value, -JNIHandles::TypeTag::global), value, tmp1, tmp2, noreg);
verify_oop(value);
b(done);
bind(weak_tagged);
// Resolve jweak. // Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF,
Address(value, -JNIHandles::weak_tag_value), value, tmp1, tmp2, noreg); Address(value, -JNIHandles::TypeTag::weak_global), value, tmp1, tmp2, noreg);
b(done);
bind(not_weak);
// Resolve (untagged) jobject.
access_load_at(T_OBJECT, IN_NATIVE,
Address(value, 0), value, tmp1, tmp2, noreg);
verify_oop(value); verify_oop(value);
bind(done);
}
void MacroAssembler::resolve_global_jobject(Register value,
Register tmp1,
Register tmp2) {
assert_different_registers(value, tmp1, tmp2);
Label done;
cbz(value, done); // Use NULL as-is.
#ifdef ASSERT
{
Label valid_global_tag;
tst(value, JNIHandles::TypeTag::global); // Test for global tag.
b(valid_global_tag, ne);
stop("non global jobject using resolve_global_jobject");
bind(valid_global_tag);
}
#endif
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, Address(value, -JNIHandles::TypeTag::global), value, tmp1, tmp2, noreg);
verify_oop(value);
bind(done); bind(done);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -356,6 +356,7 @@ public:
} }
void resolve_jobject(Register value, Register tmp1, Register tmp2); void resolve_jobject(Register value, Register tmp1, Register tmp2);
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
void nop() { void nop() {
mov(R0, R0); mov(R0, R0);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3053,13 +3053,7 @@ class StubGenerator: public StubCodeGenerator {
__ reset_last_Java_frame(Rtemp); __ reset_last_Java_frame(Rtemp);
// R0 is jobject handle result, unpack and process it through a barrier. // R0 is jobject handle result, unpack and process it through a barrier.
Label L_null_jobject; __ resolve_global_jobject(R0, Rtemp, R1);
__ cbz(R0, L_null_jobject);
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(masm, ACCESS_READ | IN_NATIVE, T_OBJECT, R0, Address(R0, 0), Rtemp, R1, R2);
__ bind(L_null_jobject);
__ raw_pop(R1, R2, LR); __ raw_pop(R1, R2, LR);
__ ret(); __ ret();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021 SAP SE. All rights reserved. * Copyright (c) 2018, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -377,8 +377,8 @@ void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value
__ cmpdi(CCR0, value, 0); __ cmpdi(CCR0, value, 0);
__ beq(CCR0, done); // Use NULL as-is. __ beq(CCR0, done); // Use NULL as-is.
__ clrrdi(tmp1, value, JNIHandles::weak_tag_size); __ clrrdi(tmp1, value, JNIHandles::tag_size);
__ andi_(tmp2, value, JNIHandles::weak_tag_mask); __ andi_(tmp2, value, JNIHandles::TypeTag::weak_global);
__ ld(value, 0, tmp1); // Resolve (untagged) jobject. __ ld(value, 0, tmp1); // Resolve (untagged) jobject.
__ beq(CCR0, not_weak); // Test for jweak tag. __ beq(CCR0, not_weak); // Test for jweak tag.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022 SAP SE. All rights reserved. * Copyright (c) 2018, 2022 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -115,31 +115,65 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators,
void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value, void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
Register tmp1, Register tmp2, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) { MacroAssembler::PreservationLevel preservation_level) {
Label done, not_weak, verify; Label done, tagged, weak_tagged, verify;
__ cmpdi(CCR0, value, 0); __ cmpdi(CCR0, value, 0);
__ beq(CCR0, done); // Use NULL as-is. __ beq(CCR0, done); // Use NULL as-is.
__ andi_(tmp1, value, JNIHandles::weak_tag_mask); __ andi_(tmp1, value, JNIHandles::tag_mask);
__ beq(CCR0, not_weak); // Test for jweak tag. __ bne(CCR0, tagged); // Test for tag.
// Resolve (untagged) jobject. __ access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, // no uncoloring
__ clrrdi(value, value, JNIHandles::weak_tag_size); value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
load_at(masm, IN_NATIVE | ON_PHANTOM_OOP_REF, T_OBJECT,
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
__ b(verify); __ b(verify);
__ bind(not_weak); __ bind(tagged);
load_at(masm, IN_NATIVE, T_OBJECT, __ andi_(tmp1, value, JNIHandles::TypeTag::weak_global);
value, (intptr_t)0, value, tmp1, tmp2, preservation_level); __ clrrdi(value, value, JNIHandles::tag_size); // Untag.
__ bne(CCR0, weak_tagged); // Test for jweak tag.
__ access_load_at(T_OBJECT, IN_NATIVE,
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
__ b(verify);
__ bind(weak_tagged);
__ access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF,
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
__ bind(verify); __ bind(verify);
__ verify_oop(value, FILE_AND_LINE); __ verify_oop(value, FILE_AND_LINE);
__ bind(done); __ bind(done);
} }
// Generic implementation. GCs can provide an optimized one.
void BarrierSetAssembler::resolve_global_jobject(MacroAssembler* masm, Register value,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) {
Label done;
__ cmpdi(CCR0, value, 0);
__ beq(CCR0, done); // Use NULL as-is.
#ifdef ASSERT
{
Label valid_global_tag;
__ andi_(tmp1, value, JNIHandles::TypeTag::global);
__ bne(CCR0, valid_global_tag); // Test for global tag.
__ stop("non global jobject using resolve_global_jobject");
__ bind(valid_global_tag);
}
#endif
__ clrrdi(value, value, JNIHandles::tag_size); // Untag.
__ access_load_at(T_OBJECT, IN_NATIVE,
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
__ verify_oop(value, FILE_AND_LINE);
__ bind(done);
}
void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env,
Register obj, Register tmp, Label& slowpath) { Register obj, Register tmp, Label& slowpath) {
__ clrrdi(dst, obj, JNIHandles::weak_tag_size); __ clrrdi(dst, obj, JNIHandles::tag_size);
__ ld(dst, 0, dst); // Resolve (untagged) jobject. __ ld(dst, 0, dst); // Resolve (untagged) jobject.
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022 SAP SE. All rights reserved. * Copyright (c) 2018, 2022 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -56,6 +56,9 @@ public:
virtual void resolve_jobject(MacroAssembler* masm, Register value, virtual void resolve_jobject(MacroAssembler* masm, Register value,
Register tmp1, Register tmp2, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level); MacroAssembler::PreservationLevel preservation_level);
virtual void resolve_global_jobject(MacroAssembler* masm, Register value,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env,
Register obj, Register tmp, Label& slowpath); Register obj, Register tmp, Label& slowpath);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021 SAP SE. All rights reserved. * Copyright (c) 2018, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -84,7 +84,7 @@ void ModRefBarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register v
__ cmpdi(CCR0, value, 0); __ cmpdi(CCR0, value, 0);
__ beq(CCR0, done); // Use NULL as-is. __ beq(CCR0, done); // Use NULL as-is.
__ clrrdi(tmp1, value, JNIHandles::weak_tag_size); __ clrrdi(tmp1, value, JNIHandles::tag_size);
__ ld(value, 0, tmp1); // Resolve (untagged) jobject. __ ld(value, 0, tmp1); // Resolve (untagged) jobject.
__ verify_oop(value, FILE_AND_LINE); __ verify_oop(value, FILE_AND_LINE);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022 SAP SE. All rights reserved. * Copyright (c) 2012, 2022 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -2892,6 +2892,12 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp
bs->resolve_jobject(this, value, tmp1, tmp2, preservation_level); bs->resolve_jobject(this, value, tmp1, tmp2, preservation_level);
} }
void MacroAssembler::resolve_global_jobject(Register value, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->resolve_global_jobject(this, value, tmp1, tmp2, preservation_level);
}
// Values for last_Java_pc, and last_Java_sp must comply to the rules // Values for last_Java_pc, and last_Java_sp must comply to the rules
// in frame_ppc.hpp. // in frame_ppc.hpp.
void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -661,6 +661,8 @@ class MacroAssembler: public Assembler {
void resolve_jobject(Register value, Register tmp1, Register tmp2, void resolve_jobject(Register value, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level); MacroAssembler::PreservationLevel preservation_level);
void resolve_global_jobject(Register value, Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
// Support for managing the JavaThread pointer (i.e.; the reference to // Support for managing the JavaThread pointer (i.e.; the reference to
// thread-local information). // thread-local information).
@ -698,7 +700,6 @@ class MacroAssembler: public Assembler {
// Access heap oop, handle encoding and GC barriers. // Access heap oop, handle encoding and GC barriers.
// Some GC barriers call C so use needs_frame = true if an extra frame is needed at the current call site. // Some GC barriers call C so use needs_frame = true if an extra frame is needed at the current call site.
private:
inline void access_store_at(BasicType type, DecoratorSet decorators, inline void access_store_at(BasicType type, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs, Register val, Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3, Register tmp1, Register tmp2, Register tmp3,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022 SAP SE. All rights reserved. * Copyright (c) 2012, 2022 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -4628,13 +4628,7 @@ class StubGenerator: public StubCodeGenerator {
address calls_return_pc = __ last_calls_return_pc(); address calls_return_pc = __ last_calls_return_pc();
__ reset_last_Java_frame(); __ reset_last_Java_frame();
// The handle is dereferenced through a load barrier. // The handle is dereferenced through a load barrier.
Label null_jobject; __ resolve_global_jobject(R3_RET, tmp1, tmp2, MacroAssembler::PRESERVATION_NONE);
__ cmpdi(CCR0, R3_RET, 0);
__ beq(CCR0, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, decorators, T_OBJECT, R3_RET /*base*/, (intptr_t)0, R3_RET /*dst*/, tmp1, tmp2, MacroAssembler::PRESERVATION_NONE);
__ bind(null_jobject);
__ pop_frame(); __ pop_frame();
__ ld(tmp1, _abi0(lr), R1_SP); __ ld(tmp1, _abi0(lr), R1_SP);
__ mtlr(tmp1); __ mtlr(tmp1);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -122,8 +122,8 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators
void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
Register obj, Register tmp, Label& slowpath) { Register obj, Register tmp, Label& slowpath) {
// If mask changes we need to ensure that the inverse is still encodable as an immediate // If mask changes we need to ensure that the inverse is still encodable as an immediate
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1); STATIC_ASSERT(JNIHandles::tag_mask == 3);
__ andi(obj, obj, ~JNIHandles::weak_tag_mask); __ andi(obj, obj, ~JNIHandles::tag_mask);
__ ld(obj, Address(obj, 0)); // *obj __ ld(obj, Address(obj, 0)); // *obj
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -556,23 +556,59 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
} }
void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) { void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
Label done, not_weak; assert_different_registers(value, tmp1, tmp2);
Label done, tagged, weak_tagged;
beqz(value, done); // Use NULL as-is. beqz(value, done); // Use NULL as-is.
// Test for tag.
andi(t0, value, JNIHandles::tag_mask);
bnez(t0, tagged);
// Test for jweak tag. // Resolve local handle
andi(t0, value, JNIHandles::weak_tag_mask); access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, value, Address(value, 0), tmp1, tmp2);
beqz(t0, not_weak);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, value,
Address(value, -JNIHandles::weak_tag_value), tmp1, tmp2);
verify_oop(value); verify_oop(value);
j(done); j(done);
bind(not_weak); bind(tagged);
// Resolve (untagged) jobject. // Test for jweak tag.
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp1, tmp2); andi(t0, value, JNIHandles::TypeTag::weak_global);
bnez(t0, weak_tagged);
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value,
Address(value, -JNIHandles::TypeTag::global), tmp1, tmp2);
j(done);
bind(weak_tagged);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, value,
Address(value, -JNIHandles::TypeTag::weak_global), tmp1, tmp2);
verify_oop(value); verify_oop(value);
bind(done);
}
void MacroAssembler::resolve_global_jobject(Register value, Register tmp1, Register tmp2) {
assert_different_registers(value, tmp1, tmp2);
Label done;
beqz(value, done); // Use NULL as-is.
#ifdef ASSERT
{
Label valid_global_tag;
andi(t0, value, JNIHandles::TypeTag::global); // Test for global tag.
bnez(t0, valid_global_tag);
stop("non global jobject using resolve_global_jobject");
bind(valid_global_tag);
}
#endif
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value,
Address(value, -JNIHandles::TypeTag::global), tmp1, tmp2);
verify_oop(value);
bind(done); bind(done);
} }

View file

@ -181,6 +181,7 @@ class MacroAssembler: public Assembler {
void resolve_weak_handle(Register result, Register tmp1, Register tmp2); void resolve_weak_handle(Register result, Register tmp1, Register tmp2);
void resolve_oop_handle(Register result, Register tmp1, Register tmp2); void resolve_oop_handle(Register result, Register tmp1, Register tmp2);
void resolve_jobject(Register value, Register tmp1, Register tmp2); void resolve_jobject(Register value, Register tmp1, Register tmp2);
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
void movoop(Register dst, jobject obj); void movoop(Register dst, jobject obj);
void mov_metadata(Register dst, Metadata* obj); void mov_metadata(Register dst, Metadata* obj);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -3979,14 +3979,8 @@ class StubGenerator: public StubCodeGenerator {
static void jfr_epilogue(MacroAssembler* _masm) { static void jfr_epilogue(MacroAssembler* _masm) {
__ reset_last_Java_frame(true); __ reset_last_Java_frame(true);
Label null_jobject; __ resolve_global_jobject(x10, t0, t1);
__ beqz(x10, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, decorators, T_OBJECT, x10, Address(x10, 0), t0, t1);
__ bind(null_jobject);
} }
// For c2: c_rarg0 is junk, call to runtime to write a checkpoint. // For c2: c_rarg0 is junk, call to runtime to write a checkpoint.
// It returns a jobject handle to the event writer. // It returns a jobject handle to the event writer.
// The handle is dereferenced and the return value is the event writer oop. // The handle is dereferenced and the return value is the event writer oop.
@ -4012,6 +4006,7 @@ class StubGenerator: public StubCodeGenerator {
address the_pc = __ pc(); address the_pc = __ pc();
jfr_prologue(the_pc, _masm, xthread); jfr_prologue(the_pc, _masm, xthread);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint), 1); __ call_VM_leaf(CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint), 1);
jfr_epilogue(_masm); jfr_epilogue(_masm);
__ leave(); __ leave();
__ ret(); __ ret();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019 SAP SE. All rights reserved. * Copyright (c) 2018, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -397,10 +397,10 @@ void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value
__ z_ltgr(tmp1, value); __ z_ltgr(tmp1, value);
__ z_bre(Ldone); // Use NULL result as-is. __ z_bre(Ldone); // Use NULL result as-is.
__ z_nill(value, ~JNIHandles::weak_tag_mask); __ z_nill(value, ~JNIHandles::tag_mask);
__ z_lg(value, 0, value); // Resolve (untagged) jobject. __ z_lg(value, 0, value); // Resolve (untagged) jobject.
__ z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag. __ z_tmll(tmp1, JNIHandles::TypeTag::weak_global); // Test for jweak tag.
__ z_braz(Lnot_weak); __ z_braz(Lnot_weak);
__ verify_oop(value, FILE_AND_LINE); __ verify_oop(value, FILE_AND_LINE);
DecoratorSet decorators = IN_NATIVE | ON_PHANTOM_OOP_REF; DecoratorSet decorators = IN_NATIVE | ON_PHANTOM_OOP_REF;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018 SAP SE. All rights reserved. * Copyright (c) 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -110,7 +110,7 @@ void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
__ z_ltgr(tmp1, value); __ z_ltgr(tmp1, value);
__ z_bre(Ldone); // Use NULL result as-is. __ z_bre(Ldone); // Use NULL result as-is.
__ z_nill(value, ~JNIHandles::weak_tag_mask); __ z_nill(value, ~JNIHandles::tag_mask);
__ z_lg(value, 0, value); // Resolve (untagged) jobject. __ z_lg(value, 0, value); // Resolve (untagged) jobject.
__ verify_oop(value, FILE_AND_LINE); __ verify_oop(value, FILE_AND_LINE);
@ -119,7 +119,7 @@ void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
Register obj, Register tmp, Label& slowpath) { Register obj, Register tmp, Label& slowpath) {
__ z_nill(obj, ~JNIHandles::weak_tag_mask); __ z_nill(obj, ~JNIHandles::tag_mask);
__ z_lg(obj, 0, obj); // Resolve (untagged) jobject. __ z_lg(obj, 0, obj); // Resolve (untagged) jobject.
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -197,7 +197,7 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators
void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
Register obj, Register tmp, Label& slowpath) { Register obj, Register tmp, Label& slowpath) {
__ clear_jweak_tag(obj); __ clear_jobject_tag(obj);
__ movptr(obj, Address(obj, 0)); __ movptr(obj, Address(obj, 0));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -93,7 +93,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
// rdx is data dependent on rcx. // rdx is data dependent on rcx.
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
__ clear_jweak_tag(rdx); __ clear_jobject_tag(rdx);
__ movptr(rdx, Address(rdx, 0)); // *obj __ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr (rax, 2); // offset __ shrptr (rax, 2); // offset
@ -214,7 +214,7 @@ address JNI_FastGetField::generate_fast_get_long_field() {
// rdx is data dependent on rcx. // rdx is data dependent on rcx.
__ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID
__ clear_jweak_tag(rdx); __ clear_jobject_tag(rdx);
__ movptr(rdx, Address(rdx, 0)); // *obj __ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rsi, 2); // offset __ shrptr(rsi, 2); // offset
@ -304,7 +304,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
// rdx is data dependent on rcx. // rdx is data dependent on rcx.
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
__ clear_jweak_tag(rdx); __ clear_jobject_tag(rdx);
__ movptr(rdx, Address(rdx, 0)); // *obj __ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rax, 2); // offset __ shrptr(rax, 2); // offset

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@
#define __ masm-> #define __ masm->
#define BUFFER_SIZE 30*wordSize #define BUFFER_SIZE 40*wordSize
// Common register usage: // Common register usage:
// rax/xmm0: result // rax/xmm0: result

View file

@ -3874,31 +3874,69 @@ void MacroAssembler::vpermd(XMMRegister dst, XMMRegister nds, AddressLiteral sr
} }
} }
void MacroAssembler::clear_jweak_tag(Register possibly_jweak) { void MacroAssembler::clear_jobject_tag(Register possibly_non_local) {
const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask); const int32_t inverted_mask = ~static_cast<int32_t>(JNIHandles::tag_mask);
STATIC_ASSERT(inverted_jweak_mask == -2); // otherwise check this code STATIC_ASSERT(inverted_mask == -4); // otherwise check this code
// The inverted mask is sign-extended // The inverted mask is sign-extended
andptr(possibly_jweak, inverted_jweak_mask); andptr(possibly_non_local, inverted_mask);
} }
void MacroAssembler::resolve_jobject(Register value, void MacroAssembler::resolve_jobject(Register value,
Register thread, Register thread,
Register tmp) { Register tmp) {
assert_different_registers(value, thread, tmp); assert_different_registers(value, thread, tmp);
Label done, not_weak; Label done, tagged, weak_tagged;
testptr(value, value); testptr(value, value);
jcc(Assembler::zero, done); // Use NULL as-is. jcc(Assembler::zero, done); // Use NULL as-is.
testptr(value, JNIHandles::weak_tag_mask); // Test for jweak tag. testptr(value, JNIHandles::tag_mask); // Test for tag.
jcc(Assembler::zero, not_weak); jcc(Assembler::notZero, tagged);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, // Resolve local handle
value, Address(value, -JNIHandles::weak_tag_value), tmp, thread); access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, value, Address(value, 0), tmp, thread);
verify_oop(value); verify_oop(value);
jmp(done); jmp(done);
bind(not_weak);
// Resolve (untagged) jobject. bind(tagged);
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread); testptr(value, JNIHandles::TypeTag::weak_global); // Test for weak tag.
jcc(Assembler::notZero, weak_tagged);
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp, thread);
verify_oop(value); verify_oop(value);
jmp(done);
bind(weak_tagged);
// Resolve jweak.
access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF,
value, Address(value, -JNIHandles::TypeTag::weak_global), tmp, thread);
verify_oop(value);
bind(done);
}
void MacroAssembler::resolve_global_jobject(Register value,
Register thread,
Register tmp) {
assert_different_registers(value, thread, tmp);
Label done;
testptr(value, value);
jcc(Assembler::zero, done); // Use NULL as-is.
#ifdef ASSERT
{
Label valid_global_tag;
testptr(value, JNIHandles::TypeTag::global); // Test for global tag.
jcc(Assembler::notZero, valid_global_tag);
stop("non global jobject using resolve_global_jobject");
bind(valid_global_tag);
}
#endif
// Resolve global handle
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp, thread);
verify_oop(value);
bind(done); bind(done);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -326,8 +326,9 @@ class MacroAssembler: public Assembler {
void reset_last_Java_frame(bool clear_fp); void reset_last_Java_frame(bool clear_fp);
// jobjects // jobjects
void clear_jweak_tag(Register possibly_jweak); void clear_jobject_tag(Register possibly_non_local);
void resolve_jobject(Register value, Register thread, Register tmp); void resolve_jobject(Register value, Register thread, Register tmp);
void resolve_global_jobject(Register value, Register thread, Register tmp);
// C 'boolean' to Java boolean: x == 0 ? 0 : 1 // C 'boolean' to Java boolean: x == 0 ? 0 : 1
void c2bool(Register x); void c2bool(Register x);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -4011,13 +4011,7 @@ class StubGenerator: public StubCodeGenerator {
Register java_thread = rdi; Register java_thread = rdi;
__ get_thread(java_thread); __ get_thread(java_thread);
__ reset_last_Java_frame(java_thread, true); __ reset_last_Java_frame(java_thread, true);
Label null_jobject; __ resolve_global_jobject(rax, java_thread, rdx);
__ testptr(rax, rax);
__ jcc(Assembler::zero, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(masm, decorators, T_OBJECT, rax, Address(rax, 0), noreg, java_thread);
__ bind(null_jobject);
} }
// For c2: c_rarg0 is junk, call to runtime to write a checkpoint. // For c2: c_rarg0 is junk, call to runtime to write a checkpoint.
@ -4036,7 +4030,7 @@ class StubGenerator: public StubCodeGenerator {
framesize framesize
}; };
int insts_size = 512; int insts_size = 1024;
int locs_size = 64; int locs_size = 64;
CodeBuffer code("jfr_write_checkpoint", insts_size, locs_size); CodeBuffer code("jfr_write_checkpoint", insts_size, locs_size);
OopMapSet* oop_maps = new OopMapSet(); OopMapSet* oop_maps = new OopMapSet();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3504,7 +3504,7 @@ RuntimeStub* StubGenerator::generate_jfr_write_checkpoint() {
framesize // inclusive of return address framesize // inclusive of return address
}; };
CodeBuffer code("jfr_write_checkpoint", 512, 64); CodeBuffer code("jfr_write_checkpoint", 1024, 64);
MacroAssembler* _masm = new MacroAssembler(&code); MacroAssembler* _masm = new MacroAssembler(&code);
address start = __ pc(); address start = __ pc();
@ -3519,14 +3519,7 @@ RuntimeStub* StubGenerator::generate_jfr_write_checkpoint() {
__ reset_last_Java_frame(true); __ reset_last_Java_frame(true);
// rax is jobject handle result, unpack and process it through a barrier. // rax is jobject handle result, unpack and process it through a barrier.
Label L_null_jobject; __ resolve_global_jobject(rax, r15_thread, c_rarg0);
__ testptr(rax, rax);
__ jcc(Assembler::zero, L_null_jobject);
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, ACCESS_READ | IN_NATIVE, T_OBJECT, rax, Address(rax, 0), c_rarg0, r15_thread);
__ bind(L_null_jobject);
__ leave(); __ leave();
__ ret(0); __ ret(0);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1115,7 +1115,8 @@ void nmethod::fix_oop_relocations(address begin, address end, bool initialize_im
oop_Relocation* reloc = iter.oop_reloc(); oop_Relocation* reloc = iter.oop_reloc();
if (initialize_immediates && reloc->oop_is_immediate()) { if (initialize_immediates && reloc->oop_is_immediate()) {
oop* dest = reloc->oop_addr(); oop* dest = reloc->oop_addr();
initialize_immediate_oop(dest, cast_from_oop<jobject>(*dest)); jobject obj = *reinterpret_cast<jobject*>(dest);
initialize_immediate_oop(dest, obj);
} }
// Refresh the oop-related bits of this instruction. // Refresh the oop-related bits of this instruction.
reloc->fix_oop_relocation(); reloc->fix_oop_relocation();

View file

@ -176,7 +176,7 @@ void CompileTask::mark_on_stack() {
} }
bool CompileTask::is_unloaded() const { bool CompileTask::is_unloaded() const {
return _method_holder != NULL && JNIHandles::is_weak_global_handle(_method_holder) && JNIHandles::is_global_weak_cleared(_method_holder); return _method_holder != NULL && JNIHandles::is_weak_global_handle(_method_holder) && JNIHandles::is_weak_global_cleared(_method_holder);
} }
// RedefineClasses support // RedefineClasses support

View file

@ -51,6 +51,7 @@
#include "opto/rootnode.hpp" #include "opto/rootnode.hpp"
#include "opto/subnode.hpp" #include "opto/subnode.hpp"
#include "prims/unsafe.hpp" #include "prims/unsafe.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.hpp"
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp" #include "runtime/stubRoutines.hpp"
@ -3124,7 +3125,8 @@ bool LibraryCallKit::inline_native_getEventWriter() {
ciInstanceKlass* const instklass_EventWriter = klass_EventWriter->as_instance_klass(); ciInstanceKlass* const instklass_EventWriter = klass_EventWriter->as_instance_klass();
const TypeKlassPtr* const aklass = TypeKlassPtr::make(instklass_EventWriter); const TypeKlassPtr* const aklass = TypeKlassPtr::make(instklass_EventWriter);
const TypeOopPtr* const xtype = aklass->as_instance_type(); const TypeOopPtr* const xtype = aklass->as_instance_type();
Node* event_writer = access_load(jobj, xtype, T_OBJECT, IN_NATIVE | C2_CONTROL_DEPENDENT_LOAD); Node* jobj_untagged = _gvn.transform(new AddPNode(top(), jobj, _gvn.MakeConX(-JNIHandles::TypeTag::global)));
Node* event_writer = access_load(jobj_untagged, xtype, T_OBJECT, IN_NATIVE | C2_CONTROL_DEPENDENT_LOAD);
// Load the current thread id from the event writer object. // Load the current thread id from the event writer object.
Node* const event_writer_tid = load_field_from_object(event_writer, "threadID", "J"); Node* const event_writer_tid = load_field_from_object(event_writer, "threadID", "J");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -66,6 +66,7 @@ jobject JNIHandles::make_local(JavaThread* thread, oop obj, AllocFailType alloc_
} else { } else {
assert(oopDesc::is_oop(obj), "not an oop"); assert(oopDesc::is_oop(obj), "not an oop");
assert(!current_thread_in_native(), "must not be in native"); assert(!current_thread_in_native(), "must not be in native");
STATIC_ASSERT(TypeTag::local == 0);
return thread->active_handles()->allocate_handle(thread, obj, alloc_failmode); return thread->active_handles()->allocate_handle(thread, obj, alloc_failmode);
} }
} }
@ -91,9 +92,10 @@ jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
oop* ptr = global_handles()->allocate(); oop* ptr = global_handles()->allocate();
// Return NULL on allocation failure. // Return NULL on allocation failure.
if (ptr != NULL) { if (ptr != NULL) {
assert(*ptr == NULL, "invariant"); assert(NativeAccess<AS_NO_KEEPALIVE>::oop_load(ptr) == oop(NULL), "invariant");
NativeAccess<>::oop_store(ptr, obj()); NativeAccess<>::oop_store(ptr, obj());
res = reinterpret_cast<jobject>(ptr); char* tptr = reinterpret_cast<char*>(ptr) + TypeTag::global;
res = reinterpret_cast<jobject>(tptr);
} else { } else {
report_handle_allocation_failure(alloc_failmode, "global"); report_handle_allocation_failure(alloc_failmode, "global");
} }
@ -102,20 +104,20 @@ jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
return res; return res;
} }
jobject JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) { jweak JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) {
assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
assert(!current_thread_in_native(), "must not be in native"); assert(!current_thread_in_native(), "must not be in native");
jobject res = NULL; jweak res = NULL;
if (!obj.is_null()) { if (!obj.is_null()) {
// ignore null handles // ignore null handles
assert(oopDesc::is_oop(obj()), "not an oop"); assert(oopDesc::is_oop(obj()), "not an oop");
oop* ptr = weak_global_handles()->allocate(); oop* ptr = weak_global_handles()->allocate();
// Return NULL on allocation failure. // Return NULL on allocation failure.
if (ptr != NULL) { if (ptr != NULL) {
assert(*ptr == NULL, "invariant"); assert(NativeAccess<AS_NO_KEEPALIVE>::oop_load(ptr) == oop(NULL), "invariant");
NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(ptr, obj()); NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(ptr, obj());
char* tptr = reinterpret_cast<char*>(ptr) + weak_tag_value; char* tptr = reinterpret_cast<char*>(ptr) + TypeTag::weak_global;
res = reinterpret_cast<jobject>(tptr); res = reinterpret_cast<jweak>(tptr);
} else { } else {
report_handle_allocation_failure(alloc_failmode, "weak global"); report_handle_allocation_failure(alloc_failmode, "weak global");
} }
@ -135,28 +137,25 @@ oop JNIHandles::resolve_external_guard(jobject handle) {
return result; return result;
} }
bool JNIHandles::is_global_weak_cleared(jweak handle) { bool JNIHandles::is_weak_global_cleared(jweak handle) {
assert(handle != NULL, "precondition"); assert(handle != NULL, "precondition");
assert(is_jweak(handle), "not a weak handle"); oop* oop_ptr = weak_global_ptr(handle);
oop* oop_ptr = jweak_ptr(handle);
oop value = NativeAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(oop_ptr); oop value = NativeAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(oop_ptr);
return value == NULL; return value == NULL;
} }
void JNIHandles::destroy_global(jobject handle) { void JNIHandles::destroy_global(jobject handle) {
if (handle != NULL) { if (handle != NULL) {
assert(!is_jweak(handle), "wrong method for destroying jweak"); oop* oop_ptr = global_ptr(handle);
oop* oop_ptr = jobject_ptr(handle);
NativeAccess<>::oop_store(oop_ptr, (oop)NULL); NativeAccess<>::oop_store(oop_ptr, (oop)NULL);
global_handles()->release(oop_ptr); global_handles()->release(oop_ptr);
} }
} }
void JNIHandles::destroy_weak_global(jobject handle) { void JNIHandles::destroy_weak_global(jweak handle) {
if (handle != NULL) { if (handle != NULL) {
assert(is_jweak(handle), "JNI handle not jweak"); oop* oop_ptr = weak_global_ptr(handle);
oop* oop_ptr = jweak_ptr(handle);
NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(oop_ptr, (oop)NULL); NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(oop_ptr, (oop)NULL);
weak_global_handles()->release(oop_ptr); weak_global_handles()->release(oop_ptr);
} }
@ -184,12 +183,12 @@ inline bool is_storage_handle(const OopStorage* storage, const oop* ptr) {
jobjectRefType JNIHandles::handle_type(JavaThread* thread, jobject handle) { jobjectRefType JNIHandles::handle_type(JavaThread* thread, jobject handle) {
assert(handle != NULL, "precondition"); assert(handle != NULL, "precondition");
jobjectRefType result = JNIInvalidRefType; jobjectRefType result = JNIInvalidRefType;
if (is_jweak(handle)) { if (is_weak_global_tagged(handle)) {
if (is_storage_handle(weak_global_handles(), jweak_ptr(handle))) { if (is_storage_handle(weak_global_handles(), weak_global_ptr(handle))) {
result = JNIWeakGlobalRefType; result = JNIWeakGlobalRefType;
} }
} else { } else if (is_global_tagged(handle)) {
switch (global_handles()->allocation_status(jobject_ptr(handle))) { switch (global_handles()->allocation_status(global_ptr(handle))) {
case OopStorage::ALLOCATED_ENTRY: case OopStorage::ALLOCATED_ENTRY:
result = JNIGlobalRefType; result = JNIGlobalRefType;
break; break;
@ -197,16 +196,16 @@ jobjectRefType JNIHandles::handle_type(JavaThread* thread, jobject handle) {
case OopStorage::UNALLOCATED_ENTRY: case OopStorage::UNALLOCATED_ENTRY:
break; // Invalid global handle break; // Invalid global handle
case OopStorage::INVALID_ENTRY:
// Not in global storage. Might be a local handle.
if (is_local_handle(thread, handle) || is_frame_handle(thread, handle)) {
result = JNILocalRefType;
}
break;
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
} else {
// Not in global storage. Might be a local handle.
if (is_local_handle(thread, handle) || is_frame_handle(thread, handle)) {
result = JNILocalRefType;
} else {
ShouldNotReachHere();
}
} }
return result; return result;
} }
@ -243,13 +242,15 @@ bool JNIHandles::is_frame_handle(JavaThread* thr, jobject handle) {
bool JNIHandles::is_global_handle(jobject handle) { bool JNIHandles::is_global_handle(jobject handle) {
assert(handle != NULL, "precondition"); assert(handle != NULL, "precondition");
return !is_jweak(handle) && is_storage_handle(global_handles(), jobject_ptr(handle)); assert(!is_global_tagged(handle) || is_storage_handle(global_handles(), global_ptr(handle)), "invalid storage");
return is_global_tagged(handle);
} }
bool JNIHandles::is_weak_global_handle(jobject handle) { bool JNIHandles::is_weak_global_handle(jobject handle) {
assert(handle != NULL, "precondition"); assert(handle != NULL, "precondition");
return is_jweak(handle) && is_storage_handle(weak_global_handles(), jweak_ptr(handle)); assert(!is_weak_global_tagged(handle) || is_storage_handle(weak_global_handles(), weak_global_ptr(handle)), "invalid storage");
return is_weak_global_tagged(handle);
} }
// We assume this is called at a safepoint: no lock is needed. // We assume this is called at a safepoint: no lock is needed.
@ -455,7 +456,7 @@ jobject JNIHandleBlock::allocate_handle(JavaThread* caller, oop obj, AllocFailTy
// Try last block // Try last block
if (_last->_top < block_size_in_oops) { if (_last->_top < block_size_in_oops) {
oop* handle = (oop*)&(_last->_handles)[_last->_top++]; oop* handle = (oop*)&(_last->_handles)[_last->_top++];
NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj); *handle = obj;
return (jobject) handle; return (jobject) handle;
} }
@ -463,7 +464,7 @@ jobject JNIHandleBlock::allocate_handle(JavaThread* caller, oop obj, AllocFailTy
if (_free_list != NULL) { if (_free_list != NULL) {
oop* handle = (oop*)_free_list; oop* handle = (oop*)_free_list;
_free_list = (uintptr_t*) untag_free_list(*_free_list); _free_list = (uintptr_t*) untag_free_list(*_free_list);
NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj); *handle = obj;
return (jobject) handle; return (jobject) handle;
} }
// Check if unused block follow last // Check if unused block follow last

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -45,9 +45,12 @@ class JNIHandles : AllStatic {
static OopStorage* global_handles(); static OopStorage* global_handles();
static OopStorage* weak_global_handles(); static OopStorage* weak_global_handles();
inline static bool is_jweak(jobject handle); inline static bool is_local_tagged(jobject handle);
inline static oop* jobject_ptr(jobject handle); // NOT jweak! inline static bool is_weak_global_tagged(jobject handle);
inline static oop* jweak_ptr(jobject handle); inline static bool is_global_tagged(jobject handle);
inline static oop* local_ptr(jobject handle);
inline static oop* global_ptr(jobject handle);
inline static oop* weak_global_ptr(jweak handle);
template <DecoratorSet decorators, bool external_guard> inline static oop resolve_impl(jobject handle); template <DecoratorSet decorators, bool external_guard> inline static oop resolve_impl(jobject handle);
@ -59,18 +62,24 @@ class JNIHandles : AllStatic {
static bool current_thread_in_native(); static bool current_thread_in_native();
public: public:
// Low tag bit in jobject used to distinguish a jweak. jweak is // Low tag bits in jobject used to distinguish its type. Checking
// type equivalent to jobject, but there are places where we need to // the underlying storage type is unsuitable for performance reasons.
// be able to distinguish jweak values from other jobjects, and enum TypeTag {
// is_weak_global_handle is unsuitable for performance reasons. To local = 0b00,
// provide such a test we add weak_tag_value to the (aligned) byte weak_global = 0b01,
// address designated by the jobject to produce the corresponding global = 0b10,
// jweak. Accessing the value of a jobject must account for it };
// being a possibly offset jweak.
static const uintptr_t weak_tag_size = 1; private:
static const uintptr_t weak_tag_alignment = (1u << weak_tag_size); inline static bool is_tagged_with(jobject handle, TypeTag tag);
static const uintptr_t weak_tag_mask = weak_tag_alignment - 1;
static const int weak_tag_value = 1; public:
static const uintptr_t tag_size = 2;
static const uintptr_t tag_mask = ((1u << tag_size) - 1u);
STATIC_ASSERT((TypeTag::local & tag_mask) == TypeTag::local);
STATIC_ASSERT((TypeTag::weak_global & tag_mask) == TypeTag::weak_global);
STATIC_ASSERT((TypeTag::global & tag_mask) == TypeTag::global);
// Resolve handle into oop // Resolve handle into oop
inline static oop resolve(jobject handle); inline static oop resolve(jobject handle);
@ -94,10 +103,10 @@ class JNIHandles : AllStatic {
static void destroy_global(jobject handle); static void destroy_global(jobject handle);
// Weak global handles // Weak global handles
static jobject make_weak_global(Handle obj, static jweak make_weak_global(Handle obj,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
static void destroy_weak_global(jobject handle); static void destroy_weak_global(jweak handle);
static bool is_global_weak_cleared(jweak handle); // Test jweak without resolution static bool is_weak_global_cleared(jweak handle); // Test jweak without resolution
// Debugging // Debugging
static void print_on(outputStream* st); static void print_on(outputStream* st);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -32,20 +32,37 @@
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
inline bool JNIHandles::is_jweak(jobject handle) { inline bool JNIHandles::is_tagged_with(jobject handle, TypeTag tag) {
STATIC_ASSERT(weak_tag_size == 1); return (reinterpret_cast<uintptr_t>(handle) & tag_mask) == tag;
STATIC_ASSERT(weak_tag_value == 1);
return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0;
} }
inline oop* JNIHandles::jobject_ptr(jobject handle) { inline bool JNIHandles::is_local_tagged(jobject handle) {
assert(!is_jweak(handle), "precondition"); return is_tagged_with(handle, TypeTag::local);
}
inline bool JNIHandles::is_weak_global_tagged(jobject handle) {
return is_tagged_with(handle, TypeTag::weak_global);
}
inline bool JNIHandles::is_global_tagged(jobject handle) {
return is_tagged_with(handle, TypeTag::global);
}
inline oop* JNIHandles::local_ptr(jobject handle) {
assert(is_local_tagged(handle), "precondition");
STATIC_ASSERT(TypeTag::local == 0);
return reinterpret_cast<oop*>(handle); return reinterpret_cast<oop*>(handle);
} }
inline oop* JNIHandles::jweak_ptr(jobject handle) { inline oop* JNIHandles::global_ptr(jobject handle) {
assert(is_jweak(handle), "precondition"); assert(is_global_tagged(handle), "precondition");
char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value; char* ptr = reinterpret_cast<char*>(handle) - TypeTag::global;
return reinterpret_cast<oop*>(ptr);
}
inline oop* JNIHandles::weak_global_ptr(jweak handle) {
assert(is_weak_global_tagged(handle), "precondition");
char* ptr = reinterpret_cast<char*>(handle) - TypeTag::weak_global;
return reinterpret_cast<oop*>(ptr); return reinterpret_cast<oop*>(ptr);
} }
@ -55,10 +72,15 @@ inline oop JNIHandles::resolve_impl(jobject handle) {
assert(handle != NULL, "precondition"); assert(handle != NULL, "precondition");
assert(!current_thread_in_native(), "must not be in native"); assert(!current_thread_in_native(), "must not be in native");
oop result; oop result;
if (is_jweak(handle)) { // Unlikely if (is_weak_global_tagged(handle)) { // Unlikely
result = NativeAccess<ON_PHANTOM_OOP_REF|decorators>::oop_load(jweak_ptr(handle)); result = NativeAccess<ON_PHANTOM_OOP_REF|decorators>::oop_load(weak_global_ptr(handle));
} else if (is_global_tagged(handle)) {
result = NativeAccess<decorators>::oop_load(global_ptr(handle));
// Construction of jobjects canonicalize a null value into a null
// jobject, so for non-jweak the pointee should never be null.
assert(external_guard || result != NULL, "Invalid JNI handle");
} else { } else {
result = NativeAccess<decorators>::oop_load(jobject_ptr(handle)); result = *local_ptr(handle);
// Construction of jobjects canonicalize a null value into a null // Construction of jobjects canonicalize a null value into a null
// jobject, so for non-jweak the pointee should never be null. // jobject, so for non-jweak the pointee should never be null.
assert(external_guard || result != NULL, "Invalid JNI handle"); assert(external_guard || result != NULL, "Invalid JNI handle");
@ -97,8 +119,7 @@ inline oop JNIHandles::resolve_non_null(jobject handle) {
inline void JNIHandles::destroy_local(jobject handle) { inline void JNIHandles::destroy_local(jobject handle) {
if (handle != NULL) { if (handle != NULL) {
assert(!is_jweak(handle), "Invalid JNI local handle"); *local_ptr(handle) = NULL;
NativeAccess<>::oop_store(jobject_ptr(handle), (oop)NULL);
} }
} }

View file

@ -1,4 +1,5 @@
/* /*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019 SAP SE and/or its affiliates. All rights reserved. * Copyright (c) 2019 SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -28,20 +29,26 @@
with primitive type are generated. with primitive type are generated.
* @requires vm.jvmti * @requires vm.jvmti
* @compile FastGetField.java * @compile FastGetField.java
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields FastGetField * @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields FastGetField 0
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable -XX:+SafepointALot -XX:GuaranteedSafepointInterval=1 FastGetField * @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields FastGetField 1
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields FastGetField 2
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable -XX:+SafepointALot -XX:GuaranteedSafepointInterval=1 FastGetField 0
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable -XX:+SafepointALot -XX:GuaranteedSafepointInterval=1 FastGetField 1
* @run main/othervm/native -agentlib:FastGetField -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyJNIFields -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable -XX:+SafepointALot -XX:GuaranteedSafepointInterval=1 FastGetField 2
*/ */
import java.lang.reflect.Field; import java.lang.reflect.Field;
public class FastGetField { public class FastGetField {
private static final String agentLib = "FastGetField"; private static final String agentLib = "FastGetField";
private native boolean initFieldIDs(Class c); private native boolean initFieldIDs(Class c);
private native boolean initWatchers(Class c); private native boolean initWatchers(Class c);
public native void registerGlobal(MyItem i);
public native void registerWeak(MyItem i);
public native long accessFields(MyItem i); public native long accessFields(MyItem i);
public native long accessFieldsViaHandle();
public static native long getFieldAccessCount(); public static native long getFieldAccessCount();
static final int loop_cnt = 10000; static final int loop_cnt = 10000;
@ -92,16 +99,43 @@ public class FastGetField {
} }
} }
private int mode;
private MyItem obj;
private FastGetField(int mode) {
this.mode = mode;
this.obj = new MyItem();
if (mode == 0) {
// Direct
} else if (mode == 1) {
registerGlobal(this.obj);
} else if ( mode == 2) {
registerWeak(this.obj);
} else {
throw new IllegalArgumentException("Unexpected mode");
}
}
private long accessFields() {
if (mode == 0) {
return accessFields(obj);
}
// Otherwise through a handle
return accessFieldsViaHandle();
}
public void TestFieldAccess() throws Exception { public void TestFieldAccess() throws Exception {
MyItem i = new MyItem();
if (!initFieldIDs(MyItem.class)) throw new RuntimeException("FieldID initialization failed!"); if (!initFieldIDs(MyItem.class)) throw new RuntimeException("FieldID initialization failed!");
long duration = System.nanoTime(); long duration = System.nanoTime();
for (int c = 0; c < loop_cnt; ++c) { for (int c = 0; c < loop_cnt; ++c) {
if (accessFields(i) != 0l) throw new RuntimeException("Wrong initial result!"); if (accessFields() != 0l) throw new RuntimeException("Wrong initial result!");
i.change_values(); obj.change_values();
if (accessFields(i) != 8l) throw new RuntimeException("Wrong result after changing!"); if (accessFields() != 8l) throw new RuntimeException("Wrong result after changing!");
i.reset_values(); obj.reset_values();
} }
duration = System.nanoTime() - duration; duration = System.nanoTime() - duration;
System.out.println(loop_cnt + " iterations took " + duration + "ns."); System.out.println(loop_cnt + " iterations took " + duration + "ns.");
@ -112,14 +146,20 @@ public class FastGetField {
if (!initWatchers(MyItem.class)) throw new RuntimeException("JVMTI missing!"); if (!initWatchers(MyItem.class)) throw new RuntimeException("JVMTI missing!");
// Try again with watchers. // Try again with watchers.
if (accessFields(i) != 0l) throw new RuntimeException("Wrong initial result!"); if (accessFields() != 0l) throw new RuntimeException("Wrong initial result!");
i.change_values(); obj.change_values();
if (accessFields(i) != 8l) throw new RuntimeException("Wrong result after changing!"); if (accessFields() != 8l) throw new RuntimeException("Wrong result after changing!");
if (getFieldAccessCount() != 16) throw new RuntimeException("Unexpected event count!"); if (getFieldAccessCount() != 16) throw new RuntimeException("Unexpected event count!");
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
FastGetField inst = new FastGetField(); if (args.length != 1) {
throw new IllegalArgumentException("Expected one argument");
}
int mode = Integer.parseInt(args[0]);
FastGetField inst = new FastGetField(mode);
inst.TestFieldAccess(); inst.TestFieldAccess();
} }
} }

View file

@ -1,4 +1,5 @@
/* /*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022 SAP SE and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2022 SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -32,7 +33,7 @@ static const char* fields[] = { "Z", "B", "C", "S", "I", "J", "F", "D" };
#define NUM_FIELDS (sizeof fields / sizeof fields[0]) #define NUM_FIELDS (sizeof fields / sizeof fields[0])
static jfieldID fieldIDs[NUM_FIELDS]; static jfieldID fieldIDs[NUM_FIELDS];
static jlong fieldAccessCount = 0; static jlong fieldAccessCount = 0;
static jobject objHandle;
JNIEXPORT jboolean JNICALL Java_FastGetField_initFieldIDs(JNIEnv *env, jobject this, jclass c) { JNIEXPORT jboolean JNICALL Java_FastGetField_initFieldIDs(JNIEnv *env, jobject this, jclass c) {
for (int i = 0; i < (int)NUM_FIELDS; ++i) { for (int i = 0; i < (int)NUM_FIELDS; ++i) {
@ -63,6 +64,13 @@ JNIEXPORT jboolean JNICALL Java_FastGetField_initWatchers(JNIEnv *env, jobject t
return JNI_TRUE; return JNI_TRUE;
} }
JNIEXPORT void JNICALL Java_FastGetField_registerGlobal(JNIEnv *env, jobject this, jobject obj) {
objHandle = (*env)->NewGlobalRef(env, obj);
}
JNIEXPORT void JNICALL Java_FastGetField_registerWeak(JNIEnv *env, jobject this, jobject obj) {
objHandle = (*env)->NewWeakGlobalRef(env, obj);
}
JNIEXPORT jlong JNICALL Java_FastGetField_accessFields(JNIEnv *env, jobject this, jobject obj) { JNIEXPORT jlong JNICALL Java_FastGetField_accessFields(JNIEnv *env, jobject this, jobject obj) {
return return
@ -76,6 +84,9 @@ JNIEXPORT jlong JNICALL Java_FastGetField_accessFields(JNIEnv *env, jobject this
(jlong)((*env)->GetDoubleField(env, obj, fieldIDs[7])); (jlong)((*env)->GetDoubleField(env, obj, fieldIDs[7]));
} }
JNIEXPORT jlong JNICALL Java_FastGetField_accessFieldsViaHandle(JNIEnv *env, jobject this) {
return Java_FastGetField_accessFields(env, this, objHandle);
}
JNIEXPORT jlong JNICALL Java_FastGetField_getFieldAccessCount(JNIEnv *env, jclass c) { JNIEXPORT jlong JNICALL Java_FastGetField_getFieldAccessCount(JNIEnv *env, jclass c) {
return fieldAccessCount; return fieldAccessCount;