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

Commits on Oct 9, 2016

  1. Copy the full SHA
    08fd868 View commit details
  2. Copy the full SHA
    abbf656 View commit details
  3. Copy the full SHA
    1393288 View commit details
31 changes: 31 additions & 0 deletions spec/truffle/specs/truffle/interop/keys_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (c) 2016 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

require_relative '../../../../ruby/spec_helper'

describe "Truffle::Interop.keys" do

class InteropKeysClass

def initialize
@a = 1
@b = 2
@c = 3
end

end

it "returns the keys of a hash" do
Truffle::Interop.keys({a: 1, b: 2, c: 3}).should == ['a', 'b', 'c']
end

it "returns the instance variables of something that isn't a hash" do
Truffle::Interop.keys(InteropKeysClass.new).sort.should == ['a', 'b', 'c']
end

end
Original file line number Diff line number Diff line change
@@ -242,6 +242,7 @@ public class CoreLibrary {
private final DynamicObject rubiniusFFIPointerClass;
private final DynamicObject signalModule;
private final DynamicObject truffleModule;
private final DynamicObject truffleInteropModule;
private final DynamicObject bigDecimalClass;
private final DynamicObject encodingCompatibilityErrorClass;
private final DynamicObject methodClass;
@@ -566,7 +567,7 @@ public CoreLibrary(RubyContext context) {
Layouts.CLASS.setInstanceFactoryUnsafe(encodingConverterClass, Layouts.ENCODING_CONVERTER.createEncodingConverterShape(encodingConverterClass, encodingConverterClass));

truffleModule = defineModule("Truffle");
defineModule(truffleModule, "Interop");
truffleInteropModule = defineModule(truffleModule, "Interop");
defineModule(truffleModule, "CExt");
defineModule(truffleModule, "Debug");
defineModule(truffleModule, "Digest");
@@ -1565,6 +1566,10 @@ public DynamicObject getTruffleModule() {
return truffleModule;
}

public Object getTruffleInteropModule() {
return truffleInteropModule;
}

private static final String[] coreFiles = {
"/core/pre.rb",
"/core/lookuptable.rb",
27 changes: 27 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/interop/InteropNodes.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.PerformanceWarnings;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.control.JavaException;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.util.ByteListUtils;
@@ -564,6 +565,32 @@ protected int getCacheLimit() {

}

@CoreMethod(names = "keys", isModuleFunction = true, required = 1)
public abstract static class KeysNode extends CoreMethodArrayArgumentsNode {

@Specialization
public Object size(
VirtualFrame frame,
TruffleObject receiver,
@Cached("createKeysNode()") Node keysNode,
@Cached("new()") SnippetNode snippetNode,
@Cached("create()") BranchProfile exceptionProfile) {
try {
return snippetNode.execute(frame,
"Truffle::Interop.enumerable(keys).map { |key| Truffle::Interop.from_java_string(key) }",
"keys", ForeignAccess.sendKeys(keysNode, frame, receiver));
} catch (UnsupportedMessageException e) {
exceptionProfile.enter();
throw new JavaException(e);
}
}

protected Node createKeysNode() {
return Message.KEYS.createNode();
}

}

@CoreMethod(names = "export", isModuleFunction = true, required = 2)
public abstract static class ExportNode extends CoreMethodArrayArgumentsNode {

Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyObjectType;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;
@@ -233,4 +234,29 @@ private ForeignWriteStringCachingHelperNode getHelperNode() {

}

@Resolve(message = "KEYS")
public static abstract class ForeignKeysNode extends Node {

@CompilationFinal private RubyContext context;

@Child private Node findContextNode;
@Child private DispatchHeadNode dispatchNode;

protected Object access(VirtualFrame frame, DynamicObject object) {
return getDispatchNode().dispatch(frame, context.getCoreLibrary().getTruffleInteropModule(), "ruby_object_keys", null, new Object[]{ object });
}

private DispatchHeadNode getDispatchNode() {
if (dispatchNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
findContextNode = insert(RubyLanguage.INSTANCE.unprotectedCreateFindContextNode());
context = RubyLanguage.INSTANCE.unprotectedFindContext(findContextNode);
dispatchNode = insert(new DispatchHeadNode(context, true, false, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD));
}

return dispatchNode;
}

}

}
12 changes: 12 additions & 0 deletions truffle/src/main/ruby/core/truffle/interop.rb
Original file line number Diff line number Diff line change
@@ -25,6 +25,18 @@ def self.export_method(name)
export(name.to_s, Object.method(name.to_sym))
end

def self.ruby_object_keys(object)
if object.is_a?(Hash)
object.keys.map do |key|
Truffle::Interop.to_java_string(key)
end
else
object.instance_variables.map do |key|
Truffle::Interop.to_java_string(key[1..-1])
end
end
end

class ForeignEnumerable
include Enumerable

5 changes: 0 additions & 5 deletions truffle/src/test/java/org/jruby/truffle/tck/RubyTckTest.java
Original file line number Diff line number Diff line change
@@ -251,9 +251,4 @@ public void testCallFunction() throws Exception {
public void testCallMethod() throws Exception {
}

@Ignore
@Override
public void testPropertiesInteropMessage() throws Exception {
}

}