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

Commits on Jul 27, 2015

  1. Copy the full SHA
    b6346d5 View commit details
  2. Revert "[Truffle] Partial fix for zsuper calls in blocks."

    * This reverts commit 5f1babf.
    * Better fix coming.
    eregon committed Jul 27, 2015
    Copy the full SHA
    c5d1e28 View commit details
  3. [Truffle] Use the existing mechanism to read local variables in zsuper.

    * So finding the right frame and slot is done by the findLocalVarNode helper.
    * Clarify the strange case of zsuper without a surrounding method.
    * Fixes #3106.
    eregon committed Jul 27, 2015
    Copy the full SHA
    4a80f53 View commit details
  4. Copy the full SHA
    140a379 View commit details
  5. Copy the full SHA
    f1a1752 View commit details
  6. Copy the full SHA
    42486a2 View commit details
  7. Copy the full SHA
    fcdd1da View commit details
3 changes: 0 additions & 3 deletions spec/truffle/tags/language/super_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
fails:The super keyword raises a RuntimeError when called with implicit arguments from a method defined with define_method
fails:The super keyword calls method_missing when a superclass method is not found
fails:The super keyword without explicit arguments passes arguments and rest arguments
fails:The super keyword without explicit arguments passes arguments and rest arguments including any modifications
10 changes: 0 additions & 10 deletions test/mri/excludes_truffle/TestSuper.rb
Original file line number Diff line number Diff line change
@@ -3,20 +3,10 @@
exclude :test_from_eval, "needs investigation"
exclude :test_keyword1, "needs investigation"
exclude :test_keyword2, "needs investigation"
exclude :test_optional1, "needs investigation"
exclude :test_optional2, "needs investigation"
exclude :test_optional3, "needs investigation"
exclude :test_optional4, "needs investigation"
exclude :test_optional5, "needs investigation"
exclude :test_super_in_BEGIN, "needs investigation"
exclude :test_super_in_at_exit, "needs investigation"
exclude :test_super_in_instance_eval, "needs investigation"
exclude :test_super_in_instance_eval_with_define_method, "needs investigation"
exclude :test_super_in_module_unbound_method, "needs investigation"
exclude :test_super_in_orphan_block_with_instance_eval, "needs investigation"
exclude :test_super_with_block, "needs investigation"
exclude :test_super_in_END, "needs investigation"
exclude :"test_array2", "regression, related to commits mentioned in https://github.com/jruby/jruby/issues/2963"
exclude :"test_array3", "regression, related to commits mentioned in https://github.com/jruby/jruby/issues/2963"
exclude :"test_array4", "regression, related to commits mentioned in https://github.com/jruby/jruby/issues/2963"
exclude :"test_double2", "regression, related to commits mentioned in https://github.com/jruby/jruby/issues/2963"
36 changes: 18 additions & 18 deletions tool/jruby_eclipse
Original file line number Diff line number Diff line change
@@ -7,24 +7,6 @@ TRUFFLEJAR = "#{Dir.home}/.m2/repository/com/oracle/truffle/0.7/truffle-0.7.jar"

java = ENV["JAVACMD"] || "java"

bootclasspath = "-Xbootclasspath/a"
[
"#{JRUBY}/lib/jruby.jar",
TRUFFLEJAR,
"#{JRUBY}/lib/jruby-stdlib-9.0.0.0-SNAPSHOT.jar",
"#{JRUBY}/truffle/build.eclipse",
"#{JRUBY}/truffle/src/main/ruby"
].each { |path| bootclasspath << ":#{path}" }

args = [java]
args << "-Djffi.boot.library.path=#{JRUBY}/lib/jni"
args << bootclasspath

args << "-Djruby.home=#{JRUBY}"
args << "-Djruby.lib=#{JRUBY}/lib"
args << "-Djruby.script=jruby"
args << "-Djruby.shell=/bin/sh"

java_flags = []
rest = []

@@ -41,6 +23,24 @@ ARGV.each { |arg|
end
}

bootclasspath = []
bootclasspath << "#{JRUBY}/lib/jruby.jar"
bootclasspath << "#{JRUBY}/lib/jruby-stdlib-9.0.0.0-SNAPSHOT.jar"
if rest.include?('-X+T')
bootclasspath << TRUFFLEJAR
bootclasspath << "#{JRUBY}/truffle/build.eclipse"
bootclasspath << "#{JRUBY}/truffle/src/main/ruby"
end

args = [java]
args << "-Djffi.boot.library.path=#{JRUBY}/lib/jni"
args << "-Xbootclasspath/a:" + bootclasspath.join(':')

args << "-Djruby.home=#{JRUBY}"
args << "-Djruby.lib=#{JRUBY}/lib"
args << "-Djruby.script=jruby"
args << "-Djruby.shell=/bin/sh"

