Skip to content

Commit

Permalink
[Truffle] Rewrite ArrayWriteNormalizedNode and helper nodes to use Ar…
Browse files Browse the repository at this point in the history
…rayStrategy.

* Allow ArrayStrategy#generalize() to be called with an identical strategy
  so that generated code can order as it wants the @cached instantiation.
  • Loading branch information
eregon committed Apr 13, 2016
1 parent c448aa7 commit 06ff2ad
Showing 4 changed files with 100 additions and 271 deletions.
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
*/
package org.jruby.truffle.core.array;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
@@ -20,69 +21,32 @@
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyNode;

import java.util.Arrays;

@NodeChildren({
@NodeChild(value="array", type=RubyNode.class),
@NodeChild(value="requiredCapacity", type=RubyNode.class)
@NodeChild(value = "array", type = RubyNode.class),
@NodeChild(value = "requiredCapacity", type = RubyNode.class)
})
@ImportStatic(ArrayGuards.class)
public abstract class ArrayEnsureCapacityNode extends RubyNode {

private final ConditionProfile allocateProfile = ConditionProfile.createCountingProfile();

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

public abstract Object executeEnsureCapacity(DynamicObject array, int requiredCapacity);

@Specialization(guards = "isIntArray(array)")
public boolean ensureCapacityInt(DynamicObject array, int requiredCapacity) {
final int[] store = (int[]) Layouts.ARRAY.getStore(array);

if (allocateProfile.profile(store.length < requiredCapacity)) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity)));
Layouts.ARRAY.setSize(array, Layouts.ARRAY.getSize(array));
return true;
} else {
return false;
}
public static ArrayEnsureCapacityNode create(RubyContext context) {
return ArrayEnsureCapacityNodeGen.create(context, null, null, null);
}

@Specialization(guards = "isLongArray(array)")
public boolean ensureCapacityLong(DynamicObject array, int requiredCapacity) {
final long[] store = (long[]) Layouts.ARRAY.getStore(array);

if (allocateProfile.profile(store.length < requiredCapacity)) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity)));
Layouts.ARRAY.setSize(array, Layouts.ARRAY.getSize(array));
return true;
} else {
return false;
}
}

@Specialization(guards = "isDoubleArray(array)")
public boolean ensureCapacityDouble(DynamicObject array, int requiredCapacity) {
final double[] store = (double[]) Layouts.ARRAY.getStore(array);

if (allocateProfile.profile(store.length < requiredCapacity)) {
Layouts.ARRAY.setStore(array, Arrays.copyOf(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity)));
Layouts.ARRAY.setSize(array, Layouts.ARRAY.getSize(array));
return true;
} else {
return false;
}
}
public abstract Object executeEnsureCapacity(DynamicObject array, int requiredCapacity);

