Skip to content

Commit

Permalink
Showing 42 changed files with 2,901 additions and 115 deletions.
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/util/Pack.java
Original file line number Diff line number Diff line change
@@ -78,8 +78,8 @@ public class Pack {
private static final String sTooFew = "too few arguments";
private static final byte[] uu_table;
private static final byte[] b64_table;
private static final byte[] sHexDigits;
private static final int[] b64_xtable = new int[256];
public static final byte[] sHexDigits;
public static final int[] b64_xtable = new int[256];
private static final Converter[] converters = new Converter[256];

private static long num2quad(IRubyObject arg) {
@@ -1390,7 +1390,7 @@ public static int utf8Decode(Ruby runtime, byte[]to, int p, int code) {

/** utf8_to_uv
*/
private static int utf8Decode(ByteBuffer buffer) {
private static int utf8Decode(ByteBuffer buffer) {
int c = buffer.get() & 0xFF;
int uv = c;
int n;
@@ -1451,7 +1451,7 @@ private static int utf8Decode(ByteBuffer buffer) {
0x80000000, /* 7 */
};

private static int safeGet(ByteBuffer encode) {
public static int safeGet(ByteBuffer encode) {
while (encode.hasRemaining()) {
int got = encode.get() & 0xff;

1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -240,6 +240,7 @@ public class Options {
public static final Option<Integer> TRUFFLE_SYMBOL_TO_PROC_CACHE = integer(TRUFFLE, "truffle.symbol_to_proc.cache", TRUFFLE_DEFAULT_CACHE.load(), "Symbol#to_proc cache size");
public static final Option<Integer> TRUFFLE_ALLOCATE_CLASS_CACHE = integer(TRUFFLE, "truffle.allocate_class.cache", TRUFFLE_DEFAULT_CACHE.load(), "Allocation size class cache size");
public static final Option<Integer> TRUFFLE_PACK_CACHE = integer(TRUFFLE, "truffle.pack.cache", TRUFFLE_DEFAULT_CACHE.load(), "Array#pack cache size");
public static final Option<Integer> TRUFFLE_UNPACK_CACHE = integer(TRUFFLE, "truffle.unpack.cache", TRUFFLE_DEFAULT_CACHE.load(), "String#unpack cache size");
public static final Option<Integer> TRUFFLE_EVAL_CACHE = integer(TRUFFLE, "truffle.eval.cache", TRUFFLE_DEFAULT_CACHE.load(), "eval lookup cache size");
public static final Option<Integer> ENCODING_COMPATIBLE_QUERY_CACHE = integer(TRUFFLE, "truffle.encoding_compatible_query.cache", TRUFFLE_DEFAULT_CACHE.load(), "Encoding.compatible? cache size");

2 changes: 2 additions & 0 deletions spec/truffle/tags/core/string/unpack/m_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
fails:String#unpack with format 'M' calls #to_str to coerce the directives string
fails:String#unpack with format 'm' calls #to_str to coerce the directives string
fails:String#unpack with format 'M' ignores the count or '*' modifier and decodes the entire string
fails:String#unpack with format 'm' ignores the count or '*' modifier and decodes the entire string
2 changes: 2 additions & 0 deletions spec/truffle/tags/core/string/unpack/z_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
fails:String#unpack with format 'Z' calls #to_str to coerce the directives string
fails:String#unpack with format 'Z' stops decoding at NULL bytes when passed the '*' modifier
fails:String#unpack with format 'Z' decodes the number of bytes specified by the count modifier and truncates the decoded string at the first NULL byte
115 changes: 60 additions & 55 deletions truffle/src/main/antlr4/org/jruby/truffle/format/parser/Pack.g4
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* Copyright (c) 2015, 2016 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:
*
@@ -11,64 +11,69 @@ grammar Pack;

sequence : directive* ;

directive : C count? # character
| (S NATIVE? LITTLE | 'v') count? # shortLittle
| (S NATIVE? BIG | 'n') count? # shortBig
| S NATIVE? count? # shortNative
| I (LITTLE NATIVE? | NATIVE? LITTLE) count? # intLittle
| I (BIG NATIVE? | NATIVE? BIG) count? # intBig
| I NATIVE? count? # intNative
| (L LITTLE | 'V') count? # longLittle
| (L BIG | 'N') count? # longBig
| L count? # longNative
| (Q | L NATIVE) LITTLE count? # quadLittle
| (Q | L NATIVE) BIG count? # quadBig
| (Q | L NATIVE) count? # quadNative
| 'U' count? # utf8Character
| 'w' count? # berInteger
| D count? # doubleNative
| F count? # floatNative
| 'E' count? # doubleLittle
| 'e' count? # floatLittle
| 'G' count? # doubleBig
| 'g' count? # floatBig
| 'A' count? # binaryStringSpacePadded
| 'a' count? # binaryStringNullPadded
| 'Z' count? # binaryStringNullStar
| 'B' count? # bitStringMSBFirst
| 'b' count? # bitStringMSBLast
| 'H' count? # hexStringHighFirst
| 'h' count? # hexStringLowFirst
| 'u' count? # uuString
| 'M' INT? # mimeString
| 'm' count? # base64String
| ('p' | 'P') # pointer
| '@' INT? # at
| 'X' count? # back
| 'x' count? # nullByte
| subSequence # subSequenceAlternate
| ('v' | 'n' | 'V' | 'N' | 'U' | 'w' | D |
F | 'E' | 'e' | 'g' | 'G' | 'A' | 'a' |
directive : 'c' count? # int8
| 'C' count? # uint8
| 's' nativeOptLittle count? # int16Little
| 's' nativeOptBig count? # int16Big
| 's' NATIVE? count? # int16Native
| ('S' nativeOptLittle | 'v') count? # uint16Little
| ('S' nativeOptBig | 'n') count? # uint16Big
| 'S' NATIVE? count? # uint16Native
| ('i' nativeOptLittle | 'l' LITTLE) count? # int32Little
| ('i' nativeOptBig | 'l' BIG) count? # int32Big
| ('i' NATIVE? | 'l') count? # int32Native
| (('I' nativeOptLittle | 'L' LITTLE) | 'V') count? # uint32Little
| (('I' nativeOptBig | 'L' BIG) | 'N') count? # uint32Big
| ('I' NATIVE? | 'L') count? # uint32Native
| ('q' nativeOptLittle | 'l' nativeLittle) count? # int64Little
| ('q' nativeOptBig | 'l' nativeBig) count? # int64Big
| ('q' NATIVE? | 'l' NATIVE) count? # int64Native
| ('Q' nativeOptLittle | 'L' nativeLittle) count? # uint64Little
| ('Q' nativeOptBig | 'L' nativeBig) count? # uint64Big
| ('Q' NATIVE? | 'L' NATIVE) count? # uint64Native
| 'U' count? # utf8Character
| 'w' count? # berInteger
| ('d' | 'D') count? # f64Native
| ('f' | 'F') count? # f32Native
| 'E' count? # f64Little
| 'e' count? # f32Little
| 'G' count? # f64Big
| 'g' count? # f32Big
| 'A' count? # binaryStringSpacePadded
| 'a' count? # binaryStringNullPadded
| 'Z' count? # binaryStringNullStar
| 'B' count? # bitStringMSBFirst
| 'b' count? # bitStringMSBLast
| 'H' count? # hexStringHighFirst
| 'h' count? # hexStringLowFirst
| 'u' count? # uuString
| 'M' INT? # mimeString
| 'm' count? # base64String
| ('p' | 'P') # pointer
| '@' count? # at
| 'X' count? # back
| 'x' count? # nullByte
| subSequence # subSequenceAlternate
| ('v' | 'n' | 'V' | 'N' | 'U' | 'w' | 'd' | 'D' |
'f' | 'F' | 'E' | 'e' | 'g' | 'G' | 'A' | 'a' |
'Z' | 'B' | 'b' | 'H' | 'h' | 'u' | 'M' |
'm' | 'p' | 'P' | 'X' | 'x') NATIVE #errorDisallowedNative ;
'm' | 'p' | 'P' | 'X' | 'x') NATIVE #errorDisallowedNative ;

subSequence : '(' directive+ ')' INT? ;
count : INT | '*' ;

count : INT | '*' ;
subSequence : '(' directive+ ')' INT? ;

C : [cC] ;
S : [sS] ;
I : [iI] ;
L : [lL] ;
Q : [qQ] ;
D : [dD] ;
F : [fF] ;
nativeOptLittle : NATIVE* LITTLE NATIVE* ;
nativeOptBig : NATIVE* BIG NATIVE* ;

LITTLE : '<' ;
BIG : '>' ;
NATIVE : [_!] ;
nativeLittle : NATIVE+ LITTLE NATIVE* | NATIVE* LITTLE NATIVE+ ;
nativeBig : NATIVE+ BIG NATIVE* | NATIVE* BIG NATIVE+ ;

INT : [0-9]+ ;
LITTLE : '<' ;
BIG : '>' ;
NATIVE : [!_] ;

WS : [ \t\n\u000b\f\r\u0000]+ -> skip ;
COMMENT : '#' .*? (('\r'? '\n') | EOF) -> skip ;
INT : [0-9]+ ;

WS : [ \t\n\u000b\f\r\u0000]+ -> skip ;
COMMENT : '#' .*? (('\r'? '\n') | EOF) -> skip ;
38 changes: 32 additions & 6 deletions truffle/src/main/java/org/jruby/truffle/format/nodes/PackNode.java
Original file line number Diff line number Diff line change
@@ -77,24 +77,50 @@ protected void setSourcePosition(VirtualFrame frame, int position) {
* element.
*/
protected int advanceSourcePosition(VirtualFrame frame) {
return advanceSourcePosition(frame, 1);
}

protected int advanceSourcePosition(VirtualFrame frame, int count) {
final int sourcePosition = getSourcePosition(frame);

if (sourcePosition == getSourceLength(frame)) {
if (sourcePosition + count > getSourceLength(frame)) {
CompilerDirectives.transferToInterpreter();
throw new TooFewArgumentsException();
}

setSourcePosition(frame, sourcePosition + 1);
setSourcePosition(frame, sourcePosition + count);

return sourcePosition;
}

protected int advanceSourcePositionNoThrow(VirtualFrame frame) {
return advanceSourcePositionNoThrow(frame, 1, false);
}

protected int advanceSourcePositionNoThrow(VirtualFrame frame, int count, boolean consumePartial) {
final int sourcePosition = getSourcePosition(frame);

final int sourceLength = getSourceLength(frame);

if (sourcePosition + count > sourceLength) {
if (consumePartial) {
setSourcePosition(frame, sourceLength);
}

return -1;
}

setSourcePosition(frame, sourcePosition + count);

return sourcePosition;
}

/**
* Get the output array we are writing to.
*/
protected byte[] getOutput(VirtualFrame frame) {
protected Object getOutput(VirtualFrame frame) {
try {
return (byte[]) frame.getObject(PackFrameDescriptor.OUTPUT_SLOT);
return frame.getObject(PackFrameDescriptor.OUTPUT_SLOT);
} catch (FrameSlotTypeException e) {
throw new IllegalStateException(e);
}
@@ -105,7 +131,7 @@ protected byte[] getOutput(VirtualFrame frame) {
* compiled code - having to change the output array to resize is is a
* deoptimizing action.
*/
protected void setOutput(VirtualFrame frame, byte[] output) {
protected void setOutput(VirtualFrame frame, Object output) {
CompilerAsserts.neverPartOfCompilation();
frame.setObject(PackFrameDescriptor.OUTPUT_SLOT, output);
}
@@ -181,7 +207,7 @@ protected void writeNullBytes(VirtualFrame frame, int length) {
}

private byte[] ensureCapacity(VirtualFrame frame, int length) {
byte[] output = getOutput(frame);
byte[] output = (byte[]) getOutput(frame);
final int outputPosition = getOutputPosition(frame);

if (outputPosition + length > output.length) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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.format.nodes;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.frame.FrameSlotTypeException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.format.runtime.PackEncoding;
import org.jruby.truffle.format.runtime.PackFrameDescriptor;
import org.jruby.truffle.format.runtime.PackResult;
import org.jruby.truffle.runtime.RubyLanguage;
import org.jruby.truffle.runtime.array.ArrayUtils;

public class UnpackRootNode extends RootNode {

private final String description;
private final PackEncoding encoding;

@Child private PackNode child;

@CompilationFinal private int expectedLength = ArrayUtils.capacity(0, 0);

public UnpackRootNode(String description, PackEncoding encoding, PackNode child) {
super(RubyLanguage.class, SourceSection.createUnavailable("unpack", description), PackFrameDescriptor.FRAME_DESCRIPTOR);
this.description = description;
this.encoding = encoding;
this.child = child;
}

@Override
public Object execute(VirtualFrame frame) {
frame.setObject(PackFrameDescriptor.SOURCE_SLOT, frame.getArguments()[0]);
frame.setInt(PackFrameDescriptor.SOURCE_LENGTH_SLOT, (int) frame.getArguments()[1]);
frame.setInt(PackFrameDescriptor.SOURCE_POSITION_SLOT, 0);
frame.setObject(PackFrameDescriptor.OUTPUT_SLOT, new Object[expectedLength]);
frame.setInt(PackFrameDescriptor.OUTPUT_POSITION_SLOT, 0);
frame.setBoolean(PackFrameDescriptor.TAINT_SLOT, false);

child.execute(frame);

final int outputLength;

try {
outputLength = frame.getInt(PackFrameDescriptor.OUTPUT_POSITION_SLOT);
} catch (FrameSlotTypeException e) {
throw new IllegalStateException(e);
}

if (outputLength > expectedLength) {
CompilerDirectives.transferToInterpreterAndInvalidate();
expectedLength = ArrayUtils.capacity(expectedLength, outputLength);
}

final Object[] output;

try {
output = (Object[]) frame.getObject(PackFrameDescriptor.OUTPUT_SLOT);
} catch (FrameSlotTypeException e) {
throw new IllegalStateException(e);
}

final boolean taint;

try {
taint = frame.getBoolean(PackFrameDescriptor.TAINT_SLOT);
} catch (FrameSlotTypeException e) {
throw new IllegalStateException(e);
}

return new PackResult(output, outputLength, taint, encoding);
}

@Override
public boolean isCloningAllowed() {
return true;
}

@Override
public String toString() {
return description;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2016 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.format.nodes.control;

import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.format.nodes.PackNode;
import org.jruby.truffle.format.runtime.exceptions.OutsideOfStringException;
import org.jruby.truffle.runtime.RubyContext;

public class AtUnpackNode extends PackNode {

private final int position;

public AtUnpackNode(RubyContext context, int position) {
super(context);
this.position = position;
}

@Override
public Object execute(VirtualFrame frame) {
if (position > getSourceLength(frame)) {
throw new OutsideOfStringException();
}

setSourcePosition(frame, position);

return null;
}

}
Loading

0 comments on commit af6c417

Please sign in to comment.