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: 8aafce4cffbc^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d4a9b116d828
Choose a head ref
  • 6 commits
  • 21 files changed
  • 1 contributor

Commits on Jun 5, 2015

  1. Copy the full SHA
    8aafce4 View commit details

Commits on Jun 8, 2015

  1. Copy the full SHA
    4c8ee62 View commit details
  2. Copy the full SHA
    72e4bc8 View commit details
  3. Copy the full SHA
    73543a3 View commit details
  4. Copy the full SHA
    48ea137 View commit details
  5. Copy the full SHA
    d4a9b11 View commit details
Showing with 229 additions and 375 deletions.
  1. +2 −1 truffle/src/main/java/org/jruby/truffle/nodes/coerce/NameToJavaStringNode.java
  2. +2 −1 truffle/src/main/java/org/jruby/truffle/nodes/conversion/ToJavaStringNode.java
  3. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/BasicObjectNodes.java
  4. +9 −9 truffle/src/main/java/org/jruby/truffle/nodes/core/BindingNodes.java
  5. +4 −4 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  6. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/MatchDataNodes.java
  7. +8 −8 truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
  8. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/ProcessNodes.java
  9. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpNodes.java
  10. +28 −313 truffle/src/main/java/org/jruby/truffle/nodes/core/SymbolNodes.java
  11. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/TruffleInteropNodes.java
  12. +21 −4 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UnresolvedDispatchNode.java
  13. +2 −1 truffle/src/main/java/org/jruby/truffle/nodes/interop/InteropNode.java
  14. +2 −1 truffle/src/main/java/org/jruby/truffle/nodes/interop/RubyToIndexLabelNode.java
  15. +3 −2 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyBasicObject.java
  16. +3 −1 truffle/src/main/java/org/jruby/truffle/runtime/core/RubySymbol.java
  17. +19 −6 truffle/src/main/java/org/jruby/truffle/runtime/core/SymbolCodeRangeableWrapper.java
  18. +40 −16 truffle/src/main/java/org/jruby/truffle/runtime/core/SymbolTable.java
  19. +2 −0 truffle/src/main/ruby/core.rb
  20. +15 −0 truffle/src/main/ruby/core/pre.rb
  21. +61 −0 truffle/src/main/ruby/core/rubinius/common/symbol.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
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.core.SymbolNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
@@ -41,7 +42,7 @@ public NameToJavaStringNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = "isRubySymbol(symbol)")
public String coerceRubySymbol(RubyBasicObject symbol) {
return symbol.toString();
return SymbolNodes.getString(symbol);
}

@Specialization
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.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
@@ -33,7 +34,7 @@ public ToJavaStringNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
protected String toJavaString(RubySymbol symbol) {
return symbol.toString();
return SymbolNodes.getString(symbol);
}

@TruffleBoundary
Original file line number Diff line number Diff line change
@@ -244,11 +244,11 @@ private Object methodMissing(Object self, RubySymbol name, Object[] args, RubyPr
if (lastCallWasVCall()) {
throw new RaiseException(
getContext().getCoreLibrary().nameErrorUndefinedLocalVariableOrMethod(
name.toString(),
SymbolNodes.getString(name),
getContext().getCoreLibrary().getLogicalClass(self).getName(),
this));
} else {
throw new RaiseException(getContext().getCoreLibrary().noMethodErrorOnReceiver(name.toString(), self, this));
throw new RaiseException(getContext().getCoreLibrary().noMethodErrorOnReceiver(SymbolNodes.getString(name), self, this));
}
}

Original file line number Diff line number Diff line change
@@ -88,7 +88,7 @@ public Object localVariableGetCached(RubyBinding binding, RubySymbol symbol,
@Cached("createReadNode(cachedFrameSlot)") ReadFrameSlotNode readLocalVariableNode) {
if (cachedFrameSlot == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(symbol.toString(), binding, this));
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(SymbolNodes.getString(symbol), binding, this));
} else {
return readLocalVariableNode.executeRead(binding.getFrame());
}
@@ -98,10 +98,10 @@ public Object localVariableGetCached(RubyBinding binding, RubySymbol symbol,
@Specialization(guards = "!isLastLine(symbol)")
public Object localVariableGetUncached(RubyBinding binding, RubySymbol symbol) {
final MaterializedFrame frame = binding.getFrame();
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));

