Skip to content

Commit

Permalink
Merge branch 'upstream-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Datadog Syncup Service committed Nov 11, 2023
2 parents a4723ad + 9938b3f commit ff21baf
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 22 deletions.
23 changes: 13 additions & 10 deletions src/hotspot/share/nmt/memBaseline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,25 @@ class MallocAllocationSiteWalker : public MallocSiteWalker {
}
};

// Compare virtual memory region's base address
int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
return r1.compare(r2);
}

// Walk all virtual memory regions for baselining
class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
private:
SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
_virtual_memory_regions;
size_t _count;

typedef LinkedListImpl<ReservedMemoryRegion, AnyObj::C_HEAP, mtNMT,
AllocFailStrategy::RETURN_NULL> EntryList;
EntryList _virtual_memory_regions;
size_t _count;
DEBUG_ONLY(address _last_base;)
public:
VirtualMemoryAllocationWalker() : _count(0) { }
VirtualMemoryAllocationWalker() :
_count(0)
#ifdef ASSERT
, _last_base(nullptr)
#endif
{}

bool do_allocation_site(const ReservedMemoryRegion* rgn) {
assert(rgn->base() >= _last_base, "region unordered?");
DEBUG_ONLY(_last_base = rgn->base());
if (rgn->size() > 0) {
if (_virtual_memory_regions.add(*rgn) != nullptr) {
_count ++;
Expand Down
17 changes: 14 additions & 3 deletions src/hotspot/share/runtime/deoptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#include "runtime/stackValue.hpp"
#include "runtime/stackWatermarkSet.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/threadSMR.hpp"
#include "runtime/threadWXSetters.inline.hpp"
#include "runtime/vframe.hpp"
Expand Down Expand Up @@ -1636,9 +1637,19 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray<MonitorInf
}
}
}
BasicLock* lock = mon_info->lock();
ObjectSynchronizer::enter(obj, lock, deoptee_thread);
assert(mon_info->owner()->is_locked(), "object must be locked now");
if (LockingMode == LM_LIGHTWEIGHT && exec_mode == Unpack_none) {
// We have lost information about the correct state of the lock stack.
// Inflate the locks instead. Enter then inflate to avoid races with
// deflation.
ObjectSynchronizer::enter(obj, nullptr, deoptee_thread);
assert(mon_info->owner()->is_locked(), "object must be locked now");
ObjectMonitor* mon = ObjectSynchronizer::inflate(deoptee_thread, obj(), ObjectSynchronizer::inflate_cause_vm_internal);
assert(mon->owner() == deoptee_thread, "must be");
} else {
BasicLock* lock = mon_info->lock();
ObjectSynchronizer::enter(obj, lock, deoptee_thread);
assert(mon_info->owner()->is_locked(), "object must be locked now");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,10 @@ private Content generateContent(Element holder, DocTree tag)
StyledText externalSnippet = null;

try {
Diags d = (text, pos) -> {
Diags d = (key, pos) -> {
var path = utils.getCommentHelper(holder)
.getDocTreePath(snippetTag.getBody());
var text = resources.getText(key);
config.getReporter().print(Diagnostic.Kind.WARNING,
path, pos, pos, pos, text);
};
Expand All @@ -397,7 +398,7 @@ private Content generateContent(Element holder, DocTree tag)

try {
var finalFileObject = fileObject;
Diags d = (text, pos) -> messages.warning(finalFileObject, pos, pos, pos, text);
Diags d = (key, pos) -> messages.warning(finalFileObject, pos, pos, pos, key);
if (externalContent != null) {
externalSnippet = parse(resources, d, language, externalContent);
}
Expand Down Expand Up @@ -484,7 +485,7 @@ private StyledText parse(Resources resources, Diags diags, Optional<Language> la
}

public interface Diags {
void warn(String text, int pos);
void warn(String key, int pos);
}

private static String stringValueOf(AttributeTree at) throws BadSnippetException {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -161,7 +161,7 @@ record OffsetAndLine(int offset, String line) { }
}
}
if (parsedTags.isEmpty()) { // (2)
diags.warn(resources.getText("doclet.snippet.markup.spurious"), next.offset() + markedUpLine.start("markup"));
diags.warn("doclet.snippet.markup.spurious", next.offset() + markedUpLine.start("markup"));
line = rawLine + (addLineTerminator ? "\n" : "");
} else { // (3)
hasMarkup = true;
Expand Down
143 changes: 143 additions & 0 deletions test/jdk/com/sun/jdi/EATests.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=1
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
Expand All @@ -50,6 +51,7 @@
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=1
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
Expand All @@ -58,6 +60,7 @@
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=1
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
Expand All @@ -66,6 +69,44 @@
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=1
*
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
* -Xbootclasspath/a:.
* -XX:CompileCommand=dontinline,*::dontinline_*
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=2
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
* -Xbootclasspath/a:.
* -XX:CompileCommand=dontinline,*::dontinline_*
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=2
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
* -Xbootclasspath/a:.
* -XX:CompileCommand=dontinline,*::dontinline_*
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=2
* @run driver EATests
* -XX:+UnlockDiagnosticVMOptions
* -Xms256m -Xmx256m
* -Xbootclasspath/a:.
* -XX:CompileCommand=dontinline,*::dontinline_*
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
* -XX:LockingMode=2
*
* @comment Excercise -XX:+DeoptimizeObjectsALot. Mostly to prevent bit-rot because the option is meant to stress object deoptimization
* with non-synthetic workloads.
Expand Down Expand Up @@ -208,11 +249,13 @@ public static void main(String[] args) {

// Relocking test cases
new EARelockingSimpleTarget() .run();
new EARelockingSimpleWithAccessInOtherThreadTarget() .run();
new EARelockingRecursiveTarget() .run();
new EARelockingNestedInflatedTarget() .run();
new EARelockingNestedInflated_02Target() .run();
new EARelockingArgEscapeLWLockedInCalleeFrameTarget() .run();
new EARelockingArgEscapeLWLockedInCalleeFrame_2Target() .run();
new EARelockingArgEscapeLWLockedInCalleeFrameNoRecursiveTarget() .run();
new EAGetOwnedMonitorsTarget() .run();
new EAEntryCountTarget() .run();
new EARelockingObjectCurrentlyWaitingOnTarget() .run();
Expand Down Expand Up @@ -328,11 +371,13 @@ protected void runTests() throws Exception {

// Relocking test cases
new EARelockingSimple() .run(this);
new EARelockingSimpleWithAccessInOtherThread() .run(this);
new EARelockingRecursive() .run(this);
new EARelockingNestedInflated() .run(this);
new EARelockingNestedInflated_02() .run(this);
new EARelockingArgEscapeLWLockedInCalleeFrame() .run(this);
new EARelockingArgEscapeLWLockedInCalleeFrame_2() .run(this);
new EARelockingArgEscapeLWLockedInCalleeFrameNoRecursive() .run(this);
new EAGetOwnedMonitors() .run(this);
new EAEntryCount() .run(this);
new EARelockingObjectCurrentlyWaitingOn() .run(this);
Expand Down Expand Up @@ -1707,6 +1752,62 @@ public void dontinline_testMethod() {

/////////////////////////////////////////////////////////////////////////////

// The debugger reads and publishes an object with eliminated locking to an instance field.
// A 2nd thread in the debuggee finds it there and changes its state using a synchronized method.
// Without eager relocking the accesses are unsynchronized which can be observed.
class EARelockingSimpleWithAccessInOtherThread extends EATestCaseBaseDebugger {

public void runTestCase() throws Exception {
BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
printStack(bpe.thread());
String l1ClassName = EARelockingSimpleWithAccessInOtherThreadTarget.SyncCounter.class.getName();
ObjectReference ctr = getLocalRef(bpe.thread().frame(1), l1ClassName, "l1");
setField(testCase, "sharedCounter", ctr);
terminateEndlessLoop();
}
}

class EARelockingSimpleWithAccessInOtherThreadTarget extends EATestCaseBaseTarget {

public static class SyncCounter {
private int val;
public synchronized int inc() { return val++; }
}

public volatile SyncCounter sharedCounter;

@Override
public void setUp() {
super.setUp();
doLoop = true;
Thread.ofPlatform().daemon().start(() -> {
while (doLoop) {
SyncCounter ctr = sharedCounter;
if (ctr != null) {
ctr.inc();
}
}
});
}

public void dontinline_testMethod() {
SyncCounter l1 = new SyncCounter();
synchronized (l1) { // Eliminated locking
l1.inc();
dontinline_brkpt(); // Debugger publishes l1 to sharedCounter.
iResult = l1.inc(); // Changes by the 2nd thread will be observed if l1
// was not relocked before passing it to the debugger.
}
}

@Override
public int getExpectedIResult() {
return 1;
}
}

/////////////////////////////////////////////////////////////////////////////

// Test recursive locking
class EARelockingRecursiveTarget extends EATestCaseBaseTarget {

Expand Down Expand Up @@ -1905,6 +2006,48 @@ public int getExpectedIResult() {

/////////////////////////////////////////////////////////////////////////////

/**
* Similar to {@link EARelockingArgEscapeLWLockedInCalleeFrame_2Target}. It does
* not use recursive locking and exposed a bug in the lightweight-locking implementation.
*/
class EARelockingArgEscapeLWLockedInCalleeFrameNoRecursive extends EATestCaseBaseDebugger {

public void runTestCase() throws Exception {
BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
printStack(bpe.thread());
@SuppressWarnings("unused")
ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
}
}

class EARelockingArgEscapeLWLockedInCalleeFrameNoRecursiveTarget extends EATestCaseBaseTarget {

@Override
public void setUp() {
super.setUp();
testMethodDepth = 2;
}

public void dontinline_testMethod() {
XYVal l1 = new XYVal(1, 1); // NoEscape, scalar replaced
XYVal l2 = new XYVal(4, 2); // NoEscape, scalar replaced
XYVal l3 = new XYVal(5, 3); // ArgEscape
synchronized (l1) { // eliminated
synchronized (l2) { // eliminated
l3.dontinline_sync_method(this); // l3 escapes
}
}
iResult = l2.x + l2.y;
}

@Override
public int getExpectedIResult() {
return 6;
}
}

/////////////////////////////////////////////////////////////////////////////

/**
* Test relocking eliminated (nested) locks of an object on which the
* target thread currently waits.
Expand Down
Loading

0 comments on commit ff21baf

Please sign in to comment.