Skip to content

Commit

Permalink
8231515: [Graal] Crash during exception throwing in InterpreterRuntim…
Browse files Browse the repository at this point in the history
…e::resolve_invoke

Reviewed-by: kvn, dlong, iveresov
  • Loading branch information
Tom Rodriguez committed Jan 23, 2020
1 parent 4df9b91 commit 2f2594d
Show file tree
Hide file tree
Showing 49 changed files with 834 additions and 255 deletions.
1 change: 1 addition & 0 deletions src/hotspot/share/aot/aotCodeHeap.cpp
Expand Up @@ -465,6 +465,7 @@ void AOTCodeHeap::link_shared_runtime_symbols() {
SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_virtual_entry", address, SharedRuntime::get_resolve_virtual_call_stub());
SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_opt_virtual_entry", address, SharedRuntime::get_resolve_opt_virtual_call_stub());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack", address, SharedRuntime::deopt_blob()->unpack());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack_with_exception_in_tls", address, SharedRuntime::deopt_blob()->unpack_with_exception_in_tls());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_uncommon_trap", address, SharedRuntime::deopt_blob()->uncommon_trap());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_ic_miss_stub", address, SharedRuntime::get_ic_miss_stub());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub());
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
Expand Up @@ -45,6 +45,7 @@ class CompilerToVM {
static address SharedRuntime_ic_miss_stub;
static address SharedRuntime_handle_wrong_method_stub;
static address SharedRuntime_deopt_blob_unpack;
static address SharedRuntime_deopt_blob_unpack_with_exception_in_tls;
static address SharedRuntime_deopt_blob_uncommon_trap;

static size_t ThreadLocalAllocBuffer_alignment_reserve;
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
Expand Up @@ -44,6 +44,7 @@ int CompilerToVM::Data::Method_extra_stack_entries;
address CompilerToVM::Data::SharedRuntime_ic_miss_stub;
address CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub;
address CompilerToVM::Data::SharedRuntime_deopt_blob_unpack;
address CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls;
address CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap;

size_t CompilerToVM::Data::ThreadLocalAllocBuffer_alignment_reserve;
Expand Down Expand Up @@ -97,6 +98,7 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
SharedRuntime_ic_miss_stub = SharedRuntime::get_ic_miss_stub();
SharedRuntime_handle_wrong_method_stub = SharedRuntime::get_handle_wrong_method_stub();
SharedRuntime_deopt_blob_unpack = SharedRuntime::deopt_blob()->unpack();
SharedRuntime_deopt_blob_unpack_with_exception_in_tls = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
SharedRuntime_deopt_blob_uncommon_trap = SharedRuntime::deopt_blob()->uncommon_trap();

ThreadLocalAllocBuffer_alignment_reserve = ThreadLocalAllocBuffer::alignment_reserve();
Expand Down
15 changes: 12 additions & 3 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Expand Up @@ -454,22 +454,31 @@ JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread *thread, oopDesc* o

JRT_END

JRT_ENTRY(void, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
JRT_BLOCK;
TempNewSymbol symbol = SymbolTable::new_symbol(exception);
SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
JRT_BLOCK_END;
return caller_is_deopted();
JRT_END

JRT_ENTRY(void, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass))
JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass))
JRT_BLOCK;
ResourceMark rm(thread);
TempNewSymbol symbol = SymbolTable::new_symbol(exception);
SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, klass->external_name());
JRT_BLOCK_END;
return caller_is_deopted();
JRT_END

JRT_ENTRY(void, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass))
JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass))
JRT_BLOCK;
ResourceMark rm(thread);
const char* message = SharedRuntime::generate_class_cast_message(caster_klass, target_klass);
TempNewSymbol symbol = SymbolTable::new_symbol(exception);
SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
JRT_BLOCK_END;
return caller_is_deopted();
JRT_END

JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/jvmci/jvmciRuntime.hpp
Expand Up @@ -332,10 +332,10 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);

// used to throw exceptions from compiled JVMCI code
static void throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
static int throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
// helper methods to throw exception with complex messages
static void throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
static void throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
static int throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
static int throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);

// Test only function
static jint test_deoptimize_call_int(JavaThread* thread, int value);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Expand Up @@ -48,6 +48,7 @@
static_field(CompilerToVM::Data, SharedRuntime_ic_miss_stub, address) \
static_field(CompilerToVM::Data, SharedRuntime_handle_wrong_method_stub, address) \
static_field(CompilerToVM::Data, SharedRuntime_deopt_blob_unpack, address) \
static_field(CompilerToVM::Data, SharedRuntime_deopt_blob_unpack_with_exception_in_tls, address) \
static_field(CompilerToVM::Data, SharedRuntime_deopt_blob_uncommon_trap, address) \
\
static_field(CompilerToVM::Data, ThreadLocalAllocBuffer_alignment_reserve, size_t) \
Expand Down
Expand Up @@ -36,15 +36,16 @@
import java.util.List;
import java.util.Map;

