Skip to content

Commit

Permalink
[Truffle] Implemented Binding#dup.
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvdrum committed Feb 9, 2015
1 parent 4593de4 commit 27255ad
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 7 deletions.
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/binding/clone_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/binding/dup_tags.txt

This file was deleted.

Expand Up @@ -13,16 +13,44 @@
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.globals.GetFromThreadLocalNode;
import org.jruby.truffle.nodes.globals.WrapInThreadLocalNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;

@CoreClass(name = "Binding")
public abstract class BindingNodes {

@CoreMethod(names = "initialize_copy", visibility = Visibility.PRIVATE, required = 1)
public abstract static class InitializeCopyNode extends CoreMethodNode {

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

public InitializeCopyNode(InitializeCopyNode prev) {
super(prev);
}

@Specialization
public Object initializeCopy(RubyBinding self, RubyBinding from) {
notDesignedForCompilation();

if (self == from) {
return self;
}

self.initialize(from.getSelf(), from.getFrame());

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Feb 10, 2015

Author Contributor

@chrisseaton This isn't quite right. The problem is the duped binding should have a shared view to any existing variables, but new ones should be local to the duped binding. I think it needs a new frame descriptor, but I'm really not sure how to go about this.

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Feb 10, 2015

Contributor

Is there a failing spec or a test I can work against to fix it?

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Feb 10, 2015

Author Contributor

I believe it's the root cause of the last failing ERB.new spec:

fails:ERB.new forget local variables defined previous one

Otherwise, I've been comparing the output between MRI and Truffle with:

bin/jruby -X+T -e "x = 3; b = binding.dup; eval('y = 7', b); p b.local_variables; p binding.local_variables; x = 5; z = 9; eval('p x'); eval('p x', b); p binding.local_variables; p b.local_variables"

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Feb 10, 2015

Contributor

Fixed in 10891a0 - it turns out Binding#local_variables wasn't even implemented! You were actually calling Kernel#local_variables, which is entirely different, instead. I also fixed #local_variable_set.

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Feb 10, 2015

Author Contributor

Oops. I didn't even think to check Kernel. Thanks for clarifying and for the fix.


return self;
}

}

@CoreMethod(names = "local_variable_get", required = 1)
public abstract static class LocalVariableGetNode extends CoreMethodNode {

Expand Down
Expand Up @@ -240,7 +240,7 @@ public CoreLibrary(RubyContext context) {
// Classes defined in Object

arrayClass = defineClass("Array", new RubyArray.ArrayAllocator());
bindingClass = defineClass("Binding");
bindingClass = defineClass("Binding", new RubyBinding.BindingAllocator());
dirClass = defineClass("Dir");
encodingClass = defineClass("Encoding", new RubyEncoding.EncodingAllocator());
falseClass = defineClass("FalseClass");
Expand Down
Expand Up @@ -9,20 +9,33 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.MaterializedFrame;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.subsystems.ObjectSpaceManager;
import org.jruby.util.ByteList;

/**
* Represents the Ruby {@code Binding} class.
*/
public class RubyBinding extends RubyBasicObject {

private final Object self;
private final MaterializedFrame frame;
@CompilerDirectives.CompilationFinal private Object self;
@CompilerDirectives.CompilationFinal private MaterializedFrame frame;

public RubyBinding(RubyClass bindingClass) {
super(bindingClass);
}

public RubyBinding(RubyClass bindingClass, Object self, MaterializedFrame frame) {
super(bindingClass);

initialize(self, frame);
}

public void initialize(Object self, MaterializedFrame frame) {
assert self != null;
assert frame != null;

Expand All @@ -43,4 +56,11 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
getContext().getObjectSpaceManager().visitFrame(frame, visitor);
}

public static class BindingAllocator implements Allocator {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyBinding(rubyClass);
}
}

}

0 comments on commit 27255ad

Please sign in to comment.