8191437: AOT doesn't work easily after thread local handshakes
Reviewed-by: kvn, rehn, aph
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Thu Nov 30 10:40:48 2017 -0800
@@ -3388,26 +3388,29 @@
// No exception case
__ bind(noException);
- Label no_adjust, bail;
+ Label no_adjust, bail, no_prefix;
if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
// If our stashed return pc was modified by the runtime we avoid touching it
__ cmpptr(rbx, Address(rbp, wordSize));
__ jccb(Assembler::notEqual, no_adjust);
-#ifdef ASSERT
// Verify the correct encoding of the poll we're about to skip.
// See NativeInstruction::is_safepoint_poll()
__ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_rex_b_prefix);
- __ jcc(Assembler::notEqual, bail);
- __ cmpb(Address(rbx, 1), NativeTstRegMem::instruction_code_memXregl);
+ __ jcc(Assembler::notEqual, no_prefix);
+ __ addptr(rbx, 1);
+ __ bind(no_prefix);
+#ifdef ASSERT
+ __ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_code_memXregl);
__ jcc(Assembler::notEqual, bail);
// Mask out the modrm bits
- __ testb(Address(rbx, 2), NativeTstRegMem::modrm_mask);
+ __ testb(Address(rbx, 1), NativeTstRegMem::modrm_mask);
// rax encodes to 0, so if the bits are nonzero it's incorrect
__ jcc(Assembler::notZero, bail);
#endif
// Adjust return pc forward to step over the safepoint poll instruction
- __ addptr(Address(rbp, wordSize), 3);
+ __ addptr(rbx, 2);
+ __ movptr(Address(rbp, wordSize), rbx);
}
__ bind(no_adjust);
--- a/src/hotspot/share/aot/aotCodeHeap.cpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp Thu Nov 30 10:40:48 2017 -0800
@@ -167,6 +167,7 @@
verify_flag(_config->_compactFields, CompactFields, "CompactFields");
verify_flag(_config->_enableContended, EnableContended, "EnableContended");
verify_flag(_config->_restrictContended, RestrictContended, "RestrictContended");
+ verify_flag(_config->_threadLocalHandshakes, ThreadLocalHandshakes, "ThreadLocalHandshakes");
if (!TieredCompilation && _config->_tieredAOT) {
handle_config_error("Shared file %s error: Expected to run with tiered compilation on", _name);
--- a/src/hotspot/share/aot/aotCodeHeap.hpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/share/aot/aotCodeHeap.hpp Thu Nov 30 10:40:48 2017 -0800
@@ -92,7 +92,7 @@
} AOTHeader;
typedef struct {
- enum { CONFIG_SIZE = 7 * jintSize + 11 };
+ enum { CONFIG_SIZE = 7 * jintSize + 12 };
// 7 int values
int _config_size;
int _narrowOopShift;
@@ -101,7 +101,7 @@
int _fieldsAllocationStyle;
int _objectAlignment;
int _codeSegmentSize;
- // byte[11] array map to boolean values here
+ // byte[12] array map to boolean values here
bool _debug_VM;
bool _useCompressedOops;
bool _useCompressedClassPointers;
@@ -113,6 +113,7 @@
bool _enableContended;
bool _restrictContended;
bool _omitAssertions;
+ bool _threadLocalHandshakes;
} AOTConfiguration;
class AOTLib : public CHeapObj<mtCode> {
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Thu Nov 30 10:40:48 2017 -0800
@@ -317,6 +317,7 @@
\
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
nonstatic_field(Thread, _allocated_bytes, jlong) \
+ nonstatic_field(Thread, _polling_page, address) \
\
nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \
nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \
--- a/src/hotspot/share/runtime/arguments.cpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Nov 30 10:40:48 2017 -0800
@@ -4397,26 +4397,7 @@
}
#endif
- bool aot_enabled = UseAOT && AOTLibrary != NULL;
- bool jvmci_enabled = NOT_JVMCI(false) JVMCI_ONLY(EnableJVMCI || UseJVMCICompiler);
- bool handshakes_supported = SafepointMechanism::supports_thread_local_poll() && !aot_enabled && !jvmci_enabled && ThreadLocalHandshakes;
// ThreadLocalHandshakesConstraintFunc handles the constraints.
- // Here we try to figure out if a mutual exclusive option have been set that conflict with a default.
- if (handshakes_supported) {
- FLAG_SET_DEFAULT(UseAOT, false); // Clear the AOT flag to make sure it doesn't try to initialize.
- } else {
- if (FLAG_IS_DEFAULT(ThreadLocalHandshakes) && ThreadLocalHandshakes) {
- if (aot_enabled) {
- // If user enabled AOT but ThreadLocalHandshakes is at default set it to false.
- log_debug(ergo)("Disabling ThreadLocalHandshakes for UseAOT.");
- FLAG_SET_DEFAULT(ThreadLocalHandshakes, false);
- } else if (jvmci_enabled){
- // If user enabled JVMCI but ThreadLocalHandshakes is at default set it to false.
- log_debug(ergo)("Disabling ThreadLocalHandshakes for EnableJVMCI/UseJVMCICompiler.");
- FLAG_SET_DEFAULT(ThreadLocalHandshakes, false);
- }
- }
- }
if (FLAG_IS_DEFAULT(ThreadLocalHandshakes) || !SafepointMechanism::supports_thread_local_poll()) {
log_debug(ergo)("ThreadLocalHandshakes %s", ThreadLocalHandshakes ? "enabled." : "disabled.");
} else {
--- a/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp Thu Nov 30 14:25:33 2017 -0800
+++ b/src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp Thu Nov 30 10:40:48 2017 -0800
@@ -138,10 +138,6 @@
CommandLineError::print(verbose, "ThreadLocalHandshakes not yet supported on this platform\n");
return Flag::VIOLATES_CONSTRAINT;
}
- if (UseAOT JVMCI_ONLY(|| EnableJVMCI || UseJVMCICompiler)) {
- CommandLineError::print(verbose, "ThreadLocalHandshakes not yet supported in combination with AOT or JVMCI\n");
- return Flag::VIOLATES_CONSTRAINT;
- }
}
return Flag::SUCCESS;
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Nov 30 10:40:48 2017 -0800
@@ -65,6 +65,8 @@
private final int codeEntryAlignment;
+ private final boolean threadLocalHandshakes;
+
/**
* Container holding code bits and any other related information.
*/
@@ -279,6 +281,8 @@
this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
+ this.threadLocalHandshakes = graalHotSpotVMConfig.threadLocalHandshakes;
+
// Section unique name is limited to 8 characters due to limitation on Windows.
// Name could be longer but only first 8 characters are stored on Windows.
@@ -323,7 +327,8 @@
TieredAOT.getValue(graalOptions),
graalHotSpotVMConfig.enableContended,
graalHotSpotVMConfig.restrictContended,
- graphBuilderConfig.omitAssertions()
+ graphBuilderConfig.omitAssertions(),
+ graalHotSpotVMConfig.threadLocalHandshakes
};
int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(),
@@ -434,6 +439,11 @@
return codeEntryAlignment;
}
+ public boolean getThreadLocalHandshakes() {
+ return threadLocalHandshakes;
+ }
+
+
/**
* Gets the global AOT symbol associated with the function name.
*
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Thu Nov 30 10:40:48 2017 -0800
@@ -45,6 +45,7 @@
* @param methodInfo compiled method info
* @param mark mark being processed
*/
+ @SuppressWarnings("fallthrough")
void process(CompiledMethodInfo methodInfo, Mark mark) {
MarkId markId = MarkId.getEnum((int) mark.id);
switch (markId) {
@@ -53,6 +54,11 @@
break;
case POLL_FAR:
case POLL_RETURN_FAR:
+ if (binaryContainer.getThreadLocalHandshakes()) {
+ // skip relocation
+ break;
+ }
+ // fallthrough
case CARD_TABLE_ADDRESS:
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -37,10 +37,18 @@
abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp {
private final GraalHotSpotVMConfig config;
+ private final Register thread;
+
+ protected AArch64HotSpotEpilogueOp(LIRInstructionClass<? extends AArch64HotSpotEpilogueOp> c, GraalHotSpotVMConfig config, Register thread) {
+ super(c);
+ this.config = config;
+ this.thread = thread;
+ }
protected AArch64HotSpotEpilogueOp(LIRInstructionClass<? extends AArch64HotSpotEpilogueOp> c, GraalHotSpotVMConfig config) {
super(c);
this.config = config;
+ this.thread = null; // no safepoint
}
protected void leaveFrame(CompilationResultBuilder crb, AArch64MacroAssembler masm, boolean emitSafepoint) {
@@ -49,7 +57,7 @@
if (emitSafepoint) {
try (ScratchRegister sc = masm.getScratchRegister()) {
Register scratch = sc.getRegister();
- AArch64HotSpotSafepointOp.emitCode(crb, masm, config, true, scratch, null);
+ AArch64HotSpotSafepointOp.emitCode(crb, masm, config, true, thread, scratch, null);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -342,7 +342,8 @@
operand = resultOperandFor(kind, input.getValueKind());
emitMove(operand, input);
}
- append(new AArch64HotSpotReturnOp(operand, getStub() != null, config));
+ Register thread = getProviders().getRegisters().getThreadRegister();
+ append(new AArch64HotSpotReturnOp(operand, getStub() != null, config, thread));
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -118,8 +118,9 @@
@Override
public void visitSafepointNode(SafepointNode i) {
LIRFrameState info = state(i);
+ Register thread = getGen().getProviders().getRegisters().getThreadRegister();
Variable scratch = gen.newVariable(LIRKind.value(getGen().target().arch.getWordKind()));
- append(new AArch64HotSpotSafepointOp(info, getGen().config, scratch));
+ append(new AArch64HotSpotSafepointOp(info, getGen().config, thread, scratch));
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotReturnOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -33,6 +33,7 @@
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.Value;
/**
@@ -46,8 +47,8 @@
@Use({REG, ILLEGAL}) private Value result;
private final boolean isStub;
- public AArch64HotSpotReturnOp(Value result, boolean isStub, GraalHotSpotVMConfig config) {
- super(TYPE, config);
+ public AArch64HotSpotReturnOp(Value result, boolean isStub, GraalHotSpotVMConfig config, Register thread) {
+ super(TYPE, config, thread);
assert validReturnValue(result);
this.result = result;
this.isStub = isStub;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -50,18 +50,20 @@
@Temp protected AllocatableValue scratchValue;
private final GraalHotSpotVMConfig config;
+ private final Register thread;
- public AArch64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, AllocatableValue scratch) {
+ public AArch64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, Register thread, AllocatableValue scratch) {
super(TYPE);
this.state = state;
this.config = config;
+ this.thread = thread;
this.scratchValue = scratch;
}
@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
Register scratch = asRegister(scratchValue);
- emitCode(crb, masm, config, false, scratch, state);
+ emitCode(crb, masm, config, false, thread, scratch, state);
}
/**
@@ -76,7 +78,15 @@
return !NumUtil.isSignedNbit(21, pollingPageAddress - config.codeCacheLowBound) || !NumUtil.isSignedNbit(21, pollingPageAddress - config.codeCacheHighBound);
}
- public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) {
+ public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register thread, Register scratch, LIRFrameState state) {
+ if (config.threadLocalHandshakes) {
+ emitThreadLocalPoll(crb, masm, config, onReturn, thread, scratch, state);
+ } else {
+ emitGlobalPoll(crb, masm, config, onReturn, scratch, state);
+ }
+ }
+
+ private static void emitGlobalPoll(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) {
if (isPollingPageFar(config)) {
crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
masm.movNativeAddress(scratch, config.safepointPollingAddress);
@@ -94,4 +104,15 @@
}
}
+ private static void emitThreadLocalPoll(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register thread, Register scratch,
+ LIRFrameState state) {
+ assert config.threadPollingPageOffset >= 0;
+ masm.ldr(64, scratch, masm.makeAddress(thread, config.threadPollingPageOffset, 8));
+ crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
+ if (state != null) {
+ crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT);
+ }
+ masm.ldr(32, zr, AArch64Address.createBaseRegisterOnlyAddress(scratch));
+ }
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Nov 30 10:40:48 2017 -0800
@@ -264,7 +264,8 @@
if (pollOnReturnScratchRegister == null) {
pollOnReturnScratchRegister = findPollOnReturnScratchRegister();
}
- append(new AMD64HotSpotReturnOp(operand, getStub() != null, pollOnReturnScratchRegister, config));
+ Register thread = getProviders().getRegisters().getThreadRegister();
+ append(new AMD64HotSpotReturnOp(operand, getStub() != null, thread, pollOnReturnScratchRegister, config));
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -121,7 +121,8 @@
@Override
public void visitSafepointNode(SafepointNode i) {
LIRFrameState info = state(i);
- append(new AMD64HotSpotSafepointOp(info, getGen().config, this));
+ Register thread = getGen().getProviders().getRegisters().getThreadRegister();
+ append(new AMD64HotSpotSafepointOp(info, getGen().config, this, thread));
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -45,13 +45,15 @@
public static final LIRInstructionClass<AMD64HotSpotReturnOp> TYPE = LIRInstructionClass.create(AMD64HotSpotReturnOp.class);
@Use({REG, ILLEGAL}) protected Value value;
private final boolean isStub;
+ private final Register thread;
private final Register scratchForSafepointOnReturn;
private final GraalHotSpotVMConfig config;
- AMD64HotSpotReturnOp(Value value, boolean isStub, Register scratchForSafepointOnReturn, GraalHotSpotVMConfig config) {
+ AMD64HotSpotReturnOp(Value value, boolean isStub, Register thread, Register scratchForSafepointOnReturn, GraalHotSpotVMConfig config) {
super(TYPE);
this.value = value;
this.isStub = isStub;
+ this.thread = thread;
this.scratchForSafepointOnReturn = scratchForSafepointOnReturn;
this.config = config;
}
@@ -61,7 +63,7 @@
leaveFrameAndRestoreRbp(crb, masm);
if (!isStub) {
// Every non-stub compile method must have a poll before the return.
- AMD64HotSpotSafepointOp.emitCode(crb, masm, config, true, null, scratchForSafepointOnReturn);
+ AMD64HotSpotSafepointOp.emitCode(crb, masm, config, true, null, thread, scratchForSafepointOnReturn);
/*
* We potentially return to the interpreter, and that's an AVX-SSE transition. The only
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -58,12 +58,14 @@
@Temp({OperandFlag.REG, OperandFlag.ILLEGAL}) private AllocatableValue temp;
private final GraalHotSpotVMConfig config;
+ private final Register thread;
- public AMD64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, NodeLIRBuilderTool tool) {
+ public AMD64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, NodeLIRBuilderTool tool, Register thread) {
super(TYPE);
this.state = state;
this.config = config;
- if (isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) {
+ this.thread = thread;
+ if (config.threadLocalHandshakes || isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) {
temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind()));
} else {
// Don't waste a register if it's unneeded
@@ -73,7 +75,15 @@
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
- emitCode(crb, asm, config, false, state, temp instanceof RegisterValue ? ((RegisterValue) temp).getRegister() : null);
+ emitCode(crb, asm, config, false, state, thread, temp instanceof RegisterValue ? ((RegisterValue) temp).getRegister() : null);
+ }
+
+ public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread, Register scratch) {
+ if (config.threadLocalHandshakes) {
+ emitThreadLocalPoll(crb, asm, config, atReturn, state, thread, scratch);
+ } else {
+ emitGlobalPoll(crb, asm, config, atReturn, state, scratch);
+ }
}
/**
@@ -85,7 +95,7 @@
return config.forceUnreachable || !isInt(pollingPageAddress - config.codeCacheLowBound) || !isInt(pollingPageAddress - config.codeCacheHighBound);
}
- public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
+ private static void emitGlobalPoll(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
assert !atReturn || state == null : "state is unneeded at return";
if (ImmutableCode.getValue(crb.getOptions())) {
JavaKind hostWordKind = JavaKind.Long;
@@ -123,4 +133,18 @@
asm.testl(rax, new AMD64Address(rip, 0));
}
}
+
+ private static void emitThreadLocalPoll(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread,
+ Register scratch) {
+ assert !atReturn || state == null : "state is unneeded at return";
+
+ assert config.threadPollingPageOffset >= 0;
+ asm.movptr(scratch, new AMD64Address(thread, config.threadPollingPageOffset));
+ crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
+ final int pos = asm.position();
+ if (state != null) {
+ crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+ }
+ asm.testl(rax, new AMD64Address(scratch));
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java Thu Nov 30 10:40:48 2017 -0800
@@ -190,7 +190,8 @@
operand = resultOperandFor(javaKind, input.getValueKind());
emitMove(operand, input);
}
- append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, getSafepointAddressValue()));
+ Register thread = getProviders().getRegisters().getThreadRegister();
+ append(new SPARCHotSpotReturnOp(operand, getStub() != null, config, thread, getSafepointAddressValue()));
}
@Override
@@ -383,7 +384,7 @@
public AllocatableValue getSafepointAddressValue() {
if (this.safepointAddressValue == null) {
- this.safepointAddressValue = newVariable(LIRKind.value(target().arch.getWordKind()));
+ this.safepointAddressValue = SPARCHotSpotSafepointOp.getSafepointAddressValue(this);
}
return this.safepointAddressValue;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -84,7 +84,8 @@
@Override
public void visitSafepointNode(SafepointNode i) {
LIRFrameState info = state(i);
- append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
+ Register thread = getGen().getProviders().getRegisters().getThreadRegister();
+ append(new SPARCHotSpotSafepointOp(info, getGen().config, thread, gen));
}
@Override
@@ -141,9 +142,7 @@
@Override
protected void emitPrologue(StructuredGraph graph) {
super.emitPrologue(graph);
- AllocatableValue var = getGen().getSafepointAddressValue();
- append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config));
- getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
+ SPARCHotSpotSafepointOp.emitPrologue(this, getGen());
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotReturnOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -24,7 +24,6 @@
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -33,6 +32,7 @@
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.sparc.SPARCControlFlow.ReturnOp;
+import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.Value;
/**
@@ -44,15 +44,17 @@
public static final SizeEstimate SIZE = SizeEstimate.create(2);
@Use({REG, ILLEGAL}) protected Value value;
- @Use({REG}) protected Value safepointPollAddress;
+ @Use({REG, ILLEGAL}) protected Value safepointPollAddress;
private final boolean isStub;
private final GraalHotSpotVMConfig config;
+ private final Register thread;
- SPARCHotSpotReturnOp(Value value, boolean isStub, GraalHotSpotVMConfig config, Value safepointPoll) {
+ SPARCHotSpotReturnOp(Value value, boolean isStub, GraalHotSpotVMConfig config, Register thread, Value safepointPoll) {
super(TYPE, SIZE);
this.value = value;
this.isStub = isStub;
this.config = config;
+ this.thread = thread;
this.safepointPollAddress = safepointPoll;
}
@@ -60,7 +62,7 @@
public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
if (!isStub) {
// Every non-stub compile method must have a poll before the return.
- SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, asRegister(safepointPollAddress));
+ SPARCHotSpotSafepointOp.emitCode(crb, masm, config, true, null, thread, safepointPollAddress);
}
ReturnOp.emitCodeHelper(crb, masm);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotSafepointOp.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -27,7 +27,10 @@
import org.graalvm.compiler.asm.sparc.SPARCAddress;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
+import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
+import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
@@ -39,6 +42,7 @@
import jdk.vm.ci.code.ValueUtil;
import jdk.vm.ci.code.site.InfopointReason;
import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
/**
* Emits a safepoint poll.
@@ -49,23 +53,37 @@
public static final SizeEstimate SIZE = SizeEstimate.create(9);
@State protected LIRFrameState state;
- @Use({OperandFlag.REG}) AllocatableValue safepointPollAddress;
+ @Use({OperandFlag.REG, OperandFlag.ILLEGAL}) AllocatableValue safepointPollAddress;
private final GraalHotSpotVMConfig config;
+ private final Register thread;
- public SPARCHotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, LIRGeneratorTool tool) {
+ public SPARCHotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, Register thread, LIRGeneratorTool tool) {
super(TYPE, SIZE);
this.state = state;
this.config = config;
+ this.thread = thread;
SPARCHotSpotLIRGenerator lirGen = (SPARCHotSpotLIRGenerator) tool;
safepointPollAddress = lirGen.getSafepointAddressValue();
}
@Override
public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
- emitCode(crb, masm, config, false, state, asRegister(safepointPollAddress));
+ emitCode(crb, masm, config, false, state, thread, safepointPollAddress);
}
- public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register safepointPollAddress) {
+ public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread,
+ Value safepointPollAddress) {
+ if (config.threadLocalHandshakes) {
+ emitThreadLocalPoll(crb, masm, config, atReturn, state, thread);
+ } else {
+ emitGlobalPoll(crb, masm, config, atReturn, state, asRegister(safepointPollAddress));
+ }
+ }
+
+ /**
+ * Emit a global safepoint poll.
+ */
+ private static void emitGlobalPoll(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register safepointPollAddress) {
crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
if (state != null) {
final int pos = masm.position();
@@ -74,6 +92,44 @@
masm.ldx(new SPARCAddress(safepointPollAddress, 0), g0);
}
+ /**
+ * Emit a thread-local safepoint poll.
+ */
+ private static void emitThreadLocalPoll(CompilationResultBuilder crb, SPARCMacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register thread) {
+ assert !atReturn || state == null : "state is unneeded at return";
+
+ assert config.threadPollingPageOffset >= 0;
+
+ try (ScratchRegister scratchReg = masm.getScratchRegister()) {
+ Register scratch = scratchReg.getRegister();
+
+ masm.ldx(new SPARCAddress(thread, config.threadPollingPageOffset), scratch);
+
+ crb.recordMark(atReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR);
+ if (state != null) {
+ final int pos = masm.position();
+ crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+ }
+ masm.ldx(new SPARCAddress(scratch, 0), g0);
+ }
+ }
+
+ static AllocatableValue getSafepointAddressValue(SPARCHotSpotLIRGenerator gen) {
+ if (gen.config.threadLocalHandshakes) {
+ return Value.ILLEGAL;
+ } else {
+ return gen.newVariable(LIRKind.value(gen.target().arch.getWordKind()));
+ }
+ }
+
+ static void emitPrologue(SPARCHotSpotNodeLIRBuilder lir, SPARCHotSpotLIRGenerator gen) {
+ if (!gen.config.threadLocalHandshakes) {
+ AllocatableValue var = gen.getSafepointAddressValue();
+ lir.append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, gen.config));
+ gen.append(((HotSpotDebugInfoBuilder) lir.getDebugInfoBuilder()).lockStack());
+ }
+ }
+
public static class SPARCLoadSafepointPollAddress extends SPARCLIRInstruction {
public static final LIRInstructionClass<SPARCLoadSafepointPollAddress> TYPE = LIRInstructionClass.create(SPARCLoadSafepointPollAddress.class);
public static final SizeEstimate SIZE = SizeEstimate.create(2);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Nov 30 14:25:33 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Nov 30 10:40:48 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -165,6 +165,7 @@
public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
+ public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
private final boolean useMultiplyToLenIntrinsic = getFlag("UseMultiplyToLenIntrinsic", Boolean.class);
private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class);
@@ -594,6 +595,7 @@
public final int basicLockSize = getFieldValue("CompilerToVM::Data::sizeof_BasicLock", Integer.class, "int");
public final int basicLockDisplacedHeaderOffset = getFieldOffset("BasicLock::_displaced_header", Integer.class, "markOop");
+ public final int threadPollingPageOffset = getFieldOffset("Thread::_polling_page", Integer.class, "address", -1);
public final int threadAllocatedBytesOffset = getFieldOffset("Thread::_allocated_bytes", Integer.class, "jlong");
public final int tlabRefillWasteIncrement = getFlag("TLABWasteIncrement", Integer.class);
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java Thu Nov 30 14:25:33 2017 -0800
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java Thu Nov 30 10:40:48 2017 -0800
@@ -29,13 +29,17 @@
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
+import sun.hotspot.WhiteBox;
+
/*
* @test HandshakeTransitionTest
* @summary This does a sanity test of the poll in the native wrapper.
* @requires vm.debug
* @library /testlibrary /test/lib
* @build HandshakeTransitionTest
- * @run main/native HandshakeTransitionTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeTransitionTest
*/
public class HandshakeTransitionTest {
@@ -44,6 +48,7 @@
public static void main(String[] args) throws Exception {
String lib = System.getProperty("test.nativepath");
+ WhiteBox wb = WhiteBox.getWhiteBox();
ProcessBuilder pb =
ProcessTools.createJavaProcessBuilder(
true,
@@ -54,6 +59,8 @@
"-XX:ParallelGCThreads=1",
"-XX:ConcGCThreads=1",
"-XX:CICompilerCount=2",
+ "-XX:+UnlockExperimentalVMOptions",
+ (wb.getBooleanVMFlag("UseJVMCICompiler") ? "-XX:+UseJVMCICompiler" : "-XX:-UseJVMCICompiler"),
"HandshakeTransitionTest$Test");