if (frameSlot == null) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(symbol.toString(), binding, this));
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(SymbolNodes.getString(symbol), binding, this));
}

return frame.getValue(frameSlot);
@@ -111,10 +111,10 @@ public Object localVariableGetUncached(RubyBinding binding, RubySymbol symbol) {
@Specialization(guards = "isLastLine(symbol)")
public Object localVariableGetLastLine(RubyBinding binding, RubySymbol symbol) {
final MaterializedFrame frame = binding.getFrame();
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));

if (frameSlot == null) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(symbol.toString(), binding, this));
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(SymbolNodes.getString(symbol), binding, this));
}

final Object value = frame.getValue(frameSlot);
@@ -130,7 +130,7 @@ protected FrameDescriptor getFrameDescriptor(RubyBinding binding) {
}

protected FrameSlot findFrameSlot(RubyBinding binding, RubySymbol symbol) {
final String symbolString = symbol.toString();
final String symbolString = SymbolNodes.getString(symbol);

MaterializedFrame frame = binding.getFrame();

@@ -187,7 +187,7 @@ public Object localVariableSetCached(RubyBinding binding, RubySymbol symbol, Obj
@Specialization(guards = "!isLastLine(symbol)")
public Object localVariableSetUncached(RubyBinding binding, RubySymbol symbol, Object value) {
final MaterializedFrame frame = binding.getFrame();
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));
frame.setObject(frameSlot, value);
return value;
}
@@ -196,7 +196,7 @@ public Object localVariableSetUncached(RubyBinding binding, RubySymbol symbol, O
@Specialization(guards = "isLastLine(symbol)")
public Object localVariableSetLastLine(RubyBinding binding, RubySymbol symbol, Object value) {
final MaterializedFrame frame = binding.getFrame();
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));
frame.setObject(frameSlot, ThreadLocalObject.wrap(getContext(), value));
return value;
}
@@ -206,7 +206,7 @@ protected FrameDescriptor getFrameDescriptor(RubyBinding binding) {
}