import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;

import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
import jdk.tools.jaotc.binformat.macho.JMachORelocObject;
import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;

/**
* A format-agnostic container class that holds various components of a binary.
Expand Down Expand Up @@ -145,6 +146,7 @@ public final class BinaryContainer implements SymbolTable {
private static final String[][] map = {
{"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", "_aot_deopt_blob_unpack"},
{"CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", "_aot_deopt_blob_uncommon_trap"},
{"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls", "_aot_deopt_blob_unpack_with_exception_in_tls"},
{"CompilerToVM::Data::SharedRuntime_ic_miss_stub", "_aot_ic_miss_stub"},
{"CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", "_aot_handle_wrong_method_stub"},
{"SharedRuntime::exception_handler_for_return_address", "_aot_exception_handler_for_return_address"},
Expand Down
Expand Up @@ -51,7 +51,14 @@ public void launchSubprocess(Runnable runnable) throws InterruptedException, IOE
vmArgs.add(SubprocessUtil.PACKAGE_OPENING_OPTIONS);
vmArgs.add("-D" + recursionPropName + "=true");
configSubprocess(vmArgs);
boolean verbose = Boolean.getBoolean(getClass().getSimpleName() + ".verbose");
if (verbose) {
System.err.println(String.join(" ", vmArgs));
}
SubprocessUtil.Subprocess proc = java(vmArgs, "com.oracle.mxtool.junit.MxJUnitWrapper", getClass().getName());
if (verbose) {
System.err.println(proc.output);
}
assertTrue(proc.exitCode == 0, proc.toString() + " failed with exit code " + proc.exitCode);
}
}
Expand Down
Expand Up @@ -41,6 +41,7 @@
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.NodeValueMap;
import org.graalvm.compiler.nodes.spi.NodeWithState;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.EscapeObjectState;
import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
Expand Down Expand Up @@ -80,7 +81,7 @@ public DebugInfoBuilder(NodeValueMap nodeValueMap, DebugContext debug) {

protected final Queue<VirtualObjectNode> pendingVirtualObjects = new ArrayDeque<>();

public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
public LIRFrameState build(NodeWithState node, FrameState topState, LabelRef exceptionEdge) {
assert virtualObjects.size() == 0;
assert objectStates.size() == 0;
assert pendingVirtualObjects.size() == 0;
Expand All @@ -100,7 +101,8 @@ public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
current = current.outerFrameState();
} while (current != null);

BytecodeFrame frame = computeFrameForState(topState);
assert verifyFrameState(node, topState);
BytecodeFrame frame = computeFrameForState(node, topState);

VirtualObject[] virtualObjectsArray = null;
if (virtualObjects.size() != 0) {
Expand Down Expand Up @@ -223,7 +225,18 @@ protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame f
return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
}

protected BytecodeFrame computeFrameForState(FrameState state) {
/**
* Perform platform dependent verification of the FrameState.
*
* @param node the node using the state
* @param topState the state
* @return true if the validation succeeded
*/
protected boolean verifyFrameState(NodeWithState node, FrameState topState) {
return true;
}

