Skip to content

Commit

Permalink
[Truffle] Fix UnboundMethod#bind.
Browse files Browse the repository at this point in the history
  • Loading branch information
eregon committed Mar 24, 2015
1 parent 767c13b commit f75b331
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/unboundmethod/bind_tags.txt

This file was deleted.

Expand Up @@ -9,13 +9,20 @@
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.NullSourceSection;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.objects.MetaClassNode;
import org.jruby.truffle.nodes.objects.MetaClassNodeFactory;
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.RubyArray;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyMethod;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyString;
Expand Down Expand Up @@ -46,16 +53,40 @@ public int arity(RubyUnboundMethod method) {
@CoreMethod(names = "bind", required = 1)
public abstract static class BindNode extends CoreMethodNode {

@Child private MetaClassNode metaClassNode;

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

public BindNode(BindNode prev) {
super(prev);
metaClassNode = prev.metaClassNode;
}

private RubyClass metaClass(VirtualFrame frame, Object object) {
if (metaClassNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
metaClassNode = insert(MetaClassNodeFactory.create(getContext(), getSourceSection(), null));
}
return metaClassNode.executeMetaClass(frame, object);
}

@Specialization
public RubyMethod bind(RubyUnboundMethod unboundMethod, Object object) {
public RubyMethod bind(VirtualFrame frame, RubyUnboundMethod unboundMethod, Object object) {
notDesignedForCompilation();
RubyModule module = unboundMethod.getMethod().getDeclaringModule();
if (!module.isOnlyAModule()) {
if (!ModuleOperations.assignableTo(metaClass(frame, object), module)) {
CompilerDirectives.transferToInterpreter();
if (((RubyClass) module).isSingleton()) {
throw new RaiseException(getContext().getCoreLibrary().typeError("singleton method called for a different object", this));
} else {
throw new RaiseException(getContext().getCoreLibrary().typeError("bind argument must be an instance of " + module.getName(), this));
}
}
}

return new RubyMethod(getContext().getCoreLibrary().getMethodClass(), object, unboundMethod.getMethod());
}

Expand Down

0 comments on commit f75b331

Please sign in to comment.