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

Commits on Sep 8, 2016

  1. Copy the full SHA
    ae2e186 View commit details
  2. Copy the full SHA
    94b70f0 View commit details
  3. Copy the full SHA
    39efbb8 View commit details
  4. Copy the full SHA
    621fff9 View commit details
  5. Copy the full SHA
    615fff0 View commit details
Original file line number Diff line number Diff line change
@@ -188,24 +188,49 @@ private static CallTarget makeGenericMethod(RubyContext context, MethodDetails m
final SourceSection sourceSection = sharedMethodInfo.getSourceSection();
final RubySourceSection rubySourceSection = new RubySourceSection(sourceSection);

final int required = method.required();
final int optional = method.optional();
final RubyNode methodNode = createCoreMethodNode(context, sourceSection, methodDetails.getNodeFactory(), method);

if (CHECK_AMBIGUOUS_OPTIONAL_ARGS) {
AmbiguousOptionalArgumentChecker.verifyNoAmbiguousOptionalArguments(methodDetails);
}

final RubyNode checkArity = Translator.createCheckArityNode(context, sourceSection.getSource(), rubySourceSection, sharedMethodInfo.getArity());

RubyNode node;
if (!isSafe(context, method.unsafe())) {
node = new UnsafeNode(context, sourceSection);
} else {
node = Translator.sequence(context, sourceSection.getSource(), rubySourceSection, Arrays.asList(checkArity, methodNode));
node = transformResult(method, node);
}

RubyNode bodyNode = new ExceptionTranslatingNode(context, sourceSection, node, method.unsupportedOperationBehavior());

if (context.getOptions().CHAOS) {
bodyNode = ChaosNodeGen.create(bodyNode);
}

final RubyRootNode rootNode = new RubyRootNode(context, sourceSection, null, sharedMethodInfo, bodyNode, false);

return Truffle.getRuntime().createCallTarget(rootNode);
}

public static RubyNode createCoreMethodNode(RubyContext context, SourceSection sourceSection, NodeFactory<? extends RubyNode> nodeFactory, CoreMethod method) {
final List<RubyNode> argumentsNodes = new ArrayList<>();

if (method.needsCallerFrame()) {
argumentsNodes.add(new ReadCallerFrameNode());
}

// Do not use needsSelf=true in module functions, it is either the module/class or the instance.
// Usage of needsSelf is quite rare for singleton methods (except constructors).
final boolean needsSelf = method.constructor() || (!method.isModuleFunction() && !method.onSingleton() && method.needsSelf());
final boolean needsSelf = needsSelf(method);

if (needsSelf) {
RubyNode readSelfNode = new ProfileArgumentNode(new ReadSelfNode());
argumentsNodes.add(transformArgument(context, sourceSection, method, readSelfNode, 0));
}

final int required = method.required();
final int optional = method.optional();
final int nArgs = required + optional;

for (int n = 0; n < nArgs; n++) {
@@ -220,8 +245,11 @@ private static CallTarget makeGenericMethod(RubyContext context, MethodDetails m
argumentsNodes.add(new ReadBlockNode(NotProvided.INSTANCE));
}

final RubyNode methodNode;
final NodeFactory<? extends RubyNode> nodeFactory = methodDetails.getNodeFactory();
return createNodeFromFactory(context, sourceSection, nodeFactory, argumentsNodes);
}

public static <T> T createNodeFromFactory(RubyContext context, SourceSection sourceSection, NodeFactory<? extends T> nodeFactory, List<RubyNode> argumentsNodes) {
final T methodNode;
List<List<Class<?>>> signatures = nodeFactory.getNodeSignatures();

assert signatures.size() == 1;
@@ -247,29 +275,13 @@ private static CallTarget makeGenericMethod(RubyContext context, MethodDetails m
}
}

if (CHECK_AMBIGUOUS_OPTIONAL_ARGS) {
AmbiguousOptionalArgumentChecker.verifyNoAmbiguousOptionalArguments(methodDetails);
}

final RubyNode checkArity = Translator.createCheckArityNode(context, sourceSection.getSource(), rubySourceSection, sharedMethodInfo.getArity());

RubyNode node;
if (!isSafe(context, method.unsafe())) {
node = new UnsafeNode(context, sourceSection);
} else {
node = Translator.sequence(context, sourceSection.getSource(), rubySourceSection, Arrays.asList(checkArity, methodNode));
node = transformResult(method, node);
}

RubyNode bodyNode = new ExceptionTranslatingNode(context, sourceSection, node, method.unsupportedOperationBehavior());

if (context.getOptions().CHAOS) {
bodyNode = ChaosNodeGen.create(bodyNode);
}

final RubyRootNode rootNode = new RubyRootNode(context, sourceSection, null, sharedMethodInfo, bodyNode, false);
return methodNode;
}

return Truffle.getRuntime().createCallTarget(rootNode);
public static boolean needsSelf(CoreMethod method) {
// Do not use needsSelf=true in module functions, it is either the module/class or the instance.
// Usage of needsSelf is quite rare for singleton methods (except constructors).
return method.constructor() || (!method.isModuleFunction() && !method.onSingleton() && method.needsSelf());
}

