Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into truffle-head
Browse files Browse the repository at this point in the history
Conflicts:
* truffle/src/main/java/org/jruby/truffle/runtime/RubyCallStack.java
  (imports)
Modified:
* truffle/src/main/java/org/jruby/truffle/nodes/LazyRubyRootNode.java
  (now a toplevel scope like $ ruby -e)
* truffle/src/main/java/org/jruby/truffle/nodes/instrument/RubyDefaultASTProber.java
  (no more SetMethodDeclarationContext)
  • Loading branch information
eregon committed Oct 2, 2015
2 parents a304bb1 + 5c29cbf commit cdabcb4
Showing 33 changed files with 179 additions and 293 deletions.
14 changes: 14 additions & 0 deletions spec/ruby/core/module/shared/set_visibility.rb
Original file line number Diff line number Diff line change
@@ -119,5 +119,19 @@ def test1() end

mod.should send(:"have_#{@method}_instance_method", :test1, false)
end

describe "within a closure" do
it "sets the visibility outside the closure" do
visibility = @method
mod = Module.new {
1.times {
send visibility
}
def test1() end
}

mod.should send(:"have_#{@method}_instance_method", :test1, false)
end
end
end
end
37 changes: 37 additions & 0 deletions spec/ruby/language/def_spec.rb
Original file line number Diff line number Diff line change
@@ -475,6 +475,43 @@ def a_singleton_method;self;end
lambda { other.a_singleton_method }.should raise_error(NoMethodError)
end

it "creates a method in the surrounding context when evaluated in a def expr.method" do
class DefSpecNested
TARGET = Object.new
def TARGET.defs_method
def inherited_method;self;end
end
end

DefSpecNested::TARGET.defs_method
DefSpecNested.should have_instance_method :inherited_method
DefSpecNested::TARGET.should_not have_method :inherited_method

obj = DefSpecNested.new
obj.inherited_method.should == obj
end

# See http://yugui.jp/articles/846#label-3
it "inside an instance_eval creates a singleton method" do
class DefSpecNested
OBJ = Object.new
OBJ.instance_eval do
def create_method_in_instance_eval(a = (def arg_method; end))
def body_method; end
end
end
end

obj = DefSpecNested::OBJ
obj.create_method_in_instance_eval

obj.should have_method :arg_method
obj.should have_method :body_method

DefSpecNested.should_not have_instance_method :arg_method
DefSpecNested.should_not have_instance_method :body_method
end

it "defines methods as public by default" do
cls = Class.new do
def do_def
4 changes: 3 additions & 1 deletion spec/ruby/language/fixtures/private.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,9 @@ def foo
end

private

def self.public_defs_method; 0; end

class C
def baz
"baz"
@@ -27,7 +30,6 @@ def public_class_method1; 1; end
private
def private_class_method1; 1; end
end
def self.public_class_method2; 2; end

def bar
"bar"
6 changes: 5 additions & 1 deletion spec/ruby/language/private_spec.rb
Original file line number Diff line number Diff line change
@@ -12,12 +12,16 @@
lambda { b.bar }.should raise_error(NoMethodError)
end

# def expr.meth() methods are always public
it "has no effect on def expr.meth() methods" do
Private::B.public_defs_method.should == 0
end

it "is overridden when a new class is opened" do
c = Private::B::C.new
c.methods.should include(:baz)
c.baz
Private::B.public_class_method1.should == 1
Private::B.public_class_method2.should == 2
lambda { Private::B.private_class_method1 }.should raise_error(NoMethodError)
end

1 change: 1 addition & 0 deletions spec/tags/ruby/core/module/private_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fails:Module#private without arguments does not affect method definitions when itself is inside an eval and method definitions are outside
fails:Module#private without arguments within a closure sets the visibility outside the closure
1 change: 1 addition & 0 deletions spec/tags/ruby/core/module/protected_tags.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
fails:Module#protected without arguments does not affect method definitions when itself is inside an eval and method definitions are outside
fails:Module#protected without arguments within a closure sets the visibility outside the closure
1 change: 1 addition & 0 deletions spec/tags/ruby/language/def_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
fails:An instance method with a default argument does not call a method with the same name as the local
fails:An instance method with a default argument shadows an existing method with the same name as the local
fails:A nested method definition creates a method in the surrounding context when evaluated in a def expr.method
1 change: 0 additions & 1 deletion spec/truffle/tags/core/kernel/public_method_tags.txt
Original file line number Diff line number Diff line change
@@ -2,4 +2,3 @@ fails:Kernel#public_method returns a method object for a valid method
fails:Kernel#public_method returns a method object for a valid singleton method
fails:Kernel#public_method returns a method object if we repond_to_missing? method
fails:Kernel#public_method changes the method called for super on a target aliased method
fails:Kernel#public_method raises a NameError if we only repond_to_missing? method, true
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/module/private_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/module/protected_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/module/public_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
fails:Module#public on a superclass method calls the redefined method
fails:Module#public without arguments affects evaled method definitions when itself is outside the eval
fails:Module#public without arguments affects normally if itself and following method definitions are inside a eval
1 change: 1 addition & 0 deletions spec/truffle/tags/language/def_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
fails:An instance method with a default argument does not call a method with the same name as the local
fails:An instance method with a default argument shadows an existing method with the same name as the local
fails:A nested method definition inside an instance_eval creates a singleton method
Original file line number Diff line number Diff line change
@@ -15,11 +15,9 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.methods.DeclarationContext;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.RubyLanguage;
import org.jruby.truffle.translator.NodeWrapper;
import org.jruby.truffle.translator.TranslatorDriver;

public class LazyRubyRootNode extends RootNode {
@@ -58,14 +56,7 @@ public Object execute(VirtualFrame virtualFrame) {

final TranslatorDriver translator = new TranslatorDriver(context);

final RubyRootNode rootNode = translator.parse(context, source, UTF8Encoding.INSTANCE, TranslatorDriver.ParserContext.EVAL, null, true, null, new NodeWrapper() {

@Override
public RubyNode wrap(RubyNode node) {
return new SetMethodDeclarationContext(node.getContext(), node.getSourceSection(), Visibility.PRIVATE, "TruffleLanguage#parse (lazy)", node);
}

});
final RubyRootNode rootNode = translator.parse(context, source, UTF8Encoding.INSTANCE, TranslatorDriver.ParserContext.TOP_LEVEL, null, true, null);

final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);

Original file line number Diff line number Diff line change
@@ -44,6 +44,10 @@ public RubyRootNode(RubyContext context, SourceSection sourceSection, FrameDescr
this.needsDeclarationFrame = needsDeclarationFrame;
}

public RubyRootNode withBody(RubyNode body) {
return new RubyRootNode(context, getSourceSection(), getFrameDescriptor(), sharedMethodInfo, body, needsDeclarationFrame);
}

@Override
public boolean isCloningAllowed() {
return true;
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ public void addCoreMethodNodes(List<? extends NodeFactory<? extends RubyNode>> n
}

private DynamicObject getSingletonClass(Object object) {
return singletonClassNode.executeSingletonClass(null, object);
return singletonClassNode.executeSingletonClass(object);
}

private void addCoreMethod(MethodDetails methodDetails) {
Original file line number Diff line number Diff line change
@@ -76,7 +76,6 @@
import org.jruby.truffle.runtime.loader.FeatureLoader;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingAction;
import org.jruby.truffle.translator.NodeWrapper;
import org.jruby.truffle.translator.TranslatorDriver;
import org.jruby.truffle.translator.TranslatorDriver.ParserContext;
import org.jruby.util.ByteList;
@@ -454,7 +453,7 @@ public DynamicObject clone(VirtualFrame frame, DynamicObject self) {

// Copy the singleton class if any.
if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(self))) {
Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(frame, newObject)).initCopy(Layouts.BASIC_OBJECT.getMetaClass(self));
Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(newObject)).initCopy(Layouts.BASIC_OBJECT.getMetaClass(self));
}

initializeCloneNode.call(frame, newObject, "initialize_clone", null, self);
@@ -676,12 +675,7 @@ protected RootNodeWrapper compileSource(VirtualFrame frame, DynamicObject source

final TranslatorDriver translator = new TranslatorDriver(getContext());

return new RootNodeWrapper(translator.parse(getContext(), source, UTF8Encoding.INSTANCE, ParserContext.EVAL, parentFrame, true, this, new NodeWrapper() {
@Override
public RubyNode wrap(RubyNode node) {
return node; // return new SetMethodDeclarationContext(node.getContext(), node.getSourceSection(), Visibility.PRIVATE, "simple eval", node);
}
}));
return new RootNodeWrapper(translator.parse(getContext(), source, UTF8Encoding.INSTANCE, ParserContext.EVAL, parentFrame, true, this));
}

protected boolean parseDependsOnDeclarationFrame(RootNodeWrapper rootNode) {
@@ -1770,8 +1764,8 @@ public SingletonClassMethodNode(RubyContext context, SourceSection sourceSection
}

@Specialization
public DynamicObject singletonClass(VirtualFrame frame, Object self) {
return singletonClassNode.executeSingletonClass(frame, self);
public DynamicObject singletonClass(Object self) {
return singletonClassNode.executeSingletonClass(self);
}

}
Original file line number Diff line number Diff line change
@@ -47,7 +47,6 @@
import org.jruby.truffle.nodes.methods.CanBindMethodToModuleNode;
import org.jruby.truffle.nodes.methods.CanBindMethodToModuleNodeGen;
import org.jruby.truffle.nodes.methods.DeclarationContext;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.nodes.objects.*;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.*;
@@ -60,8 +59,6 @@
import org.jruby.truffle.runtime.methods.Arity;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.truffle.translator.NodeWrapper;
import org.jruby.truffle.translator.TranslatorDriver;
import org.jruby.truffle.translator.TranslatorDriver.ParserContext;
import org.jruby.util.IdUtil;
import org.jruby.util.StringSupport;
@@ -74,12 +71,6 @@
@CoreClass(name = "Module")
public abstract class ModuleNodes {

/**
* The slot within a module definition method frame where we store the implicit state that is
* the current visibility for new methods.
*/
public static final Object VISIBILITY_FRAME_SLOT_ID = new Object();

public static DynamicObject createRubyModule(RubyContext context, DynamicObject selfClass, DynamicObject lexicalParent, String name, Node currentNode) {
final ModuleFields model = new ModuleFields(context, lexicalParent, name);
final DynamicObject module = Layouts.MODULE.createModule(Layouts.CLASS.getInstanceFactory(selfClass), model);
@@ -401,7 +392,7 @@ public DynamicObject generateAccessor(VirtualFrame frame, DynamicObject module,
CompilerDirectives.transferToInterpreter();
final FrameInstance callerFrame = RubyCallStack.getCallerFrame(getContext());
final SourceSection sourceSection = callerFrame.getCallNode().getEncapsulatingSourceSection();
final Visibility visibility = AddMethodNode.getVisibility(callerFrame.getFrame(FrameAccess.READ_ONLY, true));
final Visibility visibility = DeclarationContext.findVisibility(callerFrame.getFrame(FrameAccess.READ_ONLY, true));
final Arity arity = isGetter ? Arity.NO_ARGUMENTS : Arity.ONE_REQUIRED;
final String ivar = "@" + name;
final String accessorName = isGetter ? name : name + "=";
@@ -654,12 +645,7 @@ private Object classEvalSource(DynamicObject module, DynamicObject code, String
CompilerDirectives.transferToInterpreter();
Source source = Source.fromText(code.toString(), file);

return getContext().execute(source, encoding, ParserContext.MODULE, module, callerFrame, true, DeclarationContext.CLASS_EVAL, this, new NodeWrapper() {
@Override
public RubyNode wrap(RubyNode node) {
return new SetMethodDeclarationContext(node.getContext(), node.getSourceSection(), Visibility.PUBLIC, "class_eval", node);
}
});
return getContext().parseAndExecute(source, encoding, ParserContext.MODULE, module, callerFrame, true, DeclarationContext.CLASS_EVAL, this);
}

@Specialization(guards = "isRubyProc(block)")
@@ -1139,13 +1125,13 @@ public ExtendObjectNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public DynamicObject extendObject(VirtualFrame frame, DynamicObject module, DynamicObject object) {
public DynamicObject extendObject(DynamicObject module, DynamicObject object) {
if (RubyGuards.isRubyClass(module)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorWrongArgumentType(module, "Module", this));
}

Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(frame, object)).include(this, module);
Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(object)).include(this, module);
return module;
}

@@ -1394,7 +1380,7 @@ public PublicClassMethodNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public DynamicObject publicClassMethod(VirtualFrame frame, DynamicObject module, Object[] names) {
final DynamicObject singletonClass = singletonClassNode.executeSingletonClass(frame, module);
final DynamicObject singletonClass = singletonClassNode.executeSingletonClass(module);

for (Object name : names) {
setMethodVisibilityNode.executeSetMethodVisibility(frame, singletonClass, name);
@@ -1459,7 +1445,7 @@ public PrivateClassMethodNode(RubyContext context, SourceSection sourceSection)

@Specialization
public DynamicObject privateClassMethod(VirtualFrame frame, DynamicObject module, Object[] names) {
final DynamicObject singletonClass = singletonClassNode.executeSingletonClass(frame, module);
final DynamicObject singletonClass = singletonClassNode.executeSingletonClass(module);

for (Object name : names) {
setMethodVisibilityNode.executeSetMethodVisibility(frame, singletonClass, name);
@@ -1936,16 +1922,8 @@ public DynamicObject setVisibility(VirtualFrame frame, DynamicObject module, Obj
}

private void setCurrentVisibility(Visibility visibility) {
CompilerDirectives.transferToInterpreter();

final Frame callerFrame = RubyCallStack.getCallerFrame(getContext()).getFrame(FrameInstance.FrameAccess.READ_WRITE, true);
assert callerFrame != null;
assert callerFrame.getFrameDescriptor() != null;

final FrameSlot visibilitySlot = callerFrame.getFrameDescriptor().findOrAddFrameSlot(
VISIBILITY_FRAME_SLOT_ID, "visibility for frame", FrameSlotKind.Object);

callerFrame.setObject(visibilitySlot, visibility);
DeclarationContext.changeVisibility(callerFrame, visibility);
}

}
@@ -1986,7 +1964,7 @@ public DynamicObject setMethodVisibility(VirtualFrame frame, DynamicObject modul
*/
if (visibility == Visibility.MODULE_FUNCTION) {
Layouts.MODULE.getFields(module).addMethod(this, method.withVisibility(Visibility.PRIVATE));
Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(frame, module)).addMethod(this, method.withVisibility(Visibility.PUBLIC));
Layouts.MODULE.getFields(singletonClassNode.executeSingletonClass(module)).addMethod(this, method.withVisibility(Visibility.PUBLIC));
} else {
Layouts.MODULE.getFields(module).addMethod(this, method.withVisibility(visibility));
}
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@
import com.oracle.truffle.api.nodes.RootNode;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.nodes.objects.OpenModuleNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.RubyLanguage;
@@ -54,7 +53,7 @@ public boolean visit(Node node) {
// the context implied by the tag. We need to tag at the RubyRootNode because the semantics of set_trace_func
// are such that the receiver must be resolved, so we have to push as far into the callee as we can to have
// a properly constructed frame.
else if ((rubyNode.getParent() instanceof RubyRootNode) && !(rubyNode instanceof SetMethodDeclarationContext)) {
else if ((rubyNode.getParent() instanceof RubyRootNode)) {
final Probe probe = instrumenter.probe(rubyNode);
probe.tagAs(RubySyntaxTag.CALL, null);
}
Loading

0 comments on commit cdabcb4

Please sign in to comment.