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

Commits on May 12, 2015

  1. Copy the full SHA
    7491353 View commit details
  2. Copy the full SHA
    215521c View commit details
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*
* 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.core.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.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayMirror;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.core.RubyArray;

import java.util.Arrays;

@NodeChildren({
@NodeChild("array"),
@NodeChild("otherSize"),
@NodeChild("other"),
})
@ImportStatic(ArrayGuards.class)
public abstract class AppendManyNode extends RubyNode {

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

public abstract RubyArray executeAppendMany(RubyArray array, int otherSize, Object other);

// Append into an empty array

// TODO CS 12-May-15 differentiate between null and empty but possibly having enough space

@Specialization(guards = "isEmpty(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, int[] other) {
array.setStore(Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, long[] other) {
array.setStore(Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, double[] other) {
array.setStore(Arrays.copyOf(other, otherSize), otherSize);
return array;
}

@Specialization(guards = "isEmpty(array)")
public RubyArray appendManyEmpty(RubyArray array, int otherSize, Object[] other) {
array.setStore(Arrays.copyOf(other, otherSize), otherSize);
return array;
}

// Append of the correct type

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, int[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((int[]) array.getStore()),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isLongFixnum(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, long[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((long[]) array.getStore()),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isFloat(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((double[]) array.getStore()),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
public RubyArray appendManySameType(RubyArray array, int otherSize, Object[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayMirror.reflect((Object[]) array.getStore()),
otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

public void appendManySameTypeGeneric(RubyArray array, ArrayMirror storeMirror,
int otherSize, ArrayMirror otherStoreMirror,
ConditionProfile extendProfile) {
final int oldSize = array.getSize();
final int newSize = oldSize + otherSize;

final ArrayMirror newStoreMirror;

if (extendProfile.profile(newSize > storeMirror.getLength())) {
newStoreMirror = storeMirror.copyArrayAndMirror(ArrayUtils.capacity(storeMirror.getLength(), newSize));
} else {
newStoreMirror = storeMirror;
}

otherStoreMirror.copyTo(newStoreMirror, 0, oldSize, otherSize);
array.setStore(newStoreMirror.getArray(), newSize);
}

// Append something else into an Object[]

@Specialization(guards = "isObject(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, int[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, long[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

@Specialization(guards = "isObject(array)")
public RubyArray appendManyBoxIntoObject(RubyArray array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayMirror.reflect(other), extendProfile);
return array;
}

public void appendManyBoxIntoObjectGeneric(RubyArray array, int otherSize, ArrayMirror otherStoreMirror,
ConditionProfile extendProfile) {
final int oldSize = array.getSize();
final int newSize = oldSize + otherSize;

final Object[] oldStore = (Object[]) array.getStore();
final Object[] newStore;

if (extendProfile.profile(newSize > oldStore.length)) {
newStore = ArrayUtils.copyOf(oldStore, ArrayUtils.capacity(oldStore.length, newSize));
} else {
newStore = oldStore;
}

otherStoreMirror.copyTo(newStore, 0, oldSize, otherSize);
array.setStore(newStore, newSize);
}

// Append forcing a generalization from int[] to long[]

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendManyLongIntoInteger(RubyArray array, int otherSize, long[] other) {
final int oldSize = array.getSize();
final int newSize = oldSize + otherSize;

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

System.arraycopy(other, 0, newStore, oldSize, otherSize);

array.setStore(newStore, newSize);
return array;
}

// Append forcing a generalization to Object[]

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendManyGeneralizeIntegerDouble(RubyArray array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((int[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isIntegerFixnum(array)")
public RubyArray appendManyGeneralizeIntegerDouble(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((int[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isLongFixnum(array)")
public RubyArray appendManyGeneralizeLongDouble(RubyArray array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((long[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isLongFixnum(array)")
public RubyArray appendManyGeneralizeLongDouble(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((long[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
public RubyArray appendManyGeneralizeDoubleInteger(RubyArray array, int otherSize, int[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
public RubyArray appendManyGeneralizeDoubleLong(RubyArray array, int otherSize, long[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

@Specialization(guards = "isFloat(array)")
public RubyArray appendManyGeneralizeDoubleObject(RubyArray array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayMirror.reflect((double[]) array.getStore()),
otherSize, ArrayMirror.reflect(other));
return array;
}

public void appendManyGeneralizeGeneric(RubyArray array, ArrayMirror storeMirror, int otherSize, ArrayMirror otherStoreMirror) {
final int oldSize = array.getSize();
final int newSize = oldSize + otherSize;
Object[] newStore = storeMirror.getBoxedCopy(ArrayUtils.capacity(storeMirror.getLength(), newSize));
otherStoreMirror.copyTo(newStore, 0, oldSize, otherSize);
array.setStore(newStore, newSize);
}

}
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ public void appendOneSameTypeGeneric(RubyArray array, ArrayMirror storeMirror, O
final ArrayMirror newStoreMirror;

if (extendProfile.profile(newSize > storeMirror.getLength())) {
newStoreMirror = storeMirror.copyMirror(ArrayUtils.capacity(storeMirror.getLength(), newSize));
newStoreMirror = storeMirror.copyArrayAndMirror(ArrayUtils.capacity(storeMirror.getLength(), newSize));
} else {
newStoreMirror = storeMirror;
}
Original file line number Diff line number Diff line change
@@ -844,106 +844,25 @@ public Object compactObjects(RubyArray array) {
@ImportStatic(ArrayGuards.class)
public abstract static class ConcatNode extends CoreMethodNode {

@Child private AppendManyNode appendManyNode;

public ConcatNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
appendManyNode = AppendManyNodeGen.create(context, sourceSection, null, null, null);
}

public abstract RubyArray executeConcat(RubyArray array, RubyArray other);

@CreateCast("other") public RubyNode coerceOtherToAry(RubyNode other) {
return ToAryNodeGen.create(getContext(), getSourceSection(), other);
}

@Specialization(guards = "areBothNull(array, other)")
@Specialization(guards = "isNull(other)")
public RubyArray concatNull(RubyArray array, RubyArray other) {
return array;
}

@Specialization(guards = "areBothIntegerFixnum(array, other)")
public RubyArray concatIntegerFixnum(RubyArray array, RubyArray other) {
CompilerDirectives.transferToInterpreter();

final int newSize = array.getSize() + other.getSize();
int[] store = (int[]) array.getStore();

if ( store.length < newSize) {
store = Arrays.copyOf((int[]) array.getStore(), ArrayUtils.capacity(store.length, newSize));
}

System.arraycopy(other.getStore(), 0, store, array.getSize(), other.getSize());
array.setStore(store, newSize);
return array;
}

@Specialization(guards = "areBothLongFixnum(array, other)")
public RubyArray concatLongFixnum(RubyArray array, RubyArray other) {
CompilerDirectives.transferToInterpreter();

final int newSize = array.getSize() + other.getSize();
long[] store = (long[]) array.getStore();

if ( store.length < newSize) {
store = Arrays.copyOf((long[]) array.getStore(), ArrayUtils.capacity(store.length, newSize));
}

System.arraycopy(other.getStore(), 0, store, array.getSize(), other.getSize());
array.setStore(store, newSize);
return array;
}

@Specialization(guards = "areBothFloat(array, other)")
public RubyArray concatDouble(RubyArray array, RubyArray other) {
CompilerDirectives.transferToInterpreter();

final int newSize = array.getSize() + other.getSize();
double[] store = (double[]) array.getStore();

if ( store.length < newSize) {
store = Arrays.copyOf((double[]) array.getStore(), ArrayUtils.capacity(store.length, newSize));
}

System.arraycopy(other.getStore(), 0, store, array.getSize(), other.getSize());
array.setStore(store, newSize);
return array;
}

@Specialization(guards = "areBothObject(array, other)")
public RubyArray concatObject(RubyArray array, RubyArray other) {
CompilerDirectives.transferToInterpreter();

final int size = array.getSize();
final int newSize = size + other.getSize();
Object[] store = (Object[]) array.getStore();

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

System.arraycopy(other.getStore(), 0, store, size, other.getSize());
array.setStore(store, newSize);
return array;
}

@Specialization
@Specialization(guards = "!isNull(other)")
public RubyArray concat(RubyArray array, RubyArray other) {
CompilerDirectives.transferToInterpreter();

final int newSize = array.getSize() + other.getSize();

Object[] store;
if (array.getStore() instanceof Object[]) {
store = (Object[]) array.getStore();
if (store.length < newSize) {
store = Arrays.copyOf(store, ArrayUtils.capacity(store.length, newSize));
}
ArrayUtils.copy(other.getStore(), store, array.getSize(), other.getSize());
} else {
store = new Object[newSize];
ArrayUtils.copy(array.getStore(), store, 0, array.getSize());
ArrayUtils.copy(other.getStore(), store, array.getSize(), other.getSize());
}

array.setStore(store, newSize);
appendManyNode.executeAppendMany(array, other.getSize(), other.getStore());
return array;
}

Original file line number Diff line number Diff line change
@@ -32,18 +32,25 @@ public static ObjectArrayMirror reflect(Object[] array) {
public abstract int getLength();
public abstract Object get(int index);
public abstract void set(int index, Object value);
public abstract ArrayMirror copyMirror(int newLength);
public abstract Object[] getBoxedCopy(int newLength);
public abstract ArrayMirror copyArrayAndMirror(int newLength);
public abstract void copyTo(ArrayMirror destination, int sourceStart, int destinationStart, int count);
public abstract void copyTo(Object[] destination, int sourceStart, int destinationStart, int count);
public abstract Object getArray();

public Object copyMirror() {
return copyMirror(getLength());
public Object copyArrayAndMirror() {
return copyArrayAndMirror(getLength());
}

public Object[] getBoxedCopy() {
return getBoxedCopy(getLength());
}

public Object[] getBoxedCopy(int newLength) {
final Object[] boxed = new Object[newLength];
copyTo(boxed, 0, 0, Math.min(getLength(), newLength));
return boxed;
}

private static class IntegerArrayMirror extends ArrayMirror {

private final int[] array;
@@ -68,15 +75,27 @@ public void set(int index, Object value) {
}

@Override
public ArrayMirror copyMirror(int newLength) {
public ArrayMirror copyArrayAndMirror(int newLength) {
return new IntegerArrayMirror(Arrays.copyOf(array, newLength));
}

@Override
public void copyTo(ArrayMirror destination, int sourceStart, int destinationStart, int count) {
System.arraycopy(array, sourceStart, destination.getArray(), destinationStart, count);
}

@Override
public Object[] getBoxedCopy(int newLength) {
return ArrayUtils.box(array, newLength);
}

@Override
public void copyTo(Object[] destination, int sourceStart, int destinationStart, int count) {
for (int n = 0; n < count; n++) {
destination[destinationStart + n] = array[sourceStart + n];
}
}

@Override
public Object getArray() {
return array;
@@ -108,13 +127,20 @@ public void set(int index, Object value) {
}

@Override
public ArrayMirror copyMirror(int newLength) {
public ArrayMirror copyArrayAndMirror(int newLength) {
return new LongArrayMirror(Arrays.copyOf(array, newLength));
}

@Override
public Object[] getBoxedCopy(int newLength) {
return ArrayUtils.box(array, newLength);
public void copyTo(ArrayMirror destination, int sourceStart, int destinationStart, int count) {
System.arraycopy(array, sourceStart, destination.getArray(), destinationStart, count);
}

@Override
public void copyTo(Object[] destination, int sourceStart, int destinationStart, int count) {
for (int n = 0; n < count; n++) {
destination[destinationStart + n] = array[sourceStart + n];
}
}

@Override
@@ -148,13 +174,20 @@ public void set(int index, Object value) {
}

@Override
public ArrayMirror copyMirror(int newLength) {
public ArrayMirror copyArrayAndMirror(int newLength) {
return new DoubleArrayMirror(Arrays.copyOf(array, newLength));
}

@Override
public Object[] getBoxedCopy(int newLength) {
return ArrayUtils.box(array, newLength);
public void copyTo(ArrayMirror destination, int sourceStart, int destinationStart, int count) {
System.arraycopy(array, sourceStart, destination.getArray(), destinationStart, count);
}

@Override
public void copyTo(Object[] destination, int sourceStart, int destinationStart, int count) {
for (int n = 0; n < count; n++) {
destination[destinationStart + n] = array[sourceStart + n];
}
}

@Override
@@ -188,13 +221,18 @@ public void set(int index, Object value) {
}

@Override
public ArrayMirror copyMirror(int newLength) {
public ArrayMirror copyArrayAndMirror(int newLength) {
return new ObjectArrayMirror(ArrayUtils.copyOf(array, newLength));
}

@Override
public Object[] getBoxedCopy(int newLength) {
return ArrayUtils.copyOf(array, newLength);
public void copyTo(ArrayMirror destination, int sourceStart, int destinationStart, int count) {
System.arraycopy(array, sourceStart, destination.getArray(), destinationStart, count);
}

@Override
public void copyTo(Object[] destination, int sourceStart, int destinationStart, int count) {
System.arraycopy(array, sourceStart, destination, destinationStart, count);
}

@Override