Skip to content

Commit 022c60e

Browse files
committed
AArch64: Add cross modify fence verification
1 parent 853d6c7 commit 022c60e

File tree

8 files changed

+85
-7
lines changed

8 files changed

+85
-7
lines changed

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4403,10 +4403,15 @@ void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype)
44034403
// Read the polling page. The address of the polling page must
44044404
// already be in r.
44054405
address MacroAssembler::read_polling_page(Register r, relocInfo::relocType rtype) {
4406-
InstructionMark im(this);
4407-
code_section()->relocate(inst_mark(), rtype);
4408-
ldrw(zr, Address(r, 0));
4409-
return inst_mark();
4406+
address mark;
4407+
{
4408+
InstructionMark im(this);
4409+
code_section()->relocate(inst_mark(), rtype);
4410+
ldrw(zr, Address(r, 0));
4411+
mark = inst_mark();
4412+
}
4413+
verify_cross_modify_fence_not_required();
4414+
return mark;
44104415
}
44114416

44124417
void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset) {
@@ -4471,6 +4476,7 @@ void MacroAssembler::build_frame(int framesize) {
44714476
sub(sp, sp, rscratch1);
44724477
}
44734478
}
4479+
verify_cross_modify_fence_not_required();
44744480
}
44754481

44764482
void MacroAssembler::remove_frame(int framesize) {
@@ -5298,3 +5304,29 @@ void MacroAssembler::verify_ptrue() {
52985304
stop("Error: the preserved predicate register (p7) elements are not all true");
52995305
bind(verify_ok);
53005306
}
5307+
5308+
void MacroAssembler::safepoint_isb() {
5309+
isb();
5310+
#ifndef PRODUCT
5311+
if (VerifyCrossModifyFence) {
5312+
// Clear the thread state.
5313+
strb(zr, Address(rthread, in_bytes(JavaThread::requires_cross_modify_fence_offset())));
5314+
}
5315+
#endif
5316+
}
5317+
5318+
#ifndef PRODUCT
5319+
void MacroAssembler::verify_cross_modify_fence_not_required() {
5320+
if (VerifyCrossModifyFence) {
5321+
// Check if thread needs a cross modify fence.
5322+
ldrb(rscratch1, Address(rthread, in_bytes(JavaThread::requires_cross_modify_fence_offset())));
5323+
Label fence_not_required;
5324+
cbz(rscratch1, fence_not_required);
5325+
// If it does then fail.
5326+
lea(rscratch1, CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure));
5327+
mov(c_rarg0, rthread);
5328+
blr(rscratch1);
5329+
bind(fence_not_required);
5330+
}
5331+
}
5332+
#endif

src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ class MacroAssembler: public Assembler {
13071307
void mul_add(Register out, Register in, Register offs, Register len, Register k);
13081308

13091309
// Place an ISB after code may have been modified due to a safepoint.
1310-
void safepoint_isb() { isb(); }
1310+
void safepoint_isb();
13111311

13121312
private:
13131313
// Return the effective address r + (r1 << ext) + offset.
@@ -1383,6 +1383,11 @@ class MacroAssembler: public Assembler {
13831383
}
13841384
void cache_wb(Address line);
13851385
void cache_wbsync(bool is_pre);
1386+
1387+
private:
1388+
// Check the current thread doesn't need a cross modify fence.
1389+
void verify_cross_modify_fence_not_required() PRODUCT_RETURN;
1390+
13861391
};
13871392

13881393
#ifdef ASSERT

src/hotspot/share/runtime/globals.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2460,7 +2460,11 @@ const intx ObjectAlignmentInBytes = 8;
24602460
"Allow allocating fields in empty slots of super-classes") \
24612461
\
24622462
product(bool, DeoptimizeNMethodBarriersALot, false, DIAGNOSTIC, \
2463-
"Make nmethod barriers deoptimise a lot.")
2463+
"Make nmethod barriers deoptimise a lot.") \
2464+
\
2465+
develop(bool, VerifyCrossModifyFence, false, \
2466+
"Mark all threads after a safepoint, and clear on a modify " \
2467+
"fence. Add cleanliness checks.") \
24642468

24652469
// end of RUNTIME_FLAGS
24662470

src/hotspot/share/runtime/orderAccess.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,10 @@
2525
#include "precompiled.hpp"
2626
#include "runtime/orderAccess.hpp"
2727
#include "runtime/stubRoutines.hpp"
28+
29+
#ifndef PRODUCT
2830
#include "runtime/thread.hpp"
31+
#endif
2932

