Skip to content

Commit

Permalink
Showing 12 changed files with 181 additions and 29 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/flatten_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -160,8 +160,7 @@ 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 InternalMethod method = new InternalMethod(context, sharedMethodInfo, name, module, visibility, callTarget);

Layouts.MODULE.getFields(module).addMethod(context, null, method);
}
50 changes: 50 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/VMPrimitiveNodes.java
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
@@ -246,6 +256,45 @@ public boolean vmObjectKindOf(Object object, DynamicObject rubyClass) {

}

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

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

@Specialization
public boolean vmMethodIsBasic(VirtualFrame frame, DynamicObject method) {
return Layouts.METHOD.getMethod(method).isBuiltIn();
}

}

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

@Child NameToJavaStringNode nameToJavaStringNode;
@Child LookupMethodNode lookupMethodNode;

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

@Specialization
public DynamicObject vmMethodLookup(VirtualFrame frame, Object self, Object name) {
// TODO BJF Sep 14, 2016 Handle private
final String normalizedName = nameToJavaStringNode.executeToJavaString(frame, name);
InternalMethod method = lookupMethodNode.executeLookupMethod(frame, self, normalizedName);
if (method == null) {
return nil();
}
return Layouts.METHOD.createMethod(coreLibrary().getMethodFactory(), self, method);
}

}

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

@@ -263,6 +312,7 @@ public boolean vmObjectRespondTo(VirtualFrame frame, Object object, Object name,

}


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

Original file line number Diff line number Diff line change
@@ -586,6 +586,7 @@ public Object evalNoBindingCached(
final Object callerSelf = RubyArguments.getSelf(frame);

final InternalMethod method = new InternalMethod(
getContext(),
cachedRootNode.getRootNode().getSharedMethodInfo(),
cachedRootNode.getRootNode().getSharedMethodInfo().getName(),
RubyArguments.getMethod(parentFrame).getDeclaringModule(),
@@ -1222,7 +1223,7 @@ 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);
return new InternalMethod(getContext(), info, normalizedName, module, Visibility.PUBLIC, newCallTarget);
}

