Skip to content

Commit

Permalink
Showing 6 changed files with 170 additions and 138 deletions.
51 changes: 32 additions & 19 deletions mx.jruby/mx_jruby.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

import sys
import os
import subprocess
import shutil
@@ -19,7 +20,7 @@
def jt(args, suite=None, nonZeroIsFatal=True, out=None, err=None, timeout=None, env=None, cwd=None):
rubyDir = _suite.dir
jt = os.path.join(rubyDir, 'tool', 'jt.rb')
mx.run(['ruby', jt] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, timeout=timeout, env=env, cwd=cwd)
return mx.run(['ruby', jt] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, timeout=timeout, env=env, cwd=cwd)

class MavenProject(mx.Project):
def __init__(self, suite, name, deps, workingSets, theLicense, **args):
@@ -267,23 +268,29 @@ def runBenchmark(self, benchmark, bmSuiteArgs):
arguments.extend(benchmark_names)
arguments.extend(bmSuiteArgs)
out = mx.OutputCapture()
jt(arguments, out=out)

samples = [float(s) for s in out.data.split('\n')[1:-2]]

warmed_up_samples = [sample for n, sample in enumerate(samples) if n / float(len(samples)) >= 0.5]
warmed_up_mean = sum(warmed_up_samples) / float(len(warmed_up_samples))

return [{
'benchmark': benchmark,
'metric.name': 'throughput',
'metric.value': sample,
'metric.unit': 'op/s',
'metric.better': 'higher',
'metric.iteration': n,
'extra.metric.warmedup': 'true' if n / float(len(samples)) >= 0.5 else 'false',
'extra.metric.human': '%d/%d %fs' % (n, len(samples), warmed_up_mean)
} for n, sample in enumerate(samples)]
if jt(arguments, out=out, nonZeroIsFatal=False) == 0:
samples = [float(s) for s in out.data.split('\n')[1:-2]]

warmed_up_samples = [sample for n, sample in enumerate(samples) if n / float(len(samples)) >= 0.5]
warmed_up_mean = sum(warmed_up_samples) / float(len(warmed_up_samples))

return [{
'benchmark': benchmark,
'metric.name': 'throughput',
'metric.value': sample,
'metric.unit': 'op/s',
'metric.better': 'higher',
'metric.iteration': n,
'extra.metric.warmedup': 'true' if n / float(len(samples)) >= 0.5 else 'false',
'extra.metric.human': '%d/%d %fs' % (n, len(samples), warmed_up_mean)
} for n, sample in enumerate(samples)]
else:
sys.stderr.write(out.data)

# TODO CS 24-Jun-16, return an error point?
# TODO CS 24-Jun-16, how can we fail the wider suite?
return []

