Skip to content

Commit

Permalink
[Truffle] Add check_convert_type and check_funcall methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Fish committed Sep 12, 2016
1 parent 553b5c1 commit 92f09c4
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 29 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/flatten_tags.txt

This file was deleted.

11 changes: 11 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/RubyContext.java
Expand Up @@ -64,6 +64,7 @@ public class RubyContext extends ExecutionContext {

private final TruffleLanguage.Env env;
private final Ruby jrubyRuntime;
private boolean running = false;

private final Options options = new Options();
private final RopeTable ropeTable = new RopeTable();
Expand Down Expand Up @@ -183,6 +184,8 @@ public RubyContext(Ruby jrubyRuntime, TruffleLanguage.Env env) {
traceManager = new TraceManager(this, instrumenter);
coverageManager = new CoverageManager(this, instrumenter);

this.setRunning(true);

coreLibrary.initializePostBoot();
}

Expand Down Expand Up @@ -315,6 +318,14 @@ public AttachmentsManager getAttachmentsManager() {
return attachmentsManager;
}

public boolean isRunning() {
return running;
}

public void setRunning(boolean running) {
this.running = running;
}

public SourceLoader getSourceLoader() {
return sourceLoader;
}
Expand Down
Expand Up @@ -160,8 +160,8 @@ private static void addMethod(RubyContext context, DynamicObject module, SharedM
if (ModuleOperations.isMethodPrivateFromName(name)) {
visibility = Visibility.PRIVATE;
}

final InternalMethod method = new InternalMethod(sharedMethodInfo, name, module, visibility, callTarget);
final boolean builtIn = !context.isRunning();
final InternalMethod method = new InternalMethod(sharedMethodInfo, name, module, visibility, builtIn, callTarget);

Layouts.MODULE.getFields(module).addMethod(context, null, method);
}
Expand Down
70 changes: 70 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/VMPrimitiveNodes.java
Expand Up @@ -39,7 +39,10 @@

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
Expand All @@ -55,17 +58,24 @@
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
import org.jruby.truffle.core.cast.NameToJavaStringNode;
import org.jruby.truffle.core.cast.NameToSymbolOrStringNodeGen;
import org.jruby.truffle.core.kernel.KernelNodes;
import org.jruby.truffle.core.kernel.KernelNodesFactory;
import org.jruby.truffle.core.module.ModuleOperations;
import org.jruby.truffle.core.proc.ProcSignalHandler;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.core.thread.ThreadManager;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.control.ExitException;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.control.ThrowException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.methods.InternalMethod;
import org.jruby.truffle.language.methods.LookupMethodNode;
import org.jruby.truffle.language.methods.LookupMethodNodeGen;
import org.jruby.truffle.language.objects.IsANode;
import org.jruby.truffle.language.objects.IsANodeGen;
import org.jruby.truffle.language.objects.LogicalClassNode;
Expand Down Expand Up @@ -263,6 +273,66 @@ public boolean vmObjectRespondTo(VirtualFrame frame, Object object, Object name,

}

@Primitive(name = "vm_object_respond_to_no_built_in", needsSelf = false)
public static abstract class VMObjectRespondToNoBuiltInPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child NameToJavaStringNode nameToJavaStringNode;

public VMObjectRespondToNoBuiltInPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
nameToJavaStringNode = NameToJavaStringNode.create();
}

@Specialization
public boolean vmObjectRespondToNoBuiltIn(VirtualFrame frame, Object object, Object name, boolean includePrivate) {
// Used in place for this pattern:
// method_entry_get(klass, mid, &defined_class);
// if (!me || METHOD_ENTRY_BASIC(me))

final String nameString = nameToJavaStringNode.executeToJavaString(frame, name);
final InternalMethod method = ModuleOperations.lookupMethod(coreLibrary().getMetaClass(object), nameString);

// If no method was found, use #method_missing
if (method == null) {
return false;
}

// Check for methods that are explicitly undefined
if (method.isUndefined()) {
return false;
}

if(method.isBuiltIn()){
return false;
}

return true;
}

}

@Primitive(name = "vm_check_funcall_callable", needsSelf = false)
public static abstract class VMObjectFuncallCallablePrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child NameToJavaStringNode nameToJavaStringNode;
@Child LookupMethodNode lookupMethodNode;

public VMObjectFuncallCallablePrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
nameToJavaStringNode = NameToJavaStringNode.create();
lookupMethodNode = LookupMethodNodeGen.create(context, sourceSection, true, false, null, null);
}

