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: 35be34a2a91f
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b5c82e43560c
Choose a head ref
  • 9 commits
  • 16 files changed
  • 2 contributors

Commits on Jan 5, 2015

  1. Copy the full SHA
    675b098 View commit details
  2. Copy the full SHA
    462f160 View commit details
  3. [Truffle] Extract asserts in RubyArray into common utility method and…

    … remove from fast path.
    thomaswue committed Jan 5, 2015
    Copy the full SHA
    9e71afc View commit details
  4. [Truffle] Create utility ArrayUtils.extractRange as a version of Arra…

    …ys.copyOfRange with simplified semantics.
    thomaswue committed Jan 5, 2015
    Copy the full SHA
    a626ed4 View commit details
  5. Copy the full SHA
    8516451 View commit details
  6. Copy the full SHA
    47ce508 View commit details
  7. Copy the full SHA
    d913146 View commit details
  8. Copy the full SHA
    eac6545 View commit details

Commits on Jan 8, 2015

  1. Merge pull request #2425 from thomaswue/master

    Further Truffle-related clean ups and simplifications.
    chrisseaton committed Jan 8, 2015
    Copy the full SHA
    b5c82e4 View commit details
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/truffle/nodes/RubyCallNode.java
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ private Object[] splat(Object argument) {
} else if (seenLongFixnumInUnsplat && store instanceof long[]) {
return ArrayUtils.boxUntil((long[]) store, size);
} else if (seenObjectInUnsplat && store instanceof Object[]) {
return Arrays.copyOfRange((Object[]) store, 0, size);
return ArrayUtils.extractRange((Object[]) store, 0, size);
}

CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -158,7 +158,7 @@ private Object[] splat(Object argument) {
return ArrayUtils.boxUntil((long[]) store, size);
} else if (store instanceof Object[]) {
seenObjectInUnsplat = true;
return Arrays.copyOfRange((Object[]) store, 0, size);
return ArrayUtils.extractRange((Object[]) store, 0, size);
}

