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: 662fe3621f93
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ca651ec932fd
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on May 11, 2016

  1. Copy the full SHA
    1e171fc View commit details
  2. [Truffle] Replace 6 specializations by one in interop by doing the ca…

    …ching in ToJavaStringNode.
    eregon committed May 11, 2016
    Copy the full SHA
    ca651ec View commit details
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package org.jruby.truffle.interop;

/*
* Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
@@ -9,6 +7,8 @@
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
@@ -27,7 +27,7 @@
@NodeChild("receiver"),
@NodeChild("name"),
@NodeChild("stringName"),
@NodeChild("startsAt")
@NodeChild("isIVar")
})
abstract class ForeignReadStringCachedHelperNode extends RubyNode {

@@ -40,62 +40,49 @@ abstract class ForeignReadStringCachedHelperNode extends RubyNode {

protected final static String INDEX_METHOD_NAME = "[]";

public abstract Object executeStringCachedHelper(VirtualFrame frame, DynamicObject receiver, Object name,
String stringName, boolean startsAt);
public abstract Object executeStringCachedHelper(VirtualFrame frame, DynamicObject receiver, Object name, String stringName, boolean isIVar);

@Specialization(guards = "startsAt(startsAt)")
@Specialization(guards = "isIVar")
public Object readInstanceVariable(
DynamicObject receiver,
Object name,
String stringName,
boolean startsAt,
boolean isIVar,
@Cached("createReadObjectFieldNode(stringName)") ReadObjectFieldNode readObjectFieldNode) {
return readObjectFieldNode.execute(receiver);
}

protected boolean startsAt(boolean startsAt) {
return startsAt;
}

protected ReadObjectFieldNode createReadObjectFieldNode(String name) {
return ReadObjectFieldNodeGen.create(name, nil());
}

@Specialization(
guards = {
"notStartsAt(startsAt)",
"methodDefined(frame, receiver, stringName, getDefinedNode())"
}
)
@Specialization(guards = {
"!isIVar",
"methodDefined(frame, receiver, stringName, getDefinedNode())"
})
public Object callMethod(
VirtualFrame frame,
DynamicObject receiver,
Object name,
String stringName,
boolean startsAt) {
boolean isIVar) {
return getCallNode().call(frame, receiver, stringName, null);
}

@Specialization(
guards = {
"notStartsAt(startsAt)",
"!methodDefined(frame, receiver, stringName, getDefinedNode())",
"methodDefined(frame, receiver, INDEX_METHOD_NAME, getIndexDefinedNode())"
}
)
@Specialization(guards = {
"!isIVar",
"!methodDefined(frame, receiver, stringName, getDefinedNode())",
"methodDefined(frame, receiver, INDEX_METHOD_NAME, getIndexDefinedNode())"
})
public Object index(
VirtualFrame frame,
DynamicObject receiver,
Object name,
String stringName,
boolean startsAt) {
boolean isIVar) {
return getCallNode().call(frame, receiver, "[]", null, name);
}

protected boolean notStartsAt(boolean startsAt) {
return !startsAt;
}

protected DoesRespondDispatchHeadNode getDefinedNode() {
if (definedNode == null) {
CompilerDirectives.transferToInterpreter();
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package org.jruby.truffle.interop;

/*
* Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
@@ -9,6 +7,7 @@
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
@@ -20,8 +19,6 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.StringCachingGuards;
import org.jruby.truffle.language.RubyNode;

@@ -32,147 +29,52 @@
})
abstract class ForeignReadStringCachingHelperNode extends RubyNode {

@Child IsStringLikeNode isStringLikeNode;

public ForeignReadStringCachingHelperNode(RubyContext context) {
super(context, null);
}

public abstract Object executeStringCachingHelper(VirtualFrame frame, DynamicObject receiver, Object name);

@Specialization(
guards = {
"isRubyString(name)",
"ropesEqual(name, cachedRope)"
},
limit = "getCacheLimit()"
)
public Object cacheStringAndForward(
VirtualFrame frame,
DynamicObject receiver,
DynamicObject name,
@Cached("privatizeRope(name)") Rope cachedRope,
@Cached("ropeToString(cachedRope)") String cachedString,
@Cached("startsWithAt(cachedString)") boolean cachedStartsWithAt,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
return nextHelper.executeStringCachedHelper(frame, receiver, name, cachedString, cachedStartsWithAt);
}

@Specialization(
guards = "isRubyString(name)",
contains = "cacheStringAndForward"
)
public Object uncachedStringAndForward(
VirtualFrame frame,
DynamicObject receiver,
DynamicObject name,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
final String nameString = objectToString(name);
return nextHelper.executeStringCachedHelper(frame, receiver, name, nameString, startsWithAt(nameString));
}

@Specialization(
guards = {
"isRubySymbol(name)",
"name == cachedName"
},
limit = "getCacheLimit()"
)
public Object cacheSymbolAndForward(
VirtualFrame frame,
DynamicObject receiver,
DynamicObject name,
@Cached("name") DynamicObject cachedName,
@Cached("objectToString(cachedName)") String cachedString,
@Cached("startsWithAt(cachedString)") boolean cachedStartsWithAt,
@Specialization(guards = "isStringLike(name)")
public Object cacheStringLikeAndForward(VirtualFrame frame, DynamicObject receiver, Object name,
@Cached("create()") ToJavaStringNode toJavaStringNode,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
return nextHelper.executeStringCachedHelper(frame, receiver, cachedName, cachedString, cachedStartsWithAt);
String nameAsJavaString = toJavaStringNode.executeToJavaString(name);
boolean isIVar = isIVar(nameAsJavaString);
return nextHelper.executeStringCachedHelper(frame, receiver, name, nameAsJavaString, isIVar);
}

@Specialization(
guards = "isRubySymbol(name)",
contains = "cacheSymbolAndForward"
)
public Object uncachedSymbolAndForward(
VirtualFrame frame,
DynamicObject receiver,
DynamicObject name,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
final String nameString = objectToString(name);
return nextHelper.executeStringCachedHelper(frame, receiver, name, nameString, startsWithAt(nameString));
}

@Specialization(
guards = "name == cachedName",
limit = "getCacheLimit()"
)
public Object cacheJavaStringAndForward(
VirtualFrame frame,
DynamicObject receiver,
String name,
@Cached("name") String cachedName,
@Cached("startsWithAt(cachedName)") boolean cachedStartsWithAt,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
return nextHelper.executeStringCachedHelper(frame, receiver, cachedName, cachedName, cachedStartsWithAt);
@Specialization(guards = { "isRubyString(receiver)", "inRange(receiver, index)" })
public int indexString(DynamicObject receiver, int index) {
return Layouts.STRING.getRope(receiver).get(index);
}

@Specialization(contains = "cacheJavaStringAndForward")
public Object uncachedJavaStringAndForward(
VirtualFrame frame,
DynamicObject receiver,
String name,
@Cached("createNextHelper()") ForeignReadStringCachedHelperNode nextHelper) {
return nextHelper.executeStringCachedHelper(frame, receiver, name, name, startsWithAt(name));
@Specialization(guards = { "isRubyString(receiver)", "!inRange(receiver, index)" })
public int indexStringOutOfRange(DynamicObject receiver, int index) {
return 0;
}

protected ForeignReadStringCachedHelperNode createNextHelper() {
return ForeignReadStringCachedHelperNodeGen.create(null, null, null, null);
protected boolean inRange(DynamicObject string, int index) {
return index >= 0 && index < Layouts.STRING.getRope(string).byteLength();
}

@CompilerDirectives.TruffleBoundary
protected String objectToString(DynamicObject string) {
return string.toString();
}
protected boolean isStringLike(Object value) {
if (isStringLikeNode == null) {
CompilerDirectives.transferToInterpreter();
isStringLikeNode = insert(IsStringLikeNode.create());
}

protected String ropeToString(Rope rope) {
return RopeOperations.decodeRope(getContext().getJRubyRuntime(), rope);
return isStringLikeNode.executeIsStringLike(value);
}

@CompilerDirectives.TruffleBoundary
protected boolean startsWithAt(String name) {
protected boolean isIVar(String name) {
return !name.isEmpty() && name.charAt(0) == '@';
}

@Specialization(guards = {
"isRubyString(receiver)",
"index < 0"
})
public int indexStringNegative(DynamicObject receiver, int index) {
return 0;
}

@Specialization(guards = {
"isRubyString(receiver)",
"index >= 0",
"!inRange(receiver, index)"
})
public int indexStringOutOfRange(DynamicObject receiver, int index) {
return 0;
}

@Specialization(guards = {
"isRubyString(receiver)",
"index >= 0",
"inRange(receiver, index)"
})
public int indexString(DynamicObject receiver, int index) {
return Layouts.STRING.getRope(receiver).get(index);
}

protected boolean inRange(DynamicObject string, int index) {
return index < Layouts.STRING.getRope(string).byteLength();
}

protected int getCacheLimit() {
return getContext().getOptions().INTEROP_READ_CACHE;
protected ForeignReadStringCachedHelperNode createNextHelper() {
return ForeignReadStringCachedHelperNodeGen.create(null, null, null, null);
}

}
Loading