Skip to content

Commit

Permalink
[Truffle] fix cloning of tainted frozen objects
Browse files Browse the repository at this point in the history
  • Loading branch information
pitr-ch committed Dec 17, 2016
1 parent 415acd5 commit 5fba0ce
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
6 changes: 6 additions & 0 deletions spec/ruby/core/kernel/clone_spec.rb
Expand Up @@ -93,4 +93,10 @@ def bar

cloned.bar.should == ['a']
end

it 'copies frozen? and tainted?' do
o = ''.taint.freeze.clone
o.frozen?.should be_true
o.tainted?.should be_true
end
end
Expand Up @@ -488,13 +488,15 @@ private void copyInstanceVariables(DynamicObject from, DynamicObject to) {

}

@CoreMethod(names = "clone", taintFrom = 0)
@CoreMethod(names = "clone")
public abstract static class CloneNode extends CoreMethodArrayArgumentsNode {

@Child private CopyNode copyNode;
@Child private CallDispatchHeadNode initializeCloneNode;
@Child private IsFrozenNode isFrozenNode;
@Child private FreezeNode freezeNode;
@Child private IsTaintedNode isTaintedNode;
@Child private TaintNode taintNode;
@Child private SingletonClassNode singletonClassNode;

public CloneNode(RubyContext context, SourceSection sourceSection) {
Expand All @@ -503,14 +505,15 @@ public CloneNode(RubyContext context, SourceSection sourceSection) {
// Calls private initialize_clone on the new copy.
initializeCloneNode = DispatchHeadNodeFactory.createMethodCallOnSelf(context);
isFrozenNode = IsFrozenNodeGen.create(context, sourceSection, null);
freezeNode = FreezeNodeGen.create(context, sourceSection, null);
isTaintedNode = IsTaintedNodeGen.create(null, null, null);
singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
}

@Specialization
public DynamicObject clone(VirtualFrame frame, DynamicObject self,
@Cached("createBinaryProfile()") ConditionProfile isSingletonProfile,
@Cached("createBinaryProfile()") ConditionProfile isFrozenProfile,
@Cached("createBinaryProfile()") ConditionProfile taintProfile,
@Cached("createBinaryProfile()") ConditionProfile isRubyClass) {
final DynamicObject newObject = copyNode.executeCopy(frame, self);

Expand All @@ -523,7 +526,21 @@ public DynamicObject clone(VirtualFrame frame, DynamicObject self,

initializeCloneNode.call(frame, newObject, "initialize_clone", self);

if (taintProfile.profile(isTaintedNode.executeIsTainted(self))) {
if (taintNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
taintNode = insert(TaintNodeGen.create(null, null, null));
}

taintNode.executeTaint(newObject);
}

if (isFrozenProfile.profile(isFrozenNode.executeIsFrozen(self))) {
if (freezeNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
freezeNode = insert(FreezeNodeGen.create(null, null, null));
}

freezeNode.executeFreeze(newObject);
}

Expand Down

0 comments on commit 5fba0ce

Please sign in to comment.