Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9ceb2fe524e9
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 998803c8178c
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Sep 10, 2015

  1. [Truffle] avoid using ruby in RangeNodes which may cause local jump e…

    …rrors
    
    - use CallDispatchHeadNode instead
    - fixes ActiveSupport failing test
    pitr-ch committed Sep 10, 2015
    Copy the full SHA
    b71acc6 View commit details
  2. Copy the full SHA
    998803c View commit details
102 changes: 69 additions & 33 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/RangeNodes.java
Original file line number Diff line number Diff line change
@@ -20,14 +20,16 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.BooleanCastNodeGen;
import org.jruby.truffle.nodes.core.array.ArrayBuilderNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

@CoreClass(name = "Range")
public abstract class RangeNodes {

@CoreMethod(names = {"collect", "map"}, needsBlock = true, lowerFixnumSelf = true)
@CoreMethod(names = { "collect", "map" }, needsBlock = true, lowerFixnumSelf = true)
public abstract static class CollectNode extends YieldingCoreMethodNode {

@Child private ArrayBuilderNode arrayBuilder;
@@ -37,7 +39,7 @@ public CollectNode(RubyContext context, SourceSection sourceSection) {
arrayBuilder = new ArrayBuilderNode.UninitializedArrayBuilderNode(context);
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isIntegerFixnumRange(range)", "isRubyProc(block)" })
public DynamicObject collect(VirtualFrame frame, DynamicObject range, DynamicObject block) {
final int begin = Layouts.INTEGER_FIXNUM_RANGE.getBegin(range);
int result;
@@ -75,11 +77,13 @@ public DynamicObject collect(VirtualFrame frame, DynamicObject range, DynamicObj
@CoreMethod(names = "each", needsBlock = true, lowerFixnumSelf = true, returnsEnumeratorIfNoBlock = true)
public abstract static class EachNode extends YieldingCoreMethodNode {

@Child private CallDispatchHeadNode eachInternalCall;

public EachNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isIntegerFixnumRange(range)", "isRubyProc(block)" })
public Object eachInt(VirtualFrame frame, DynamicObject range, DynamicObject block) {
int result;
if (Layouts.INTEGER_FIXNUM_RANGE.getExcludedEnd(((DynamicObject) range))) {
@@ -108,7 +112,7 @@ public Object eachInt(VirtualFrame frame, DynamicObject range, DynamicObject blo
return range;
}

@Specialization(guards = {"isLongFixnumRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isLongFixnumRange(range)", "isRubyProc(block)" })
public Object eachLong(VirtualFrame frame, DynamicObject range, DynamicObject block) {
long result;
if (Layouts.LONG_FIXNUM_RANGE.getExcludedEnd(((DynamicObject) range))) {
@@ -137,19 +141,28 @@ public Object eachLong(VirtualFrame frame, DynamicObject range, DynamicObject bl
return range;
}

private Object eachInternal(VirtualFrame frame, DynamicObject range, DynamicObject block) {
if (eachInternalCall == null) {
CompilerDirectives.transferToInterpreter();
eachInternalCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return eachInternalCall.call(frame, range, "each_internal", block);
}

@Specialization(guards = "isLongFixnumRange(range)")
public Object eachObject(VirtualFrame frame, DynamicObject range, NotProvided block) {
return ruby(frame, "each_internal(&block)", "block", nil());
return eachInternal(frame, range, null);
}

@Specialization(guards = "isObjectRange(range)")
public Object each(VirtualFrame frame, DynamicObject range, NotProvided block) {
return ruby(frame, "each_internal(&block)", "block", nil());
return eachInternal(frame, range, null);
}

@Specialization(guards = {"isObjectRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isObjectRange(range)", "isRubyProc(block)" })
public Object each(VirtualFrame frame, DynamicObject range, DynamicObject block) {
return ruby(frame, "each_internal(&block)", "block", block);
return eachInternal(frame, range, block);
}

}
@@ -251,11 +264,13 @@ public Object lastObject(DynamicObject range) {
@CoreMethod(names = "step", needsBlock = true, optional = 1, returnsEnumeratorIfNoBlock = true)
public abstract static class StepNode extends YieldingCoreMethodNode {

@Child private CallDispatchHeadNode stepInternalCall;

public StepNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "step > 0", "isRubyProc(block)"})
@Specialization(guards = { "isIntegerFixnumRange(range)", "step > 0", "isRubyProc(block)" })
public Object stepInt(VirtualFrame frame, DynamicObject range, int step, DynamicObject block) {
int count = 0;

@@ -282,7 +297,7 @@ public Object stepInt(VirtualFrame frame, DynamicObject range, int step, Dynamic
return range;
}

@Specialization(guards = {"isLongFixnumRange(range)", "step > 0", "isRubyProc(block)"})
@Specialization(guards = { "isLongFixnumRange(range)", "step > 0", "isRubyProc(block)" })
public Object stepLong(VirtualFrame frame, DynamicObject range, int step, DynamicObject block) {
int count = 0;

@@ -309,71 +324,86 @@ public Object stepLong(VirtualFrame frame, DynamicObject range, int step, Dynami
return range;
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "wasProvided(step)", "isRubyProc(block)"})
private Object stepInternal(VirtualFrame frame, DynamicObject range, DynamicObject block) {
return stepInternal(frame, range, 1, block);
}

private Object stepInternal(VirtualFrame frame, DynamicObject range, Object step, DynamicObject block) {
if (stepInternalCall == null) {
CompilerDirectives.transferToInterpreter();
stepInternalCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return stepInternalCall.call(frame, range, "step_internal", block, step);
}

@Specialization(guards = { "isIntegerFixnumRange(range)", "wasProvided(step)", "isRubyProc(block)" })
public Object stepFallbackInt(VirtualFrame frame, DynamicObject range, Object step, DynamicObject block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
return stepInternal(frame, range, step, block);
}

@Specialization(guards = {"isLongFixnumRange(range)", "wasProvided(step)", "isRubyProc(block)"})
@Specialization(guards = { "isLongFixnumRange(range)", "wasProvided(step)", "isRubyProc(block)" })
public Object stepFallbackLong(VirtualFrame frame, DynamicObject range, Object step, DynamicObject block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
return stepInternal(frame, range, step, block);
}

@Specialization(guards = "isIntegerFixnumRange(range)")
public Object stepInt(VirtualFrame frame, DynamicObject range, NotProvided step, NotProvided block) {
return ruby(frame, "step_internal");
return stepInternal(frame, range, null);
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isIntegerFixnumRange(range)", "isRubyProc(block)" })
public Object stepInt(VirtualFrame frame, DynamicObject range, NotProvided step, DynamicObject block) {
return ruby(frame, "step_internal(&block)", "block", block);
return stepInternal(frame, range, block);
}

@Specialization(guards = {"isIntegerFixnumRange(range)", "!isInteger(step)", "!isLong(step)", "wasProvided(step)"})
@Specialization(guards = { "isIntegerFixnumRange(range)", "!isInteger(step)", "!isLong(step)", "wasProvided(step)" })
public Object stepInt(VirtualFrame frame, DynamicObject range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
return stepInternal(frame, range, step, null);
}

@Specialization(guards = "isLongFixnumRange(range)")
public Object stepLong(VirtualFrame frame, DynamicObject range, NotProvided step, NotProvided block) {
return ruby(frame, "step_internal");
return stepInternal(frame, range, null);
}

@Specialization(guards = {"isLongFixnumRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isLongFixnumRange(range)", "isRubyProc(block)" })
public Object stepLong(VirtualFrame frame, DynamicObject range, NotProvided step, DynamicObject block) {
return ruby(frame, "step_internal(&block)", "block", block);
return stepInternal(frame, range, block);
}

@Specialization(guards = {"isLongFixnumRange(range)", "wasProvided(step)"})
@Specialization(guards = { "isLongFixnumRange(range)", "wasProvided(step)" })
public Object stepLong(VirtualFrame frame, DynamicObject range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
return stepInternal(frame, range, step, null);
}

@Specialization(guards = {"isObjectRange(range)", "wasProvided(step)", "isRubyProc(block)"})
@Specialization(guards = { "isObjectRange(range)", "wasProvided(step)", "isRubyProc(block)" })
public Object stepObject(VirtualFrame frame, DynamicObject range, Object step, DynamicObject block) {
return ruby(frame, "step_internal(step, &block)", "step", step, "block", block);
return stepInternal(frame, range, step, block);
}

@Specialization(guards = "isObjectRange(range)")
public Object stepObject(VirtualFrame frame, DynamicObject range, NotProvided step, NotProvided block) {
return ruby(frame, "step_internal");
return stepInternal(frame, range, null);
}

@Specialization(guards = {"isObjectRange(range)", "isRubyProc(block)"})
@Specialization(guards = { "isObjectRange(range)", "isRubyProc(block)" })
public Object stepObject(VirtualFrame frame, DynamicObject range, NotProvided step, DynamicObject block) {
return ruby(frame, "step_internal(&block)", "block", block);
return stepInternal(frame, range, block);
}

@Specialization(guards = {"isObjectRange(range)", "wasProvided(step)"})
@Specialization(guards = { "isObjectRange(range)", "wasProvided(step)" })
public Object step(VirtualFrame frame, DynamicObject range, Object step, NotProvided block) {
return ruby(frame, "step_internal(step)", "step", step);
return stepInternal(frame, range, step, null);
}

}

@CoreMethod(names = "to_a", lowerFixnumSelf = true)
public abstract static class ToANode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode toAInternalCall;

public ToANode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -404,7 +434,12 @@ public DynamicObject toA(DynamicObject range) {

@Specialization(guards = "isObjectRange(range)")
public Object toA(VirtualFrame frame, DynamicObject range) {
return ruby(frame, "to_a_internal");
if (toAInternalCall == null) {
CompilerDirectives.transferToInterpreter();
toAInternalCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return toAInternalCall.call(frame, range, "to_a_internal", null);
}

}
@@ -456,7 +491,8 @@ public InternalSetExcludeEndNode(RubyContext context, SourceSection sourceSectio
super(context, sourceSection);
}

@CreateCast("excludeEnd") public RubyNode castToBoolean(RubyNode excludeEnd) {
@CreateCast("excludeEnd")
public RubyNode castToBoolean(RubyNode excludeEnd) {
return BooleanCastNodeGen.create(getContext(), getSourceSection(), excludeEnd);
}

Original file line number Diff line number Diff line change
@@ -4315,6 +4315,8 @@ public DynamicObject unshift(DynamicObject array, Object... args) {
@CoreMethod(names = "zip", rest = true, required = 1)
public abstract static class ZipNode extends ArrayCoreMethodNode {

@Child private CallDispatchHeadNode zipInternalCall;

public ZipNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -4380,21 +4382,24 @@ public DynamicObject zipObjectObject(DynamicObject array, DynamicObject other, O

@Specialization(guards = { "isRubyArray(other)", "fallback(array, other, others)" })
public Object zipObjectObjectNotSingleObject(VirtualFrame frame, DynamicObject array, DynamicObject other, Object[] others) {
return zipRuby(frame);
return zipRuby(frame, array);
}

@Specialization(guards = { "!isRubyArray(other)" })
public Object zipObjectObjectNotArray(VirtualFrame frame, DynamicObject array, DynamicObject other, Object[] others) {
return zipRuby(frame);
return zipRuby(frame, array);
}

private Object zipRuby(VirtualFrame frame) {
DynamicObject proc = RubyArguments.getBlock(frame.getArguments());
if (proc == null) {
proc = nil();
private Object zipRuby(VirtualFrame frame, DynamicObject array) {
if (zipInternalCall == null) {
CompilerDirectives.transferToInterpreter();
zipInternalCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final DynamicObject proc = RubyArguments.getBlock(frame.getArguments());
final Object[] others = RubyArguments.extractUserArguments(frame.getArguments());
return ruby(frame, "zip_internal(*others, &block)", "others", Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), others, others.length), "block", proc);

return zipInternalCall.call(frame, array, "zip_internal", proc, others);
}

protected static boolean fallback(DynamicObject array, DynamicObject other, Object[] others) {
14 changes: 0 additions & 14 deletions truffle/src/main/ruby/core/rubinius/api/shims/range.rb
Original file line number Diff line number Diff line change
@@ -26,20 +26,6 @@

class Range

def include?(value)
if @begin.respond_to?(:to_int) ||
@end.respond_to?(:to_int) ||
@begin.kind_of?(Numeric) ||
@end.kind_of?(Numeric)
cover? value
else
# super # MODIFIED inlined this because of local jump error
each_internal { |val| return true if val == value }
false
end
end

alias_method :member?, :include?

def to_a_internal # MODIFIED called from java to_a
return to_a_from_enumerable unless @begin.kind_of? Fixnum and @end.kind_of? Fixnum