# HG changeset patch # User Andreas Woess # Date 1405516728 -7200 # Node ID ada0a7729b6f6229fff944ac2e1616462ea7f810 # Parent 4aaa97f42b9206eb05898e22412a27c0a2009519 Truffle: introduce debug option to print the stack trace when transferring to the interpreter diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Wed Jul 16 15:18:48 2014 +0200 @@ -41,4 +41,5 @@ RuntimeConstraint, LoopLimitCheck, Aliasing, + TransferToInterpreter, } diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jul 16 15:18:48 2014 +0200 @@ -1014,6 +1014,7 @@ @HotSpotVMField(name = "ThreadShadow::_pending_exception", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset; @HotSpotVMField(name = "ThreadShadow::_pending_deoptimization", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset; @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset; + @HotSpotVMField(name = "ThreadShadow::_pending_transfer_to_interpreter", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingTransferToInterpreterOffset; @HotSpotVMFlag(name = "UseHSAILDeoptimization") @Stable public boolean useHSAILDeoptimization; @HotSpotVMFlag(name = "UseHSAILSafepoints") @Stable public boolean useHSAILSafepoints; @@ -1460,6 +1461,7 @@ @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint; @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck; @HotSpotVMConstant(name = "Deoptimization::Reason_aliasing") @Stable public int deoptReasonAliasing; + @HotSpotVMConstant(name = "Deoptimization::Reason_transfer_to_interpreter") @Stable public int deoptReasonTransferToInterpreter; @HotSpotVMConstant(name = "Deoptimization::Reason_LIMIT") @Stable public int deoptReasonOSROffset; @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone; diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Wed Jul 16 15:18:48 2014 +0200 @@ -230,6 +230,8 @@ return config.deoptReasonLoopLimitCheck; case Aliasing: return config.deoptReasonAliasing; + case TransferToInterpreter: + return config.deoptReasonTransferToInterpreter; default: throw GraalInternalError.shouldNotReachHere(); } @@ -282,6 +284,9 @@ if (reason == config.deoptReasonAliasing) { return DeoptimizationReason.Aliasing; } + if (reason == config.deoptReasonTransferToInterpreter) { + return DeoptimizationReason.TransferToInterpreter; + } throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason)); } diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Jul 16 15:18:48 2014 +0200 @@ -29,6 +29,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.stream.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; @@ -41,6 +42,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; @@ -52,6 +54,7 @@ import com.oracle.graal.printer.*; import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; +import com.oracle.graal.word.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.frame.*; @@ -342,4 +345,25 @@ public void reinstallStubs() { installOptimizedCallTargetCallMethod(); } + + public void notifyTransferToInterpreter() { + CompilerAsserts.neverPartOfCompilation(); + if (TraceTruffleTransferToInterpreter.getValue()) { + Word thread = CurrentJavaThreadNode.get(HotSpotGraalRuntime.runtime().getTarget().wordKind); + boolean deoptimized = thread.readByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset) != 0; + if (deoptimized) { + thread.writeByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset, (byte) 0); + + logTransferToInterpreter(); + } + } + } + + private static void logTransferToInterpreter() { + final int skip = 2; + final int limit = 20; + StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + String suffix = stackTrace.length > skip + limit ? "\n ..." : ""; + TTY.out().out().println(Arrays.stream(stackTrace).skip(skip).limit(limit).map(StackTraceElement::toString).collect(Collectors.joining("\n ", "", suffix))); + } } diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Jul 16 15:18:48 2014 +0200 @@ -119,6 +119,8 @@ public static final OptionValue TraceTruffleInlining = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleSplitting = new OptionValue<>(false); + @Option(help = "Print stack trace on transfer to interpreter") + public static final OptionValue TraceTruffleTransferToInterpreter = new StableOptionValue<>(false); @Option(help = "") public static final OptionValue TruffleCallTargetProfiling = new StableOptionValue<>(false); // @formatter:on diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Wed Jul 16 15:18:48 2014 +0200 @@ -41,12 +41,12 @@ @MethodSubstitution public static void transferToInterpreter() { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.UnreachedCode); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter); } @MethodSubstitution public static void transferToInterpreterAndInvalidate() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter); } @MethodSubstitution diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Wed Jul 16 15:18:48 2014 +0200 @@ -65,6 +65,9 @@ * insert a transfer to the interpreter. */ public static void transferToInterpreter() { + if (inInterpreter()) { + Truffle.getRuntime().notifyTransferToInterpreter(); + } } /** @@ -72,6 +75,9 @@ * insert a transfer to the interpreter, invalidating the currently executing machine code. */ public static void transferToInterpreterAndInvalidate() { + if (inInterpreter()) { + Truffle.getRuntime().notifyTransferToInterpreter(); + } } /** diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Wed Jul 16 15:18:48 2014 +0200 @@ -131,4 +131,8 @@ */ FrameInstance getCurrentFrame(); + /** + * Internal API method. Do not use. + */ + void notifyTransferToInterpreter(); } diff -r 4aaa97f42b92 -r ada0a7729b6f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Tue Jul 15 11:52:45 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Wed Jul 16 15:18:48 2014 +0200 @@ -135,4 +135,7 @@ public FrameInstance getCurrentFrame() { return currentFrames.get(); } + + public void notifyTransferToInterpreter() { + } } diff -r 4aaa97f42b92 -r ada0a7729b6f src/share/vm/graal/vmStructs_graal.hpp --- a/src/share/vm/graal/vmStructs_graal.hpp Tue Jul 15 11:52:45 2014 +0200 +++ b/src/share/vm/graal/vmStructs_graal.hpp Wed Jul 16 15:18:48 2014 +0200 @@ -34,12 +34,14 @@ nonstatic_field(InstanceKlass, _graal_node_class, oop) \ nonstatic_field(ThreadShadow, _pending_deoptimization, int) \ nonstatic_field(ThreadShadow, _pending_failed_speculation, oop) \ + nonstatic_field(ThreadShadow, _pending_transfer_to_interpreter, bool) \ nonstatic_field(MethodData, _graal_node_count, int) \ #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type) \ #define VM_INT_CONSTANTS_GRAAL(declare_constant, declare_preprocessor_constant) \ declare_constant(Deoptimization::Reason_aliasing) \ + declare_constant(Deoptimization::Reason_transfer_to_interpreter) \ declare_constant(GraalEnv::ok) \ declare_constant(GraalEnv::dependencies_failed) \ declare_constant(GraalEnv::cache_full) \ diff -r 4aaa97f42b92 -r ada0a7729b6f src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Tue Jul 15 11:52:45 2014 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Jul 16 15:18:48 2014 +0200 @@ -1393,7 +1393,12 @@ trap_bci = 0; Thread::current()->set_pending_monitorenter(true); } + + if (reason == Deoptimization::Reason_transfer_to_interpreter) { + thread->set_pending_transfer_to_interpreter(true); + } #endif + Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci); if (trap_scope->rethrow_exception()) { @@ -1996,7 +2001,10 @@ "age" GRAAL_ONLY("_or_jsr_mismatch"), "predicate", "loop_limit_check", - GRAAL_ONLY("aliasing") +#ifdef GRAAL + "aliasing", + "transfer_to_interpreter", +#endif }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff -r 4aaa97f42b92 -r ada0a7729b6f src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Tue Jul 15 11:52:45 2014 +0200 +++ b/src/share/vm/runtime/deoptimization.hpp Wed Jul 16 15:18:48 2014 +0200 @@ -74,6 +74,7 @@ Reason_loop_limit_check, // compiler generated loop limits check failed #ifdef GRAAL Reason_aliasing, // optimistic assumption about aliasing failed + Reason_transfer_to_interpreter, // explicit transferToInterpreter() #endif Reason_LIMIT, diff -r 4aaa97f42b92 -r ada0a7729b6f src/share/vm/utilities/exceptions.hpp --- a/src/share/vm/utilities/exceptions.hpp Tue Jul 15 11:52:45 2014 +0200 +++ b/src/share/vm/utilities/exceptions.hpp Wed Jul 16 15:18:48 2014 +0200 @@ -65,6 +65,7 @@ int _pending_deoptimization; oop _pending_failed_speculation; bool _pending_monitorenter; + bool _pending_transfer_to_interpreter; #endif oop _pending_exception; // Thread has gc actions. const char* _exception_file; // file information for exception (debugging only) @@ -100,6 +101,7 @@ void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } void set_pending_deoptimization(int reason) { _pending_deoptimization = reason; } void set_pending_failed_speculation(oop failed_speculation) { _pending_failed_speculation = failed_speculation; } + void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; } #endif // use THROW whenever possible! @@ -111,7 +113,7 @@ ThreadShadow() : _pending_exception(NULL), _exception_file(NULL), _exception_line(0) #ifdef GRAAL - , _pending_monitorenter(false), _pending_deoptimization(-1), _pending_failed_speculation(NULL) + , _pending_monitorenter(false), _pending_deoptimization(-1), _pending_failed_speculation(NULL), _pending_transfer_to_interpreter(false) #endif {} };