8191437: AOT doesn't work easily after thread local handshakes
Reviewed-by: kvn, rehn, aph
This commit is contained in:
parent
40f06dc0e3
commit
15ea766de2
@ -3388,26 +3388,29 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
// 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);
|
||||
|
@ -167,6 +167,7 @@ void AOTLib::verify_config() {
|
||||
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);
|
||||
|
@ -92,7 +92,7 @@ typedef struct {
|
||||
} 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 @@ typedef struct {
|
||||
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 @@ typedef struct {
|
||||
bool _enableContended;
|
||||
bool _restrictContended;
|
||||
bool _omitAssertions;
|
||||
bool _threadLocalHandshakes;
|
||||
} AOTConfiguration;
|
||||
|
||||
class AOTLib : public CHeapObj<mtCode> {
|
||||
|
@ -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*) \
|
||||
|
@ -4397,26 +4397,7 @@ jint Arguments::apply_ergo() {
|
||||
}
|
||||
#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 {
|
||||
|
@ -138,10 +138,6 @@ Flag::Error ThreadLocalHandshakesConstraintFunc(bool value, bool verbose) {
|
||||
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;
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ public final class BinaryContainer implements SymbolTable {
|
||||
|
||||
private final int codeEntryAlignment;
|
||||
|
||||
private final boolean threadLocalHandshakes;
|
||||
|
||||
/**
|
||||
* Container holding code bits and any other related information.
|
||||
*/
|
||||
@ -279,6 +281,8 @@ public final class BinaryContainer implements SymbolTable {
|
||||
|
||||
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 @@ public final class BinaryContainer implements SymbolTable {
|
||||
TieredAOT.getValue(graalOptions),
|
||||
graalHotSpotVMConfig.enableContended,
|
||||
graalHotSpotVMConfig.restrictContended,
|
||||
graphBuilderConfig.omitAssertions()
|
||||
graphBuilderConfig.omitAssertions(),
|
||||
graalHotSpotVMConfig.threadLocalHandshakes
|
||||
};
|
||||
|
||||
int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(),
|
||||
@ -434,6 +439,11 @@ public final class BinaryContainer implements SymbolTable {
|
||||
return codeEntryAlignment;
|
||||
}
|
||||
|
||||
public boolean getThreadLocalHandshakes() {
|
||||
return threadLocalHandshakes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the global AOT symbol associated with the function name.
|
||||
*
|
||||
|
@ -45,6 +45,7 @@ final class MarkProcessor {
|
||||
* @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 @@ final class MarkProcessor {
|
||||
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:
|
||||
|
@ -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 @@ import jdk.vm.ci.code.Register;
|
||||
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 @@ abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen
|
||||
@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
|
||||
|
@ -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.LIRInstructionClass;
|
||||
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 @@ public final class AArch64HotSpotReturnOp extends AArch64HotSpotEpilogueOp {
|
||||
@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;
|
||||
|
@ -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 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction {
|
||||
@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 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction {
|
||||
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 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -264,7 +264,8 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
|
||||
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
|
||||
|
@ -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 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H
|
||||
@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
|
||||
|
@ -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 @@ final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueBlockEndOp implemen
|
||||
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 @@ final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueBlockEndOp implemen
|
||||
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
|
||||
|
@ -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 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction {
|
||||
@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 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction {
|
||||
|
||||
@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 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction {
|
||||
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 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp
|
||||
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 class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp
|
||||
|
||||
public AllocatableValue getSafepointAddressValue() {
|
||||
if (this.safepointAddressValue == null) {
|
||||
this.safepointAddressValue = newVariable(LIRKind.value(target().arch.getWordKind()));
|
||||
this.safepointAddressValue = SPARCHotSpotSafepointOp.getSafepointAddressValue(this);
|
||||
}
|
||||
return this.safepointAddressValue;
|
||||
}
|
||||
|
@ -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 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H
|
||||
@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 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H
|
||||
@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
|
||||
|
@ -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 @@ package org.graalvm.compiler.hotspot.sparc;
|
||||
|
||||
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.Opcode;
|
||||
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 @@ final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp {
|
||||
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 @@ final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp {
|
||||
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);
|
||||
}
|
||||
|
@ -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 static jdk.vm.ci.sparc.SPARC.g0;
|
||||
|
||||
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.Register;
|
||||
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 class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
|
||||
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 @@ public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
|
||||
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);
|
||||
|
@ -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 class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
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 class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
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);
|
||||
|
@ -29,13 +29,17 @@ import java.time.Duration;
|
||||
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 class HandshakeTransitionTest {
|
||||
|
||||
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 @@ public class HandshakeTransitionTest {
|
||||
"-XX:ParallelGCThreads=1",
|
||||
"-XX:ConcGCThreads=1",
|
||||
"-XX:CICompilerCount=2",
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
(wb.getBooleanVMFlag("UseJVMCICompiler") ? "-XX:+UseJVMCICompiler" : "-XX:-UseJVMCICompiler"),
|
||||
"HandshakeTransitionTest$Test");
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user