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: 813a0cd3cbd0
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dffe5aa180b8
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Oct 6, 2015

  1. Copy the full SHA
    bbfadac View commit details
  2. 7
    Copy the full SHA
    dffe5aa View commit details
Original file line number Diff line number Diff line change
@@ -1113,16 +1113,15 @@ public Object merge(VirtualFrame frame, DynamicObject hash, Object other, Object

}

@CoreMethod(names = "default=", required = 1)
@CoreMethod(names = "default=", required = 1, raiseIfFrozenSelf = true)
public abstract static class SetDefaultNode extends CoreMethodArrayArgumentsNode {

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

@Specialization
public Object setDefault(VirtualFrame frame, DynamicObject hash, Object defaultValue) {
ruby(frame, "Rubinius.check_frozen");
public Object setDefault(DynamicObject hash, Object defaultValue) {
Layouts.HASH.setDefaultValue(hash, defaultValue);
Layouts.HASH.setDefaultBlock(hash, null);
return defaultValue;
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@
import org.jruby.truffle.nodes.core.BasicObjectNodesFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.objects.IsFrozenNode;
import org.jruby.truffle.nodes.objects.IsFrozenNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.*;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -48,6 +50,12 @@ public abstract class SetNode extends RubyNode {
private final BranchProfile extendProfile = BranchProfile.create();
private final ConditionProfile strategyProfile = ConditionProfile.createBinaryProfile();

@Child private IsFrozenNode isFrozenNode;
@Child private CallDispatchHeadNode dupNode;
@Child private CallDispatchHeadNode freezeNode;

private final ConditionProfile frozenProfile = ConditionProfile.createBinaryProfile();

public SetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = new HashNode(context, sourceSection);
@@ -72,12 +80,12 @@ public Object setNull(VirtualFrame frame, DynamicObject hash, Object key, Object

@Specialization(guards = {"isNullHash(hash)", "byIdentity", "isRubyString(key)"})
public Object setNullByIdentity(VirtualFrame frame, DynamicObject hash, DynamicObject key, Object value, boolean byIdentity) {
return setNull(frame, hash, (Object) key, value, byIdentity);
return setNull(frame, hash, key, value, byIdentity);
}

@Specialization(guards = {"isNullHash(hash)", "!byIdentity", "isRubyString(key)"})
public Object setNullNotByIdentity(VirtualFrame frame, DynamicObject hash, DynamicObject key, Object value, boolean byIdentity) {
return setNull(frame, hash, ruby(frame, "key.frozen? ? key : key.dup.freeze", "key", key), value, byIdentity);
return setNull(frame, hash, freezeAndDupIfNeeded(frame, key), value, byIdentity);
}

@ExplodeLoop
@@ -133,7 +141,7 @@ public Object setPackedArrayByIdentity(VirtualFrame frame, DynamicObject hash, D

@Specialization(guards = {"isPackedHash(hash)", "!byIdentity", "isRubyString(key)"})
public Object setPackedArrayNotByIdentity(VirtualFrame frame, DynamicObject hash, DynamicObject key, Object value, boolean byIdentity) {
return setPackedArray(frame, hash, ruby(frame, "key.frozen? ? key : key.dup.freeze", "key", key), value, byIdentity);
return setPackedArray(frame, hash, freezeAndDupIfNeeded(frame, key), value, byIdentity);
}

// Can't be @Cached yet as we call from the RubyString specialisation
@@ -197,12 +205,36 @@ public Object setBuckets(VirtualFrame frame, DynamicObject hash, Object key, Obj

@Specialization(guards = {"isBucketHash(hash)", "byIdentity", "isRubyString(key)"})
public Object setBucketsByIdentity(VirtualFrame frame, DynamicObject hash, DynamicObject key, Object value, boolean byIdentity) {
return setBuckets(frame, hash, (Object) key, value, byIdentity);
return setBuckets(frame, hash, key, value, byIdentity);
}

@Specialization(guards = {"isBucketHash(hash)", "!byIdentity", "isRubyString(key)"})
public Object setBucketsNotByIdentity(VirtualFrame frame, DynamicObject hash, DynamicObject key, Object value, boolean byIdentity) {
return setBuckets(frame, hash, ruby(frame, "key.frozen? ? key : key.dup.freeze", "key", key), value, byIdentity);
return setBuckets(frame, hash, freezeAndDupIfNeeded(frame, key), value, byIdentity);
}

private DynamicObject freezeAndDupIfNeeded(VirtualFrame frame, DynamicObject key) {
if (isFrozenNode == null) {
CompilerDirectives.transferToInterpreter();
isFrozenNode = insert(IsFrozenNodeGen.create(getContext(), getSourceSection(), null));
}

if (frozenProfile.profile(isFrozenNode.executeIsFrozen(key))) {
if (dupNode == null) {
CompilerDirectives.transferToInterpreter();
dupNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

if (freezeNode == null) {
CompilerDirectives.transferToInterpreter();
freezeNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object dupped = dupNode.call(frame, key, "dup", null);
return (DynamicObject) freezeNode.call(frame, dupped, "freeze", null);
} else {
return key;
}
}

}