Skip to content

Commit

Permalink
Merge pull request #2571 from jruby/truffle-arrays
Browse files Browse the repository at this point in the history
Truffle arrays
  • Loading branch information
chrisseaton committed Feb 6, 2015
2 parents 7b206aa + ab9231e commit 584ec92
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 218 deletions.
@@ -0,0 +1,53 @@
/*
* 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.CompilerDirectives;
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.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyArray;

@NodeChildren({
@NodeChild(value="array", type=RubyNode.class),
@NodeChild(value="index", type=RubyNode.class)
})
public abstract class ArrayReadDenormalizedNode extends RubyNode {

@Child private ArrayReadNormalizedNode readNode;

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

public ArrayReadDenormalizedNode(ArrayReadDenormalizedNode prev) {
super(prev);
readNode = prev.readNode;
}

public abstract Object executeRead(VirtualFrame frame, RubyArray array, int index);

@Specialization
public Object read(VirtualFrame frame, RubyArray array, int index) {
if (readNode == null) {
CompilerDirectives.transferToInterpreter();
readNode = insert(ArrayReadNormalizedNodeFactory.create(getContext(), getSourceSection(), null, null));
}

final int normalizedIndex = array.normaliseIndex(index);

return readNode.executeRead(frame, array, normalizedIndex);
}

}
@@ -0,0 +1,84 @@
/*
* 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.ImportGuards;
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.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
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.core.RubyNilClass;

@NodeChildren({
@NodeChild(value="array", type=RubyNode.class),
@NodeChild(value="index", type=RubyNode.class)
})
@ImportGuards(ArrayGuards.class)
public abstract class ArrayReadNormalizedNode extends RubyNode {

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

public ArrayReadNormalizedNode(ArrayReadNormalizedNode prev) {
super(prev);
}

public abstract Object executeRead(VirtualFrame frame, RubyArray array, int index);

@Specialization(
guards="isNullArray"
)
public RubyNilClass readNull(RubyArray array, int index) {
return getContext().getCoreLibrary().getNilObject();
}

@Specialization(
guards={"isNormalisedInBounds", "isIntegerArray"}
)
public int readIntegerInBounds(RubyArray array, int index) {
return ((int[]) array.getStore())[index];
}

@Specialization(
guards={"isNormalisedInBounds", "isLongArray"}
)
public long readLongInBounds(RubyArray array, int index) {
return ((long[]) array.getStore())[index];
}

@Specialization(
guards={"isNormalisedInBounds", "isDoubleArray"}
)
public double readDoubleInBounds(RubyArray array, int index) {
return ((double[]) array.getStore())[index];
}

@Specialization(
guards={"isNormalisedInBounds", "isObjectArray"}
)
public Object readObjectInBounds(RubyArray array, int index) {
return ((Object[]) array.getStore())[index];
}

@Specialization(
guards="!isNormalisedInBounds"
)
public RubyNilClass readOutOfBounds(RubyArray array, int index) {
return getContext().getCoreLibrary().getNilObject();
}

}
@@ -0,0 +1,55 @@
/*
* 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.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.CoreLibrary;

/**
* Passes through {@code int} values unmodified, but will convert a {@code long} value to an {@code int}, if it fits
* within the range of an {@code int}. Leaves all other values unmodified. Used where a specialisation only accepts
* {@code int}, such as Java array indexing, but we would like to also handle {@code long} if they also fit within an
* {@code int}.
*/
@NodeChild(value="child", type=RubyNode.class)
public abstract class NewFixnumLowerNode extends RubyNode {

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

public NewFixnumLowerNode(NewFixnumLowerNode prev) {
super(prev);
}

@Specialization
public int lower(int value) {
return value;
}

@Specialization(guards="canLower")
public int lower(long value) {
return (int) value;
}

@Specialization(guards="!canLower")
public long lowerFails(long value) {
return value;
}

protected static boolean canLower(long value) {
return CoreLibrary.fitsIntoInteger(value);
}

}
@@ -0,0 +1,32 @@
/*
* 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.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.literal.FixnumLiteralNode;
import org.jruby.truffle.runtime.RubyContext;

public abstract class PrimitiveArrayNodeFactory {

/**
* Create a node to read from an array with a constant denormalised index.
*/
public static RubyNode read(RubyContext context, SourceSection sourceSection, RubyNode array, int index) {
final RubyNode literalIndex = new FixnumLiteralNode.IntegerFixnumLiteralNode(context, sourceSection, index);

if (index > 0) {
return ArrayReadNormalizedNodeFactory.create(context, sourceSection, array, literalIndex);
} else {
return ArrayReadDenormalizedNodeFactory.create(context, sourceSection, array, literalIndex);
}
}

}
Expand Up @@ -73,4 +73,30 @@ public static boolean areBothObject(RubyArray a, RubyArray b) {
return a.getStore() instanceof Object[] && b.getStore() instanceof Object[];
}

// New names

public static boolean isNullArray(RubyArray array) {
return array.getStore() == null;
}

public static boolean isIntegerArray(RubyArray array) {
return array.getStore() instanceof int[];
}

public static boolean isLongArray(RubyArray array) {
return array.getStore() instanceof long[];
}

public static boolean isDoubleArray(RubyArray array) {
return array.getStore() instanceof double[];
}

public static boolean isObjectArray(RubyArray array) {
return array.getStore() instanceof Object[];
}

public static boolean isNormalisedInBounds(RubyArray array, int index) {
return index >= 0 && index < array.getSize();
}

}
125 changes: 0 additions & 125 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayIndexNode.java

This file was deleted.

0 comments on commit 584ec92

Please sign in to comment.