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

Commits on Jan 10, 2016

  1. [Truffle] Don't add one for kwargs to the minimum size for optional a…

    …rguments, when reading from an array.
    chrisseaton committed Jan 10, 2016
    Copy the full SHA
    44aa087 View commit details
  2. Copy the full SHA
    0bb4df5 View commit details
  3. Copy the full SHA
    afa734e View commit details
  4. Copy the full SHA
    3f90570 View commit details
  5. Copy the full SHA
    f1372e5 View commit details
7 changes: 0 additions & 7 deletions spec/truffle/tags/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
fails:A block yielded a single Array assigns elements to mixed argument types
fails:A block yielded a single Array assigns elements to required arguments when a keyword rest argument is present
fails:A block yielded a single Array assigns non-symbol keys to non-keyword arguments
fails:A block yielded a single Array assigns symbol keys from a Hash returned by #to_hash to keyword arguments
fails:A block yielded a single Array assigns symbol keys from a Hash to keyword arguments
fails:A block yielded a single Array assigns the last element to a non-keyword argument if #to_hash returns nil
fails:A block yielded a single Array calls #to_hash on the argument but does not use the result when no keywords are present
fails:A block yielded a single Array calls #to_hash on the last element if keyword arguments are present
fails:A block yielded a single Array calls #to_hash on the last element when there are more arguments than parameters
fails:A block yielded a single Array does not treat hashes with string keys as keyword arguments
fails:A block yielded a single Array raises a TypeError if #to_hash does not return a Hash
fails:A block yielded a single Array raises the error raised inside #to_hash
fails:A block yielded a single Object receives the object if #to_ary returns nil
fails:Block-local variables override shadowed variables from the outer scope
fails:Post-args with optional args with a circular argument reference shadows an existing method with the same name as the argument
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.nodes.arguments;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNode;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNodeGen;
import org.jruby.truffle.nodes.locals.WriteFrameSlotNode;
import org.jruby.truffle.nodes.locals.WriteFrameSlotNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

public class RunBlockKWArgsHelperNode extends RubyNode {

@Child private ReadFrameSlotNode readArrayNode;
@Child private WriteFrameSlotNode writeArrayNode;

private final Object kwrestName;

public RunBlockKWArgsHelperNode(RubyContext context, SourceSection sourceSection, FrameSlot arrayFrameSlot, Object kwrestName) {
super(context, sourceSection);
readArrayNode = ReadFrameSlotNodeGen.create(arrayFrameSlot);
writeArrayNode = WriteFrameSlotNodeGen.create(arrayFrameSlot);
this.kwrestName = kwrestName;
}

@Override
public Object execute(VirtualFrame frame) {
CompilerDirectives.bailout("blocks with kwargs are not optimized yet");

final Object array = readArrayNode.executeRead(frame);

final Object remainingArray = ruby(frame, "Truffle::Primitive.load_arguments_from_array_kw_helper(array, kwrest_name, binding)", "array", array, "kwrest_name", kwrestName, "binding", Layouts.BINDING.createBinding(getContext().getCoreLibrary().getBindingFactory(), frame.materialize()));

writeArrayNode.executeWrite(frame, remainingArray);

return nil();
}

}
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@

import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.nodes.Node;
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.MultipleAsgnNode;
@@ -26,6 +27,7 @@
import org.jruby.truffle.nodes.core.array.ArrayLiteralNode;
import org.jruby.truffle.nodes.core.array.ArraySliceNodeGen;
import org.jruby.truffle.nodes.core.array.PrimitiveArrayNodeFactory;
import org.jruby.truffle.nodes.literal.NilNode;
import org.jruby.truffle.nodes.locals.ReadLocalVariableNode;
import org.jruby.truffle.nodes.locals.WriteLocalVariableNode;
import org.jruby.truffle.runtime.RubyContext;
@@ -88,6 +90,28 @@ public RubyNode visitArgsNode(org.jruby.ast.ArgsNode node) {

final List<RubyNode> sequence = new ArrayList<>();
final org.jruby.ast.Node[] args = node.getArgs();

final boolean useHelper = useArray() && node.hasKeyRest();

if (useHelper) {
sequence.add(node.getKeyRest().accept(this));

final Object keyRestNameOrNil;

if (node.hasKeyRest()) {
final String name = node.getKeyRest().getName();
methodBodyTranslator.getEnvironment().declareVar(name);
keyRestNameOrNil = context.getSymbol(name);
} else {
keyRestNameOrNil = context.getCoreLibrary().getNilObject();
}

sequence.add(new IfNode(context, sourceSection,
new ArrayIsAtLeastAsLargeAsNode(context, sourceSection, loadArray(sourceSection), node.getPreCount() + node.getPostCount() + 1),
new RunBlockKWArgsHelperNode(context, sourceSection, arraySlotStack.peek().getArraySlot(), keyRestNameOrNil),
new NilNode(context, sourceSection)));
}

final int preCount = node.getPreCount();

if (preCount > 0) {
@@ -178,7 +202,9 @@ public RubyNode visitArgsNode(org.jruby.ast.ArgsNode node) {
}

if (node.getKeyRest() != null) {
sequence.add(node.getKeyRest().accept(this));
if (!useHelper) {
sequence.add(node.getKeyRest().accept(this));
}
}

if (node.getBlock() != null) {
@@ -327,17 +353,17 @@ private RubyNode translateLocalAssignment(ISourcePosition sourcePosition, String

int minimum = index + 1 + argsNode.getPostCount();

if (argsNode.hasKwargs()) {
minimum += 1;
}

if (useArray()) {
// TODO CS 10-Jan-16 we should really hoist this check, or see if Graal does it for us
readNode = new IfNode(context, sourceSection,
new ArrayIsAtLeastAsLargeAsNode(context, sourceSection, loadArray(sourceSection), minimum),
PrimitiveArrayNodeFactory.read(context, sourceSection, loadArray(sourceSection), index),
defaultValue);
} else {
if (argsNode.hasKwargs()) {
minimum += 1;
}

readNode = new ReadOptionalArgumentNode(context, sourceSection, index, minimum, defaultValue);
}
}
15 changes: 15 additions & 0 deletions truffle/src/main/ruby/core/shims.rb
Original file line number Diff line number Diff line change
@@ -269,3 +269,18 @@ def self.get_data(path, offset)
file
end
end

module Truffle::Primitive
def self.load_arguments_from_array_kw_helper(array, kwrest_name, binding)
array = array.dup

kwargs = array.pop.to_hash.select { |key, value|
symbol = key.is_a? Symbol
array.push({key => value}) unless symbol
symbol
}

binding.local_variable_set(kwrest_name, kwargs) if kwrest_name
array
end
end