Skip to content

Commit

Permalink
Showing 7 changed files with 143 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.arguments;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ValueProfile;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.UndefinedPlaceholder;

public class WritePreArgumentNode extends RubyNode {

@Child private RubyNode rhs;

private final int index;

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

@Override
public Object execute(VirtualFrame frame) {
RubyArguments.setUserArgument(frame.getArguments(), index, rhs.execute(frame));
return nil();
}

}
Original file line number Diff line number Diff line change
@@ -21,16 +21,20 @@
public class GeneralSuperReCallNode extends AbstractGeneralSuperCallNode {

private final boolean inBlock;
@Child private RubyNode reload;
@Child private RubyNode block;

public GeneralSuperReCallNode(RubyContext context, SourceSection sourceSection, boolean inBlock, RubyNode block) {
public GeneralSuperReCallNode(RubyContext context, SourceSection sourceSection, boolean inBlock, RubyNode reload, RubyNode block) {
super(context, sourceSection);
this.inBlock = inBlock;
this.reload = reload;
this.block = block;
}

@Override
public final Object execute(VirtualFrame frame) {
reload.execute(frame);

final Object self = RubyArguments.getSelf(frame.getArguments());

if (!guard(frame, self)) {
Original file line number Diff line number Diff line change
@@ -90,6 +90,10 @@ public static Object getUserArgument(Object[] internalArguments, int index) {
return internalArguments[RUNTIME_ARGUMENT_COUNT + index];
}

public static void setUserArgument(Object[] internalArguments, int index, Object value) {
internalArguments[RUNTIME_ARGUMENT_COUNT + index] = value;
}

public static RubyHash getUserKeywordsHash(Object[] internalArguments, int minArgumentCount) {
final int argumentCount = getUserArgumentsCount(internalArguments);

@@ -138,5 +142,4 @@ private static MaterializedFrame getDeclarationFrame(MaterializedFrame frame, in

return parentFrame;
}

}
Original file line number Diff line number Diff line change
@@ -1131,9 +1131,9 @@ protected RubyNode translateMethodDefinition(SourceSection sourceSection, RubyNo

// ownScopeForAssignments is the same for the defined method as the current one.

final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, false, source);
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, false, source, argsNode);

final MethodDefinitionNode functionExprNode = (MethodDefinitionNode) methodCompiler.compileFunctionNode(sourceSection, methodName, argsNode, bodyNode, sharedMethodInfo);
final MethodDefinitionNode functionExprNode = (MethodDefinitionNode) methodCompiler.compileFunctionNode(sourceSection, methodName, bodyNode, sharedMethodInfo);

return new AddMethodNode(context, sourceSection, classNode, functionExprNode);
}
@@ -1707,14 +1707,14 @@ public RubyNode visitIterNode(org.jruby.ast.IterNode node) {
final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(
context, environment, environment.getParseEnvironment(), environment.getReturnID(), hasOwnScope, false,
sharedMethodInfo, environment.getNamedMethodName(), true, environment.getParseEnvironment().allocateBlockID());
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, true, source);
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, true, source, argsNode);
methodCompiler.translatingForStatement = translatingForStatement;

if (translatingForStatement && useClassVariablesAsIfInClass) {
methodCompiler.useClassVariablesAsIfInClass = true;
}

return methodCompiler.compileFunctionNode(translate(node.getPosition()), sharedMethodInfo.getName(), argsNode, node.getBodyNode(), sharedMethodInfo);
return methodCompiler.compileFunctionNode(translate(node.getPosition()), sharedMethodInfo.getName(), node.getBodyNode(), sharedMethodInfo);
}

@Override
@@ -2837,9 +2837,9 @@ public RubyNode visitLambdaNode(org.jruby.ast.LambdaNode node) {
final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(
context, environment, environment.getParseEnvironment(), environment.getReturnID(), false, false,
sharedMethodInfo, sharedMethodInfo.getName(), true, environment.getParseEnvironment().allocateBlockID());
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, false, source);
final MethodTranslator methodCompiler = new MethodTranslator(currentNode, context, this, newEnvironment, false, source, argsNode);

final RubyNode definitionNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), sharedMethodInfo.getName(), argsNode, node.getBodyNode(), sharedMethodInfo);
final RubyNode definitionNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), sharedMethodInfo.getName(), node.getBodyNode(), sharedMethodInfo);

return new LambdaNode(context, translate(node.getPosition()), definitionNode);
}
Original file line number Diff line number Diff line change
@@ -40,14 +40,16 @@

