Skip to content

Commit

Permalink
Showing 36 changed files with 1,182 additions and 1,137 deletions.
2 changes: 0 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/RubyContext.java
Original file line number Diff line number Diff line change
@@ -53,8 +53,6 @@
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class RubyContext extends ExecutionContext {

Original file line number Diff line number Diff line change
@@ -11,105 +11,31 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.interop.InteropNode;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;
import org.jruby.truffle.core.basicobject.BasicObjectForeignAccessFactory;
import org.jruby.truffle.interop.InteropExecute;
import org.jruby.truffle.interop.RubyInteropRootNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;

public class RubyMethodForeignAccessFactory implements ForeignAccess.Factory10 {
private final RubyContext context;
public class RubyMethodForeignAccessFactory extends BasicObjectForeignAccessFactory {

private RubyMethodForeignAccessFactory(RubyContext context) {
this.context = context;
}

public static ForeignAccess create(RubyContext context) {
return ForeignAccess.create(DynamicObject.class, new RubyMethodForeignAccessFactory(context));
public RubyMethodForeignAccessFactory(RubyContext context) {
super(context);
}

@Override
public CallTarget accessIsNull() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsNull(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessIsExecutable() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsExecutable(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsBoxed() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsBoxedPrimitive(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessHasSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createHasSizePropertyFalse(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessGetSize() {
return null;
}

@Override
public CallTarget accessUnbox() {
return null;
}

@Override
public CallTarget accessRead() {
return null;
}

@Override
public CallTarget accessWrite() {
return null;
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, true)));
}

@Override
public CallTarget accessExecute(int i) {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createExecute(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessInvoke(int i) {
return null;
}

@Override
public CallTarget accessNew(int argumentsLength) {
return null;
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropExecute(context, null)));
}

@Override
public CallTarget accessMessage(com.oracle.truffle.api.interop.Message msg) {
return null;
}

protected static final class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, node.getSourceSection(), null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -11,106 +11,31 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.interop.InteropNode;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;
import org.jruby.truffle.core.basicobject.BasicObjectForeignAccessFactory;
import org.jruby.truffle.interop.InteropGetSizeProperty;
import org.jruby.truffle.interop.RubyInteropRootNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;

public class ArrayForeignAccessFactory implements ForeignAccess.Factory10 {
private final RubyContext context;
public class ArrayForeignAccessFactory extends BasicObjectForeignAccessFactory {

private ArrayForeignAccessFactory(RubyContext context) {
this.context = context;
}

public static ForeignAccess create(RubyContext context) {
return ForeignAccess.create(DynamicObject.class, new ArrayForeignAccessFactory(context));
public ArrayForeignAccessFactory(RubyContext context) {
super(context);
}

@Override
public CallTarget accessIsNull() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsNull(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsExecutable() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsExecutable(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsBoxed() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsBoxedPrimitive(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessHasSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createHasSizePropertyTrue(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, true)));
}

@Override
public CallTarget accessGetSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createGetSize(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessUnbox() {
return null;
}

@Override
public CallTarget accessRead() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createRead(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessWrite() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createWrite(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropGetSizeProperty(context, null)));
}

@Override
public CallTarget accessExecute(int i) {
return null;
}

@Override
public CallTarget accessInvoke(int arity) {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createExecuteAfterRead(context, SourceSection.createUnavailable("", ""), arity)));
}

@Override
public CallTarget accessNew(int argumentsLength) {
return null;
}

@Override
public CallTarget accessMessage(Message msg) {
return null;
}

protected static final class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, node.getSourceSection(), null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -11,48 +11,42 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.interop.InteropNode;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;
import org.jruby.truffle.interop.InteropIsNull;
import org.jruby.truffle.interop.RubyInteropRootNode;
import org.jruby.truffle.interop.UnresolvedInteropExecuteAfterReadNode;
import org.jruby.truffle.interop.UnresolvedInteropReadNode;
import org.jruby.truffle.interop.UnresolvedInteropWriteNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;

public class BasicForeignAccessFactory implements ForeignAccess.Factory10 {
public class BasicObjectForeignAccessFactory implements ForeignAccess.Factory10 {

private final RubyContext context;
protected final RubyContext context;

private BasicForeignAccessFactory(RubyContext context) {
public BasicObjectForeignAccessFactory(RubyContext context) {
this.context = context;
}

public static ForeignAccess create(RubyContext context) {
return ForeignAccess.create(DynamicObject.class, new BasicForeignAccessFactory(context));
}

@Override
public CallTarget accessIsNull() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsNull(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropIsNull(context, null)));
}

@Override
public CallTarget accessIsExecutable() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsExecutable(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessIsBoxed() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsBoxedPrimitive(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessHasSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createHasSizePropertyFalse(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
@@ -67,12 +61,12 @@ public CallTarget accessUnbox() {

@Override
public CallTarget accessRead() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createRead(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new UnresolvedInteropReadNode(context, null)));
}

@Override
public CallTarget accessWrite() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createWrite(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new UnresolvedInteropWriteNode(context, null)));
}

@Override
@@ -82,7 +76,7 @@ public CallTarget accessExecute(int i) {

@Override
public CallTarget accessInvoke(int arity) {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createExecuteAfterRead(context, SourceSection.createUnavailable("", ""), arity)));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new UnresolvedInteropExecuteAfterReadNode(context, null, arity)));
}

@Override
@@ -95,23 +89,4 @@ public CallTarget accessMessage(Message msg) {
return null;
}

protected static final class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, node.getSourceSection(), null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -11,115 +11,31 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.interop.InteropNode;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;
import org.jruby.truffle.core.basicobject.BasicObjectForeignAccessFactory;
import org.jruby.truffle.interop.InteropGetSizeProperty;
import org.jruby.truffle.interop.RubyInteropRootNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;

public class HashForeignAccessFactory implements ForeignAccess.Factory10, ForeignAccess.Factory {
public class HashForeignAccessFactory extends BasicObjectForeignAccessFactory {

private final RubyContext context;

private HashForeignAccessFactory(RubyContext context) {
this.context = context;
}

public static ForeignAccess create(RubyContext context) {
final HashForeignAccessFactory hashFactory = new HashForeignAccessFactory(context);
return ForeignAccess.create(null, hashFactory);
}


@Override
public boolean canHandle(TruffleObject to) {
return RubyGuards.isRubyHash(to);
public HashForeignAccessFactory(RubyContext context) {
super(context);
}

@Override
public CallTarget accessIsNull() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsNull(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsExecutable() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsExecutable(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsBoxed() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsBoxedPrimitive(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessHasSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createHasSizePropertyTrue(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, true)));
}

@Override
public CallTarget accessGetSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createGetSize(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessUnbox() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsBoxedPrimitive(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropGetSizeProperty(context, null)));
}

@Override
public CallTarget accessRead() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createRead(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessWrite() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createWrite(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessExecute(int i) {
return null;
}

@Override
public CallTarget accessInvoke(int arity) {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createExecuteAfterRead(context, SourceSection.createUnavailable("", ""), arity)));
}

@Override
public CallTarget accessNew(int argumentsLength) {
return null;
}

@Override
public CallTarget accessMessage(Message msg) {
return null;
}

protected static final class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, node.getSourceSection(), null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -18,9 +18,7 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import java.util.Locale;
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.CoreClass;
import org.jruby.truffle.core.CoreMethod;
@@ -31,6 +29,8 @@
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;

import java.util.Locale;

@CoreClass(name = "Float")
public abstract class FloatNodes {

Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.util.ByteList;
import org.jruby.util.ByteListHolder;
import org.jruby.util.StringSupport;

import static org.jruby.truffle.core.rope.CodeRange.CR_7BIT;
Original file line number Diff line number Diff line change
@@ -11,107 +11,49 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.interop.InteropNode;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;
import org.jruby.truffle.core.basicobject.BasicObjectForeignAccessFactory;
import org.jruby.truffle.interop.InteropGetSizeProperty;
import org.jruby.truffle.interop.InteropStringIsBoxed;
import org.jruby.truffle.interop.InteropStringUnboxNode;
import org.jruby.truffle.interop.RubyInteropRootNode;
import org.jruby.truffle.interop.UnresolvedInteropStringReadNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;

public class StringForeignAccessFactory implements ForeignAccess.Factory10 {
public class StringForeignAccessFactory extends BasicObjectForeignAccessFactory {

private final RubyContext context;

private StringForeignAccessFactory(RubyContext context) {
this.context = context;
}

public static ForeignAccess create(RubyContext context) {
return ForeignAccess.create(DynamicObject.class, new StringForeignAccessFactory(context));
public StringForeignAccessFactory(RubyContext context) {
super(context);
}

@Override
public CallTarget accessIsNull() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsNull(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessIsExecutable() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createIsExecutable(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, false)));
}

@Override
public CallTarget accessIsBoxed() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createStringIsBoxed(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropStringIsBoxed(context, null)));
}

@Override
public CallTarget accessHasSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createHasSizePropertyTrue(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new BooleanLiteralNode(context, null, true)));
}

@Override
public CallTarget accessGetSize() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createGetSize(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropGetSizeProperty(context, null)));
}

@Override
public CallTarget accessUnbox() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createStringUnbox(context, SourceSection.createUnavailable("", ""))));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new InteropStringUnboxNode(context, null)));
}