throw new UnsupportedOperationException();
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/truffle/nodes/RubyRootNode.java
Original file line number Diff line number Diff line change
@@ -50,8 +50,7 @@ public boolean isCloningAllowed() {

@Override
public Object execute(VirtualFrame frame) {
context.getSafepointManager().poll();

context.getSafepointManager().poll();
return body.execute(frame);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -52,7 +52,6 @@ public TryNode(RubyContext context, SourceSection sourceSection, ExceptionTransl
@Override
public Object execute(VirtualFrame frame) {
while (true) {
getContext().getSafepointManager().poll();

Object result;

@@ -67,6 +66,7 @@ public Object execute(VirtualFrame frame) {
try {
return handleException(frame, exception);
} catch (RetryException e) {
getContext().getSafepointManager().poll();
continue;
}
} finally {
66 changes: 57 additions & 9 deletions core/src/main/java/org/jruby/truffle/nodes/control/WhileNode.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
* Copyright (c) 2013, 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:
*
@@ -15,45 +15,68 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RepeatingNode;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.BooleanCastNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.BreakException;
import org.jruby.truffle.runtime.control.NextException;
import org.jruby.truffle.runtime.control.RedoException;

public class WhileNode extends RubyNode {
public final class WhileNode extends RubyNode {

@Child protected LoopNode loopNode;
private final BranchProfile breakUsed = BranchProfile.create();

public WhileNode(RubyContext context, SourceSection sourceSection, BooleanCastNode condition, RubyNode body) {
private WhileNode(RubyContext context, SourceSection sourceSection, RepeatingNode repeatingNode) {
super(context, sourceSection);
loopNode = Truffle.getRuntime().createLoopNode(new WhileRepeatingNode(context, condition, body));
this.loopNode = Truffle.getRuntime().createLoopNode(repeatingNode);
}

public static WhileNode createWhile(RubyContext context, SourceSection sourceSection, BooleanCastNode condition, RubyNode body) {
RepeatingNode repeatingNode = new WhileRepeatingNode(context, condition, body);
return new WhileNode(context, sourceSection, repeatingNode);
}

public static WhileNode createDoWhile(RubyContext context, SourceSection sourceSection, BooleanCastNode condition, RubyNode body) {
RepeatingNode repeatingNode = new DoWhileRepeatingNode(context, condition, body);
return new WhileNode(context, sourceSection, repeatingNode);
}

@Override
public Object execute(VirtualFrame frame) {
try {
loopNode.executeLoop(frame);
} catch (BreakException e) {
breakUsed.enter();
return e.getResult();
}

return getContext().getCoreLibrary().getNilObject();
}

private static abstract class WhileRepeatingBaseNode extends Node implements RepeatingNode {

private static class WhileRepeatingNode extends Node implements RepeatingNode {

private final RubyContext context;
protected final RubyContext context;

@Child protected BooleanCastNode condition;
@Child protected RubyNode body;
protected final BranchProfile redoUsed = BranchProfile.create();
protected final BranchProfile nextUsed = BranchProfile.create();

public WhileRepeatingNode(RubyContext context, BooleanCastNode condition, RubyNode body) {
public WhileRepeatingBaseNode(RubyContext context, BooleanCastNode condition, RubyNode body) {
this.context = context;
this.condition = condition;
this.body = body;
}
}

private static class WhileRepeatingNode extends WhileRepeatingBaseNode implements RepeatingNode {

public WhileRepeatingNode(RubyContext context, BooleanCastNode condition, RubyNode body) {
super(context, condition, body);
}

@Override
public boolean executeRepeating(VirtualFrame frame) {
@@ -63,18 +86,43 @@ public boolean executeRepeating(VirtualFrame frame) {

while (true) { // for redo
context.getSafepointManager().poll();

try {
body.execute(frame);
return true;
} catch (NextException e) {
nextUsed.enter();
return true;
} catch (RedoException e) {
// Just continue in the while(true) loop.
redoUsed.enter();
}
}
}

}

private static class DoWhileRepeatingNode extends WhileRepeatingNode implements RepeatingNode {

public DoWhileRepeatingNode(RubyContext context, BooleanCastNode condition, RubyNode body) {
super(context, condition, body);
}

@Override
public boolean executeRepeating(VirtualFrame frame) {
context.getSafepointManager().poll();
try {
body.execute(frame);
} catch (NextException e) {
nextUsed.enter();
} catch (RedoException e) {
// Just continue to next iteration without executing the condition.
redoUsed.enter();
return true;
}

return condition.executeBoolean(frame);
}

}

}
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyCallNode;
import org.jruby.truffle.nodes.RubyNode;
@@ -28,6 +29,7 @@
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.util.ArrayUtils;
import org.jruby.util.cli.Options;

import java.util.Arrays;
@@ -272,7 +274,7 @@ public Object methodMissing(Object self, Object[] args, RubyProc block) {
notDesignedForCompilation();

final RubySymbol name = (RubySymbol) args[0];
final Object[] sentArgs = Arrays.copyOfRange(args, 1, args.length);
final Object[] sentArgs = ArrayUtils.extractRange(args, 1, args.length);
return methodMissing(self, name, sentArgs, block);
}

@@ -334,7 +336,7 @@ public Object send(VirtualFrame frame, Object self, Object[] args, UndefinedPlac
@Specialization
public Object send(VirtualFrame frame, Object self, Object[] args, RubyProc block) {
final Object name = args[0];
final Object[] sendArgs = Arrays.copyOfRange(args, 1, args.length);
final Object[] sendArgs = ArrayUtils.extractRange(args, 1, args.length);
return dispatchNode.call(frame, self, name, block, sendArgs);
}

Original file line number Diff line number Diff line change
@@ -1300,7 +1300,7 @@ public abstract static class LoopNode extends CoreMethodNode {

public LoopNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
whileNode = new WhileNode(context, sourceSection, BooleanCastNodeFactory.create(context, sourceSection,
whileNode = WhileNode.createWhile(context, sourceSection, BooleanCastNodeFactory.create(context, sourceSection,
new BooleanLiteralNode(context, sourceSection, true)),
new YieldNode(context, getSourceSection(), new RubyNode[]{}, false)
);
Original file line number Diff line number Diff line change
@@ -108,19 +108,24 @@ public RubyArray executeArray(VirtualFrame frame) {
try {
executedValues[n] = values[n].executeFloat(frame);
} catch (UnexpectedResultException e) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
return makeGeneric(frame, executedValues, n);
}
}

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

private RubyArray makeGeneric(VirtualFrame frame,
final double[] executedValues, int n) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
}

}

public static class IntegerFixnumArrayLiteralNode extends ArrayLiteralNode {
@@ -141,13 +146,7 @@ public RubyArray executeArray(VirtualFrame frame) {
try {
executedValues[n] = values[n].executeLongFixnum(frame);
} catch (UnexpectedResultException e) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
return makeGeneric(frame, executedValues, n);
}
}

@@ -159,20 +158,36 @@ public RubyArray executeArray(VirtualFrame frame) {
try {
executedValues[n] = values[n].executeIntegerFixnum(frame);
} catch (UnexpectedResultException e) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
return makeGeneric(frame, executedValues, n);
}
}

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), arrayAllocationSite, executedValues, values.length);
}
}

private RubyArray makeGeneric(VirtualFrame frame,
final int[] executedValues, int n) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
}

private RubyArray makeGeneric(VirtualFrame frame,
final long[] executedValues, int n) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
}

}

public static class LongFixnumArrayLiteralNode extends ArrayLiteralNode {
@@ -190,19 +205,24 @@ public RubyArray executeArray(VirtualFrame frame) {
try {
executedValues[n] = values[n].executeLongFixnum(frame);
} catch (UnexpectedResultException e) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
return makeGeneric(frame, executedValues, n);
}
}

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

private RubyArray makeGeneric(VirtualFrame frame,
final long[] executedValues, int n) {
final Object[] executedObjects = new Object[n];

for (int i = 0; i < n; i++) {
executedObjects[i] = executedValues[i];
}

return makeGeneric(frame, executedObjects);
}

}

public static class ObjectArrayLiteralNode extends ArrayLiteralNode {
Original file line number Diff line number Diff line change
@@ -30,12 +30,12 @@ public RedoableNode(RubyContext context, SourceSection sourceSection, RubyNode b
@Override
public Object execute(VirtualFrame frame) {
while (true) {
getContext().getSafepointManager().poll();

try {
return body.execute(frame);
} catch (RedoException e) {
redoProfile.enter();
getContext().getSafepointManager().poll();
continue;
}
}
Original file line number Diff line number Diff line change
@@ -11,10 +11,12 @@

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.util.ArrayUtils;

import java.util.Arrays;

@@ -37,7 +39,7 @@ public Object execute(VirtualFrame frame) {
final Object[] args = frame.getArguments();
final Object receiver = RubyArguments.getUserArgument(args, 0);
final Object[] arguments = RubyArguments.extractUserArguments(args);
final Object[] sendArgs = Arrays.copyOfRange(arguments, 1, arguments.length);
final Object[] sendArgs = ArrayUtils.extractRange(arguments, 1, arguments.length);
return dispatch.call(frame, receiver, symbol, RubyArguments.getBlock(args), sendArgs);
}

Original file line number Diff line number Diff line change
@@ -12,12 +12,14 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.util.ArrayUtils;

import java.util.Arrays;

@@ -69,7 +71,7 @@ public Object execute(VirtualFrame frame) {
subsetOfArgumentsProfile.enter();
final Object[] arguments = RubyArguments.extractUserArguments(frame.getArguments());
// TODO(CS): risk here of widening types too much - always going to be Object[] - does seem to be something that does happen
return new RubyArray(arrayClass, Arrays.copyOfRange(arguments, startIndex, endIndex), length);
return new RubyArray(arrayClass, ArrayUtils.extractRange(arguments, startIndex, endIndex), length);
}
}
}
Original file line number Diff line number Diff line change
@@ -12,8 +12,10 @@
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;

import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.MethodLike;
import org.jruby.truffle.runtime.util.ArrayUtils;

import java.util.Arrays;

@@ -53,7 +55,7 @@ public static RubyProc getBlock(Object[] arguments) {
}

public static Object[] extractUserArguments(Object[] arguments) {
return Arrays.copyOfRange(arguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
return ArrayUtils.extractRange(arguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
}

public static Object[] concatUserArguments(Object o, Object[] arguments) {
37 changes: 6 additions & 31 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyArray.java
Original file line number Diff line number Diff line change
@@ -42,24 +42,8 @@ public RubyArray(RubyClass arrayClass, Object store, int size) {

public RubyArray(RubyClass arrayClass, ArrayAllocationSite allocationSite, Object store, int size) {
super(arrayClass);

this.allocationSite = allocationSite;

assert store == null
|| store instanceof Object[]
|| store instanceof int[]
|| store instanceof long[]
|| store instanceof double[];

assert !(store instanceof Object[]) || size <= ((Object[]) store).length;
assert !(store instanceof int[]) || size <= ((int[]) store).length;
assert !(store instanceof long[]) || size <= ((long[]) store).length;
assert !(store instanceof double[]) || size <= ((double[]) store).length;

// TODO: assert that an object array doesn't contain all primitives - performance warning?

this.store = store;
this.size = size;
setStore(store, size);
}

public static RubyArray fromObject(RubyClass arrayClass, Object object) {
@@ -222,30 +206,21 @@ public Object getStore() {
}

public void setStore(Object store, int size) {
assert verifyStore(store, size);
this.store = store;
this.size = size;

assert store == null
|| store instanceof Object[]
|| store instanceof int[]
|| store instanceof long[]
|| store instanceof double[];

assert !(store instanceof Object[]) || size <= ((Object[]) store).length;
assert !(store instanceof int[]) || size <= ((int[]) store).length;
assert !(store instanceof long[]) || size <= ((long[]) store).length;
assert !(store instanceof double[]) || size <= ((double[]) store).length;

// TODO: assert that an object array doesn't contain all primitives - performance warning?
}

public int getSize() {
return size;
}

public void setSize(int size) {
assert verifyStore(this.store, size);
this.size = size;
}

private boolean verifyStore(Object store, int size) {
assert store == null
|| store instanceof Object[]
|| store instanceof int[]
@@ -256,6 +231,7 @@ public void setSize(int size) {
assert !(store instanceof int[]) || size <= ((int[]) store).length;
assert !(store instanceof long[]) || size <= ((long[]) store).length;
assert !(store instanceof double[]) || size <= ((double[]) store).length;
return true;
}

public ArrayAllocationSite getAllocationSite() {
@@ -279,5 +255,4 @@ public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNo
}

}

}
Original file line number Diff line number Diff line change
@@ -66,13 +66,17 @@ public void poll() {
try {
assumption.check();
} catch (InvalidAssumptionException e) {
waitOnBarrier();
assumptionInvalidated();
}
}

try {
action.accept(false);
} finally {
waitOnBarrier();
}
private void assumptionInvalidated() {
waitOnBarrier();

try {
action.accept(false);
} finally {
waitOnBarrier();
}
}

25 changes: 25 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/util/ArrayUtils.java
Original file line number Diff line number Diff line change
@@ -10,13 +10,38 @@
package org.jruby.truffle.runtime.util;

import com.oracle.truffle.api.CompilerAsserts;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;

import java.util.Arrays;

public abstract class ArrayUtils {

/**
* Extracts part of an array into a newly allocated Object[] array. Does not perform safety checks on parameters.
* @param source the source array whose values should be extracted
* @param start the start index, must be >= 0 and < source.length
* @param end the end index (exclusive), must be >= 0 and <= source.length and >= start
* @return a newly allocated array with the extracted elements and length (end - start)
*/
public static Object[] extractRange(Object[] source, int start, int end) {
assert checkExtractRangeArgs(source, start, end);
int length = end - start;
Object[] result = new Object[length];
System.arraycopy(source, start, result, 0, length);
return result;
}

private static boolean checkExtractRangeArgs(Object[] source, int start, int end) {
assert source != null;
assert start >= 0;
assert start <= source.length;
assert end >= start;
assert end <= source.length;
return true;
}

public static boolean contains(int[] array, int value) {
for (int n = 0; n < array.length; n++) {
if (array[n] == value) {
Original file line number Diff line number Diff line change
@@ -2433,9 +2433,9 @@ public RubyNode visitUntilNode(org.jruby.ast.UntilNode node) {
RubyNode body = node.getBodyNode().accept(this);

if (node.evaluateAtStart()) {
return new WhileNode(context, sourceSection, conditionCastNotCast, body);
return WhileNode.createWhile(context, sourceSection, conditionCastNotCast, body);
} else {
return new DoWhileNode(context, sourceSection, conditionCastNotCast, body);
return WhileNode.createDoWhile(context, sourceSection, conditionCastNotCast, body);
}
}

@@ -2465,9 +2465,9 @@ public RubyNode visitWhileNode(org.jruby.ast.WhileNode node) {
RubyNode body = node.getBodyNode().accept(this);

if (node.evaluateAtStart()) {
return new WhileNode(context, sourceSection, conditionCast, body);
return WhileNode.createWhile(context, sourceSection, conditionCast, body);
} else {
return new DoWhileNode(context, sourceSection, conditionCast, body);
return WhileNode.createDoWhile(context, sourceSection, conditionCast, body);
}
}