protected FrameSlot findFrameSlot(RubyBinding binding, RubySymbol symbol) {
final String symbolString = symbol.toString();
final String symbolString = SymbolNodes.getString(symbol);

MaterializedFrame frame = binding.getFrame();

Original file line number Diff line number Diff line change
@@ -850,7 +850,7 @@ public boolean isInstanceVariableDefined(RubyBasicObject object, RubyString name
public boolean isInstanceVariableDefined(RubyBasicObject object, RubySymbol name) {
CompilerDirectives.transferToInterpreter();

return object.isFieldDefined(RubyContext.checkInstanceVariableName(getContext(), name.toString(), this));
return object.isFieldDefined(RubyContext.checkInstanceVariableName(getContext(), SymbolNodes.getString(name), this));
}

}
@@ -871,7 +871,7 @@ public Object instanceVariableGet(RubyBasicObject object, RubyString name) {
@TruffleBoundary
@Specialization
public Object instanceVariableGet(RubyBasicObject object, RubySymbol name) {
return instanceVariableGet(object, name.toString());
return instanceVariableGet(object, SymbolNodes.getString(name));
}

private Object instanceVariableGet(RubyBasicObject object, String name) {
@@ -899,7 +899,7 @@ public Object instanceVariableSet(RubyBasicObject object, RubyString name, Objec
@TruffleBoundary
@Specialization
public Object instanceVariableSet(RubyBasicObject object, RubySymbol name, Object value) {
RubyBasicObject.setInstanceVariable(object, RubyContext.checkInstanceVariableName(getContext(), name.toString(), this), value);
RubyBasicObject.setInstanceVariable(object, RubyContext.checkInstanceVariableName(getContext(), SymbolNodes.getString(name), this), value);
return value;
}

@@ -1071,7 +1071,7 @@ public MethodNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public RubyBasicObject method(Object object, RubySymbol name) {
return method(object, name.toString());
return method(object, SymbolNodes.getString(name));
}

@Specialization
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ public Object getIndex(RubyMatchData matchData, RubySymbol index, NotProvided le
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
getContext().getCoreLibrary().indexError(String.format("undefined group name reference: %s", index.toString()), this));
getContext().getCoreLibrary().indexError(String.format("undefined group name reference: %s", SymbolNodes.getString(index)), this));
}
}

Original file line number Diff line number Diff line change
@@ -530,7 +530,7 @@ public AutoloadNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public RubyBasicObject autoload(RubyModule module, RubySymbol name, RubyString filename) {
return autoload(module, name.toString(), filename);
return autoload(module, SymbolNodes.getString(name), filename);
}

@Specialization
@@ -564,7 +564,7 @@ public AutoloadQueryNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public Object autoloadQuery(RubyModule module, RubySymbol name) {
return autoloadQuery(module, name.toString());
return autoloadQuery(module, SymbolNodes.getString(name));
}

@Specialization
@@ -713,7 +713,7 @@ public boolean isClassVariableDefined(RubyModule module, RubyString name) {
public boolean isClassVariableDefined(RubyModule module, RubySymbol name) {
CompilerDirectives.transferToInterpreter();

return module.getClassVariables().containsKey(name.toString());
return module.getClassVariables().containsKey(SymbolNodes.getString(name));
}

}
@@ -881,12 +881,12 @@ public Object getConstant(VirtualFrame frame, RubyModule module, RubySymbol name

@Specialization(guards = "inherit")
public Object getConstant(VirtualFrame frame, RubyModule module, RubySymbol name, boolean inherit) {
return getConstantNode.executeGetConstant(frame, module, name.toString());
return getConstantNode.executeGetConstant(frame, module, SymbolNodes.getString(name));
}

@Specialization(guards = "!inherit")
public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, RubySymbol name, boolean inherit) {
return getConstantNoInherit(module, name.toString(), this);
return getConstantNoInherit(module, SymbolNodes.getString(name), this);
}

// String
@@ -1645,7 +1645,7 @@ public RubyModule privateConstant(RubyModule module, Object[] args) {

for (Object name : args) {
if (RubyGuards.isRubySymbol(name)) {
module.changeConstantVisibility(this, name.toString(), true);
module.changeConstantVisibility(this, SymbolNodes.getString((RubyBasicObject) name), true);
} else {
throw new UnsupportedOperationException();
}
@@ -1667,7 +1667,7 @@ public RubyModule publicConstant(RubyModule module, Object[] args) {

for (Object name : args) {
if (RubyGuards.isRubySymbol(name)) {
module.changeConstantVisibility(this, name.toString(), false);
module.changeConstantVisibility(this, SymbolNodes.getString((RubyBasicObject) name), false);
} else {
throw new UnsupportedOperationException();
}
@@ -1712,7 +1712,7 @@ public RubyModule removeClassVariable(RubyModule module, RubyString name) {
public RubyModule removeClassVariable(RubyModule module, RubySymbol name) {
CompilerDirectives.transferToInterpreter();

module.removeClassVariable(this, name.toString());
module.removeClassVariable(this, SymbolNodes.getString(name));
return module;
}

Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ Object timeToUnit(long time, RubySymbol unit) {
} else if (unit == floatSecondSymbol) {
return time / 1e9;
} else {
throw new UnsupportedOperationException(unit.toString());
throw new UnsupportedOperationException(SymbolNodes.getString(unit));
}
}

@@ -92,7 +92,7 @@ public int kill(RubySymbol signalName, int pid) {
int self = posix().getpid();

if (self == pid) {
Signal signal = new Signal(signalName.toString());
Signal signal = new Signal(SymbolNodes.getString(signalName));

SignalOperations.raise(signal);
return 1;
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ public RubyBasicObject quote(RubyBasicObject raw) {

@Specialization
public RubyBasicObject quote(RubySymbol raw) {
return quote(StringNodes.createString(raw.getContext().getCoreLibrary().getStringClass(), raw.toString()));
return quote(StringNodes.createString(raw.getContext().getCoreLibrary().getStringClass(), SymbolNodes.getString(raw)));
}

}
341 changes: 28 additions & 313 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/SymbolNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -167,7 +167,7 @@ public Object executeForeign(VirtualFrame frame, TruffleObject receiver, long id
public Object executeForeign(VirtualFrame frame, TruffleObject receiver, RubySymbol identifier) {
if (this.identifier == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
this.identifier = identifier.toString().intern();
this.identifier = SymbolNodes.getString(identifier).intern();
}
return node.executeForeign(frame, receiver, this.identifier);
}
@@ -210,7 +210,7 @@ public Object executeForeign(VirtualFrame frame, TruffleObject receiver, long id
public Object executeForeign(VirtualFrame frame, TruffleObject receiver, RubySymbol identifier, Object value) {
if (this.identifier == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
this.identifier = identifier.toString().intern();
this.identifier = SymbolNodes.getString(identifier).intern();
}
return node.executeForeign(frame, receiver, this.identifier, value);
}
Original file line number Diff line number Diff line change
@@ -19,12 +19,15 @@
import com.oracle.truffle.interop.messages.Receiver;
import com.oracle.truffle.interop.node.ForeignObjectAccessNode;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.nodes.objects.SingletonClassNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
import org.jruby.truffle.runtime.methods.InternalMethod;

import java.util.concurrent.Callable;
@@ -125,7 +128,9 @@ private DispatchNode doUnboxedObject(
callerClass = getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));
}

final InternalMethod method = lookup(callerClass, receiverObject, methodName.toString(), ignoreVisibility);
final String methodNameString = toString(methodName);

final InternalMethod method = lookup(callerClass, receiverObject, methodNameString, ignoreVisibility);

if (method == null) {
return createMethodMissingNode(first, methodName, receiverObject);
@@ -136,14 +141,14 @@ private DispatchNode doUnboxedObject(
getContext().getCoreLibrary().getFalseClass().getUnmodifiedAssumption();

final InternalMethod falseMethod =
lookup(callerClass, false, methodName.toString(),
lookup(callerClass, false, methodNameString,
ignoreVisibility);

final Assumption trueUnmodifiedAssumption =
getContext().getCoreLibrary().getTrueClass().getUnmodifiedAssumption();

final InternalMethod trueMethod =
lookup(callerClass, true, methodName.toString(),
lookup(callerClass, true, methodNameString,
ignoreVisibility);

if ((falseMethod == null) && (trueMethod == null)) {
@@ -169,7 +174,7 @@ private DispatchNode doRubyBasicObject(
Object argumentsObjects) {
final RubyClass callerClass = ignoreVisibility ? null : getContext().getCoreLibrary().getMetaClass(RubyArguments.getSelf(frame.getArguments()));

final InternalMethod method = lookup(callerClass, receiverObject, methodName.toString(), ignoreVisibility);
final InternalMethod method = lookup(callerClass, receiverObject, toString(methodName), ignoreVisibility);

if (method == null) {
final DispatchNode multilanguage = tryMultilanguage(frame, first, methodName, argumentsObjects);
@@ -188,6 +193,18 @@ private DispatchNode doRubyBasicObject(
}
}

private String toString(Object methodName) {
if (methodName instanceof String) {
return (String) methodName;
} else if (RubyGuards.isRubyString(methodName)) {
return methodName.toString();
} else if (RubyGuards.isRubySymbol(methodName)) {
return SymbolNodes.getString((RubySymbol) methodName);
} else {
throw new UnsupportedOperationException();
}
}

private DispatchNode tryMultilanguage(VirtualFrame frame, DispatchNode first, Object methodName, Object argumentsObjects) {
if (getContext().getMultilanguageObject() != null) {
CompilerAsserts.neverPartOfCompilation();
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.nodes.dispatch.DispatchAction;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.MissingBehavior;
@@ -540,7 +541,7 @@ private static class ResolvedInteropWriteToSymbolNode extends InteropNode {
public ResolvedInteropWriteToSymbolNode(RubyContext context, SourceSection sourceSection, RubySymbol name, int labelIndex, int valueIndex) {
super(context, sourceSection);
this.name = name;
this.accessName = context.getSymbol(name.toString() + "=");
this.accessName = context.getSymbol(SymbolNodes.getString(name) + "=");
this.head = new DispatchHeadNode(context, true, false, MissingBehavior.CALL_METHOD_MISSING, DispatchAction.CALL_METHOD);
this.labelIndex = labelIndex;
this.valueIndex = valueIndex;
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;
@@ -45,6 +46,6 @@ private String toString(RubyString index) {

@TruffleBoundary
private String toString(RubySymbol index) {
return index.toString();
return SymbolNodes.getString(index);
}
}
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import org.jruby.runtime.Helpers;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.ModuleOperations;
@@ -202,12 +203,12 @@ public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node c

@Override
public String toString() {
CompilerAsserts.neverPartOfCompilation("should never use RubyBasicObject#toString to implement Ruby functionality");
CompilerAsserts.neverPartOfCompilation("RubyBasicObject#toString should only be used for debugging");

if (this instanceof RubyString) {
return Helpers.decodeByteList(getContext().getRuntime(), StringNodes.getByteList(((RubyString) this)));
} else if (RubyGuards.isRubySymbol(this)) {
return ((RubySymbol) this).symbol;
return SymbolNodes.getString((RubySymbol) this);
} else {
return String.format("RubyBasicObject@%x<logicalClass=%s>", System.identityHashCode(this), logicalClass.getName());
}
Original file line number Diff line number Diff line change
@@ -16,13 +16,15 @@ public class RubySymbol extends RubyBasicObject {

public final String symbol;
public final ByteList bytes;
public final int hashCode;
public int codeRange = StringSupport.CR_UNKNOWN;
public SymbolCodeRangeableWrapper codeRangeableWrapper;

public RubySymbol(RubyClass symbolClass, String symbol, ByteList bytes) {
public RubySymbol(RubyClass symbolClass, String symbol, ByteList bytes, int hashCode) {
super(symbolClass);
this.symbol = symbol;
this.bytes = bytes;
this.hashCode = hashCode;
}

}
Original file line number Diff line number Diff line change
@@ -9,10 +9,12 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives;
import org.jcodings.Encoding;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.util.ByteList;
import org.jruby.util.CodeRangeable;
import org.jruby.util.StringSupport;

public class SymbolCodeRangeableWrapper implements CodeRangeable {

@@ -24,22 +26,30 @@ public SymbolCodeRangeableWrapper(RubySymbol symbol) {

@Override
public String toString() {
return symbol.toString();
return SymbolNodes.getString(symbol);
}

@Override
public int getCodeRange() {
return SymbolNodes.getCodeRange(symbol);
}

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

if (cr == StringSupport.CR_UNKNOWN) {
cr = StringSupport.codeRangeScan(SymbolNodes.getByteList(symbol).getEncoding(), symbol.bytes);
SymbolNodes.setCodeRange(symbol, cr);
}

return cr;
}

@Override
public boolean isCodeRangeValid() {
return SymbolNodes.isCodeRangeValid(symbol);
return SymbolNodes.getCodeRange(symbol) == StringSupport.CR_VALID;
}

@Override
@@ -49,12 +59,14 @@ public void setCodeRange(int codeRange) {

@Override
public void clearCodeRange() {
SymbolNodes.clearCodeRange(symbol);
SymbolNodes.setCodeRange(symbol, StringSupport.CR_UNKNOWN);
}

@Override
public void keepCodeRange() {
SymbolNodes.keepCodeRange(symbol);
if (SymbolNodes.getCodeRange(symbol) == StringSupport.CR_BROKEN) {
SymbolNodes.setCodeRange(symbol, StringSupport.CR_UNKNOWN);
}
}

@Override
@@ -74,7 +86,8 @@ public void modifyAndKeepCodeRange() {

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

@Override
Original file line number Diff line number Diff line change
@@ -15,13 +15,15 @@

import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class SymbolTable {

private final RubyContext context;

private final Map<ByteList, WeakReference<RubyBasicObject>> symbolsTable
= Collections.synchronizedMap(new WeakHashMap<ByteList, WeakReference<RubyBasicObject>>());
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final WeakHashMap<ByteList, WeakReference<RubyBasicObject>> symbolsTable = new WeakHashMap<>();

public SymbolTable(RubyContext context) {
this.context = context;
@@ -34,33 +36,55 @@ public RubyBasicObject getSymbol(String string) {

@CompilerDirectives.TruffleBoundary
public RubyBasicObject getSymbol(ByteList bytes) {
final WeakReference<RubyBasicObject> symbolReference = symbolsTable.get(bytes);
lock.readLock().lock();

if (symbolReference != null) {
final RubyBasicObject symbol = symbolReference.get();
try {
final WeakReference<RubyBasicObject> symbolReference = symbolsTable.get(bytes);

if (symbol != null) {
return symbol;
if (symbolReference != null) {
final RubyBasicObject symbol = symbolReference.get();

if (symbol != null) {
return symbol;
}
}
} finally {
lock.readLock().unlock();
}

final ByteList storedBytes = bytes.dup();
lock.writeLock().lock();

final RubyBasicObject newSymbol = new RubySymbol(context.getCoreLibrary().getSymbolClass(), bytes.toString(), storedBytes);
try {
final WeakReference<RubyBasicObject> symbolReference = symbolsTable.get(bytes);

final WeakReference<RubyBasicObject> interleavedSymbolReference
= symbolsTable.putIfAbsent(storedBytes, new WeakReference<>(newSymbol));
if (symbolReference != null) {
final RubyBasicObject symbol = symbolReference.get();

if (interleavedSymbolReference != null) {
return interleavedSymbolReference.get();
}
if (symbol != null) {
return symbol;
}
}

return newSymbol;
final ByteList storedBytes = bytes.dup();
final RubyBasicObject newSymbol = new RubySymbol(context.getCoreLibrary().getSymbolClass(), bytes.toString(), storedBytes, bytes.toString().hashCode());
symbolsTable.put(storedBytes, new WeakReference<>(newSymbol));
return newSymbol;
} finally {
lock.writeLock().unlock();
}
}

@CompilerDirectives.TruffleBoundary
public Collection<RubyBasicObject> allSymbols() {
final Collection<WeakReference<RubyBasicObject>> symbolReferences = symbolsTable.values();
final Collection<WeakReference<RubyBasicObject>> symbolReferences;

lock.readLock().lock();

try {
symbolReferences = symbolsTable.values();
} finally {
lock.readLock().unlock();
}

final Collection<RubyBasicObject> symbols = new ArrayList<>(symbolReferences.size());

2 changes: 2 additions & 0 deletions truffle/src/main/ruby/core.rb
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require_relative 'core/pre'

# Load Rubinius API

require_relative 'core/rubinius/api/compat/type'
15 changes: 15 additions & 0 deletions truffle/src/main/ruby/core/pre.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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

class Symbol

def to_sym
self
end

end
61 changes: 61 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/symbol.rb
Original file line number Diff line number Diff line change
@@ -72,4 +72,65 @@ def [](index, other = undefined)

alias_method :slice, :[]

def <=>(other)
return unless other.kind_of? Symbol

to_s <=> other.to_s
end

def capitalize
to_s.capitalize.to_sym
end

def casecmp(other)
return unless other.kind_of? Symbol

to_s.casecmp(other.to_s)
end

def downcase
to_s.downcase.to_sym
end

def empty?
to_s.empty?
end

alias_method :intern, :to_sym
alias_method :id2name, :to_s

def length
to_s.length
end

alias_method :size, :length

def swapcase
to_s.swapcase.to_sym
end

def upcase
to_s.upcase.to_sym
end

##
# Returns a pretty version of the symbol, fit for viewing
# :symbol.inspect #=> ":symbol"
def inspect
str = to_s

case str
when /\A(\$|@@?)[a-z_][a-z_\d]*\z/i, # Variable names
/\A[a-z_][a-z_\d]*[=?!]?\z/i, # Method names
/\A\$(-[a-z_\d]|[+~:?<_\/'"$.,`!;\\=*>&@]|\d+)\z/i, # Special global variables
/\A([|^&\/%~`!]|!=|!~|<<|>>|<=>|===?|=~|[<>]=?|[+-]@?|\*\*?|\[\]=?)\z/ # Operators
":#{str}"
else
":#{str.inspect}"
end
end

# Use equal? for ===
alias_method :===, :equal?

end