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: 0db6d2d0c577
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d37982c821e3
Choose a head ref
  • 3 commits
  • 1 file changed
  • 1 contributor

Commits on Oct 13, 2015

  1. [Truffle] Fixed a problem with the string_byte_index returning the …

    …wrong value.
    
    The `string_byte_index` should be returning values normalized to a ByteList 'begin' value of 0. The operations that use the results of this primitive will add the 'begin' value themselves, so this primitive was effectively double-counting the 'begin' value. Of course, when the 'begin' value is 0 this doesn't matter, but in all other cases we end up with invalid values.
    nirvdrum committed Oct 13, 2015
    Copy the full SHA
    b61c707 View commit details
  2. Copy the full SHA
    818fa8c View commit details
  3. Copy the full SHA
    d37982c View commit details
Showing with 29 additions and 11 deletions.
  1. +29 −11 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java
Original file line number Diff line number Diff line change
@@ -870,13 +870,28 @@ public Object stringCharacterIndex(DynamicObject string, DynamicObject pattern,
}

@RubiniusPrimitive(name = "string_byte_index", needsSelf = false, lowerFixnumParameters = { 0, 1 })
@ImportStatic(StringGuards.class)
public static abstract class StringByteIndexPrimitiveNode extends RubiniusPrimitiveNode {

private final ConditionProfile indexTooLargeProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile invalidByteProfile = ConditionProfile.createBinaryProfile();

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

@Specialization
@Specialization(guards = "isSingleByteOptimizable(string)")
public Object stringByteIndexSingleByte(DynamicObject string, int index, int start) {
final ByteList byteList = StringOperations.getByteList(string);

if (indexTooLargeProfile.profile(byteList.realSize() < index)) {
return nil();
}

return index;
}

@Specialization(guards = "!isSingleByteOptimizable(string)")
public Object stringByteIndex(DynamicObject string, int index, int start) {
// Taken from Rubinius's String::byte_index.

@@ -897,17 +912,17 @@ public Object stringByteIndex(DynamicObject string, int index, int start) {
final int c = StringSupport.preciseLength(enc, bytes.getUnsafeBytes(), p, e);

// If it's an invalid byte, just treat it as a single byte
if(! StringSupport.MBCLEN_CHARFOUND_P(c)) {
if(invalidByteProfile.profile(! StringSupport.MBCLEN_CHARFOUND_P(c))) {
++p;
} else {
p += StringSupport.MBCLEN_CHARFOUND_LEN(c);
}
}

if (i < k) {
if (indexTooLargeProfile.profile(i < k)) {
return nil();
} else {
return p;
return p - bytes.begin();
}
}

@@ -928,16 +943,19 @@ public Object stringByteIndex(DynamicObject string, DynamicObject pattern, int o
return nil();
}

final ByteList stringByteList = StringOperations.getByteList(string);
final ByteList patternByteList = StringOperations.getByteList(pattern);

final Encoding encoding = StringOperations.checkEncoding(getContext(), string, StringOperations.getCodeRangeable(pattern), this);
int p = StringOperations.getByteList(string).getBegin();
final int e = p + StringOperations.getByteList(string).getRealSize();
int pp = StringOperations.getByteList(pattern).getBegin();
final int pe = pp + StringOperations.getByteList(pattern).getRealSize();
int p = stringByteList.getBegin();
final int e = p + stringByteList.getRealSize();
int pp = patternByteList.getBegin();
final int pe = pp + patternByteList.getRealSize();
int s;
int ss;

final byte[] stringBytes = StringOperations.getByteList(string).getUnsafeBytes();
final byte[] patternBytes = StringOperations.getByteList(pattern).getUnsafeBytes();
final byte[] stringBytes = stringByteList.getUnsafeBytes();
final byte[] patternBytes = patternByteList.getUnsafeBytes();

for(s = p, ss = pp; p < e; s = ++p) {
if (stringBytes[p] != patternBytes[pp]) continue;
@@ -954,7 +972,7 @@ public Object stringByteIndex(DynamicObject string, DynamicObject pattern, int o
final int c = StringSupport.preciseLength(encoding, stringBytes, s, e);

if (StringSupport.MBCLEN_CHARFOUND_P(c)) {
return s;
return s - stringByteList.begin();
} else {
return nil();
}