private static RubyNode transformArgument(RubyContext context, SourceSection sourceSection, CoreMethod method, RubyNode argument, int n) {
Original file line number Diff line number Diff line change
@@ -15,10 +15,9 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;

import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.array.ArrayUtils;
import org.jruby.truffle.core.cast.BooleanCastNode;
import org.jruby.truffle.core.cast.BooleanCastNodeGen;
@@ -57,32 +56,26 @@ public class RubyCallNode extends RubyNode {

private final ConditionProfile nilProfile;

public RubyCallNode(RubyContext context, SourceSection section, RubyNode receiver, String methodName, RubyNode block, RubyNode[] arguments,
boolean isSplatted, boolean ignoreVisibility) {
this(context, section, receiver, methodName, block, arguments, isSplatted, ignoreVisibility, false, false, false);
}

public RubyCallNode(RubyContext context, SourceSection section, RubyNode receiver, String methodName, RubyNode block, RubyNode[] arguments,
boolean isSplatted, boolean ignoreVisibility, boolean isVCall, boolean isSafeNavigation, boolean isAttrAssign) {
super(context, section);
public RubyCallNode(RubyCallNodeParameters parameters) {
super(parameters.getContext(), parameters.getSection());

this.methodName = methodName;
this.receiver = receiver;
this.arguments = arguments;
this.methodName = parameters.getMethodName();
this.receiver = parameters.getReceiver();
this.arguments = parameters.getArguments();

if (block == null) {
if (parameters.getBlock() == null) {
this.block = null;
} else {
this.block = ProcOrNullNodeGen.create(context, section, block);
this.block = ProcOrNullNodeGen.create(parameters.getContext(), parameters.getSection(), parameters.getBlock());
}

this.isSplatted = isSplatted;
this.ignoreVisibility = ignoreVisibility;
this.isVCall = isVCall;
this.isSafeNavigation = isSafeNavigation;
this.isAttrAssign = isAttrAssign;
this.isSplatted = parameters.isSplatted();
this.ignoreVisibility = parameters.isIgnoreVisibility();
this.isVCall = parameters.isVCall();
this.isSafeNavigation = parameters.isSafeNavigation();
this.isAttrAssign = parameters.isAttrAssign();

if (isSafeNavigation) {
if (parameters.isSafeNavigation()) {
nilProfile = ConditionProfile.createCountingProfile();
} else {
nilProfile = null;
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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
*/
package org.jruby.truffle.language.dispatch;

import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

import com.oracle.truffle.api.source.SourceSection;

public class RubyCallNodeParameters {

private final RubyContext context;
private final SourceSection section;
private final RubyNode receiver;
private final String methodName;
private final RubyNode block;
private final RubyNode[] arguments;
private final boolean isSplatted;
private final boolean ignoreVisibility;
private final boolean isVCall;
private final boolean isSafeNavigation;
private final boolean isAttrAssign;

public RubyCallNodeParameters(RubyContext context, SourceSection section,
RubyNode receiver, String methodName, RubyNode block, RubyNode[] arguments,
boolean isSplatted, boolean ignoreVisibility) {
this(context, section, receiver, methodName, block, arguments, isSplatted, ignoreVisibility, false, false, false);
}

public RubyCallNodeParameters(RubyContext context, SourceSection section,
RubyNode receiver, String methodName, RubyNode block, RubyNode[] arguments,
boolean isSplatted, boolean ignoreVisibility,
boolean isVCall, boolean isSafeNavigation, boolean isAttrAssign) {
this.context = context;
this.section = section;
this.receiver = receiver;
this.methodName = methodName;
this.block = block;
this.arguments = arguments;
this.isSplatted = isSplatted;
this.ignoreVisibility = ignoreVisibility;
this.isVCall = isVCall;
this.isSafeNavigation = isSafeNavigation;
this.isAttrAssign = isAttrAssign;
}

public RubyContext getContext() {
return context;
}

public SourceSection getSection() {
return section;
}

public RubyNode getReceiver() {
return receiver;
}

public String getMethodName() {
return methodName;
}

public RubyNode getBlock() {
return block;
}

public RubyNode[] getArguments() {
return arguments;
}

public boolean isSplatted() {
return isSplatted;
}

public boolean isIgnoreVisibility() {
return ignoreVisibility;
}

public boolean isVCall() {
return isVCall;
}

public boolean isSafeNavigation() {
return isSafeNavigation;
}

public boolean isAttrAssign() {
return isAttrAssign;
}
}
Original file line number Diff line number Diff line change
@@ -10,23 +10,25 @@
package org.jruby.truffle.language.objects;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.HiddenKey;

import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.locals.ReadFrameSlotNode;
import org.jruby.truffle.language.locals.ReadFrameSlotNodeGen;

public class SelfNode extends RubyNode {

public static HiddenKey SELF_IDENTIFIER = new HiddenKey("(self)");
public static final HiddenKey SELF_IDENTIFIER = new HiddenKey("(self)");

private final FrameSlot selfSlot;

@Child private ReadFrameSlotNode readSelfSlotNode;

public SelfNode(FrameSlot selfSlot) {
this.selfSlot = selfSlot;
public SelfNode(FrameDescriptor frameDescriptor) {
this.selfSlot = frameDescriptor.findOrAddFrameSlot(SelfNode.SELF_IDENTIFIER);
}

@Override
Loading