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

Commits on Apr 12, 2016

  1. Copy the full SHA
    465c3e5 View commit details
  2. Copy the full SHA
    d972d06 View commit details
Showing with 62 additions and 253 deletions.
  1. +41 −175 truffle/src/main/java/org/jruby/truffle/core/array/ArrayAppendManyNode.java
  2. +21 −78 truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
*/
package org.jruby.truffle.core.array;

import static org.jruby.truffle.core.array.ArrayHelpers.getSize;
import static org.jruby.truffle.core.array.ArrayHelpers.setStoreAndSize;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NodeChild;
@@ -21,11 +23,8 @@
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyNode;

import java.util.Arrays;

@NodeChildren({
@NodeChild("array"),
@NodeChild("otherSize"),
@NodeChild("other"),
})
@ImportStatic(ArrayGuards.class)
@@ -35,207 +34,74 @@ public ArrayAppendManyNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

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

// Append into an empty array

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

@Specialization(guards = "isEmptyArray(array)")
public DynamicObject appendManyEmpty(DynamicObject array, int otherSize, int[] other) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(other, otherSize));
Layouts.ARRAY.setSize(array, otherSize);
return array;
}

@Specialization(guards = "isEmptyArray(array)")
public DynamicObject appendManyEmpty(DynamicObject array, int otherSize, long[] other) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(other, otherSize));
Layouts.ARRAY.setSize(array, otherSize);
return array;
}

@Specialization(guards = "isEmptyArray(array)")
public DynamicObject appendManyEmpty(DynamicObject array, int otherSize, double[] other) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(other, otherSize));
Layouts.ARRAY.setSize(array, otherSize);
return array;
}

@Specialization(guards = "isEmptyArray(array)")
public DynamicObject appendManyEmpty(DynamicObject array, int otherSize, Object[] other) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(other, otherSize));
Layouts.ARRAY.setSize(array, otherSize);
return array;
}

// Append of the correct type