@Specialization(guards = "isObjectArray(array)")
public boolean ensureCapacityObject(DynamicObject array, int requiredCapacity) {
final Object[] store = (Object[]) Layouts.ARRAY.getStore(array);
@Specialization(guards = "strategy.matches(array)", limit = "ARRAY_STRATEGIES")
public boolean ensureCapacity(DynamicObject array, int requiredCapacity,
@Cached("of(array)") ArrayStrategy strategy,
@Cached("createCountingProfile()") ConditionProfile extendProfile) {
final ArrayMirror mirror = strategy.newMirror(array);

if (allocateProfile.profile(store.length < requiredCapacity)) {
Layouts.ARRAY.setStore(array, ArrayUtils.grow(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity)));
Layouts.ARRAY.setSize(array, Layouts.ARRAY.getSize(array));
if (extendProfile.profile(mirror.getLength() < requiredCapacity)) {
final int capacity = ArrayUtils.capacity(getContext(), mirror.getLength(), requiredCapacity);
Layouts.ARRAY.setStore(array, mirror.copyArrayAndMirror(capacity).getArray());
return true;
} else {
return false;
Original file line number Diff line number Diff line change
@@ -9,11 +9,13 @@
*/
package org.jruby.truffle.core.array;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
@@ -30,34 +32,34 @@ public ArrayGeneralizeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract Object executeGeneralize(DynamicObject array, int requiredCapacity);

@Specialization(guards = "isNullArray(array)")
public DynamicObject generalizeNull(DynamicObject array, int requiredCapacity) {
Object store = new Object[requiredCapacity];
Layouts.ARRAY.setStore(array, store);
return array;
public static ArrayGeneralizeNode create(RubyContext context) {
return ArrayGeneralizeNodeGen.create(context, null, null, null);
}

@Specialization(guards = "isIntArray(array)")
public DynamicObject generalizeInt(DynamicObject array, int requiredCapacity) {
final int[] store = (int[]) Layouts.ARRAY.getStore(array);
Layouts.ARRAY.setStore(array, ArrayUtils.boxExtra(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity) - store.length));
return array;
}
public abstract Object[] executeGeneralize(DynamicObject array, int requiredCapacity);

@Specialization(guards = "isLongArray(array)")
public DynamicObject generalizeLong(DynamicObject array, int requiredCapacity) {
final long[] store = (long[]) Layouts.ARRAY.getStore(array);
Layouts.ARRAY.setStore(array, ArrayUtils.boxExtra(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity) - store.length));
return array;
@Specialization(guards = "isNullArray(array)")
public Object[] generalizeNull(DynamicObject array, int requiredCapacity) {
Object[] store = new Object[requiredCapacity];
Layouts.ARRAY.setStore(array, store);
return store;
}

@Specialization(guards = "isDoubleArray(array)")
public DynamicObject generalizeDouble(DynamicObject array, int requiredCapacity) {
final double[] store = (double[]) Layouts.ARRAY.getStore(array);
Layouts.ARRAY.setStore(array, ArrayUtils.boxExtra(store, ArrayUtils.capacity(getContext(), store.length, requiredCapacity) - store.length));
return array;
@Specialization(guards = "strategy.matches(array)", limit = "ARRAY_STRATEGIES")
public Object[] generalize(DynamicObject array, int requiredCapacity,
@Cached("of(array)") ArrayStrategy strategy,
@Cached("createCountingProfile()") ConditionProfile extendProfile) {
assert !ArrayGuards.isObjectArray(array);
final ArrayMirror mirror = strategy.newMirror(array);
final int capacity;
if (extendProfile.profile(mirror.getLength() < requiredCapacity)) {
capacity = ArrayUtils.capacity(getContext(), mirror.getLength(), requiredCapacity);
} else {
capacity = mirror.getLength();
}
final Object[] store = mirror.getBoxedCopy(capacity);
Layouts.ARRAY.setStore(array, store);
return store;
}

}
Original file line number Diff line number Diff line change
@@ -31,7 +31,10 @@ public boolean specializesFor(Object value) {
public abstract String toString();

public ArrayStrategy generalize(ArrayStrategy other) {
generalizeCheck(other);
CompilerAsserts.neverPartOfCompilation();
if (other == this) {
return this;
}
for (ArrayStrategy generalized : TYPE_STRATEGIES) {
if (generalized.canStore(type()) && generalized.canStore(other.type())) {
return generalized;
@@ -46,12 +49,6 @@ public ArrayStrategy generalizeFor(Object value) {

// Helpers

protected void generalizeCheck(ArrayStrategy other) {
CompilerAsserts.neverPartOfCompilation();
assert other != this;
assert !canStore(other.type());
}

protected static RuntimeException unsupported() {
return new UnsupportedOperationException();
}
@@ -137,8 +134,10 @@ public boolean matches(DynamicObject array) {

@Override
public ArrayStrategy generalize(ArrayStrategy other) {
generalizeCheck(other);
if (other == LongArrayStrategy.INSTANCE) {
CompilerAsserts.neverPartOfCompilation();
if (other == this) {
return this;
} else if (other == LongArrayStrategy.INSTANCE) {
return LongArrayStrategy.INSTANCE;
} else {
return IntToObjectGeneralizationArrayStrategy.INSTANCE;
Loading

0 comments on commit 06ff2ad

Please sign in to comment.