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: 220534d56673
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 75239af85921
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Feb 27, 2015

  1. 5
    Copy the full SHA
    a667bd2 View commit details
  2. Copy the full SHA
    5143268 View commit details
  3. Copy the full SHA
    75239af View commit details
1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/slice_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fails:String#slice calls to_int on the given index
fails:String#slice with index, length always taints resulting strings when self is tainted
fails:String#slice with index, length calls to_int on the given index and the given length
fails:String#slice with index, length returns subclass instances
111 changes: 111 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/coerce/ToIntNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2015 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 org.jruby.truffle.nodes.coerce;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.FloatNodes;
import org.jruby.truffle.nodes.core.FloatNodesFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBignum;

@NodeChild(value = "child", type = RubyNode.class)
public abstract class ToIntNode extends RubyNode {

@Child private CallDispatchHeadNode toIntNode;
@Child private FloatNodes.ToINode floatToIntNode;

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

public ToIntNode(ToIntNode prev) {
super(prev);
}

@Specialization
public int coerceInt(int value) {
return value;
}

@Specialization
public long coerceLong(long value) {
return value;
}

@Specialization
public RubyBignum coerceRubyBignum(RubyBignum value) {
return value;
}

@Specialization
public Object coerceDouble(double value) {
if (floatToIntNode == null) {
CompilerDirectives.transferToInterpreter();
floatToIntNode = insert(FloatNodesFactory.ToINodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}));
}

return floatToIntNode.toI(value);
}

@Specialization(guards = "!isRubyBignum")
public Object coerceObject(VirtualFrame frame, Object object) {
notDesignedForCompilation();

if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object coerced;

try {
coerced = toIntNode.call(frame, object, "to_int", null);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
getContext().getCoreLibrary().typeErrorNoImplicitConversion(object, "Integer", this));
} else {
throw e;
}
}

if (getContext().getCoreLibrary().getLogicalClass(coerced) == getContext().getCoreLibrary().getFixnumClass()) {
return coerced;
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
getContext().getCoreLibrary().typeErrorBadCoercion(object, "Integer", "to_int", coerced, this));
}
}

@Override
public abstract int executeIntegerFixnum(VirtualFrame frame);

public abstract int executeIntegerFixnum(VirtualFrame frame, Object object);

@Override
public abstract long executeLongFixnum(VirtualFrame frame);

@Override
public abstract RubyBignum executeBignum(VirtualFrame frame);
}
Original file line number Diff line number Diff line change
@@ -25,16 +25,16 @@
@NodeChild(value = "child", type = RubyNode.class)
public abstract class ToStrNode extends RubyNode {

@Child private CallDispatchHeadNode toStr;
@Child private CallDispatchHeadNode toStrNode;

public ToStrNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = DispatchHeadNodeFactory.createMethodCall(context);
toStrNode = DispatchHeadNodeFactory.createMethodCall(context);
}

public ToStrNode(ToStrNode prev) {
super(prev);
toStr = prev.toStr;
toStrNode = prev.toStrNode;
}

@Specialization
@@ -49,7 +49,7 @@ public RubyString coerceObject(VirtualFrame frame, Object object) {
final Object coerced;

try {
coerced = toStr.call(frame, object, "to_str", null);
coerced = toStrNode.call(frame, object, "to_str", null);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
CompilerDirectives.transferToInterpreter();
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@
import org.joni.Region;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.coerce.ToIntNode;
import org.jruby.truffle.nodes.coerce.ToIntNodeFactory;
import org.jruby.truffle.nodes.coerce.ToStrNode;
import org.jruby.truffle.nodes.coerce.ToStrNodeFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
@@ -281,6 +283,8 @@ private RubyString formatSlow(RubyString format, Object[] args) {
@CoreMethod(names = {"[]", "slice"}, required = 1, optional = 1, lowerFixnumParameters = {0, 1})
public abstract static class GetIndexNode extends CoreMethodNode {

@Child private ToIntNode toIntNode;

private final BranchProfile outOfBounds = BranchProfile.create();

public GetIndexNode(RubyContext context, SourceSection sourceSection) {
@@ -316,6 +320,18 @@ public Object getIndex(RubyString string, int index, UndefinedPlaceholder undefi
}
}

@Specialization(guards = "!isRubyRange(arguments[1])")
public Object getIndex(VirtualFrame frame, RubyString string, Object index, UndefinedPlaceholder undefined) {
notDesignedForCompilation();

if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeFactory.create(getContext(), getSourceSection(), null));
}

return getIndex(string, toIntNode.executeIntegerFixnum(frame, index), undefined);
}

@Specialization
public Object slice(RubyString string, RubyRange.IntegerFixnumRange range, UndefinedPlaceholder undefined) {
notDesignedForCompilation();
@@ -1348,7 +1364,7 @@ public RubyString rstrip(RubyString string) {
last--;
}

return getContext().makeString(str.substring(0, last+1));
return getContext().makeString(str.substring(0, last + 1));
}

}