3033
void OrderAccess::StubRoutines_fence() {
3134
// Use a stub if it exists. It may not exist during bootstrap so do
@@ -38,3 +41,11 @@ void OrderAccess::StubRoutines_fence() {
3841
}
3942
assert(Threads::number_of_threads() == 0, "for bootstrap only");
4043
}
44+
45+
#ifndef PRODUCT
46+
void OrderAccess::cross_modify_fence_verify() {
47+
if (VerifyCrossModifyFence) {
48+
JavaThread::current()->set_requires_cross_modify_fence(false);
49+
}
50+
}
51+
#endif

src/hotspot/share/runtime/orderAccess.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ class OrderAccess : public AllStatic {
258258

259259
static void cross_modify_fence() {
260260
cross_modify_fence_impl();
261+
cross_modify_fence_verify();
261262
}
262263

263264
// Processors which are not multi-copy-atomic require a full fence
@@ -277,6 +278,8 @@ class OrderAccess : public AllStatic {
277278
static void StubRoutines_fence();
278279

279280
static void cross_modify_fence_impl();
281+
282+
static void cross_modify_fence_verify() PRODUCT_RETURN;
280283
};
281284

282285
#include OS_CPU_HEADER(orderAccess)

src/hotspot/share/runtime/safepoint.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,14 @@ void SafepointSynchronize::begin() {
381381
assert(_waiting_to_block == 0, "No thread should be running");
382382

383383
#ifndef PRODUCT
384+
// Mark all threads
385+
if (VerifyCrossModifyFence) {
386+
JavaThreadIteratorWithHandle jtiwh;
387+
for (; JavaThread *cur = jtiwh.next(); ) {
388+
cur->set_requires_cross_modify_fence(true);
389+
}
390+
}
391+
384392
if (safepoint_limit_time != 0) {
385393
jlong current_time = os::javaTimeNanos();
386394
if (safepoint_limit_time < current_time) {

src/hotspot/share/runtime/thread.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,9 @@ JavaThread::JavaThread() :
17751775
ThreadSafepointState::create(this);
17761776

17771777
SafepointMechanism::initialize_header(this);
1778+
1779+
set_requires_cross_modify_fence(false);
1780+
17781781
pd_initialize();
17791782
assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
17801783
}
@@ -4959,3 +4962,9 @@ void Threads::verify() {
49594962
VMThread* thread = VMThread::vm_thread();
49604963
if (thread != NULL) thread->verify();
49614964
}
4965+
4966+
#ifndef PRODUCT
4967+
void JavaThread::verify_cross_modify_fence_failure(JavaThread *thread) {
4968+
report_vm_error(__FILE__, __LINE__, "Cross modify fence failure", "%p", thread);
4969+
}
4970+
#endif

src/hotspot/share/runtime/thread.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ class JavaThread: public Thread {
11091109
private:
11101110
ThreadSafepointState* _safepoint_state; // Holds information about a thread during a safepoint
11111111
address _saved_exception_pc; // Saved pc of instruction where last implicit exception happened
1112+
NOT_PRODUCT(bool _requires_cross_modify_fence;) // State used by VerifyCrossModifyFence
11121113

11131114
// JavaThread termination support
11141115
enum TerminatedTypes {
@@ -1339,6 +1340,8 @@ class JavaThread: public Thread {
13391340

13401341
SafepointMechanism::ThreadData* poll_data() { return &_poll_data; }
13411342

1343+
void set_requires_cross_modify_fence(bool val) PRODUCT_RETURN NOT_PRODUCT({ _requires_cross_modify_fence = val; })
1344+
13421345
private:
13431346
// Support for thread handshake operations
13441347
HandshakeState _handshake;
@@ -1634,6 +1637,7 @@ class JavaThread: public Thread {
16341637
return byte_offset_of(JavaThread, _should_post_on_exceptions_flag);
16351638
}
16361639
static ByteSize doing_unsafe_access_offset() { return byte_offset_of(JavaThread, _doing_unsafe_access); }
1640+
NOT_PRODUCT(static ByteSize requires_cross_modify_fence_offset() { return byte_offset_of(JavaThread, _requires_cross_modify_fence); })
16371641

16381642
// Returns the jni environment for this thread
16391643
JNIEnv* jni_environment() { return &_jni_environment; }
@@ -1923,6 +1927,8 @@ class JavaThread: public Thread {
19231927
bool is_interrupted(bool clear_interrupted);
19241928

19251929
static OopStorage* thread_oop_storage();
1930+
1931+
static void verify_cross_modify_fence_failure(JavaThread *thread) PRODUCT_RETURN;
19261932
};
19271933

19281934
// Inline implementation of JavaThread::current

0 commit comments

Comments
 (0)