@Override
public CallTarget accessRead() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createStringRead(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessWrite() {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createWrite(context, SourceSection.createUnavailable("", ""))));
}

@Override
public CallTarget accessExecute(int arity) {
return null;
}

@Override
public CallTarget accessInvoke(int arity) {
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(InteropNode.createExecuteAfterRead(context, SourceSection.createUnavailable("", ""), arity)));
return Truffle.getRuntime().createCallTarget(new RubyInteropRootNode(new UnresolvedInteropStringReadNode(context, null)));
}

@Override
public CallTarget accessNew(int argumentsLength) {
return null;
}

@Override
public CallTarget accessMessage(Message msg) {
return null;
}

protected static final class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, node.getSourceSection(), null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

abstract class AbstractExecuteMethodNode extends RubyNode {
public AbstractExecuteMethodNode(RubyContext context,
SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract Object executeWithTarget(VirtualFrame frame, Object method);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
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.interop.ForeignAccess;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;

import java.util.List;

@NodeChild(value="method", type = RubyNode.class)
abstract class ExecuteMethodNode extends AbstractExecuteMethodNode {
@Child private IndirectCallNode callNode;
public ExecuteMethodNode(RubyContext context,
SourceSection sourceSection) {
super(context, sourceSection);
callNode = Truffle.getRuntime().createIndirectCallNode();
}

@Specialization(guards = {"isRubyProc(proc)", "proc == cachedProc"})
protected Object doCallProc(VirtualFrame frame, DynamicObject proc,
@Cached("proc") DynamicObject cachedProc,
@Cached("create(getCallTarget(cachedProc))") DirectCallNode callNode) {
final List<Object> faArgs = ForeignAccess.getArguments(frame);
Object[] args = faArgs.toArray();
return callNode.call(frame, RubyArguments.pack(Layouts.PROC.getDeclarationFrame(cachedProc), null, Layouts.PROC.getMethod(cachedProc), DeclarationContext.METHOD, null, Layouts.PROC.getSelf(cachedProc), null, args));
}

@Specialization(guards = "isRubyProc(proc)")
protected Object doCallProc(VirtualFrame frame, DynamicObject proc) {
final List<Object> faArgs = ForeignAccess.getArguments(frame);
Object[] args = faArgs.toArray();
return callNode.call(frame, Layouts.PROC.getCallTargetForType(proc), RubyArguments.pack(Layouts.PROC.getDeclarationFrame(proc), null, Layouts.PROC.getMethod(proc), DeclarationContext.METHOD, null, Layouts.PROC.getSelf(proc), null, args));
}

@Specialization(guards = {"isRubyMethod(method)", "method == cachedMethod"})
protected Object doCall(VirtualFrame frame, DynamicObject method,
@Cached("method") DynamicObject cachedMethod,
@Cached("getMethod(cachedMethod)") InternalMethod internalMethod,
@Cached("create(getMethod(cachedMethod).getCallTarget())") DirectCallNode callNode) {
final List<Object> faArgs = ForeignAccess.getArguments(frame);

Object[] args = faArgs.subList(0, faArgs.size()).toArray();
return callNode.call(frame, RubyArguments.pack(null, null, internalMethod, DeclarationContext.METHOD, null, Layouts.METHOD.getReceiver(cachedMethod), null, args));
}

@Specialization(guards = "isRubyMethod(method)")
protected Object doCall(VirtualFrame frame, DynamicObject method) {
final InternalMethod internalMethod = Layouts.METHOD.getMethod(method);
final List<Object> faArgs = ForeignAccess.getArguments(frame);

Object[] args = faArgs.subList(0, faArgs.size()).toArray();
return callNode.call(frame, internalMethod.getCallTarget(), RubyArguments.pack(null, null, internalMethod, DeclarationContext.METHOD, null, Layouts.METHOD.getReceiver(method), null, args));
}

protected InternalMethod getMethodFromProc(DynamicObject proc) {
return Layouts.PROC.getMethod(proc);
}

protected CallTarget getCallTarget(DynamicObject proc) {
return Layouts.PROC.getCallTargetForType(proc);
}

protected InternalMethod getMethod(DynamicObject method) {
return Layouts.METHOD.getMethod(method);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

class InteropArgumentNode extends RubyNode {
private final int index;

public InteropArgumentNode(RubyContext context, SourceSection sourceSection, int index) {
super(context, sourceSection);
this.index = index;
}

public Object execute(VirtualFrame frame) {
return ForeignAccess.getArguments(frame).get(index);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

class InteropArgumentsNode extends RubyNode {

@Children private final InteropArgumentNode[] arguments;

public InteropArgumentsNode(RubyContext context, SourceSection sourceSection, int arity) {
super(context, sourceSection);
this.arguments = new InteropArgumentNode[arity];
// index 0 is the lable
for (int i = 1; i < 1 + arity; i++) {
arguments[i - 1] = new InteropArgumentNode(context, sourceSection, i);
}
}

public int getCount(VirtualFrame frame) {
return arguments.length;
}

public Object execute(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException();
}

@ExplodeLoop
public void executeFillObjectArray(VirtualFrame frame, Object[] args) {
for (int i = 0; i < arguments.length; i++) {
args[i] = arguments[i].execute(frame);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

public class InteropExecute extends RubyNode {
@Child private ExecuteMethodNode execute;

public InteropExecute(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.execute = ExecuteMethodNodeGen.create(context, sourceSection, null);
}

@Override
public Object execute(VirtualFrame frame) {
Object result = execute.executeWithTarget(frame, ForeignAccess.getReceiver(frame));
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

public class InteropGetSizeProperty extends RubyNode {

@Child private DispatchHeadNode head;
public InteropGetSizeProperty(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
}

@Override
public Object execute(VirtualFrame frame) {
return head.dispatch(frame, ForeignAccess.getReceiver(frame), "size", null, new Object[] {});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.objects.ReadInstanceVariableNode;

class InteropInstanceVariableReadNode extends RubyNode {

@Child private ReadInstanceVariableNode read;
private final String name;
private final int labelIndex;

public InteropInstanceVariableReadNode(RubyContext context, SourceSection sourceSection, String name, int labelIndex) {
super(context, sourceSection);
this.name = name;
this.read = new ReadInstanceVariableNode(context, sourceSection, name, new RubyInteropReceiverNode(context, sourceSection));
this.labelIndex = labelIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
return read.execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.objects.WriteInstanceVariableNode;

class InteropInstanceVariableWriteNode extends RubyNode {

@Child private WriteInstanceVariableNode write;
private final String name;
private final int labelIndex;

public InteropInstanceVariableWriteNode(RubyContext context, SourceSection sourceSection, String name, int labelIndex, int valueIndex) {
super(context, sourceSection);
this.name = name;
this.labelIndex = labelIndex;
this.write = new WriteInstanceVariableNode(context, sourceSection, name, new RubyInteropReceiverNode(context, sourceSection), new RubyInteropArgumentNode(context, sourceSection, valueIndex));
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
return write.execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Not implemented");
}
}
}
27 changes: 27 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/interop/InteropIsNull.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

public class InteropIsNull extends RubyNode {
public InteropIsNull(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Override
public Object execute(VirtualFrame frame) {
return ForeignAccess.getReceiver(frame) == nil();
}
}
745 changes: 0 additions & 745 deletions truffle/src/main/java/org/jruby/truffle/interop/InteropNode.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;

class InteropReadStringByteNode extends RubyNode {

private final int labelIndex;

public InteropReadStringByteNode(RubyContext context, SourceSection sourceSection, int labelIndex) {
super(context, sourceSection);
this.labelIndex = labelIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (RubyGuards.isRubyString(ForeignAccess.getReceiver(frame))) {
final DynamicObject string = (DynamicObject) ForeignAccess.getReceiver(frame);
final int index = (int) ForeignAccess.getArguments(frame).get(labelIndex);
if (index >= Layouts.STRING.getRope(string).byteLength()) {
return 0;
} else {
return (byte) StringOperations.getByteListReadOnly(string).get(index);
}
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Not implemented");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;

public class InteropStringIsBoxed extends RubyNode {

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

@Override
public Object execute(VirtualFrame frame) {
Object o = ForeignAccess.getReceiver(frame);
return RubyGuards.isRubyString(o) && StringOperations.rope((DynamicObject) o).byteLength() == 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyNode;

public class InteropStringUnboxNode extends RubyNode {

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

@Override
public Object execute(VirtualFrame frame) {
return StringOperations.getByteListReadOnly(((DynamicObject) ForeignAccess.getReceiver(frame))).get(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropExecuteAfterReadNode extends RubyNode {

@Child private DispatchHeadNode head;
@Child private InteropArgumentsNode arguments;
private final String name;
private final int labelIndex;
private final int receiverIndex;

public ResolvedInteropExecuteAfterReadNode(RubyContext context, SourceSection sourceSection, String name, int arity) {
super(context, sourceSection);
this.name = name;
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.arguments = new InteropArgumentsNode(context, sourceSection, arity); // [0] is receiver, [1] is the label
this.labelIndex = 1;
this.receiverIndex = 0;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(frame.getArguments()[labelIndex])) {
Object[] args = new Object[arguments.getCount(frame)];
arguments.executeFillObjectArray(frame, args);
return head.dispatch(frame, frame.getArguments()[receiverIndex], frame.getArguments()[labelIndex], null, args);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Name changed");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropIndexedReadNode extends RubyNode {

private final String name;
@Child private DispatchHeadNode head;
@Child private IndexLabelToRubyNode toRubyIndex;
private final int indexIndex;

public ResolvedInteropIndexedReadNode(RubyContext context, SourceSection sourceSection, int indexIndex) {
super(context, sourceSection);
this.name = "[]";
this.indexIndex = indexIndex;
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.toRubyIndex = IndexLabelToRubyNodeGen.create(context, sourceSection, null);
}

@Override
public Object execute(VirtualFrame frame) {
Object index = toRubyIndex.executeWithTarget(frame, ForeignAccess.getArguments(frame).get(indexIndex));
return head.dispatch(frame, ForeignAccess.getReceiver(frame), name, null, new Object[] {index});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropIndexedWriteNode extends RubyNode {

private final String name;
@Child private DispatchHeadNode head;
@Child private IndexLabelToRubyNode toRubyIndex;
private final int indexIndex;
private final int valueIndex;

public ResolvedInteropIndexedWriteNode(RubyContext context, SourceSection sourceSection, int indexIndex, int valueIndex) {
super(context, sourceSection);
this.name = "[]=";
this.indexIndex = indexIndex;
this.valueIndex = valueIndex;
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.toRubyIndex = IndexLabelToRubyNodeGen.create(context, sourceSection, null);
}

@Override
public Object execute(VirtualFrame frame) {
Object index = toRubyIndex.executeWithTarget(frame, ForeignAccess.getArguments(frame).get(indexIndex));
Object value = ForeignAccess.getArguments(frame).get(valueIndex);
return head.dispatch(frame, ForeignAccess.getReceiver(frame), name, null, new Object[] {index, value});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropReadFromSymbolNode extends RubyNode {

@Child private DispatchHeadNode head;
private final DynamicObject name;
private final int labelIndex;

public ResolvedInteropReadFromSymbolNode(RubyContext context, SourceSection sourceSection, DynamicObject name, int labelIndex) {
super(context, sourceSection);
this.name = name;
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.labelIndex = labelIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
return head.dispatch(frame, ForeignAccess.getReceiver(frame), name, null, new Object[]{});
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Name changed");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropReadNode extends RubyNode {

@Child private DispatchHeadNode head;
private final String name;
private final int labelIndex;

public ResolvedInteropReadNode(RubyContext context, SourceSection sourceSection, String name, int labelIndex) {
super(context, sourceSection);
this.name = name;
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.labelIndex = labelIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
return head.dispatch(frame, ForeignAccess.getReceiver(frame), name, null, new Object[]{});
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Name changed");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropWriteNode extends RubyNode {

@Child private DispatchHeadNode head;
private final String name;
private final String accessName;
private final int labelIndex;
private final int valueIndex;

public ResolvedInteropWriteNode(RubyContext context, SourceSection sourceSection, String name, int labelIndex, int valueIndex) {
super(context, sourceSection);
this.name = name;
this.accessName = name + "=";
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.labelIndex = labelIndex;
this.valueIndex = valueIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
Object value = ForeignAccess.getArguments(frame).get(valueIndex);
return head.dispatch(frame, ForeignAccess.getReceiver(frame), accessName, null, new Object[]{value});
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Name changed");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.dispatch.DispatchAction;
import org.jruby.truffle.language.dispatch.DispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;

class ResolvedInteropWriteToSymbolNode extends RubyNode {

@Child private DispatchHeadNode head;
private final DynamicObject name;
private final DynamicObject accessName;
private final int labelIndex;
private final int valueIndex;

public ResolvedInteropWriteToSymbolNode(RubyContext context, SourceSection sourceSection, DynamicObject name, int labelIndex, int valueIndex) {
super(context, sourceSection);
this.name = name;
this.accessName = context.getSymbolTable().getSymbol(Layouts.SYMBOL.getString(name) + "=");
this.head = new DispatchHeadNode(context, true, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.labelIndex = labelIndex;
this.valueIndex = valueIndex;
}

@Override
public Object execute(VirtualFrame frame) {
if (name.equals(ForeignAccess.getArguments(frame).get(labelIndex))) {
Object value = ForeignAccess.getArguments(frame).get(valueIndex);
return head.dispatch(frame, ForeignAccess.getReceiver(frame), accessName, null, new Object[]{value});
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Name changed");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

class RubyInteropArgumentNode extends RubyNode {

private final int index;

public RubyInteropArgumentNode(RubyContext context, SourceSection sourceSection, int index) {
super(context, sourceSection);
this.index = index;
}

@Override
public Object execute(VirtualFrame frame) {
return ForeignAccess.getArguments(frame).get(index);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

class RubyInteropReceiverNode extends RubyNode {
public RubyInteropReceiverNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Override
public Object execute(VirtualFrame frame) {
return ForeignAccess.getReceiver(frame);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.backtrace.InternalRootNode;

public class RubyInteropRootNode extends RootNode implements InternalRootNode {

@Child private RubyNode node;

public RubyInteropRootNode(RubyNode node) {
super(RubyLanguage.class, null, null);
this.node = node;
}

@Override
public Object execute(VirtualFrame virtualFrame) {
return node.execute(virtualFrame);
}

@Override
public String toString() {
return "Root of: " + node.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

public class UnresolvedInteropExecuteAfterReadNode extends RubyNode {

private final int arity;
private final int labelIndex;

public UnresolvedInteropExecuteAfterReadNode(RubyContext context, SourceSection sourceSection, int arity){
super(context, sourceSection);
this.arity = arity;
this.labelIndex = 0;
}

@Override
public Object execute(VirtualFrame frame) {
if (ForeignAccess.getArguments(frame).get(labelIndex) instanceof String) {
return this.replace(new ResolvedInteropExecuteAfterReadNode(getContext(), getSourceSection(), (String) ForeignAccess.getArguments(frame).get(labelIndex), arity)).execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(ForeignAccess.getArguments(frame).get(0) + " not allowed as name");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.module.ModuleOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.methods.InternalMethod;

public class UnresolvedInteropReadNode extends RubyNode {

private final int labelIndex;

public UnresolvedInteropReadNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.labelIndex = 0;
}

@Override
public Object execute(VirtualFrame frame) {
Object label = ForeignAccess.getArguments(frame).get(labelIndex);
if (label instanceof String || RubyGuards.isRubySymbol(label) || label instanceof Integer) {
if (label instanceof String) {
String name = (String) label;
if (name.startsWith("@")) {
return this.replace(new InteropInstanceVariableReadNode(getContext(), getSourceSection(), name, labelIndex)).execute(frame);
}
}
DynamicObject receiver = (DynamicObject) ForeignAccess.getReceiver(frame);
InternalMethod labelMethod = ModuleOperations.lookupMethod(coreLibrary().getMetaClass(receiver), label.toString());
InternalMethod indexedSetter = ModuleOperations.lookupMethod(coreLibrary().getMetaClass(receiver), "[]=");
if (labelMethod == null && indexedSetter != null) {
return this.replace(new ResolvedInteropIndexedReadNode(getContext(), getSourceSection(), labelIndex)).execute(frame);
} else if (label instanceof String) {
return this.replace(new ResolvedInteropReadNode(getContext(), getSourceSection(), (String) label, labelIndex)).execute(frame);
} else if (RubyGuards.isRubySymbol(label)) {
return this.replace(new ResolvedInteropReadFromSymbolNode(getContext(), getSourceSection(), (DynamicObject) label, labelIndex)).execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;

public class UnresolvedInteropStringReadNode extends RubyNode {

private final int labelIndex;

public UnresolvedInteropStringReadNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.labelIndex = 0;
}

@Override
public Object execute(VirtualFrame frame) {
Object label = ForeignAccess.getArguments(frame).get(labelIndex);
if (label instanceof String || RubyGuards.isRubySymbol(label) || label instanceof Integer) {
if (label instanceof String) {
String name = (String) label;
if (name.startsWith("@")) {
return this.replace(new InteropInstanceVariableReadNode(getContext(), getSourceSection(), name, labelIndex)).execute(frame);
}
}
if (label instanceof Integer || label instanceof Long) {
return this.replace(new InteropReadStringByteNode(getContext(), getSourceSection(), labelIndex)).execute(frame);
} else if (label instanceof String) {
return this.replace(new ResolvedInteropReadNode(getContext(), getSourceSection(), (String) label, labelIndex)).execute(frame);
} else if (RubyGuards.isRubySymbol(label)) {
return this.replace(new ResolvedInteropReadFromSymbolNode(getContext(), getSourceSection(), (DynamicObject) label, labelIndex)).execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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,
* 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.interop;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.module.ModuleOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.methods.InternalMethod;

public class UnresolvedInteropWriteNode extends RubyNode {

private final int labelIndex;
private final int valueIndex;

public UnresolvedInteropWriteNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.labelIndex = 0;
this.valueIndex = 1;
}

@Override
public Object execute(VirtualFrame frame) {
Object label = ForeignAccess.getArguments(frame).get(labelIndex);
if (label instanceof String || RubyGuards.isRubySymbol(label) || label instanceof Integer) {
if (label instanceof String) {
String name = (String) label;
if (name.startsWith("@")) {
return this.replace(new InteropInstanceVariableWriteNode(getContext(), getSourceSection(), name, labelIndex, valueIndex)).execute(frame);
}
}
DynamicObject receiver = (DynamicObject) ForeignAccess.getReceiver(frame);
InternalMethod labelMethod = ModuleOperations.lookupMethod(coreLibrary().getMetaClass(receiver), label.toString());
InternalMethod indexedSetter = ModuleOperations.lookupMethod(coreLibrary().getMetaClass(receiver), "[]=");
if (labelMethod == null && indexedSetter != null) {
return this.replace(new ResolvedInteropIndexedWriteNode(getContext(), getSourceSection(), labelIndex, valueIndex)).execute(frame);
} else if (label instanceof String) {
return this.replace(new ResolvedInteropWriteNode(getContext(), getSourceSection(), (String) label, labelIndex, valueIndex)).execute(frame);
} else if (RubyGuards.isRubySymbol(label)) {
return this.replace(new ResolvedInteropWriteToSymbolNode(getContext(), getSourceSection(), (DynamicObject) label, labelIndex, valueIndex)).execute(frame);
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(label + " not allowed as name");
}
}
}
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.RubyMethodForeignAccessFactory;
import org.jruby.truffle.core.array.ArrayForeignAccessFactory;
import org.jruby.truffle.core.basicobject.BasicForeignAccessFactory;
import org.jruby.truffle.core.basicobject.BasicObjectForeignAccessFactory;
import org.jruby.truffle.core.hash.HashForeignAccessFactory;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.StringForeignAccessFactory;
@@ -47,19 +47,21 @@ public String toString(DynamicObject object) {
public ForeignAccess getForeignAccessFactory(DynamicObject object) {
CompilerAsserts.neverPartOfCompilation();

if (Layouts.METHOD.isMethod(object)) {
return RubyMethodForeignAccessFactory.create(getContext());
} else if (Layouts.PROC.isProc(object)) {
return RubyMethodForeignAccessFactory.create(getContext());
final ForeignAccess.Factory10 factory;

if (Layouts.METHOD.isMethod(object) || Layouts.PROC.isProc(object)) {
factory = new RubyMethodForeignAccessFactory(getContext());
} else if (Layouts.ARRAY.isArray(object)) {
return ArrayForeignAccessFactory.create(getContext());
factory = new ArrayForeignAccessFactory(getContext());
} else if (Layouts.HASH.isHash(object)) {
return HashForeignAccessFactory.create(getContext());
factory = new HashForeignAccessFactory(getContext());
} else if (Layouts.STRING.isString(object)) {
return StringForeignAccessFactory.create(getContext());
factory = new StringForeignAccessFactory(getContext());
} else {
return BasicForeignAccessFactory.create(getContext());
factory = new BasicObjectForeignAccessFactory(getContext());
}

return ForeignAccess.create(DynamicObject.class, factory);
}

private RubyContext getContext() {

0 comments on commit 880b69c

Please sign in to comment.