private static class CallMethodMissingWithStaticName extends RubyNode {
Original file line number Diff line number Diff line change
@@ -396,7 +396,7 @@ 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 InternalMethod method = new InternalMethod(getContext(), sharedMethodInfo, accessorName, module, visibility, callTarget);

Layouts.MODULE.getFields(module).addMethod(getContext(), this, method);
}
@@ -1058,7 +1058,7 @@ private DynamicObject defineMethod(DynamicObject module, String name, DynamicObj
final RubyRootNode newRootNode = new RubyRootNode(getContext(), info.getSourceSection(), rootNode.getFrameDescriptor(), info, newBody, false);
final CallTarget newCallTarget = Truffle.getRuntime().createCallTarget(newRootNode);

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

Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@ public Object execute(VirtualFrame frame) {
callNode.forceInlining();

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

Original file line number Diff line number Diff line change
@@ -77,8 +77,8 @@ public DeferredCall prepareExecute(ParserContext parserContext,
} else {
declaringModule = context.getCoreLibrary().getObjectClass();
}

final InternalMethod method = new InternalMethod(
context,
rootNode.getSharedMethodInfo(),
rootNode.getSharedMethodInfo().getName(),
declaringModule,
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.objects.ObjectGraphNode;

@@ -33,20 +34,23 @@ 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;
private final DynamicObject capturedBlock;
private final DynamicObject capturedDefaultDefinee;

public static InternalMethod fromProc(
RubyContext context,
SharedMethodInfo sharedMethodInfo,
String name,
DynamicObject declaringModule,
Visibility visibility,
DynamicObject proc,
CallTarget callTarget) {
return new InternalMethod(
context,
sharedMethodInfo,
name,
declaringModule,
@@ -59,23 +63,40 @@ public static InternalMethod fromProc(
}

public InternalMethod(
RubyContext context,
SharedMethodInfo sharedMethodInfo,
String name,
DynamicObject declaringModule,
Visibility visibility,
CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget, null, null);
this(context, sharedMethodInfo, name, declaringModule, visibility, false, null, callTarget, null, null);
}

public InternalMethod(
RubyContext context,
SharedMethodInfo sharedMethodInfo,
String name,
DynamicObject declaringModule,
Visibility visibility,
boolean undefined,
DynamicObject proc,
CallTarget callTarget) {
this(sharedMethodInfo, name, declaringModule, visibility, undefined, proc, callTarget, null, null);
this(context, sharedMethodInfo, name, declaringModule, visibility, undefined, proc, callTarget, null, null);
}

public InternalMethod(
RubyContext context,
SharedMethodInfo sharedMethodInfo,
String name,
DynamicObject declaringModule,
Visibility visibility,
boolean undefined,
DynamicObject proc,
CallTarget callTarget,
DynamicObject capturedBlock,
DynamicObject capturedDefaultDefinee) {
this(sharedMethodInfo, name, declaringModule, visibility, undefined, !context.getCoreLibrary().isLoaded(),
proc, callTarget, capturedBlock, capturedDefaultDefinee);
}

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

public boolean isBuiltIn() {
return builtIn;
}

public CallTarget getCallTarget() {
return callTarget;
}
@@ -136,6 +163,7 @@ public InternalMethod withDeclaringModule(DynamicObject newDeclaringModule) {
newDeclaringModule,
visibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
@@ -153,6 +181,7 @@ public InternalMethod withName(String newName) {
declaringModule,
visibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
@@ -170,6 +199,7 @@ public InternalMethod withVisibility(Visibility newVisibility) {
declaringModule,
newVisibility,
undefined,
builtIn,
proc,
callTarget,
capturedBlock,
@@ -184,6 +214,7 @@ public InternalMethod undefined() {
declaringModule,
visibility,
true,
builtIn,
proc,
callTarget,
capturedBlock,
Original file line number Diff line number Diff line change
@@ -53,8 +53,7 @@ public InternalMethod executeMethod(VirtualFrame frame) {
} else {
capturedDefaultDefinee = null;
}

return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, null,
return new InternalMethod(getContext(), sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, null,
capturedDefaultDefinee);
}

Original file line number Diff line number Diff line change
@@ -65,8 +65,7 @@ public InternalMethod executeMethod(VirtualFrame frame) {
} else {
capturedBlock = null;
}

return new InternalMethod(sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, capturedBlock, null);
return new InternalMethod(getContext(), sharedMethodInfo, name, dummyModule, dummyVisibility, false, null, callTarget, capturedBlock, null);
}

@Override
20 changes: 5 additions & 15 deletions truffle/src/main/ruby/core/array.rb
Original file line number Diff line number Diff line change
@@ -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
84 changes: 84 additions & 0 deletions truffle/src/main/ruby/core/type.rb
Original file line number Diff line number Diff line change
@@ -82,6 +82,16 @@ def self.object_respond_to?(obj, name, include_private = false)
Truffle.invoke_primitive :vm_object_respond_to, obj, name, include_private
end

def self.object_respond_to_no_built_in?(obj, name, include_private = false)
meth = Truffle.invoke_primitive :vm_method_lookup, obj, name
!meth.nil? && !Truffle.invoke_primitive(:vm_method_is_basic, meth)
end

def self.check_funcall_callable(obj, name)
# TODO BJF Review rb_method_call_status
!(Truffle.invoke_primitive :vm_method_lookup, obj, name).nil?
end

def self.object_equal(a, b)
Truffle.primitive :vm_object_equal
raise PrimitiveFailure, "Rubinius::Type.object_equal primitive failed"
@@ -210,6 +220,80 @@ def self.execute_check_convert_type(obj, cls, meth)
raise TypeError, msg
end

def self.rb_check_convert_type(obj, cls, meth)
return obj if object_kind_of?(obj, cls)
v = convert_type(obj, cls, meth, false)
return nil if v.nil?
unless object_kind_of?(v, cls)
raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{object_class(v)})"
end
v
end

def self.convert_type(obj, cls, meth, raise_on_error)
r = check_funcall(obj, meth)
if undefined.equal?(r)
if raise_on_error
raise TypeError, "can't convert #{obj} into #{cls} with #{meth}"
end
return nil
end
r
end

def self.check_funcall(recv, meth, args = [])
check_funcall_default(recv, meth, args, undefined)
end

def self.check_funcall_default(recv, meth, args, default)
respond = check_funcall_respond_to(recv, meth, true)
return default if respond == 0
unless check_funcall_callable(recv, meth)
return check_funcall_missing(recv, meth, args, respond, default);
end
recv.__send__(meth)
end

def self.check_funcall_respond_to(obj, meth, priv)
# TODO Review BJF vm_respond_to
return -1 unless object_respond_to_no_built_in?(obj, :respond_to?, true)
if !!obj.__send__(:respond_to?, meth, true)
1
else
0
end
end

def self.check_funcall_missing(recv, meth, args, respond, default)
ret = respond > 0
ret = basic_obj_respond_to_missing(recv, meth, false) #PRIV false
return default unless ret
respond_to_missing = !undefined.equal?(ret)
ret = default
if object_respond_to_no_built_in?(recv, :method_missing, true)
begin
return recv.__send__(:method_missing, meth, *args)
rescue NoMethodError
# TODO BJF usually more is done here
meth = Truffle.invoke_primitive :vm_method_lookup, recv, meth
if meth
ret = false
else
ret = respond_to_missing
end
if ret
raise
end
end
end
return undefined
end

def self.basic_obj_respond_to_missing(obj, mid, priv)
return undefined unless object_respond_to_no_built_in?(obj, :respond_to_missing?, true)
obj.__send__(:respond_to_missing?, mid, priv);
end

##
# Uses the logic of [Array, Hash, String].try_convert.
#

0 comments on commit 33b1667

Please sign in to comment.