# HG changeset patch # User Chris Seaton # Date 1392003561 0 # Node ID 22bf5a8ba9ebbce0fb127928d48ab51f1a3b6239 # Parent f2345d7c52efdd75ac93a2dd84e82371e701bc48 Ruby: restore prototype debugger. diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java Mon Feb 10 03:37:32 2014 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java Mon Feb 10 03:39:21 2014 +0000 @@ -17,6 +17,7 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.ruby.nodes.*; import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.debug.*; import com.oracle.truffle.ruby.nodes.methods.arguments.*; import com.oracle.truffle.ruby.nodes.objects.*; import com.oracle.truffle.ruby.runtime.*; @@ -74,6 +75,7 @@ getMethods(methods, ThreadNodesFactory.getFactories()); getMethods(methods, TimeNodesFactory.getFactories()); getMethods(methods, TrueClassNodesFactory.getFactories()); + getMethods(methods, DebugNodesFactory.getFactories()); return methods; } diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveEnterDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveEnterDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public abstract class ActiveEnterDebugProbe extends RubyProbe { + + private final Assumption activeAssumption; + + private final InlinableMethodImplementation inlinable; + private final RubyRootNode inlinedRoot; + + public ActiveEnterDebugProbe(RubyContext context, Assumption activeAssumption, RubyProc proc) { + super(context, false); + this.activeAssumption = activeAssumption; + inlinable = ((InlinableMethodImplementation) proc.getMethod().getImplementation()); + inlinedRoot = inlinable.getCloneOfPristineRootNode(); + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + try { + activeAssumption.check(); + } catch (InvalidAssumptionException e) { + replace(createInactive()); + return; + } + + final RubyArguments arguments = new RubyArguments(inlinable.getDeclarationFrame(), NilPlaceholder.INSTANCE, null, 14); + final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, inlinable.getFrameDescriptor()); + inlinedRoot.execute(inlinedFrame); + } + + protected abstract InactiveEnterDebugProbe createInactive(); + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLeaveDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLeaveDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public abstract class ActiveLeaveDebugProbe extends RubyProbe { + + private final Assumption activeAssumption; + + private final InlinableMethodImplementation inlinable; + private final RubyRootNode inlinedRoot; + + public ActiveLeaveDebugProbe(RubyContext context, Assumption activeAssumption, RubyProc proc) { + super(context, false); + this.activeAssumption = activeAssumption; + inlinable = ((InlinableMethodImplementation) proc.getMethod().getImplementation()); + inlinedRoot = inlinable.getCloneOfPristineRootNode(); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + try { + activeAssumption.check(); + } catch (InvalidAssumptionException e) { + replace(createInactive()); + return; + } + + final RubyArguments arguments = new RubyArguments(inlinable.getDeclarationFrame(), NilPlaceholder.INSTANCE, null, result); + final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, inlinable.getFrameDescriptor()); + inlinedRoot.execute(inlinedFrame); + } + + protected abstract InactiveLeaveDebugProbe createInactive(); + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLineDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLineDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; + +public class ActiveLineDebugProbe extends ActiveEnterDebugProbe { + + private final SourceLineLocation sourceLine; + + public ActiveLineDebugProbe(RubyContext context, SourceLineLocation sourceLine, Assumption activeAssumption, RubyProc proc) { + super(context, activeAssumption, proc); + this.sourceLine = sourceLine; + } + + @Override + protected InactiveEnterDebugProbe createInactive() { + final RubyContext rubyContext = (RubyContext) getContext(); + final RubyDebugManager manager = rubyContext.getRubyDebugManager(); + return new InactiveLineDebugProbe(rubyContext, sourceLine, manager.getAssumption(sourceLine)); + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLocalDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLocalDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; + +public class ActiveLocalDebugProbe extends ActiveLeaveDebugProbe { + + private final MethodLocal methodLocal; + + public ActiveLocalDebugProbe(RubyContext context, MethodLocal methodLocal, Assumption activeAssumption, RubyProc proc) { + super(context, activeAssumption, proc); + this.methodLocal = methodLocal; + } + + @Override + protected InactiveLeaveDebugProbe createInactive() { + final RubyContext rubyContext = (RubyContext) getContext(); + final RubyDebugManager manager = rubyContext.getRubyDebugManager(); + return new InactiveLocalDebugProbe(rubyContext, methodLocal, manager.getAssumption(methodLocal)); + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.nodes.core.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@CoreClass(name = "Debug") +public abstract class DebugNodes { + + @CoreMethod(names = "break", isModuleMethod = true, needsSelf = false, needsBlock = true, appendCallNode = true, minArgs = 0, maxArgs = 3) + public abstract static class BreakNode extends CoreMethodNode { + + public BreakNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BreakNode(BreakNode prev) { + super(prev); + } + + @Specialization(order = 1) + public NilPlaceholder debugBreak(VirtualFrame frame, Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder undefined0, @SuppressWarnings("unused") UndefinedPlaceholder undefined1, + @SuppressWarnings("unused") UndefinedPlaceholder block) { + getContext().runShell(callNode, frame.materialize()); + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 2) + public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getRubyDebugManager().setBreakpoint(lineLocation, null); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 3) + public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, RubyProc block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getRubyDebugManager().setBreakpoint(lineLocation, block); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 4) + public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString()); + context.getRubyDebugManager().setBreakpoint(methodLocal, null); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 5) + public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, RubyProc block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString()); + context.getRubyDebugManager().setBreakpoint(methodLocal, block); + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "continue", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class ContinueNode extends CoreMethodNode { + + public ContinueNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ContinueNode(ContinueNode prev) { + super(prev); + } + + @Specialization + public Object debugContinue() { + if (getContext().getConfiguration().getDebug()) { + throw new BreakShellException(); + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "enabled?", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class EnabledNode extends CoreMethodNode { + + public EnabledNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EnabledNode(ContinueNode prev) { + super(prev); + } + + @Specialization + public boolean enabled() { + return getContext().getConfiguration().getDebug(); + } + + } + + @CoreMethod(names = "where", isModuleMethod = true, needsSelf = false, appendCallNode = true, minArgs = 1, maxArgs = 1) + public abstract static class WhereNode extends CoreMethodNode { + + public WhereNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public WhereNode(WhereNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder where(Node callNode) { + getContext().getConfiguration().getStandardOut().println(callNode.getSourceSection()); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "remove", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2) + public abstract static class RemoveNode extends CoreMethodNode { + + public RemoveNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RemoveNode(RemoveNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder debugRemove(RubyString fileName, int line) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getRubyDebugManager().removeBreakpoint(lineLocation); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization + public NilPlaceholder debugRemove(RubySymbol methodName, RubySymbol localName) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString()); + context.getRubyDebugManager().removeBreakpoint(methodLocal); + } + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveEnterDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveEnterDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public abstract class InactiveEnterDebugProbe extends RubyProbe { + + private final Assumption inactiveAssumption; + + public InactiveEnterDebugProbe(RubyContext context, Assumption inactiveAssumption) { + super(context, false); + this.inactiveAssumption = inactiveAssumption; + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + try { + inactiveAssumption.check(); + } catch (InvalidAssumptionException e) { + final ActiveEnterDebugProbe activeNode = createActive(); + replace(activeNode); + activeNode.enter(astNode, frame); + } + } + + protected abstract ActiveEnterDebugProbe createActive(); + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLeaveDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLeaveDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public abstract class InactiveLeaveDebugProbe extends RubyProbe { + + private final Assumption inactiveAssumption; + + public InactiveLeaveDebugProbe(RubyContext context, Assumption inactiveAssumption) { + super(context, false); + this.inactiveAssumption = inactiveAssumption; + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + try { + inactiveAssumption.check(); + } catch (InvalidAssumptionException e) { + final ActiveLeaveDebugProbe activeNode = createActive(); + replace(activeNode); + activeNode.leave(astNode, frame, result); + } + } + + protected abstract ActiveLeaveDebugProbe createActive(); + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLineDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLineDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.debug.*; + +public class InactiveLineDebugProbe extends InactiveEnterDebugProbe { + + private final SourceLineLocation sourceLine; + + public InactiveLineDebugProbe(RubyContext context, SourceLineLocation sourceLine, Assumption inactiveAssumption) { + super(context, inactiveAssumption); + this.sourceLine = sourceLine; + } + + @Override + protected ActiveEnterDebugProbe createActive() { + final RubyContext rubyContext = (RubyContext) getContext(); + final RubyDebugManager manager = rubyContext.getRubyDebugManager(); + return new ActiveLineDebugProbe(rubyContext, sourceLine, manager.getAssumption(sourceLine), manager.getBreakpoint(sourceLine)); + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLocalDebugProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLocalDebugProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.debug.*; + +public class InactiveLocalDebugProbe extends InactiveLeaveDebugProbe { + + private final MethodLocal methodLocal; + + public InactiveLocalDebugProbe(RubyContext context, MethodLocal methodLocal, Assumption inactiveAssumption) { + super(context, inactiveAssumption); + this.methodLocal = methodLocal; + } + + @Override + protected ActiveLeaveDebugProbe createActive() { + final RubyContext rubyContext = (RubyContext) getContext(); + final RubyDebugManager manager = rubyContext.getRubyDebugManager(); + return new ActiveLocalDebugProbe(rubyContext, methodLocal, manager.getAssumption(methodLocal), manager.getBreakpoint(methodLocal)); + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.nodes.instrument.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A "probe node" implemented specifically for the Ruby implementation; subclasses need only + * override those members of {@link InstrumentationProbeEvents} for which some action is needed. + */ +public abstract class RubyProbe extends InstrumentationProbeNode.DefaultProbeNode { + + protected final boolean oneShot; + + protected final RubyContext context; + + /** + * OneShot is this a one-shot (self-removing) probe? + */ + public RubyProbe(RubyContext context, boolean oneShot) { + super(context); + this.oneShot = oneShot; + this.context = context; + } + + /** + * Is this a one-shot (self-removing) probe? If so, it will remove itself the first time + * activated. + */ + public boolean isOneShot() { + return oneShot; + } +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyTraceProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyTraceProbe.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * A "trace" probe that has no runtime cost until activated, at which time it invokes a trace + * message. + */ +public final class RubyTraceProbe extends RubyProbe { + + private final Assumption notTracingAssumption; + + @CompilerDirectives.CompilationFinal private boolean tracingEverEnabled = false; + + public RubyTraceProbe(RubyContext context) { + super(context, false); + this.notTracingAssumption = context.getTraceManager().getNotTracingAssumption(); + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + if (!tracingEverEnabled) { + try { + notTracingAssumption.check(); + } catch (InvalidAssumptionException e) { + tracingEverEnabled = true; + } + } + final TraceManager traceManager = context.getTraceManager(); + if (tracingEverEnabled && traceManager.hasTraceProc()) { + final SourceSection sourceSection = astNode.getEncapsulatingSourceSection(); + traceManager.trace("line", sourceSection.getSource().getName(), sourceSection.getStartLine(), 0, null, null); + } + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java --- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java Mon Feb 10 03:37:32 2014 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java Mon Feb 10 03:39:21 2014 +0000 @@ -9,7 +9,9 @@ */ package com.oracle.truffle.ruby.parser; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.instrument.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.ruby.nodes.*; import com.oracle.truffle.ruby.nodes.debug.*; import com.oracle.truffle.ruby.runtime.*; @@ -26,17 +28,33 @@ public DefaultRubyNodeInstrumenter() { } - public RubyNode instrumentAsStatement(RubyNode rubyNode) { - assert rubyNode != null; - assert !(rubyNode instanceof RubyProxyNode); - final RubyContext context = rubyNode.getContext(); + public RubyNode instrumentAsStatement(RubyNode node) { + assert node != null; + + final RubyContext context = node.getContext(); + + RubyProxyNode proxy; + + if (node instanceof RubyProxyNode) { + proxy = (RubyProxyNode) node; + } else { + proxy = new RubyProxyNode(node.getContext(), node); + proxy.markAs(NodePhylum.STATEMENT); + proxy.clearSourceSection(); + proxy.assignSourceSection(node.getSourceSection()); + } + if (context.getConfiguration().getTrace()) { - final RubyProxyNode proxy = new RubyProxyNode(context, rubyNode); - proxy.markAs(NodePhylum.STATEMENT); proxy.getProbeChain().appendProbe(new RubyTraceProbe(context)); - return proxy; } - return rubyNode; + + if (context.getConfiguration().getDebug()) { + final SourceSection sourceSection = proxy.getChild().getSourceSection(); + final SourceLineLocation sourceLine = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); + proxy.getProbeChain().appendProbe(new InactiveLineDebugProbe(context, sourceLine, context.getRubyDebugManager().getAssumption(sourceLine))); + } + + return proxy; } public RubyNode instrumentAsCall(RubyNode node, String callName) { @@ -44,7 +62,27 @@ } public RubyNode instrumentAsLocalAssignment(RubyNode node, UniqueMethodIdentifier methodIdentifier, String localName) { - return node; + assert node != null; + + final RubyContext context = node.getContext(); + + RubyProxyNode proxy; + + if (node instanceof RubyProxyNode) { + proxy = (RubyProxyNode) node; + } else { + proxy = new RubyProxyNode(node.getContext(), node); + proxy.markAs(NodePhylum.STATEMENT); + proxy.clearSourceSection(); + proxy.assignSourceSection(node.getSourceSection()); + } + + if (context.getConfiguration().getDebug()) { + final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName); + proxy.getProbeChain().appendProbe(new InactiveLocalDebugProbe(context, methodLocal, context.getRubyDebugManager().getAssumption(methodLocal))); + } + + return proxy; } } diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java --- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java Mon Feb 10 03:37:32 2014 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java Mon Feb 10 03:39:21 2014 +0000 @@ -1102,7 +1102,6 @@ @Override public Object visitLocalAsgnNode(org.jrubyparser.ast.LocalAsgnNode node) { - final SourceSection sourceSection = translate(node.getPosition()); if (environment.getNeverAssignInParentScope()) { diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java --- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java Mon Feb 10 03:37:32 2014 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java Mon Feb 10 03:39:21 2014 +0000 @@ -22,6 +22,7 @@ import com.oracle.truffle.ruby.runtime.configuration.*; import com.oracle.truffle.ruby.runtime.control.*; import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; import com.oracle.truffle.ruby.runtime.methods.*; import com.oracle.truffle.ruby.runtime.objects.*; import com.oracle.truffle.ruby.runtime.subsystems.*; @@ -41,6 +42,7 @@ private final FiberManager fiberManager; private final AtExitManager atExitManager; private final DebugManager debugManager; + private final RubyDebugManager rubyDebugManager; private final SourceManager sourceManager; private final ASTPrinter astPrinter; @@ -77,6 +79,7 @@ sourceManager = new SourceManager(); debugManager = new DefaultDebugManager(this); + rubyDebugManager = new RubyDebugManager(); // Must initialize threads before fibers @@ -300,4 +303,8 @@ return sourceManager; } + public RubyDebugManager getRubyDebugManager() { + return rubyDebugManager; + } + } diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.ruby.runtime.methods.*; + +/* + * Identifies a local in a method. + */ +public class MethodLocal { + + private final UniqueMethodIdentifier method; + private final String local; + + public MethodLocal(UniqueMethodIdentifier method, String local) { + this.method = method; + this.local = local; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((local == null) ? 0 : local.hashCode()); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MethodLocal other = (MethodLocal) obj; + if (local == null) { + if (other.local != null) { + return false; + } + } else if (!local.equals(other.local)) { + return false; + } + if (method == null) { + if (other.method != null) { + return false; + } + } else if (!method.equals(other.method)) { + return false; + } + return true; + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java Mon Feb 10 03:39:21 2014 +0000 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public final class RubyDebugManager { + + private final Map lineAssumptions = new HashMap<>(); + private final Map lineBreakpoints = new HashMap<>(); + + private final Map localAssumptions = new HashMap<>(); + private final Map localBreakpoints = new HashMap<>(); + + public void setBreakpoint(SourceLineLocation sourceLine, RubyProc proc) { + final CyclicAssumption assumption = lineAssumptions.get(sourceLine); + + if (assumption == null) { + throw new RuntimeException("Breakpoint " + sourceLine + " not found"); + } else { + lineBreakpoints.put(sourceLine, proc); + assumption.invalidate(); + } + } + + public void setBreakpoint(MethodLocal methodLocal, RubyProc proc) { + final CyclicAssumption assumption = localAssumptions.get(methodLocal); + + if (assumption == null) { + throw new RuntimeException("Breakpoint " + methodLocal + " not found"); + } else { + localBreakpoints.put(methodLocal, proc); + assumption.invalidate(); + } + } + + public void removeBreakpoint(SourceLineLocation sourceLine) { + final CyclicAssumption assumption = lineAssumptions.get(sourceLine); + + if (assumption == null) { + throw new RuntimeException("Breakpoint " + sourceLine + " not found"); + } else { + lineBreakpoints.remove(sourceLine); + assumption.invalidate(); + } + } + + public void removeBreakpoint(MethodLocal methodLocal) { + final CyclicAssumption assumption = localAssumptions.get(methodLocal); + + if (assumption == null) { + throw new RuntimeException("Breakpoint " + methodLocal + " not found"); + } else { + localBreakpoints.remove(methodLocal); + assumption.invalidate(); + } + } + + public Assumption getAssumption(SourceLineLocation sourceLine) { + CyclicAssumption assumption = lineAssumptions.get(sourceLine); + + if (assumption == null) { + assumption = new CyclicAssumption(sourceLine.toString()); + lineAssumptions.put(sourceLine, assumption); + } + + return assumption.getAssumption(); + } + + public RubyProc getBreakpoint(SourceLineLocation sourceLine) { + return lineBreakpoints.get(sourceLine); + } + + public Assumption getAssumption(MethodLocal methodLocal) { + CyclicAssumption assumption = localAssumptions.get(methodLocal); + + if (assumption == null) { + assumption = new CyclicAssumption(methodLocal.toString()); + localAssumptions.put(methodLocal, assumption); + } + + return assumption.getAssumption(); + } + + public RubyProc getBreakpoint(MethodLocal methodLocal) { + return localBreakpoints.get(methodLocal); + } + +} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java --- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java Mon Feb 10 03:37:32 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This - * code is released under a tri EPL/GPL/LGPL license. You can use it, - * redistribute it and/or modify it under the terms of the: - * - * Eclipse Public License version 1.0 - * GNU General Public License version 2 - * GNU Lesser General Public License version 2.1 - */ -package com.oracle.truffle.ruby.runtime.debug; - -import com.oracle.truffle.api.nodes.instrument.*; -import com.oracle.truffle.ruby.runtime.*; - -/** - * A "probe node" implemented specifically for the Ruby implementation; subclasses need only - * override those members of {@link InstrumentationProbeEvents} for which some action is needed. - */ -public abstract class RubyProbe extends InstrumentationProbeNode.DefaultProbeNode { - - protected final boolean oneShot; - - protected final RubyContext context; - - /** - * OneShot is this a one-shot (self-removing) probe? - */ - public RubyProbe(RubyContext context, boolean oneShot) { - super(context); - this.oneShot = oneShot; - this.context = context; - } - - /** - * Is this a one-shot (self-removing) probe? If so, it will remove itself the first time - * activated. - */ - public boolean isOneShot() { - return oneShot; - } -} diff -r f2345d7c52ef -r 22bf5a8ba9eb graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java --- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java Mon Feb 10 03:37:32 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This - * code is released under a tri EPL/GPL/LGPL license. You can use it, - * redistribute it and/or modify it under the terms of the: - * - * Eclipse Public License version 1.0 - * GNU General Public License version 2 - * GNU Lesser General Public License version 2.1 - */ -package com.oracle.truffle.ruby.runtime.debug; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.ruby.runtime.*; -import com.oracle.truffle.ruby.runtime.subsystems.*; - -/** - * A "trace" probe that has no runtime cost until activated, at which time it invokes a trace - * message. - */ -public final class RubyTraceProbe extends RubyProbe { - - private final Assumption notTracingAssumption; - - @CompilerDirectives.CompilationFinal private boolean tracingEverEnabled = false; - - public RubyTraceProbe(RubyContext context) { - super(context, false); - this.notTracingAssumption = context.getTraceManager().getNotTracingAssumption(); - } - - @Override - public void enter(Node astNode, VirtualFrame frame) { - if (!tracingEverEnabled) { - try { - notTracingAssumption.check(); - } catch (InvalidAssumptionException e) { - tracingEverEnabled = true; - } - } - final TraceManager traceManager = context.getTraceManager(); - if (tracingEverEnabled && traceManager.hasTraceProc()) { - final SourceSection sourceSection = astNode.getEncapsulatingSourceSection(); - traceManager.trace("line", sourceSection.getSource().getName(), sourceSection.getStartLine(), 0, null, null); - } - } -}