protected BytecodeFrame computeFrameForState(NodeWithState node, FrameState state) {
try {
assert state.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI;
assert state.bci != BytecodeFrame.UNKNOWN_BCI;
Expand All @@ -249,7 +262,7 @@ protected BytecodeFrame computeFrameForState(FrameState state) {

BytecodeFrame caller = null;
if (state.outerFrameState() != null) {
caller = computeFrameForState(state.outerFrameState());
caller = computeFrameForState(node, state.outerFrameState());
}

if (!state.canProduceBytecodeFrame()) {
Expand Down
Expand Up @@ -104,6 +104,7 @@
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.spi.NodeValueMap;
import org.graalvm.compiler.nodes.spi.NodeWithState;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;

Expand Down Expand Up @@ -735,26 +736,26 @@ public LIRFrameState state(DeoptimizingNode deopt) {
if (!deopt.canDeoptimize()) {
return null;
}
return stateFor(getFrameState(deopt));
return stateFor(deopt, getFrameState(deopt));
}

public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
if (!deopt.canDeoptimize()) {
return null;
}
return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
return stateForWithExceptionEdge(deopt, getFrameState(deopt), exceptionEdge);
}

public LIRFrameState stateFor(FrameState state) {
return stateForWithExceptionEdge(state, null);
public LIRFrameState stateFor(NodeWithState deopt, FrameState state) {
return stateForWithExceptionEdge(deopt, state, null);
}

public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
public LIRFrameState stateForWithExceptionEdge(NodeWithState deopt, FrameState state, LabelRef exceptionEdge) {
if (gen.needOnlyOopMaps()) {
return new LIRFrameState(null, null, null);
}
assert state != null;
return getDebugInfoBuilder().build(state, exceptionEdge);
assert state != null : deopt;
return getDebugInfoBuilder().build(deopt, state, exceptionEdge);
}

@Override
Expand All @@ -765,7 +766,7 @@ public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, Abstrac

@Override
public void visitFullInfopointNode(FullInfopointNode i) {
append(new FullInfopointOp(stateFor(i.getState()), i.getReason()));
append(new FullInfopointOp(stateFor(i, i.getState()), i.getReason()));
}

@Override
Expand Down
Expand Up @@ -390,7 +390,7 @@ private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler
AArch64Call.directCall(crb, masm, linkage, helper, null);
}
crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER);
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK);
masm.adr(lr, 0); // Warning: the argument is an offset from the instruction!
AArch64Call.directJmp(crb, masm, linkage);
} else {
Expand Down
Expand Up @@ -24,7 +24,7 @@

package org.graalvm.compiler.hotspot.aarch64;

import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;

import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
Expand All @@ -47,6 +47,6 @@ public AArch64HotSpotDeoptimizeCallerOp(GraalHotSpotVMConfig config) {
@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
leaveFrame(crb, masm, /* emitSafepoint */false, false);
AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP));
}
}
Expand Up @@ -24,7 +24,7 @@

package org.graalvm.compiler.hotspot.aarch64;

import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;

import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
import org.graalvm.compiler.lir.LIRFrameState;
Expand All @@ -49,7 +49,7 @@ public AArch64HotSpotDeoptimizeOp(LIRFrameState info) {
@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) {
AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), scratch.getRegister(), info, null);
AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP), scratch.getRegister(), info, null);
}
}

Expand Down
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2013, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.aarch64;

import static jdk.vm.ci.aarch64.AArch64.lr;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS;

import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.aarch64.AArch64Call;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;

import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.Value;

/**
* Removes the current frame and tail calls the uncommon trap routine.
*/
@Opcode("DEOPT_WITH_EXCEPTION_IN_CALLER")
public class AArch64HotSpotDeoptimizeWithExceptionCallerOp extends AArch64HotSpotEpilogueOp {
public static final LIRInstructionClass<AArch64HotSpotDeoptimizeWithExceptionCallerOp> TYPE = LIRInstructionClass.create(AArch64HotSpotDeoptimizeWithExceptionCallerOp.class);

@Use(OperandFlag.REG) private Value exception;

public AArch64HotSpotDeoptimizeWithExceptionCallerOp(GraalHotSpotVMConfig config, Value exception, Register thread) {
super(TYPE, config, thread);
this.exception = exception;
}

@Override
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
Register exc = asRegister(exception);

leaveFrame(crb, masm, /* emitSafepoint */false, false);

// Save exception oop in TLS
masm.str(64, exc, masm.makeAddress(thread, config.threadExceptionOopOffset, 8));
// Store original return address in TLS
masm.str(64, lr, masm.makeAddress(thread, config.threadExceptionPcOffset, 8));

AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS));
}
}
Expand Up @@ -53,8 +53,8 @@
*/
abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp {

private final GraalHotSpotVMConfig config;
private final Register thread;
protected final GraalHotSpotVMConfig config;
protected final Register thread;

protected AArch64HotSpotEpilogueOp(LIRInstructionClass<? extends AArch64HotSpotEpilogueOp> c, GraalHotSpotVMConfig config, Register thread) {
super(c);
Expand Down
Expand Up @@ -399,6 +399,12 @@ public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReas
append(new AArch64HotSpotDeoptimizeCallerOp(config));
}

@Override
public void emitDeoptimizeWithExceptionInCaller(Value exception) {
Register thread = getProviders().getRegisters().getThreadRegister();
append(new AArch64HotSpotDeoptimizeWithExceptionCallerOp(config, exception, thread));
}

@Override
public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) {
moveDeoptValuesToThread(actionAndReason, failedSpeculation);
Expand Down

0 comments on commit 2f2594d

Please sign in to comment.