args += java_flags
args << "org.jruby.Main"
args += rest
Original file line number Diff line number Diff line change
@@ -14,7 +14,10 @@
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.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNodeGen;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.methods.CallMethodNode;
import org.jruby.truffle.nodes.methods.CallMethodNodeGen;
@@ -34,6 +37,7 @@ public class GeneralSuperCallNode extends RubyNode {
@Child private RubyNode block;
@Children private final RubyNode[] arguments;

@Child ProcOrNullNode procOrNullNode;
@Child LookupSuperMethodNode lookupSuperMethodNode;
@Child CallMethodNode callMethodNode;

@@ -45,6 +49,7 @@ public GeneralSuperCallNode(RubyContext context, SourceSection sourceSection, Ru
this.arguments = arguments;
this.isSplatted = isSplatted;

procOrNullNode = ProcOrNullNodeGen.create(context, sourceSection, null);
lookupSuperMethodNode = LookupSuperMethodNodeGen.create(context, sourceSection, null);
callMethodNode = CallMethodNodeGen.create(context, sourceSection, null, new RubyNode[] {});
}
@@ -65,12 +70,7 @@ public final Object execute(VirtualFrame frame) {
// Execute the block
final RubyBasicObject blockObject;
if (block != null) {
final Object blockTempObject = block.execute(frame);
if (blockTempObject == nil()) {
blockObject = null;
} else {
blockObject = (RubyBasicObject) blockTempObject;
}
blockObject = procOrNullNode.executeProcOrNull(block.execute(frame));
} else {
blockObject = null;
}
Original file line number Diff line number Diff line change
@@ -9,42 +9,48 @@
*/
package org.jruby.truffle.nodes.supercall;

import com.oracle.truffle.api.CompilerAsserts;
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 java.util.Arrays;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNodeGen;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.methods.CallMethodNode;
import org.jruby.truffle.nodes.methods.CallMethodNodeGen;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.methods.InternalMethod;

import com.oracle.truffle.api.CompilerAsserts;
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;

/**
* Represents a super call with implicit arguments (using the ones of the surrounding methods).
*/
public class GeneralSuperReCallNode extends RubyNode {

private final boolean inBlock;
private final boolean isSplatted;
private final boolean hasRestParameter;
@Children private final RubyNode[] reloadNodes;
@Child private RubyNode block;

@Child ProcOrNullNode procOrNullNode;
@Child LookupSuperMethodNode lookupSuperMethodNode;
@Child CallMethodNode callMethodNode;

public GeneralSuperReCallNode(RubyContext context, SourceSection sourceSection, boolean inBlock, boolean isSplatted, RubyNode[] reloadNodes, RubyNode block) {
public GeneralSuperReCallNode(RubyContext context, SourceSection sourceSection, boolean hasRestParameter, RubyNode[] reloadNodes, RubyNode block) {
super(context, sourceSection);
this.inBlock = inBlock;
this.isSplatted = isSplatted;
this.hasRestParameter = hasRestParameter;
this.reloadNodes = reloadNodes;
this.block = block;

procOrNullNode = ProcOrNullNodeGen.create(context, sourceSection, null);
lookupSuperMethodNode = LookupSuperMethodNodeGen.create(context, sourceSection, null);
callMethodNode = CallMethodNodeGen.create(context, sourceSection, null, new RubyNode[] {});
}
@@ -56,39 +62,29 @@ public final Object execute(VirtualFrame frame) {

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

final Object[] originalArguments;
if (inBlock) {
originalArguments = RubyArguments.getDeclarationFrame(frame.getArguments()).getArguments();
} else {
originalArguments = frame.getArguments();
final Object[] originalArguments = frame.getArguments();

// Reload the arguments
Object[] superArguments = new Object[reloadNodes.length];
for (int n = 0; n < superArguments.length; n++) {
superArguments[n] = reloadNodes[n].execute(frame);
}

Object[] superArguments = RubyArguments.extractUserArguments(originalArguments);

if (!inBlock) {
// Reload the arguments
superArguments = new Object[reloadNodes.length];
for (int n = 0; n < superArguments.length; n++) {
superArguments[n] = reloadNodes[n].execute(frame);
}

if (isSplatted) {
CompilerDirectives.transferToInterpreter();
assert superArguments.length == 1;
assert RubyGuards.isRubyArray(superArguments[0]);
superArguments = ArrayNodes.slowToArray(((RubyBasicObject) superArguments[0]));
}
if (hasRestParameter) {
CompilerDirectives.transferToInterpreter();
// TODO (eregon, 22 July 2015): Assumes rest arg is last, not true if post or keyword args.
final Object restArg = superArguments[superArguments.length - 1];
assert RubyGuards.isRubyArray(restArg);
final Object[] restArgs = ArrayNodes.slowToArray((RubyBasicObject) restArg);
final int restArgIndex = reloadNodes.length - 1;
superArguments = Arrays.copyOf(superArguments, restArgIndex + restArgs.length);
ArrayUtils.arraycopy(restArgs, 0, superArguments, restArgIndex, restArgs.length);
}

// Execute or inherit the block
final RubyBasicObject blockObject;
if (block != null) {
final Object blockTempObject = block.execute(frame);
if (blockTempObject == nil()) {
blockObject = null;
} else {
blockObject = (RubyBasicObject) blockTempObject;
}
blockObject = procOrNullNode.executeProcOrNull(block.execute(frame));
} else {
blockObject = RubyArguments.getBlock(originalArguments);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.supercall;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.methods.InternalMethod;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

/**
* Represents a super call with implicit arguments without a surrounding method
*/
public class ZSuperOutsideMethodNode extends RubyNode {

final boolean insideDefineMethod;
@Child LookupSuperMethodNode lookupSuperMethodNode;

public ZSuperOutsideMethodNode(RubyContext context, SourceSection sourceSection, boolean insideDefineMethod) {
super(context, sourceSection);
this.insideDefineMethod = insideDefineMethod;
lookupSuperMethodNode = LookupSuperMethodNodeGen.create(context, sourceSection, null);
}

@Override
public final Object execute(VirtualFrame frame) {
// This is MRI behavior
CompilerDirectives.transferToInterpreter();
if (insideDefineMethod) { // TODO (eregon, 22 July 2015): This check should be more dynamic.
throw new RaiseException(getContext().getCoreLibrary().runtimeError(
"implicit argument passing of super from method defined by define_method() is not supported." +
" Specify all arguments explicitly.", this));
} else {
throw new RaiseException(getContext().getCoreLibrary().noSuperMethodError(this));
}
}

@Override
public Object isDefined(VirtualFrame frame) {
final Object self = RubyArguments.getSelf(frame.getArguments());
final InternalMethod superMethod = lookupSuperMethodNode.executeLookupSuperMethod(frame, self);

if (superMethod == null) {
return nil();
} else {
return createString("super");
}
}

}
Original file line number Diff line number Diff line change
@@ -1026,6 +1026,16 @@ public RubyBasicObject noMethodError(String message, String name, Node currentNo
return noMethodError;
}

public RubyBasicObject noSuperMethodError(Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
String message = "super called outside of method";
RubyBasicObject noMethodError = ExceptionNodes.createRubyException(context.getCoreLibrary().getNoMethodErrorClass(),
StringNodes.createString(context.getCoreLibrary().getStringClass(), message),
RubyCallStack.getBacktrace(currentNode));
RubyBasicObject.setInstanceVariable(noMethodError, "@name", nilObject);
return noMethodError;
}

public RubyBasicObject noMethodErrorOnModule(String name, RubyBasicObject module, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
assert RubyGuards.isRubyModule(module);
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@ public RubyNode visitArgsNode(org.jruby.ast.ArgsNode node) {
index = 0;
for (org.jruby.ast.Node arg : node.getPre().children()) {
sequence.add(arg.accept(this));
++index;
index++;
required++;
}
}
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.ast.ArgsNode;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.arguments.CheckArityNode;
@@ -34,6 +36,7 @@
import org.jruby.truffle.nodes.methods.*;
import org.jruby.truffle.nodes.supercall.GeneralSuperCallNode;
import org.jruby.truffle.nodes.supercall.GeneralSuperReCallNode;
import org.jruby.truffle.nodes.supercall.ZSuperOutsideMethodNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.methods.Arity;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
@@ -279,22 +282,33 @@ public RubyNode visitZSuperNode(org.jruby.ast.ZSuperNode node) {
environment.setNeedsDeclarationFrame();
}

final RubyNode blockNode;
currentCallMethodName = environment.getNamedMethodName();

final RubyNode blockNode;
if (node.getIterNode() != null) {
currentCallMethodName = environment.getNamedMethodName();
blockNode = node.getIterNode().accept(this);
} else {
blockNode = null;
}

boolean insideDefineMethod = false;
MethodTranslator methodArgumentsTranslator = this;
while (methodArgumentsTranslator.isBlock) {
if (!(methodArgumentsTranslator.parent instanceof MethodTranslator)) {
return new ZSuperOutsideMethodNode(context, sourceSection, insideDefineMethod);
} else if (methodArgumentsTranslator.currentCallMethodName.equals("define_method")) {
insideDefineMethod = true;
}
methodArgumentsTranslator = (MethodTranslator) methodArgumentsTranslator.parent;
}

final ReloadArgumentsTranslator reloadTranslator = new ReloadArgumentsTranslator(
currentNode, context, source, this);

final ArgsNode argsNode = methodArgumentsTranslator.argsNode;
final SequenceNode reloadSequence = (SequenceNode) reloadTranslator.visitArgsNode(argsNode);

return new GeneralSuperReCallNode(context, sourceSection,
environment.isBlock(),
reloadTranslator.isSplatted(),
reloadSequence.getSequence(),
blockNode);
Loading