Skip to content

Commit

Permalink
[Truffle] Improve implementation of System#size
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Feb 17, 2015
1 parent 7b3c0cb commit fa086f5
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 13 deletions.
4 changes: 0 additions & 4 deletions spec/truffle/tags/core/symbol/size_tags.txt
@@ -1,5 +1 @@
fails:Symbol#size returns 0 for empty name
fails:Symbol#size returns 1 for name formed by a NUL character
fails:Symbol#size returns 3 for name formed by 3 ASCII characters
fails:Symbol#size returns 4 for name formed by 4 ASCII characters
fails:Symbol#size returns 4 for name formed by 1 multibyte and 3 ASCII characters
Expand Up @@ -18,6 +18,7 @@
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;

@CoreClass(name = "Symbol")
public abstract class SymbolNodes {
Expand Down Expand Up @@ -212,7 +213,7 @@ public RubyString inspect(RubySymbol symbol) {

}

@CoreMethod(names = { "size"})
@CoreMethod(names = "size")
public abstract static class SizeNode extends CoreMethodNode {

public SizeNode(RubyContext context, SourceSection sourceSection) {
Expand All @@ -225,8 +226,7 @@ public SizeNode(SizeNode prev) {

@Specialization
public int size(RubySymbol symbol) {
notDesignedForCompilation();
return symbol.toString().length();
return StringSupport.strLengthFromRubyString(symbol);
}

}
Expand Down
Expand Up @@ -10,30 +10,36 @@
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.Encoding;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.methods.SymbolProcNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.util.ByteList;
import org.jruby.util.ByteListHolder;
import org.jruby.util.CodeRangeable;
import org.jruby.util.StringSupport;

import java.util.concurrent.ConcurrentHashMap;

/**
* Represents the Ruby {@code Symbol} class.
*/
public class RubySymbol extends RubyBasicObject {
public class RubySymbol extends RubyBasicObject implements CodeRangeable {

private final String symbol;
private final ByteList symbolBytes;
private final ByteList bytes;
private int codeRange = StringSupport.CR_UNKNOWN;

private RubySymbol(RubyClass symbolClass, String symbol, ByteList byteList) {
private RubySymbol(RubyClass symbolClass, String symbol, ByteList bytes) {
super(symbolClass);
this.symbol = symbol;
this.symbolBytes = byteList;
this.bytes = bytes;
}

public static RubySymbol newSymbol(RubyContext runtime, String name) {
Expand All @@ -59,13 +65,13 @@ public RubyProc toProc(SourceSection sourceSection, final RubyNode currentNode)
}

public ByteList getSymbolBytes() {
return symbolBytes;
return bytes;
}

public org.jruby.RubySymbol getJRubySymbol() {
RubyNode.notDesignedForCompilation();

return getContext().getRuntime().newSymbol(symbolBytes);
return getContext().getRuntime().newSymbol(bytes);
}

@Override
Expand Down Expand Up @@ -95,6 +101,65 @@ public RubyString toRubyString() {
return getContext().makeString(toString());
}

@Override
public int getCodeRange() {
return codeRange;
}

@Override
@CompilerDirectives.TruffleBoundary
public int scanForCodeRange() {
int cr = getCodeRange();

if (cr == StringSupport.CR_UNKNOWN) {
cr = slowCodeRangeScan();
setCodeRange(cr);
}

return cr;
}

@Override
public boolean isCodeRangeValid() {
return codeRange == StringSupport.CR_VALID;
}

@Override
public final void setCodeRange(int codeRange) {
this.codeRange = codeRange;
}

@Override
public final void clearCodeRange() {
codeRange = StringSupport.CR_UNKNOWN;
}

@Override
public final void modify() {
throw new UnsupportedOperationException();
}

@Override
public final void modify(int length) {
throw new UnsupportedOperationException();
}

@Override
public Encoding checkEncoding(ByteListHolder other) {
// TODO (nirvdrum Jan. 13, 2015): This should check if the encodings are compatible rather than just always succeeding.
return bytes.getEncoding();
}

@Override
public ByteList getByteList() {
return bytes;
}

@CompilerDirectives.TruffleBoundary
private int slowCodeRangeScan() {
return StringSupport.codeRangeScan(bytes.getEncoding(), bytes);
}

public static final class SymbolTable {

private final ConcurrentHashMap<ByteList, RubySymbol> symbolsTable = new ConcurrentHashMap<>();
Expand Down

0 comments on commit fa086f5

Please sign in to comment.