class MethodTranslator extends BodyTranslator {

private final org.jruby.ast.ArgsNode argsNode;
private boolean isBlock;

public MethodTranslator(Node currentNode, RubyContext context, BodyTranslator parent, TranslatorEnvironment environment, boolean isBlock, Source source) {
public MethodTranslator(Node currentNode, RubyContext context, BodyTranslator parent, TranslatorEnvironment environment, boolean isBlock, Source source, org.jruby.ast.ArgsNode argsNode) {
super(currentNode, context, parent, environment, source, false);
this.isBlock = isBlock;
this.argsNode = argsNode;
}

public RubyNode compileFunctionNode(SourceSection sourceSection, String methodName, ArgsNode argsNode, org.jruby.ast.Node bodyNode, SharedMethodInfo sharedMethodInfo) {
public RubyNode compileFunctionNode(SourceSection sourceSection, String methodName, org.jruby.ast.Node bodyNode, SharedMethodInfo sharedMethodInfo) {
if (PRINT_PARSE_TREE_METHOD_NAMES.contains(methodName)) {
System.err.println(sourceSection + " " + methodName);
System.err.println(sharedMethodInfo.getParseTree().toString(true, 0));
@@ -282,7 +284,9 @@ public RubyNode visitZSuperNode(org.jruby.ast.ZSuperNode node) {
blockNode = null;
}

return new GeneralSuperReCallNode(context, sourceSection, environment.isBlock(), blockNode);
return new GeneralSuperReCallNode(context, sourceSection, environment.isBlock(),
new ReloadArgumentsTranslator(currentNode, context, source, this).visitArgsNode(argsNode),
blockNode);
}

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.translator;

import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.ast.ArgumentNode;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.arguments.WritePreArgumentNode;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.literal.ObjectLiteralNode;
import org.jruby.truffle.nodes.locals.ReadLocalVariableNode;
import org.jruby.truffle.runtime.RubyContext;

import java.util.ArrayList;
import java.util.List;

/**
* Produces code to reload arguments from local variables back into the
* arguments array. Only works for simple cases. Used for zsuper calls which
* pass the same arguments, but will pick up modifications made to them in the
* method so far.
*/
public class ReloadArgumentsTranslator extends Translator {

private final BodyTranslator methodBodyTranslator;

private int index;

public ReloadArgumentsTranslator(Node currentNode, RubyContext context, Source source, BodyTranslator methodBodyTranslator) {
super(currentNode, context, source);
this.methodBodyTranslator = methodBodyTranslator;
}

@Override
public RubyNode visitArgsNode(org.jruby.ast.ArgsNode node) {
final SourceSection sourceSection = translate(node.getPosition());

final List<RubyNode> sequence = new ArrayList<>();

if (node.getPre() != null) {
for (org.jruby.ast.Node arg : node.getPre().childNodes()) {
sequence.add(arg.accept(this));
index++;
}
}

return SequenceNode.sequence(context, sourceSection, sequence);
}

@Override
public RubyNode visitArgumentNode(ArgumentNode node) {
final SourceSection sourceSection = translate(node.getPosition());

final FrameSlot slot = methodBodyTranslator.getEnvironment().getFrameDescriptor().findFrameSlot(node.getName());
final RubyNode read = new ReadLocalVariableNode(context, sourceSection, slot);
return new WritePreArgumentNode(context, sourceSection, index, read);
}

@Override
protected RubyNode defaultVisit(org.jruby.ast.Node node) {
final SourceSection sourceSection = translate(node.getPosition());
return new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getNilObject());
}

@Override
protected String getIdentifier() {
return methodBodyTranslator.getIdentifier();
}

}
Original file line number Diff line number Diff line change
@@ -61,12 +61,12 @@ public RubyNode parse(RubyContext context, org.jruby.ast.Node parseTree, org.jru
final MethodTranslator translator;

try {
translator = new MethodTranslator(currentNode, context, null, environment, false, Source.fromFileName(bodyNode.getPosition().getFile()));
translator = new MethodTranslator(currentNode, context, null, environment, false, Source.fromFileName(bodyNode.getPosition().getFile()), argsNode);
} catch (IOException e) {
throw new RuntimeException(e);
}

return translator.compileFunctionNode(null, "(unknown)", argsNode, bodyNode, sharedMethod);
return translator.compileFunctionNode(null, "(unknown)", bodyNode, sharedMethod);
}

public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEncoding, ParserContext parserContext, MaterializedFrame parentFrame, boolean ownScopeForAssignments, Node currentNode, NodeWrapper wrapper) {

0 comments on commit 9505ba8

Please sign in to comment.