classic_benchmarks = [
'binary-trees',
@@ -425,8 +432,14 @@ def benchmarks(self):
if name.endswith('.rb'):
benchmark_file = os.path.join(root, name)[len(all_ruby_benchmarks)+1:]
out = mx.OutputCapture()
jt(['benchmark', 'list', benchmark_file], out=out)
benchmarks.extend([benchmark_file + ':' + b.strip() for b in out.data.split('\n') if len(b.strip()) > 0])
if jt(['benchmark', 'list', benchmark_file], out=out):
benchmarks.extend([benchmark_file + ':' + b.strip() for b in out.data.split('\n') if len(b.strip()) > 0])
else:
sys.stderr.write(out.data)

# TODO CS 24-Jun-16, return an error point?
# TODO CS 24-Jun-16, how can we fail the wider suite?
return []
return benchmarks

def time(self):
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/string/modulo_tags.txt
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@ fails:String#% always allows unused arguments when positional argument style is
fails:String#% replaces trailing absolute argument specifier without type with percent sign
fails:String#% raises an ArgumentError when given invalid argument specifiers
fails:String#% raises an ArgumentError when multiple positional argument tokens are given for one format specifier
fails:String#% respects positional arguments and precision tokens given for one format specifier
fails:String#% raises an ArgumentError when multiple width star tokens are given for one format specifier
fails:String#% raises an ArgumentError when a width star token is seen after a width token
fails:String#% raises an ArgumentError when multiple precision tokens are given
@@ -24,8 +23,6 @@ fails:String#% raises a TypeError if #to_ary does not return an Array
fails:String#% tries to convert the argument to Array by calling #to_ary
fails:String#% doesn't return subclass instances when called on a subclass
fails:String#% always taints the result when the format string is tainted
fails:String#% supports binary formats using %b for positive numbers
fails:String#% supports binary formats using %b for negative numbers
fails:String#% supports character formats using %c
fails:String#% supports single character strings as argument for %c
fails:String#% raises an exception for multiple character strings as argument for %c
Original file line number Diff line number Diff line change
@@ -27,40 +27,48 @@ public abstract class FormatFloatNode extends FormatNode {
private final String infiniteFormatString;
private final String finiteFormatString;

public FormatFloatNode(RubyContext context, int spacePadding, int zeroPadding, int precision, char format) {
public FormatFloatNode(RubyContext context, int width, int precision, char format, boolean hasSpaceFlag, boolean hasZeroFlag) {
super(context);

final StringBuilder inifiniteFormatBuilder = new StringBuilder();
inifiniteFormatBuilder.append("%");

if (spacePadding != PrintfTreeBuilder.DEFAULT) {
if (hasSpaceFlag) {
inifiniteFormatBuilder.append(" ");
inifiniteFormatBuilder.append(spacePadding + 5);
inifiniteFormatBuilder.append(width + 5);
}

if (zeroPadding != PrintfTreeBuilder.DEFAULT && zeroPadding != 0) {
if (hasZeroFlag && width != 0) {
inifiniteFormatBuilder.append("0");
inifiniteFormatBuilder.append(zeroPadding + 5);
inifiniteFormatBuilder.append(width + 5);
}
if(!hasSpaceFlag && !hasZeroFlag){
inifiniteFormatBuilder.append(width + 5);
}


inifiniteFormatBuilder.append(format);

infiniteFormatString = inifiniteFormatBuilder.toString();

final StringBuilder finiteFormatBuilder = new StringBuilder();
finiteFormatBuilder.append("%");

if (spacePadding != PrintfTreeBuilder.DEFAULT) {
if (hasSpaceFlag) {
finiteFormatBuilder.append(" ");
finiteFormatBuilder.append(spacePadding);
finiteFormatBuilder.append(width);

if (zeroPadding != PrintfTreeBuilder.DEFAULT) {
if (hasZeroFlag) {
finiteFormatBuilder.append(".");
finiteFormatBuilder.append(zeroPadding);
finiteFormatBuilder.append(width);
}
} else if (zeroPadding != PrintfTreeBuilder.DEFAULT && zeroPadding != 0) {
} else if (hasZeroFlag) {
finiteFormatBuilder.append("0");
finiteFormatBuilder.append(zeroPadding);
if(width > 0){
finiteFormatBuilder.append(width);
} else {
finiteFormatBuilder.append(1);
}
} else if (!hasSpaceFlag && !hasSpaceFlag && width > 0) {
finiteFormatBuilder.append(width);
}

if (precision != PrintfTreeBuilder.DEFAULT) {
Original file line number Diff line number Diff line change
@@ -9,70 +9,94 @@
*/
package org.jruby.truffle.core.format.format;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.format.FormatNode;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
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 org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.format.FormatNode;
import org.jruby.truffle.core.format.printf.PrintfTreeBuilder;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

@NodeChildren({
@NodeChild(value = "spacePadding", type = FormatNode.class),
@NodeChild(value = "zeroPadding", type = FormatNode.class),
@NodeChild(value = "width", type = FormatNode.class),
@NodeChild(value = "value", type = FormatNode.class),
})
public abstract class FormatIntegerBinaryNode extends FormatNode {

private final char format;
private final boolean hasPlusFlag;
private final boolean useAlternativeFormat;
private final boolean isLeftJustified;
private final boolean hasSpaceFlag;
private final boolean hasZeroFlag;
private final int precision;

public FormatIntegerBinaryNode(RubyContext context, char format, boolean hasPlusFlag, boolean useAlternativeFormat) {
public FormatIntegerBinaryNode(RubyContext context, char format, int precision, boolean hasPlusFlag, boolean useAlternativeFormat,
boolean isLeftJustified, boolean hasSpaceFlag, boolean hasZeroFlag) {
super(context);
this.format = format;
this.hasPlusFlag = hasPlusFlag;
this.useAlternativeFormat = useAlternativeFormat;
this.isLeftJustified = isLeftJustified;
this.hasSpaceFlag = hasSpaceFlag;
this.precision = precision;
this.hasZeroFlag = hasZeroFlag;
}

@Specialization
public byte[] format(int spacePadding,
int zeroPadding,
int value) {
final boolean isSpacePadded = spacePadding != PrintfTreeBuilder.DEFAULT;
public byte[] format(int width, int value) {
final boolean isNegative = value < 0;
final boolean negativeAndPadded = isNegative && (isSpacePadded || this.hasPlusFlag);
final boolean negativeAndPadded = isNegative && (this.hasSpaceFlag || this.hasPlusFlag);
final String formatted = negativeAndPadded ? Integer.toBinaryString(-value) : Integer.toBinaryString(value);
return getFormattedString(formatted, spacePadding, zeroPadding, isNegative, isSpacePadded, this.hasPlusFlag,
this.useAlternativeFormat, this.format);
return getFormattedString(formatted, width, this.precision, isNegative, this.hasSpaceFlag, this.hasPlusFlag,
this.hasZeroFlag, this.useAlternativeFormat, this.isLeftJustified, this.format);
}

@TruffleBoundary
@Specialization(guards = "isRubyBignum(value)")
public byte[] format(int spacePadding, int zeroPadding, DynamicObject value) {
final boolean isSpacePadded = spacePadding != PrintfTreeBuilder.DEFAULT;
public byte[] format(int width, DynamicObject value) {
final BigInteger bigInteger = Layouts.BIGNUM.getValue(value);
final boolean isNegative = bigInteger.signum() == -1;
final boolean negativeAndPadded = isNegative && (isSpacePadded || this.hasPlusFlag);
final String formatted = negativeAndPadded ? bigInteger.abs().toString(2) : bigInteger.toString(2);
return getFormattedString(formatted, spacePadding, zeroPadding, isNegative, isSpacePadded, this.hasPlusFlag,
this.useAlternativeFormat, this.format);
final boolean negativeAndPadded = isNegative && (this.hasSpaceFlag || this.hasPlusFlag);

final String formatted;
if(negativeAndPadded) {
formatted = bigInteger.abs().toString(2);
} else if (!isNegative) {
formatted = bigInteger.toString(2);
} else {
StringBuilder builder = new StringBuilder();
final byte[] bytes = bigInteger.toByteArray();
for(byte b: bytes){
builder.append(Integer.toBinaryString(b & 0xFF));
}
formatted = builder.toString();
}
return getFormattedString(formatted, width, this.precision, isNegative, this.hasSpaceFlag, this.hasPlusFlag,
this.hasZeroFlag, this.useAlternativeFormat, this.isLeftJustified, this.format);
}

@TruffleBoundary
private static byte[] getFormattedString(String formatted, int spacePadding, int zeroPadding, boolean isNegative,
boolean isSpacePadded, boolean hasPlusFlag, boolean useAlternativeFormat,
private static byte[] getFormattedString(String formatted, int width, int precision, boolean isNegative,
boolean isSpacePadded, boolean hasPlusFlag, boolean hasZeroFlag,
boolean useAlternativeFormat, boolean isLeftJustified,
char format) {
if(width < 0 && width != PrintfTreeBuilder.DEFAULT){
width = -width;
isLeftJustified = true;
}

if (isNegative && !(isSpacePadded || hasPlusFlag)) {
if (formatted.contains("0")) {
formatted = formatted.substring(formatted.indexOf('0'), formatted.length());
if (formatted.length() + 3 < zeroPadding) {
final int addOnes = zeroPadding - (formatted.length() + 3);
if (formatted.length() + 3 < precision) {
final int addOnes = precision - (formatted.length() + 3);
for (int i = addOnes; i > 0; i--) {
formatted = "1" + formatted;
}
@@ -82,11 +106,27 @@ private static byte[] getFormattedString(String formatted, int spacePadding, int
formatted = "..1";
}
} else {
while (formatted.length() < zeroPadding) {
formatted = "0" + formatted;
if(hasZeroFlag || precision != PrintfTreeBuilder.DEFAULT) {
if(!isLeftJustified){
final int padZeros = precision != PrintfTreeBuilder.DEFAULT ? precision : width;
while (formatted.length() < padZeros) {
formatted = "0" + formatted;
}
}
}
}

while (formatted.length() < width) {
if(!isLeftJustified){
formatted = " " + formatted;
} else {
formatted = formatted + " ";
}

}



if (useAlternativeFormat) {
if(format == 'B'){
formatted = "0B" + formatted;
Original file line number Diff line number Diff line change
@@ -25,47 +25,48 @@
import java.util.Locale;

@NodeChildren({
@NodeChild(value = "spacePadding", type = FormatNode.class),
@NodeChild(value = "zeroPadding", type = FormatNode.class),
@NodeChild(value = "width", type = FormatNode.class),
@NodeChild(value = "value", type = FormatNode.class),
})
public abstract class FormatIntegerNode extends FormatNode {

private final char format;
private final boolean hasSpaceFlag;
private final boolean hasZeroFlag;
private final int precision;

public FormatIntegerNode(RubyContext context, char format) {
public FormatIntegerNode(RubyContext context, char format, boolean hasSpaceFlag, boolean hasZeroFlag, int precision) {
super(context);
this.format = format;
this.hasSpaceFlag = hasSpaceFlag;
this.hasZeroFlag = hasZeroFlag;
this.precision = precision;
}

@Specialization(
guards = {
"!isRubyBignum(value)",
"spacePadding == cachedSpacePadding",
"zeroPadding == cachedZeroPadding"
"width == cachedWidth"
},
limit = "getLimit()"
)
public byte[] formatCached(int spacePadding,
int zeroPadding,
public byte[] formatCached(int width,
Object value,
@Cached("spacePadding") int cachedSpacePadding,
@Cached("zeroPadding") int cachedZeroPadding,
@Cached("makeFormatString(spacePadding, zeroPadding)") String cachedFormatString) {
@Cached("width") int cachedWidth,
@Cached("makeFormatString(width)") String cachedFormatString) {
return doFormat(value, cachedFormatString);
}

@TruffleBoundary
@Specialization(guards = "!isRubyBignum(value)", contains = "formatCached")
public byte[] formatUncached(int spacePadding,
int zeroPadding,
public byte[] formatUncached(int width,
Object value) {
return doFormat(value, makeFormatString(spacePadding, zeroPadding));
return doFormat(value, makeFormatString(width));
}

@TruffleBoundary
@Specialization(guards = "isRubyBignum(value)")
public byte[] format(int spacePadding, int zeroPadding, DynamicObject value) {
public byte[] format(int width, DynamicObject value) {
final BigInteger bigInteger = Layouts.BIGNUM.getValue(value);

String formatted;
@@ -93,12 +94,12 @@ public byte[] format(int spacePadding, int zeroPadding, DynamicObject value) {
throw new UnsupportedOperationException();
}

while (formatted.length() < spacePadding) {
formatted = " " + formatted;
while (formatted.length() < this.precision) {
formatted = "0" + formatted;
}

while (formatted.length() < zeroPadding) {
formatted = "0" + formatted;
while (formatted.length() < width) {
formatted = " " + formatted;
}

return formatted.getBytes(StandardCharsets.US_ASCII);
@@ -109,22 +110,24 @@ protected byte[] doFormat(Object value, String formatString) {
return String.format(formatString, value).getBytes(StandardCharsets.US_ASCII);
}

protected String makeFormatString(int spacePadding, int zeroPadding) {
protected String makeFormatString(int width) {
final StringBuilder builder = new StringBuilder();

builder.append("%");

if (spacePadding != PrintfTreeBuilder.DEFAULT) {
final int padZeros = precision != PrintfTreeBuilder.DEFAULT ? precision : width;

if (this.hasSpaceFlag) {
builder.append(" ");
builder.append(spacePadding);
builder.append(width);

if (zeroPadding != PrintfTreeBuilder.DEFAULT) {
if (this.hasZeroFlag || precision != PrintfTreeBuilder.DEFAULT) {
builder.append(".");
builder.append(zeroPadding);
builder.append(padZeros);
}
} else if (zeroPadding != PrintfTreeBuilder.DEFAULT) {
} else if (this.hasZeroFlag || precision != PrintfTreeBuilder.DEFAULT) {
builder.append("0");
builder.append(zeroPadding);
builder.append(padZeros);
}

builder.append(format);
Original file line number Diff line number Diff line change
@@ -84,9 +84,10 @@ public void exitFormat(PrintfParser.FormatContext ctx) {
}

boolean leftJustified = false;
int spacePadding = DEFAULT;
int zeroPadding = DEFAULT;
boolean hasPlusFlag = false;
boolean hasSpaceFlag = false;
boolean hasStarFlag = false;
boolean hasZeroFlag = false;
boolean useAlternativeFormat = false;
int absoluteArgumentIndex = DEFAULT;

@@ -96,21 +97,11 @@ public void exitFormat(PrintfParser.FormatContext ctx) {
if (flag.MINUS() != null) {
leftJustified = true;
} else if (flag.SPACE() != null) {
if (n + 1 < ctx.flag().size() && ctx.flag(n + 1).STAR() != null) {
spacePadding = PADDING_FROM_ARGUMENT;
} else if(width != DEFAULT) {
spacePadding = width;
} else {
spacePadding = 1;
}
hasSpaceFlag = true;
} else if (flag.ZERO() != null) {
if (n + 1 < ctx.flag().size() && ctx.flag(n + 1).STAR() != null) {
zeroPadding = PADDING_FROM_ARGUMENT;
} else {
zeroPadding = width;
}
hasZeroFlag = true;
} else if (flag.STAR() != null) {
// Handled in space and zero, above
hasStarFlag = true;
} else if (flag.PLUS() != null) {
hasPlusFlag = true;
} else if (flag.HASH() != null) {
@@ -122,10 +113,6 @@ public void exitFormat(PrintfParser.FormatContext ctx) {
}
}

if (spacePadding == DEFAULT && zeroPadding == DEFAULT) {
spacePadding = width;
}

final char type = ctx.TYPE().getSymbol().getText().charAt(0);

final FormatNode valueNode;
@@ -162,10 +149,10 @@ public void exitFormat(PrintfParser.FormatContext ctx) {
conversionNode = ToStringNodeGen.create(context, true, conversionMethodName, false, EMPTY_BYTES, valueNode);
}

if (spacePadding == DEFAULT) {
if (width == DEFAULT) {
node = WriteBytesNodeGen.create(context, conversionNode);
} else {
node = WritePaddedBytesNodeGen.create(context, spacePadding, leftJustified, conversionNode);
node = WritePaddedBytesNodeGen.create(context, width, leftJustified, conversionNode);
}

break;
@@ -177,27 +164,11 @@ public void exitFormat(PrintfParser.FormatContext ctx) {
case 'u':
case 'x':
case 'X':
final FormatNode spacePaddingNode;
if (spacePadding == PADDING_FROM_ARGUMENT) {
spacePaddingNode = ReadIntegerNodeGen.create(context, new SourceNode());
} else {
spacePaddingNode = new LiteralFormatNode(context, spacePadding);
}

final FormatNode zeroPaddingNode;

/*
* Precision and zero padding both set zero padding -
* but precision has priority and explicit zero padding
* is actually ignored if it's set.
*/

if (zeroPadding == PADDING_FROM_ARGUMENT) {
zeroPaddingNode = ReadIntegerNodeGen.create(context, new SourceNode());
} else if (ctx.precision != null) {
zeroPaddingNode = new LiteralFormatNode(context, Integer.parseInt(ctx.precision.getText()));
final FormatNode widthNode;
if (hasStarFlag) {
widthNode = ReadIntegerNodeGen.create(context, new SourceNode());
} else {
zeroPaddingNode = new LiteralFormatNode(context, zeroPadding);
widthNode = new LiteralFormatNode(context, width);
}

final char format;
@@ -225,25 +196,25 @@ public void exitFormat(PrintfParser.FormatContext ctx) {

if(type == 'b' || type == 'B'){
node = WriteBytesNodeGen.create(context,
FormatIntegerBinaryNodeGen.create(context, format, hasPlusFlag, useAlternativeFormat,
spacePaddingNode,
zeroPaddingNode,
FormatIntegerBinaryNodeGen.create(context, format, precision, hasPlusFlag, useAlternativeFormat,
leftJustified,
hasSpaceFlag,
hasZeroFlag,
widthNode,
ToIntegerNodeGen.create(context, valueNode)));
} else {
node = WriteBytesNodeGen.create(context,
FormatIntegerNodeGen.create(context, format,
spacePaddingNode,
zeroPaddingNode,
FormatIntegerNodeGen.create(context, format, hasSpaceFlag, hasZeroFlag, precision,
widthNode,
ToIntegerNodeGen.create(context, valueNode)));
}
break;
case 'f':
case 'e':
case 'E':
node = WriteBytesNodeGen.create(context,
FormatFloatNodeGen.create(context, spacePadding,
zeroPadding, precision,
type,
FormatFloatNodeGen.create(context, width, precision,
type, hasSpaceFlag, hasZeroFlag,
ToDoubleWithCoercionNodeGen.create(context,
valueNode)));
break;

0 comments on commit 5194ff8

Please sign in to comment.