# HG changeset patch # User Chris Seaton # Date 1389203096 0 # Node ID b63357fbe40c2ac9208758f212378424c503fe9c # Parent 44288fe54352620923b4bf29a91d26982179e8bb# Parent d49f006043473a7151420eeea0143792c073b449 Merge. diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CallNode.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CallNode.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CallNode.java Wed Jan 08 17:44:56 2014 +0000 @@ -79,7 +79,7 @@ this.name = name; this.isSplatted = isSplatted; - dispatchHead = adoptChild(adoptChild(new DispatchHeadNode(context, section, name, isSplatted))); + dispatchHead = adoptChild(new DispatchHeadNode(context, section, name, isSplatted)); } @Override diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/BreakNode.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/BreakNode.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/BreakNode.java Wed Jan 08 17:44:56 2014 +0000 @@ -13,6 +13,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.literal.*; import com.oracle.truffle.ruby.runtime.*; import com.oracle.truffle.ruby.runtime.control.*; @@ -28,7 +29,11 @@ @Override public Object execute(VirtualFrame frame) { - throw new BreakException(child.execute(frame)); + if (child instanceof NilNode) { + throw BreakException.NIL; + } else { + throw new BreakException(child.execute(frame)); + } } } diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NextNode.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NextNode.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NextNode.java Wed Jan 08 17:44:56 2014 +0000 @@ -13,19 +13,27 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.literal.*; import com.oracle.truffle.ruby.runtime.*; import com.oracle.truffle.ruby.runtime.control.*; @NodeInfo(shortName = "next") public class NextNode extends RubyNode { - public NextNode(RubyContext context, SourceSection sourceSection) { + @Child private RubyNode child; + + public NextNode(RubyContext context, SourceSection sourceSection, RubyNode child) { super(context, sourceSection); + + this.child = adoptChild(child); } @Override public Object execute(VirtualFrame frame) { - throw new NextException(); + if (child instanceof NilNode) { + throw NextException.NIL; + } else { + throw new NextException(child.execute(frame)); + } } - } diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -16,6 +16,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.ruby.runtime.*; import com.oracle.truffle.ruby.runtime.control.*; import com.oracle.truffle.ruby.runtime.core.*; @@ -457,6 +458,10 @@ @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) public abstract static class EachNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public EachNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -466,12 +471,21 @@ } @Specialization - public NilPlaceholder each(VirtualFrame frame, RubyArray array, RubyProc block) { - for (int n = 0; n < array.size(); n++) { - try { - yield(frame, block, array.get(n)); - } catch (BreakException e) { - break; + public Object each(VirtualFrame frame, RubyArray array, RubyProc block) { + outer: for (int n = 0; n < array.size(); n++) { + while (true) { + try { + yield(frame, block, array.get(n)); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } } } diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BignumNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BignumNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BignumNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -14,7 +14,9 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; 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.core.array.*; @@ -602,6 +604,10 @@ @CoreMethod(names = "times", needsBlock = true, maxArgs = 0) public abstract static class TimesNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public TimesNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -611,9 +617,22 @@ } @Specialization - public BigInteger times(VirtualFrame frame, BigInteger n, RubyProc block) { - for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) { - yield(frame, block, i); + public Object times(VirtualFrame frame, BigInteger n, RubyProc block) { + outer: for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) { + while (true) { + try { + yield(frame, block, i); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } } return n; diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FixnumNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FixnumNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FixnumNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -14,7 +14,9 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; 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.core.array.*; @@ -755,6 +757,10 @@ @CoreMethod(names = "times", needsBlock = true, maxArgs = 0) public abstract static class TimesNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public TimesNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -764,9 +770,22 @@ } @Specialization - public int times(VirtualFrame frame, int n, RubyProc block) { - for (int i = 0; i < n; i++) { - yield(frame, block, i); + public Object times(VirtualFrame frame, int n, RubyProc block) { + outer: for (int i = 0; i < n; i++) { + while (true) { + try { + yield(frame, block, i); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } } return n; @@ -831,6 +850,10 @@ @CoreMethod(names = "upto", needsBlock = true, minArgs = 1, maxArgs = 1) public abstract static class UpToNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public UpToNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -840,9 +863,22 @@ } @Specialization - public NilPlaceholder upto(VirtualFrame frame, int from, int to, RubyProc block) { - for (int i = from; i <= to; i++) { - yield(frame, block, i); + public Object upto(VirtualFrame frame, int from, int to, RubyProc block) { + outer: for (int i = from; i <= to; i++) { + while (true) { + try { + yield(frame, block, i); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } } return NilPlaceholder.INSTANCE; diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -44,7 +44,10 @@ hash.put(keyValue.get(0), keyValue.get(1)); } } else { - assert args.length % 2 == 0; + if (args.length % 2 != 0) { + // TODO(CS): figure out what error to throw here + throw new UnsupportedOperationException(); + } for (int n = 0; n < args.length; n += 2) { hash.put(args[n], args[n + 1]); diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RangeNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RangeNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RangeNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -12,8 +12,10 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.ruby.nodes.call.*; 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.core.array.*; import com.oracle.truffle.ruby.runtime.core.range.*; @@ -50,6 +52,10 @@ @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) public abstract static class EachNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public EachNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -59,9 +65,22 @@ } @Specialization - public FixnumRange each(VirtualFrame frame, FixnumRange range, RubyProc block) { - for (int n = range.getBegin(); n < range.getExclusiveEnd(); n++) { - yield(frame, block, n); + public Object each(VirtualFrame frame, FixnumRange range, RubyProc block) { + outer: for (int n = range.getBegin(); n < range.getExclusiveEnd(); n++) { + while (true) { + try { + yield(frame, block, n); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } } return range; @@ -182,6 +201,10 @@ @CoreMethod(names = "step", needsBlock = true, minArgs = 1, maxArgs = 1) public abstract static class StepNode extends YieldingCoreMethodNode { + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + public StepNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } @@ -191,9 +214,22 @@ } @Specialization - public FixnumRange step(VirtualFrame frame, FixnumRange range, int step, RubyProc block) { - for (int n = range.getBegin(); n < range.getExclusiveEnd(); n += step) { - yield(frame, block, n); + public Object step(VirtualFrame frame, FixnumRange range, int step, RubyProc block) { + outer: for (int n = range.getBegin(); n < range.getExclusiveEnd(); n += step) { + while (true) { + try { + yield(frame, block, n); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } } return range; diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java Wed Jan 08 17:44:56 2014 +0000 @@ -304,13 +304,13 @@ } @CoreMethod(names = "inspect", maxArgs = 0) - public abstract static class InpsectNode extends CoreMethodNode { + public abstract static class InspectNode extends CoreMethodNode { - public InpsectNode(RubyContext context, SourceSection sourceSection) { + public InspectNode(RubyContext context, SourceSection sourceSection) { super(context, sourceSection); } - public InpsectNode(InpsectNode prev) { + public InspectNode(InspectNode prev) { super(prev); } diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchNextNode.java --- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchNextNode.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchNextNode.java Wed Jan 08 17:44:56 2014 +0000 @@ -36,8 +36,7 @@ return body.execute(frame); } catch (NextException e) { nextProfile.enter(); - return NilPlaceholder.INSTANCE; + return e.getResult(); } } - } diff -r d49f00604347 -r b63357fbe40c 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 Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java Wed Jan 08 17:44:56 2014 +0000 @@ -1484,7 +1484,17 @@ @Override public Object visitNextNode(org.jrubyparser.ast.NextNode node) { - return new NextNode(context, translate(node.getPosition())); + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode resultNode; + + if (node.getValueNode() == null) { + resultNode = new NilNode(context, sourceSection); + } else { + resultNode = (RubyNode) node.getValueNode().accept(this); + } + + return new NextNode(context, sourceSection, resultNode); } @Override diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakException.java --- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakException.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakException.java Wed Jan 08 17:44:56 2014 +0000 @@ -17,6 +17,8 @@ */ public final class BreakException extends ControlFlowException { + public static final BreakException NIL = new BreakException(NilPlaceholder.INSTANCE); + private final Object result; public BreakException(Object result) { diff -r d49f00604347 -r b63357fbe40c graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/NextException.java --- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/NextException.java Wed Jan 08 16:57:30 2014 +0100 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/NextException.java Wed Jan 08 17:44:56 2014 +0000 @@ -10,12 +10,27 @@ package com.oracle.truffle.ruby.runtime.control; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; /** * Controls moving to the next iteration in a control structure or method. */ public final class NextException extends ControlFlowException { + public static final NextException NIL = new NextException(NilPlaceholder.INSTANCE); + + private final Object result; + + public NextException(Object result) { + assert RubyContext.shouldObjectBeVisible(result); + + this.result = result; + } + + public Object getResult() { + return result; + } + private static final long serialVersionUID = -302759969186731457L; }