Skip to content

Commit

Permalink
Showing 18 changed files with 146 additions and 26 deletions.
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/array/collect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/delete_if_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/each_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/array/map_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/array/reject_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/select_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/hash/each_pair_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Hash#each_pair properly expands (or not) child class's 'each'-yielded args
fails:Hash#each_pair when no block is given returned Enumerator size returns the enumerable size
1 change: 0 additions & 1 deletion spec/truffle/tags/core/hash/each_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Hash#each properly expands (or not) child class's 'each'-yielded args
fails:Hash#each when no block is given returned Enumerator size returns the enumerable size
1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/each_byte_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/each_char_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -73,4 +73,6 @@

UnsafeGroup[] unsafe() default {};

String snippetIfNoBlock() default "";

}
Original file line number Diff line number Diff line change
@@ -263,7 +263,9 @@ private static CallTarget makeGenericMethod(RubyContext context, MethodDetails m
} else {
sequence = Translator.sequence(context, sourceSection, Arrays.asList(checkArity, methodNode));

if (method.returnsEnumeratorIfNoBlock()) {
if(!method.snippetIfNoBlock().isEmpty()) {
sequence = new SnippetIfNoBlockNode(method.snippetIfNoBlock(), sequence);
} else if (method.returnsEnumeratorIfNoBlock()) {
// TODO BF 3-18-2015 Handle multiple method names correctly
sequence = new ReturnEnumeratorIfNoBlockNode(method.names()[0], sequence);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.builtins;

import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.arguments.RubyArguments;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;

public class SnippetIfNoBlockNode extends RubyNode
{

@Child
private RubyNode method;
@Child
private SnippetNode snippetNode;
private final ConditionProfile noBlockProfile = ConditionProfile.createBinaryProfile();
private final String snippet;

public SnippetIfNoBlockNode(String snippet, RubyNode method)
{
super(method.getContext(), method.getEncapsulatingSourceSection());
this.method = method;
this.snippet = snippet;
}

@Override
public Object execute(VirtualFrame frame)
{
final DynamicObject block = RubyArguments.getBlock(frame);

if (noBlockProfile.profile(block == null))
{
if (snippetNode == null)
{
CompilerDirectives.transferToInterpreterAndInvalidate();
snippetNode = insert(new SnippetNode());
}
return snippetNode.execute(frame, this.snippet);
}
else
{
return method.execute(frame);
}
}

}
24 changes: 16 additions & 8 deletions truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -95,6 +95,14 @@
import static org.jruby.truffle.core.array.ArrayHelpers.getSize;
import static org.jruby.truffle.core.array.ArrayHelpers.getStore;
import static org.jruby.truffle.core.array.ArrayHelpers.setStoreAndSize;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_DELETE_IF_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_EACH_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_EACH_WITH_INDEX_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_MAP_BANG_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_MAP_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_REJECT_BANG_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_REJECT_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.ARRAY_SELECT_TO_ENUM;

@CoreClass("Array")
public abstract class ArrayNodes {
@@ -791,7 +799,7 @@ public Object deleteAt(DynamicObject array, int index,

}

@CoreMethod(names = "each", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "each", needsBlock = true, snippetIfNoBlock = ARRAY_EACH_TO_ENUM)
@ImportStatic(ArrayGuards.class)
public abstract static class EachNode extends YieldingCoreMethodNode {

@@ -827,7 +835,7 @@ public Object eachOther(VirtualFrame frame, DynamicObject array, DynamicObject b

}

@CoreMethod(names = "each_with_index", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "each_with_index", needsBlock = true, snippetIfNoBlock = ARRAY_EACH_WITH_INDEX_TO_ENUM)
@ImportStatic(ArrayGuards.class)
public abstract static class EachWithIndexNode extends YieldingCoreMethodNode {

@@ -1196,7 +1204,7 @@ public Object injectSymbolHelper(VirtualFrame frame, DynamicObject array, Dynami

}

@CoreMethod(names = { "map", "collect" }, needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = { "map", "collect" }, needsBlock = true, snippetIfNoBlock = ARRAY_MAP_TO_ENUM)
@ImportStatic(ArrayGuards.class)
public abstract static class MapNode extends YieldingCoreMethodNode {

@@ -1230,7 +1238,7 @@ public Object map(VirtualFrame frame, DynamicObject array, DynamicObject block,

}

@CoreMethod(names = { "map!", "collect!" }, needsBlock = true, returnsEnumeratorIfNoBlock = true, raiseIfFrozenSelf = true)
@CoreMethod(names = { "map!", "collect!" }, needsBlock = true, snippetIfNoBlock = ARRAY_MAP_BANG_TO_ENUM, raiseIfFrozenSelf = true)
@ImportStatic(ArrayGuards.class)
public abstract static class MapInPlaceNode extends YieldingCoreMethodNode {

@@ -1742,7 +1750,7 @@ public DynamicObject pushMany(VirtualFrame frame, DynamicObject array, Object va

}

@CoreMethod(names = "reject", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "reject", needsBlock = true, snippetIfNoBlock = ARRAY_REJECT_TO_ENUM)
@ImportStatic(ArrayGuards.class)
public abstract static class RejectNode extends YieldingCoreMethodNode {

@@ -1781,7 +1789,7 @@ public Object rejectOther(VirtualFrame frame, DynamicObject array, DynamicObject

}

@CoreMethod(names = "delete_if" , needsBlock = true, returnsEnumeratorIfNoBlock = true, raiseIfFrozenSelf = true)
@CoreMethod(names = "delete_if" , needsBlock = true, snippetIfNoBlock = ARRAY_DELETE_IF_TO_ENUM, raiseIfFrozenSelf = true)
@ImportStatic(ArrayGuards.class)
public abstract static class DeleteIfNode extends YieldingCoreMethodNode {

@@ -1799,7 +1807,7 @@ protected RejectInPlaceNode createRejectInPlaceNode() {
}


@CoreMethod(names = "reject!", needsBlock = true, returnsEnumeratorIfNoBlock = true, raiseIfFrozenSelf = true)
@CoreMethod(names = "reject!", needsBlock = true, snippetIfNoBlock = ARRAY_REJECT_BANG_TO_ENUM, raiseIfFrozenSelf = true)
@ImportStatic(ArrayGuards.class)
public abstract static class RejectInPlaceNode extends YieldingCoreMethodNode {

@@ -1881,7 +1889,7 @@ public DynamicObject replace(DynamicObject array, DynamicObject other,

}

@CoreMethod(names = "select", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "select", needsBlock = true, snippetIfNoBlock = ARRAY_SELECT_TO_ENUM)
@ImportStatic(ArrayGuards.class)
public abstract static class SelectNode extends YieldingCoreMethodNode {

Original file line number Diff line number Diff line change
@@ -51,6 +51,8 @@
import java.util.Arrays;
import java.util.Map;

import static org.jruby.truffle.core.rubinius.RubiniusSnippets.HASH_EACH_TO_ENUM;

@CoreClass("Hash")
public abstract class HashNodes {

@@ -581,7 +583,7 @@ public Object delete(VirtualFrame frame, DynamicObject hash, Object key, Object

}

@CoreMethod(names = { "each", "each_pair" }, needsBlock = true)
@CoreMethod(names = { "each", "each_pair" }, needsBlock = true, snippetIfNoBlock = HASH_EACH_TO_ENUM)
@ImportStatic(HashGuards.class)
public abstract static class EachNode extends YieldingCoreMethodNode {

Original file line number Diff line number Diff line change
@@ -41,6 +41,8 @@
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.AllocateObjectNodeGen;

import static org.jruby.truffle.core.rubinius.RubiniusSnippets.RANGE_EACH_TO_ENUM;

@CoreClass("Range")
public abstract class RangeNodes {

@@ -82,7 +84,7 @@ public DynamicObject map(

}

@CoreMethod(names = "each", needsBlock = true, lowerFixnumSelf = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "each", needsBlock = true, lowerFixnumSelf = true, snippetIfNoBlock = RANGE_EACH_TO_ENUM)
public abstract static class EachNode extends YieldingCoreMethodNode {

@Child private CallDispatchHeadNode eachInternalCall;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2015, 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
*
*
* Copyright (c) 2007-2014, Evan Phoenix and contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Rubinius nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jruby.truffle.core.rubinius;

public abstract class RubiniusSnippets
{
public static final String ARRAY_DELETE_IF_TO_ENUM = "to_enum(:delete_if) { size }";
public static final String ARRAY_EACH_TO_ENUM = "to_enum(:each) { size }";
public static final String ARRAY_EACH_WITH_INDEX_TO_ENUM = "to_enum(:each_with_index) { size }";
public static final String ARRAY_MAP_TO_ENUM = "to_enum(:map) { size }";
public static final String ARRAY_MAP_BANG_TO_ENUM = "to_enum(:map!) { size }";
public static final String ARRAY_REJECT_TO_ENUM = "to_enum(:reject) { size }";
public static final String ARRAY_REJECT_BANG_TO_ENUM = "to_enum(:reject!) { size }";
public static final String ARRAY_SELECT_TO_ENUM = "to_enum(:select) { size }";

public static final String HASH_EACH_TO_ENUM = "to_enum(:each) { size }";

public static final String RANGE_EACH_TO_ENUM = "to_enum { size }";

public static final String STRING_EACH_BYTE_TO_ENUM = "to_enum(:each_byte) { bytesize }";
public static final String STRING_EACH_CHAR_TO_ENUM = "to_enum(:each_char) { size }";

}
Original file line number Diff line number Diff line change
@@ -151,6 +151,8 @@
import java.util.Arrays;
import java.util.List;
import static org.jruby.truffle.core.rope.RopeConstants.EMPTY_ASCII_8BIT_ROPE;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.STRING_EACH_BYTE_TO_ENUM;
import static org.jruby.truffle.core.rubinius.RubiniusSnippets.STRING_EACH_CHAR_TO_ENUM;
import static org.jruby.truffle.core.string.StringOperations.encoding;
import static org.jruby.truffle.core.string.StringOperations.rope;

@@ -1020,7 +1022,7 @@ private boolean multiByteDowncase(Encoding encoding, byte[] bytes, int s, int en
}
}

@CoreMethod(names = "each_byte", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "each_byte", needsBlock = true, snippetIfNoBlock = STRING_EACH_BYTE_TO_ENUM)
public abstract static class EachByteNode extends YieldingCoreMethodNode {

@Specialization
@@ -1044,7 +1046,7 @@ public DynamicObject eachByte(VirtualFrame frame, DynamicObject string, DynamicO

}

@CoreMethod(names = "each_char", needsBlock = true, returnsEnumeratorIfNoBlock = true)
@CoreMethod(names = "each_char", needsBlock = true, snippetIfNoBlock = STRING_EACH_CHAR_TO_ENUM)
@ImportStatic(StringGuards.class)
public abstract static class EachCharNode extends YieldingCoreMethodNode {

0 comments on commit 628217c

Please sign in to comment.