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

Commits on May 2, 2015

  1. Copy the full SHA
    c368694 View commit details
  2. Copy the full SHA
    5aab309 View commit details
170 changes: 170 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/array/AppendOneNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* 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.array;

import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayGuards;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.util.ArrayUtils;

import java.util.Arrays;

@NodeChildren({
@NodeChild("array"),
@NodeChild("value"),
})
@ImportStatic(ArrayGuards.class)
public abstract class AppendOneNode extends RubyNode {

public AppendOneNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract RubyArray executeAppendOne(RubyArray array, Object value);

// Append into an array with null storage

@Specialization(guards = "isNull(array)")
public RubyArray appendNull(RubyArray array, int value) {
array.setStore(new int[]{value}, 1);
return array;
}

@Specialization(guards = "isNull(array)")
public RubyArray appendNull(RubyArray array, long value) {
array.setStore(new long[]{value}, 1);
return array;
}

@Specialization(guards = "isNull(array)")
public RubyArray appendNull(RubyArray array, Object value) {
array.setStore(new Object[]{value}, 1);
return array;
}

// Append into empty, but non-null storage; we would be better off reusing any existing space, but don't worry for now

@Specialization(guards = {"!isNull(array)", "isEmpty(array)"})
public RubyArray appendEmpty(RubyArray array, int value) {
array.setStore(new int[]{value}, 1);
return array;
}

@Specialization(guards = {"!isNull(array)", "isEmpty(array)"})
public RubyArray appendEmpty(RubyArray array, long value) {
array.setStore(new long[]{value}, 1);
return array;
}

@Specialization(guards ={"!isNull(array)", "isEmpty(array)"})
public RubyArray appendEmpty(RubyArray array, Object value) {
array.setStore(new Object[]{value}, 1);
return array;
}

// Append of the correct type

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendInteger(RubyArray array, int value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

int[] store = (int[]) array.getStore();

if (extendProfile.profile(newSize > store.length)) {
store = Arrays.copyOf(store, ArrayUtils.capacity(store.length, newSize));
}

store[oldSize] = value;
array.setStore(store, newSize);
return array;
}

@Specialization(guards = "isLongFixnum(array)")
public RubyArray appendLong(RubyArray array, long value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

long[] store = (long[]) array.getStore();

if (extendProfile.profile(newSize > store.length)) {
store = Arrays.copyOf(store, ArrayUtils.capacity(store.length, newSize));
}

store[oldSize] = value;
array.setStore(store, newSize);
return array;
}

@Specialization(guards = "isObject(array)")
public RubyArray appendObject(RubyArray array, Object value,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

Object[] store = (Object[]) array.getStore();

if (extendProfile.profile(newSize > store.length)) {
store = Arrays.copyOf(store, ArrayUtils.capacity(store.length, newSize));
}

store[oldSize] = value;
array.setStore(store, newSize);
return array;
}

// Append forcing a generalization

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendLongIntoInteger(RubyArray array, long value) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

final int[] oldStore = (int[]) array.getStore();
long[] newStore = ArrayUtils.longCopyOf(oldStore, ArrayUtils.capacity(oldStore.length, newSize));

newStore[oldSize] = value;
array.setStore(newStore, newSize);
return array;
}

@Specialization(guards = {"isIntegerFixnum(array)", "!isInteger(value)", "!isLong(value)"})
public RubyArray appendObjectIntoInteger(RubyArray array, Object value) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

final int[] oldStore = (int[]) array.getStore();
Object[] newStore = ArrayUtils.box(oldStore, ArrayUtils.capacity(oldStore.length, newSize) - oldStore.length);

newStore[oldSize] = value;
array.setStore(newStore, newSize);
return array;
}

@Specialization(guards = {"isLongFixnum(array)", "!isInteger(value)", "!isLong(value)"})
public RubyArray appendObjectIntoLong(RubyArray array, Object value) {
final int oldSize = array.getSize();
final int newSize = oldSize + 1;

final long[] oldStore = (long[]) array.getStore();
Object[] newStore = ArrayUtils.box(oldStore, ArrayUtils.capacity(oldStore.length, newSize) - oldStore.length);

newStore[oldSize] = value;
array.setStore(newStore, newSize);
return array;
}

}
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.nodes.CoreSourceSection;
@@ -3178,7 +3179,24 @@ public Object popObjectWithNumObj(VirtualFrame frame, RubyArray array, Object ob

}

@CoreMethod(names = {"push", "<<", "__append__"}, argumentsAsArray = true, raiseIfFrozenSelf = true)
@CoreMethod(names = "<<", raiseIfFrozenSelf = true, required = 1)
public abstract static class ShiftIntoNode extends ArrayCoreMethodNode {

@Child private AppendOneNode appendOneNode;

public ShiftIntoNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
appendOneNode = AppendOneNodeGen.create(context, sourceSection, null, null);
}

@Specialization
public RubyArray pushNullEmptySingleIntegerFixnum(RubyArray array, Object value) {
return appendOneNode.executeAppendOne(array, value);
}

}

@CoreMethod(names = {"push", "__append__"}, argumentsAsArray = true, raiseIfFrozenSelf = true)
public abstract static class PushNode extends ArrayCoreMethodNode {

private final BranchProfile extendBranch = BranchProfile.create();
Original file line number Diff line number Diff line change
@@ -110,8 +110,6 @@ public static boolean isSmallArrayOfPairs(Object[] args) {
return false;
}

final Object[] store = (Object[]) array.getStore();

if (PackedArrayStrategy.MAX_ELEMENTS > PackedArrayStrategy.MAX_ENTRIES) {
return false;
}
Original file line number Diff line number Diff line change
@@ -125,6 +125,8 @@ public Object downto(VirtualFrame frame, int from, double to, RubyProc block) {
@CoreMethod(names = "times", needsBlock = true)
public abstract static class TimesNode extends YieldingCoreMethodNode {

// TODO CS 2-May-15 we badly need OSR in this node

@Child private FixnumOrBignumNode fixnumOrBignum;

private final BranchProfile breakProfile = BranchProfile.create();
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.util;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import org.jruby.truffle.nodes.RubyNode;

import java.lang.reflect.Array;
@@ -284,7 +285,13 @@ public static void copy(Object source, Object[] destination, int destinationStar
}

public static long[] longCopyOf(int[] ints) {
final long[] longs = new long[ints.length];
return longCopyOf(ints, ints.length);
}

public static long[] longCopyOf(int[] ints, int newLength) {
assert newLength >= ints.length;

final long[] longs = new long[newLength];

for (int n = 0; n < ints.length; n++) {
longs[n] = ints[n];
@@ -293,6 +300,7 @@ public static long[] longCopyOf(int[] ints) {
return longs;
}

@CompilerDirectives.TruffleBoundary
public static int capacity(int current, int needed) {
if (needed < 16) {
return 16;