@Specialization
public boolean vmCheckFuncallCallable(VirtualFrame frame, Object self, Object name) {
final String nameString = nameToJavaStringNode.executeToJavaString(frame, name);
final InternalMethod method = lookupMethodNode.executeLookupMethod(frame, self, nameString);
return method != null;
}

}


@Primitive(name = "vm_object_singleton_class", needsSelf = false)
public static abstract class VMObjectSingletonClassPrimitiveNode extends PrimitiveArrayArgumentsNode {

Expand Down
Expand Up @@ -589,6 +589,7 @@ public Object evalNoBindingCached(
cachedRootNode.getRootNode().getSharedMethodInfo().getName(),
RubyArguments.getMethod(parentFrame).getDeclaringModule(),
Visibility.PUBLIC,
false,
cachedCallTarget);

return callNode.call(frame, RubyArguments.pack(parentFrame, null, method, RubyArguments.getDeclarationContext(parentFrame), null, callerSelf, null, new Object[]{}));
Expand Down Expand Up @@ -1217,7 +1218,8 @@ private InternalMethod createMissingMethod(Object self, DynamicObject name, Stri
final CallTarget newCallTarget = Truffle.getRuntime().createCallTarget(newRootNode);

final DynamicObject module = coreLibrary().getMetaClass(self);
return new InternalMethod(info, normalizedName, module, Visibility.PUBLIC, newCallTarget);
final boolean builtIn = !getContext().isRunning();
return new InternalMethod(info, normalizedName, module, Visibility.PUBLIC, builtIn, newCallTarget);
}

private static class CallMethodMissingWithStaticName extends RubyNode {
Expand Down
Expand Up @@ -398,7 +398,8 @@ private void createAccesor(DynamicObject module, String name) {
final RubyNode sequence = Translator.sequence(getContext(), sourceSection.getSource(), rubySourceSection, Arrays.asList(checkArity, accessInstanceVariable));
final RubyRootNode rootNode = new RubyRootNode(getContext(), sourceSection, null, sharedMethodInfo, sequence, false);
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
final InternalMethod method = new InternalMethod(sharedMethodInfo, accessorName, module, visibility, callTarget);
final boolean builtIn = !getContext().isRunning();
final InternalMethod method = new InternalMethod(sharedMethodInfo, accessorName, module, visibility, builtIn, callTarget);

Layouts.MODULE.getFields(module).addMethod(getContext(), this, method);
}
Expand Down Expand Up @@ -1062,8 +1063,9 @@ private DynamicObject defineMethod(DynamicObject module, String name, DynamicObj
final RubyNode newBody = new CallMethodWithProcBody(getContext(), info.getSourceSection(), Layouts.PROC.getDeclarationFrame(proc), body);
final RubyRootNode newRootNode = new RubyRootNode(getContext(), info.getSourceSection(), rootNode.getFrameDescriptor(), info, newBody, false);
final CallTarget newCallTarget = Truffle.getRuntime().createCallTarget(newRootNode);
final boolean builtIn = !getContext().isRunning();

final InternalMethod method = InternalMethod.fromProc(info, name, module, Visibility.PUBLIC, proc, newCallTarget);
final InternalMethod method = InternalMethod.fromProc(info, name, module, Visibility.PUBLIC, builtIn, proc, newCallTarget);
return addMethod(module, name, method);
}

Expand Down
Expand Up @@ -76,7 +76,7 @@ public Object execute(VirtualFrame frame) {

mainObject = context.getCoreLibrary().getMainObject();
method = new InternalMethod(rootNode.getSharedMethodInfo(), rootNode.getSharedMethodInfo().getName(),
context.getCoreLibrary().getObjectClass(), Visibility.PUBLIC, callTarget);
context.getCoreLibrary().getObjectClass(), Visibility.PUBLIC, false, callTarget);
}

Object[] arguments = RubyArguments.pack(
Expand Down
Expand Up @@ -77,12 +77,13 @@ public DeferredCall prepareExecute(ParserContext parserContext,
} else {
declaringModule = context.getCoreLibrary().getObjectClass();
}

final boolean builtIn = !context.isRunning();
final InternalMethod method = new InternalMethod(
rootNode.getSharedMethodInfo(),
rootNode.getSharedMethodInfo().getName(),
declaringModule,
Visibility.PUBLIC,
builtIn,
callTarget);

return new DeferredCall(callTarget, RubyArguments.pack(
Expand Down
Expand Up @@ -33,6 +33,7 @@ public class InternalMethod implements ObjectGraphNode {
private final DynamicObject declaringModule;
private final Visibility visibility;
private final boolean undefined;
private final boolean builtIn;
private final DynamicObject proc; // only if method is created from a Proc

private final CallTarget callTarget;
Expand All @@ -44,6 +45,7 @@ public static InternalMethod fromProc(
String name,
DynamicObject declaringModule,
Visibility visibility,
boolean builtIn,
DynamicObject proc,
CallTarget callTarget) {
return new InternalMethod(
Expand All @@ -52,6 +54,7 @@ public static InternalMethod fromProc(
declaringModule,
visibility,
false,
builtIn,
proc,
callTarget,
Layouts.PROC.getBlock(proc),
Expand All @@ -63,8 +66,9 @@ public InternalMethod(
String name,
DynamicObject declaringModule,
Visibility visibility,
boolean builtIn,
CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget, null, null);
this(sharedMethodInfo, name, declaringModule, visibility, false, builtIn, null, callTarget, null, null);
}

public InternalMethod(
Expand All @@ -73,9 +77,10 @@ public InternalMethod(
DynamicObject declaringModule,
Visibility visibility,
boolean undefined,
boolean builtIn,
DynamicObject proc,
CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, undefined, proc, callTarget, null, null);
this(sharedMethodInfo, name, declaringModule, visibility, undefined, builtIn, proc, callTarget, null, null);
}

public InternalMethod(
Expand All @@ -84,6 +89,7 @@ public InternalMethod(
DynamicObject declaringModule,
Visibility visibility,
boolean undefined,
boolean builtIn,
DynamicObject proc,
CallTarget callTarget,
DynamicObject capturedBlock,
Expand All @@ -94,6 +100,7 @@ public InternalMethod(
this.name = name;
this.visibility = visibility;
this.undefined = undefined;
this.builtIn = builtIn;
this.proc = proc;
this.callTarget = callTarget;
this.capturedBlock = capturedBlock;
Expand All @@ -120,6 +127,10 @@ public boolean isUndefined() {
return undefined;
}

public boolean isBuiltIn() {
return builtIn;
}

public CallTarget getCallTarget() {
return callTarget;
}
Expand All @@ -136,6 +147,7 @@ public InternalMethod withDeclaringModule(DynamicObject newDeclaringModule) {
newDeclaringModule,
visibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
Expand All @@ -153,6 +165,7 @@ public InternalMethod withName(String newName) {
declaringModule,
visibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
Expand All @@ -170,6 +183,7 @@ public InternalMethod withVisibility(Visibility newVisibility) {
declaringModule,
newVisibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
Expand All @@ -184,6 +198,7 @@ public InternalMethod undefined() {
declaringModule,
visibility,
true,
builtIn,
proc,
callTarget,
capturedBlock,
Expand Down
Expand Up @@ -53,8 +53,8 @@ public InternalMethod executeMethod(VirtualFrame frame) {
} else {
capturedDefaultDefinee = null;
}

return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, null,
final boolean builtIn = !getContext().isRunning();
return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, builtIn, null, callTarget, null,
capturedDefaultDefinee);
}

Expand Down
Expand Up @@ -65,8 +65,8 @@ public InternalMethod executeMethod(VirtualFrame frame) {
} else {
capturedBlock = null;
}

return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, capturedBlock, null);
final boolean builtIn = !getContext().isRunning();
return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, builtIn, null, callTarget, capturedBlock, null);
}

@Override
Expand Down
20 changes: 5 additions & 15 deletions truffle/src/main/ruby/core/array.rb
Expand Up @@ -1193,22 +1193,12 @@ def recursively_flatten(array, out, max_levels = -1)
while i < size
o = array.at i

if Rubinius::Type.object_kind_of? o, Array
modified = true
recursively_flatten o, out, max_levels
elsif Rubinius::Type.object_respond_to? o, :to_ary
ary = o.__send__ :to_ary
if nil.equal? ary
out << o
else
modified = true
recursively_flatten ary, out, max_levels
end
elsif ary = Rubinius::Type.execute_check_convert_type(o, Array, :to_ary)
modified = true
recursively_flatten ary, out, max_levels
else
tmp = Rubinius::Type.rb_check_convert_type(o, Array, :to_ary)
if tmp.nil?
out << o
else
modified = true
recursively_flatten tmp, out, max_levels
end

i += 1
Expand Down

0 comments on commit 92f09c4

Please sign in to comment.