@Specialization(guards = "isIntArray(array)")
public DynamicObject appendManySameType(DynamicObject array, int otherSize, int[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayReflector.reflect((int[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other), extendProfile);
@Specialization(guards = { "isEmptyArray(array)", "isNullArray(other)" })
public DynamicObject appendManyNullNull(DynamicObject array, DynamicObject other) {
return array;
}

@Specialization(guards = "isLongArray(array)")
public DynamicObject appendManySameType(DynamicObject array, int otherSize, long[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayReflector.reflect((long[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other), extendProfile);
@Specialization(guards = { "isEmptyArray(array)", "strategy.matches(other)" }, limit = "ARRAY_STRATEGIES")
public DynamicObject appendManyEmpty(DynamicObject array, DynamicObject other,
@Cached("of(other)") ArrayStrategy strategy) {
final int otherSize = getSize(other);
Object store = strategy.newMirror(other).copyArrayAndMirror(otherSize).getArray();
setStoreAndSize(array, store, otherSize);
return array;
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject appendManySameType(DynamicObject array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayReflector.reflect((double[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other), extendProfile);
@Specialization(guards = "isEmptyArray(other)")
public DynamicObject appendManyOtherEmpty(DynamicObject array, DynamicObject other) {
return array;
}

@Specialization(guards = "isObjectArray(array)")
public DynamicObject appendManySameType(DynamicObject array, int otherSize, Object[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManySameTypeGeneric(array, ArrayReflector.reflect((Object[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other), extendProfile);
return array;
}
// Append of a compatible type

public void appendManySameTypeGeneric(DynamicObject array, ArrayMirror storeMirror,
int otherSize, ArrayMirror otherStoreMirror,
ConditionProfile extendProfile) {
final int oldSize = Layouts.ARRAY.getSize(array);
@Specialization(guards = { "strategy.matches(array)", "otherStrategy.matches(other)",
"strategy.canStore(otherStrategy.type())" }, limit = "ARRAY_STRATEGIES")
public DynamicObject appendManySameType(DynamicObject array, DynamicObject other,
@Cached("of(array)") ArrayStrategy strategy,
@Cached("of(other)") ArrayStrategy otherStrategy,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
final int oldSize = getSize(array);
final int otherSize = getSize(other);
final int newSize = oldSize + otherSize;
final ArrayMirror storeMirror = strategy.newMirror(array);
final ArrayMirror otherStoreMirror = otherStrategy.newMirror(other);

if (extendProfile.profile(newSize > storeMirror.getLength())) {
final ArrayMirror newStoreMirror = storeMirror.copyArrayAndMirror(ArrayUtils.capacity(getContext(), storeMirror.getLength(), newSize));
final int capacity = ArrayUtils.capacity(getContext(), storeMirror.getLength(), newSize);
final ArrayMirror newStoreMirror = storeMirror.copyArrayAndMirror(capacity);
otherStoreMirror.copyTo(newStoreMirror, 0, oldSize, otherSize);
Layouts.ARRAY.setStore(array, newStoreMirror.getArray());
Layouts.ARRAY.setSize(array, newSize);
setStoreAndSize(array, newStoreMirror.getArray(), newSize);
} else {
otherStoreMirror.copyTo(storeMirror, 0, oldSize, otherSize);
Layouts.ARRAY.setSize(array, newSize);
}
}

// Append something else into an Object[]

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

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

@Specialization(guards = "isObjectArray(array)")
public DynamicObject appendManyBoxIntoObject(DynamicObject array, int otherSize, double[] other,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
appendManyBoxIntoObjectGeneric(array, otherSize, ArrayReflector.reflect(other), extendProfile);
return array;
}
// Generalizations

public void appendManyBoxIntoObjectGeneric(DynamicObject array, int otherSize, ArrayMirror otherStoreMirror,
ConditionProfile extendProfile) {
final int oldSize = Layouts.ARRAY.getSize(array);
@Specialization(guards = { "strategy.matches(array)", "otherStrategy.matches(other)",
"!strategy.canStore(otherStrategy.type())" }, limit = "ARRAY_STRATEGIES")
public DynamicObject appendManyGeneralize(DynamicObject array, DynamicObject other,
@Cached("of(array)") ArrayStrategy strategy,
@Cached("of(other)") ArrayStrategy otherStrategy,
@Cached("strategy.generalize(otherStrategy)") ArrayStrategy generalized,
@Cached("createBinaryProfile()") ConditionProfile extendProfile) {
final int oldSize = getSize(array);
final int otherSize = getSize(other);
final int newSize = oldSize + otherSize;

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

if (extendProfile.profile(newSize > oldStore.length)) {
final Object[] newStore = ArrayUtils.grow(oldStore, ArrayUtils.capacity(getContext(), oldStore.length, newSize));
otherStoreMirror.copyTo(newStore, 0, oldSize, otherSize);
Layouts.ARRAY.setStore(array, newStore);
Layouts.ARRAY.setSize(array, newSize);
} else {
otherStoreMirror.copyTo(oldStore, 0, oldSize, otherSize);
Layouts.ARRAY.setSize(array, newSize);
}
}

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

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

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

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

Layouts.ARRAY.setStore(array, newStore);
Layouts.ARRAY.setSize(array, newSize);
return array;
}

// Append forcing a generalization to Object[]

@Specialization(guards = "isIntArray(array)")
public DynamicObject appendManyGeneralizeIntegerDouble(DynamicObject array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((int[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

@Specialization(guards = "isIntArray(array)")
public DynamicObject appendManyGeneralizeIntegerDouble(DynamicObject array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((int[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

@Specialization(guards = "isLongArray(array)")
public DynamicObject appendManyGeneralizeLongDouble(DynamicObject array, int otherSize, double[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((long[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
final ArrayMirror newStoreMirror = generalized.newArray(newSize);
strategy.newMirror(array).copyTo(newStoreMirror, 0, 0, oldSize);
otherStrategy.newMirror(other).copyTo(newStoreMirror, 0, oldSize, otherSize);
setStoreAndSize(array, newStoreMirror.getArray(), newSize);
return array;
}

@Specialization(guards = "isLongArray(array)")
public DynamicObject appendManyGeneralizeLongDouble(DynamicObject array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((long[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject appendManyGeneralizeDoubleInteger(DynamicObject array, int otherSize, int[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((double[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject appendManyGeneralizeDoubleLong(DynamicObject array, int otherSize, long[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((double[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject appendManyGeneralizeDoubleObject(DynamicObject array, int otherSize, Object[] other) {
appendManyGeneralizeGeneric(array, ArrayReflector.reflect((double[]) Layouts.ARRAY.getStore(array)),
otherSize, ArrayReflector.reflect(other));
return array;
}

public void appendManyGeneralizeGeneric(DynamicObject array, ArrayMirror storeMirror, int otherSize, ArrayMirror otherStoreMirror) {
final int oldSize = Layouts.ARRAY.getSize(array);
final int newSize = oldSize + otherSize;
Object[] newStore = storeMirror.getBoxedCopy(newSize);
otherStoreMirror.copyTo(newStore, 0, oldSize, otherSize);
Layouts.ARRAY.setStore(array, newStore);
Layouts.ARRAY.setSize(array, newSize);
}

}
99 changes: 21 additions & 78 deletions truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -206,92 +206,32 @@ public DynamicObject mulEmpty(DynamicObject array, int count) {
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), null, 0);
}

@Specialization(guards = "isIntArray(array)")
public DynamicObject mulIntegerFixnum(DynamicObject array, int count) {
@Specialization(guards = { "strategy.matches(array)", "!isNullArray(array)" }, limit = "ARRAY_STRATEGIES")
public DynamicObject mulIntegerFixnum(DynamicObject array, int count,
@Cached("of(array)") ArrayStrategy strategy) {
if (count < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().argumentError("negative argument", this));
}
final int[] store = (int[]) getStore(array);
final int storeLength = store.length;
final int newStoreLength = storeLength * count;
final int[] newStore = new int[newStoreLength];

for (int n = 0; n < count; n++) {
System.arraycopy(store, 0, newStore, storeLength * n, storeLength);
}

return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), newStore, newStoreLength);
}

@Specialization(guards = "isLongArray(array)")
public DynamicObject mulLongFixnum(DynamicObject array, int count) {
if (count < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().argumentError("negative argument", this));
}
final long[] store = (long[]) getStore(array);
final int storeLength = store.length;
final int newStoreLength = storeLength * count;
final long[] newStore = new long[newStoreLength];

for (int n = 0; n < count; n++) {
System.arraycopy(store, 0, newStore, storeLength * n, storeLength);
}

return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), newStore, newStoreLength);
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject mulFloat(DynamicObject array, int count) {
if (count < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().argumentError("negative argument", this));
}
final double[] store = (double[]) getStore(array);
final int storeLength = store.length;
final int newStoreLength = storeLength * count;
final double[] newStore = new double[newStoreLength];

for (int n = 0; n < count; n++) {
System.arraycopy(store, 0, newStore, storeLength * n, storeLength);
}

return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), newStore, newStoreLength);
}

@Specialization(guards = "isObjectArray(array)")
public DynamicObject mulObject(DynamicObject array, int count) {
if (count < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().argumentError("negative argument", this));
}
final Object[] store = (Object[]) getStore(array);
final int storeLength = getSize(array);
final int newStoreLength = storeLength * count;
final Object[] newStore = new Object[newStoreLength];

final int size = getSize(array);
final int newSize = size * count;
final ArrayMirror store = strategy.newMirror(array);
final ArrayMirror newStore = strategy.newArray(newSize);
for (int n = 0; n < count; n++) {
System.arraycopy(store, 0, newStore, storeLength * n, storeLength);
store.copyTo(newStore, 0, n * size, size);
}

return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), newStore, newStoreLength);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(array), newStore.getArray(), newSize);
}

@Specialization(guards = "isRubyString(string)")
public Object mulObject(VirtualFrame frame, DynamicObject array, DynamicObject string) {
CompilerDirectives.transferToInterpreter();
return ruby("join(sep)", "sep", string);
}

@Specialization(guards = { "!isInteger(object)", "!isRubyString(object)" })
public Object mulObjectCount(VirtualFrame frame, DynamicObject array, Object object) {
CompilerDirectives.transferToInterpreter();
if (respondToToStrNode == null) {
CompilerDirectives.transferToInterpreter();
respondToToStrNode = insert(KernelNodesFactory.RespondToNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
if (respondToToStrNode.doesRespondToString(frame, object, create7BitString("to_str", UTF8Encoding.INSTANCE), false)) {
if (respondToToStr(frame, object)) {
return ruby("join(sep.to_str)", "sep", object);
} else {
if (toIntNode == null) {
@@ -303,6 +243,14 @@ public Object mulObjectCount(VirtualFrame frame, DynamicObject array, Object obj
}
}

public boolean respondToToStr(VirtualFrame frame, Object object) {
if (respondToToStrNode == null) {
CompilerDirectives.transferToInterpreter();
respondToToStrNode = insert(KernelNodesFactory.RespondToNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
return respondToToStrNode.doesRespondToString(frame, object, create7BitString("to_str", UTF8Encoding.INSTANCE), false);
}

}

@CoreMethod(names = { "[]", "slice" }, required = 1, optional = 1, lowerFixnumParameters = { 0, 1 })
@@ -817,21 +765,16 @@ public abstract static class ConcatNode extends CoreMethodNode {

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

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

@Specialization(guards = {"isRubyArray(other)", "isNullArray(other)"})
public DynamicObject concatNull(DynamicObject array, DynamicObject other) {
return array;
}

@Specialization(guards = {"isRubyArray(other)", "!isNullArray(other)"})
@Specialization
public DynamicObject concat(DynamicObject array, DynamicObject other) {
appendManyNode.executeAppendMany(array, getSize(other), getStore(other));
appendManyNode.executeAppendMany(array, other);
return array;
}