mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
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:
parent
66f7387b5f
commit
c7056737e3
36 changed files with 470 additions and 227 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,21 +115,28 @@ 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);
|
|
||||||
load_at(masm, IN_NATIVE | ON_PHANTOM_OOP_REF, T_OBJECT,
|
|
||||||
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
|
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);
|
||||||
|
__ 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);
|
value, (intptr_t)0, value, tmp1, tmp2, preservation_level);
|
||||||
|
|
||||||
__ bind(verify);
|
__ bind(verify);
|
||||||
|
@ -137,9 +144,36 @@ void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
|
||||||
__ 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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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,14 +196,14 @@ 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:
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Not in global storage. Might be a local handle.
|
// Not in global storage. Might be a local handle.
|
||||||
if (is_local_handle(thread, handle) || is_frame_handle(thread, handle)) {
|
if (is_local_handle(thread, handle) || is_frame_handle(thread, handle)) {
|
||||||
result = JNILocalRefType;
|
result = JNILocalRefType;
|
||||||
}
|
} else {
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue