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

Commits on Jul 24, 2015

  1. 5
    Copy the full SHA
    ef81cae View commit details
  2. Revert "[Truffle] fix class of returned value from Rubinius :time_s_n…

    …ow primitive"
    
    * This reverts commit e5eb36e.
    * Better fix coming.
    eregon committed Jul 24, 2015
    Copy the full SHA
    cf17cdb View commit details
  3. Copy the full SHA
    b9c10e3 View commit details
  4. Copy the full SHA
    565f080 View commit details
  5. Copy the full SHA
    b3ce35f View commit details
  6. Copy the full SHA
    4dbce41 View commit details
26 changes: 26 additions & 0 deletions spec/ruby/core/module/define_method_spec.rb
Original file line number Diff line number Diff line change
@@ -180,6 +180,32 @@ def inspect_data
lambda{o.other_inspect}.should raise_error(NoMethodError)
end

it "raises a TypeError when a Method from a singleton class is defined on another class" do
c = Class.new do
class << self
def foo
end
end
end
m = c.method(:foo)

lambda {
Class.new { define_method :bar, m }
}.should raise_error(TypeError)
end

it "raises a TypeError when a Method from one class is defined on an unrelated class" do
c = Class.new do
def foo
end
end
m = c.new.method(:foo)

lambda {
Class.new { define_method :bar, m }
}.should raise_error(TypeError)
end

it "maintains the Proc's scope" do
class DefineMethodByProcClass
in_scope = true
4 changes: 2 additions & 2 deletions spec/ruby/core/time/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ class SubTime < Time; end

class MethodHolder
class << self
define_method(:now, &::Time.method(:now))
define_method(:new, &::Time.method(:new))
define_method(:now, &Time.method(:now))
define_method(:new, &Time.method(:new))
end
end

2 changes: 1 addition & 1 deletion spec/ruby/core/time/shared/now.rb
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@
describe :time_now, :shared => true do
it "creates a subclass instance if called on a subclass" do
TimeSpecs::SubTime.send(@method).should be_an_instance_of(TimeSpecs::SubTime)
TimeSpecs::MethodHolder.send(@method).should be_an_instance_of(::Time)
TimeSpecs::MethodHolder.send(@method).should be_an_instance_of(Time)
end
end
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/method/to_proc_tags.txt

This file was deleted.

Empty file.
Original file line number Diff line number Diff line change
@@ -9,19 +9,31 @@
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.*;
import com.oracle.truffle.api.source.NullSourceSection;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.ast.ArgsNode;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.runtime.Helpers;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNode;
import org.jruby.truffle.nodes.cast.ProcOrNullNodeGen;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.core.BasicObjectNodes.ReferenceEqualNode;
import org.jruby.truffle.nodes.core.MethodNodesFactory.CallNodeFactory;
import org.jruby.truffle.nodes.core.MethodNodesFactory.CallNodeFactory.CallNodeGen;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.methods.CallMethodNode;
import org.jruby.truffle.nodes.methods.CallMethodNodeGen;
@@ -266,23 +278,64 @@ public ToProcNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = "methodObject == cachedMethodObject", limit = "getCacheLimit()")
public RubyBasicObject toProcCached(RubyBasicObject methodObject,
@Cached("methodObject") RubyBasicObject cachedMethodObject,
@Cached("toProcUncached(cachedMethodObject)") RubyBasicObject proc) {
return proc;
}

@Specialization
public RubyBasicObject toProc(RubyBasicObject methodObject) {
public RubyBasicObject toProcUncached(RubyBasicObject methodObject) {
final CallTarget callTarget = method2proc(methodObject);
final InternalMethod method = getMethod(methodObject);

return ProcNodes.createRubyProc(
getContext().getCoreLibrary().getProcClass(),
ProcNodes.Type.LAMBDA,
method.getSharedMethodInfo(),
method.getCallTarget(),
method.getCallTarget(),
method.getCallTarget(),
callTarget,
callTarget,
callTarget,
method.getDeclarationFrame(),
method,
getReceiver(methodObject),
null);
}

protected CallTarget method2proc(RubyBasicObject methodObject) {
// translate to something like:
// lambda { |same args list| method.call(args) }
// We need to preserve the method receiver and we want to have the same argument list

final InternalMethod method = getMethod(methodObject);
final SourceSection sourceSection = method.getSharedMethodInfo().getSourceSection();
final RootNode oldRootNode = ((RootCallTarget) method.getCallTarget()).getRootNode();

final SetReceiverNode setReceiverNode = new SetReceiverNode(getContext(), sourceSection, getReceiver(methodObject), method.getCallTarget());
final RootNode newRootNode = new RubyRootNode(getContext(), sourceSection, oldRootNode.getFrameDescriptor(), method.getSharedMethodInfo(), setReceiverNode);
return Truffle.getRuntime().createCallTarget(newRootNode);
}

}

private static class SetReceiverNode extends RubyNode {

private final Object receiver;
private final DirectCallNode methodCallNode;

public SetReceiverNode(RubyContext context, SourceSection sourceSection, Object receiver, CallTarget methodCallTarget) {
super(context, sourceSection);
this.receiver = receiver;
this.methodCallNode = DirectCallNode.create(methodCallTarget);
}

@Override
public Object execute(VirtualFrame frame) {
frame.getArguments()[RubyArguments.SELF_INDEX] = receiver;
return methodCallNode.call(frame, frame.getArguments());
}

}

}
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
@@ -23,6 +24,7 @@
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jcodings.Encoding;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyGuards;
@@ -43,10 +45,13 @@
import org.jruby.truffle.nodes.core.ModuleNodesFactory.GenerateAccessorNodeGen;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetMethodVisibilityNodeGen;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetVisibilityNodeGen;
import org.jruby.truffle.nodes.core.UnboundMethodNodes.BindNode;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.methods.AddMethodNode;
import org.jruby.truffle.nodes.methods.CanBindMethodToModuleNode;
import org.jruby.truffle.nodes.methods.CanBindMethodToModuleNodeGen;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.nodes.objects.*;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
@@ -1065,9 +1070,24 @@ public RubyBasicObject defineMethodProc(RubyBasicObject module, String name, Rub
}

@TruffleBoundary
@Specialization(guards = "isRubyMethod(method)")
public RubyBasicObject defineMethodMethod(RubyBasicObject module, String name, RubyBasicObject method, NotProvided block) {
getModel(module).addMethod(this, MethodNodes.getMethod(method).withName(name));
@Specialization(guards = "isRubyMethod(methodObject)")
public RubyBasicObject defineMethodMethod(RubyBasicObject module, String name, RubyBasicObject methodObject, NotProvided block,
@Cached("createCanBindMethodToModuleNode()") CanBindMethodToModuleNode canBindMethodToModuleNode) {
final InternalMethod method = MethodNodes.getMethod(methodObject);

if (!canBindMethodToModuleNode.executeCanBindMethodToModule(method, module)) {
CompilerDirectives.transferToInterpreter();
final RubyBasicObject declaringModule = method.getDeclaringModule();
if (RubyGuards.isRubyClass(declaringModule) && ModuleNodes.getModel(declaringModule).isSingleton()) {
throw new RaiseException(getContext().getCoreLibrary().typeError(
"can't bind singleton method to a different class", this));
} else {
throw new RaiseException(getContext().getCoreLibrary().typeError(
"class must be a subclass of " + ModuleNodes.getModel(declaringModule).getName(), this));
}
}

getModel(module).addMethod(this, method.withName(name));
return getSymbol(name);
}

@@ -1109,6 +1129,10 @@ private RubyBasicObject addMethod(RubyBasicObject module, String name, InternalM
return getSymbol(name);
}

protected CanBindMethodToModuleNode createCanBindMethodToModuleNode() {
return CanBindMethodToModuleNodeGen.create(getContext(), getSourceSection(), null, null);
}

}

@CoreMethod(names = "extend_object", required = 1, visibility = Visibility.PRIVATE)
Original file line number Diff line number Diff line change
@@ -128,7 +128,7 @@ public BindNode(RubyContext context, SourceSection sourceSection) {
public RubyBasicObject bind(VirtualFrame frame, RubyBasicObject unboundMethod, Object object) {
final RubyBasicObject objectMetaClass = metaClass(frame, object);

if (!canBindMethodToModuleNode.executeCanBindMethodToModule(frame, getMethod(unboundMethod), objectMetaClass)) {
if (!canBindMethodToModuleNode.executeCanBindMethodToModule(getMethod(unboundMethod), objectMetaClass)) {
CompilerDirectives.transferToInterpreter();
final RubyBasicObject declaringModule = getMethod(unboundMethod).getDeclaringModule();
if (RubyGuards.isRubyClass(declaringModule) && ModuleNodes.getModel(declaringModule).isSingleton()) {
Original file line number Diff line number Diff line change
@@ -31,20 +31,20 @@ public CanBindMethodToModuleNode(RubyContext context, SourceSection sourceSectio
super(context, sourceSection);
}

public abstract boolean executeCanBindMethodToModule(VirtualFrame frame, InternalMethod method, RubyBasicObject module);
public abstract boolean executeCanBindMethodToModule(InternalMethod method, RubyBasicObject module);

@Specialization(
guards = { "isRubyModule(module)", "method.getDeclaringModule() == declaringModule", "module == cachedModule" },
limit = "getCacheLimit()")
protected boolean canBindMethodToCached(VirtualFrame frame, InternalMethod method, RubyBasicObject module,
protected boolean canBindMethodToCached(InternalMethod method, RubyBasicObject module,
@Cached("method.getDeclaringModule()") RubyBasicObject declaringModule,
@Cached("module") RubyBasicObject cachedModule,
@Cached("canBindMethodTo(declaringModule, cachedModule)") boolean canBindMethodTo) {
return canBindMethodTo;
}

@Specialization(guards = "isRubyModule(module)")
protected boolean canBindMethodToUncached(VirtualFrame frame, InternalMethod method, RubyBasicObject module) {
protected boolean canBindMethodToUncached(InternalMethod method, RubyBasicObject module) {
final RubyBasicObject declaringModule = method.getDeclaringModule();
return canBindMethodTo(declaringModule, module);
}
Original file line number Diff line number Diff line change
@@ -15,14 +15,12 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.core.TimeNodes;
import org.jruby.truffle.nodes.time.ReadTimeZoneNode;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
@@ -37,29 +35,18 @@ public abstract class TimePrimitiveNodes {
public static abstract class TimeSNowPrimitiveNode extends RubiniusPrimitiveNode {

@Child private ReadTimeZoneNode readTimeZoneNode;
private final ConditionProfile timeClassDescendantProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile timeClassProfile = ConditionProfile.createBinaryProfile();


public TimeSNowPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readTimeZoneNode = new ReadTimeZoneNode(context, sourceSection);
}

@Specialization(guards = "isRubyClass(receiverClass)")
public RubyBasicObject timeSNow(VirtualFrame frame, RubyBasicObject receiverClass) {
@Specialization
public RubyBasicObject timeSNow(VirtualFrame frame, RubyBasicObject timeClass) {
// TODO CS 4-Mar-15 whenever we get time we have to convert lookup and time zone to a string and look it up - need to cache somehow...

final RubyBasicObject timeClass = getContext().getCoreLibrary().getTimeClass();
final boolean useReceiverClass = timeClassProfile.profile(receiverClass == timeClass) ||
timeClassDescendantProfile.profile(ModuleOperations.includesModule(receiverClass, timeClass));
final RubyBasicObject creationClass = useReceiverClass ? receiverClass : timeClass;

return TimeNodes.createRubyTime(
creationClass,
now((RubyBasicObject) readTimeZoneNode.execute(frame)),
nil());
return TimeNodes.createRubyTime(timeClass, now((RubyBasicObject) readTimeZoneNode.execute(frame)), nil());
}

@TruffleBoundary
private DateTime now(RubyBasicObject timeZone) {
assert RubyGuards.isRubyString(timeZone);
@@ -220,7 +207,7 @@ public RubyBasicObject timeStrftime(RubyBasicObject time, RubyBasicObject format

}

@RubiniusPrimitive(name = "time_s_from_array", needsSelf = true, lowerFixnumParameters = { 0 /*sec*/, 6 /*nsec*/, 7 /*isdst*/ })
@RubiniusPrimitive(name = "time_s_from_array", needsSelf = true, lowerFixnumParameters = { 0 /*sec*/, 6 /*nsec*/, 7 /*isdst*/})
public static abstract class TimeSFromArrayPrimitiveNode extends RubiniusPrimitiveNode {

@Child ReadTimeZoneNode readTimeZoneNode;
2 changes: 1 addition & 1 deletion truffle/src/main/ruby/core/library.rb
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ def attach_function(name, a2, a3, a4=nil, a5=nil)
suffixes.each do |suffix|
if caller[-suffix.length, suffix.length] == suffix
if Rubinius::FFI::Platform::POSIX.respond_to? mname
define_method mname, Rubinius::FFI::Platform::POSIX.method(mname)
define_method mname, &Rubinius::FFI::Platform::POSIX.method(mname)
module_function mname
return
end
2 changes: 1 addition & 1 deletion truffle/src/main/ruby/core/shims.rb
Original file line number Diff line number Diff line change
@@ -197,7 +197,7 @@ def printf(fmt, *args)
end
end

class Exception
class Exception

def locations
# These should be Rubinius::Location