Skip to content

Commit

Permalink
Showing 25 changed files with 189 additions and 94 deletions.
5 changes: 3 additions & 2 deletions core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -211,10 +211,11 @@ public static void main(String[] args) {
t.printStackTrace(System.err);
} else {
// print out as a nice Ruby backtrace
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t));
System.err.println("Unhandled Java exception: " + t);
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t, false));
while ((t = t.getCause()) != null) {
System.err.println("Caused by:");
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t));
System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t, false));
}
}

11 changes: 10 additions & 1 deletion core/src/main/java/org/jruby/RubyProc.java
Original file line number Diff line number Diff line change
@@ -265,7 +265,16 @@ public static IRubyObject[] prepareArgs(ThreadContext context, Block.Type type,
// for procs and blocks, single array passed to multi-arg must be spread
if ((signature != Signature.ONE_ARGUMENT && required != 0 && (isFixed || signature != Signature.OPTIONAL) || restKwargs) &&
actual == 1 && args[0].respondsTo("to_ary")) {
args = args[0].convertToArray().toJavaArray();
IRubyObject newAry = Helpers.aryToAry(args[0]);

// This is very common to yield in *IRBlockBody. When we tackle call protocol for blocks this will combine.
if (newAry.isNil()) {
args = new IRubyObject[] { args[0] };
} else if (newAry instanceof RubyArray){
args = ((RubyArray) newAry).toJavaArray();
} else {
throw context.runtime.newTypeError(args[0].getType().getName() + "#to_ary should return Array");
}
actual = args.length;
}

8 changes: 6 additions & 2 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -481,10 +481,14 @@ public static IRubyObject[] convertValueIntoArgArray(ThreadContext context, IRub
return (value instanceof RubyArray) ? ((RubyArray)value).toJavaArray() : new IRubyObject[] { value };
} else {
IRubyObject val0 = Helpers.aryToAry(value);
if (!(val0 instanceof RubyArray)) {
// FIXME: This logic exists in RubyProc and IRRubyBlockBody. consolidate when we do block call protocol work
if (val0.isNil()) {
return new IRubyObject[] { value };
} else if (!(val0 instanceof RubyArray)) {
throw context.runtime.newTypeError(value.getType().getName() + "#to_ary should return Array");
} else {
return ((RubyArray) val0).toJavaArray();
}
return ((RubyArray)val0).toJavaArray();
}
}
}
15 changes: 11 additions & 4 deletions core/src/main/java/org/jruby/runtime/IRBlockBody.java
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg

@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Binding binding, Type type) {
return call(context, new IRubyObject[] {arg0, arg1, arg2}, binding, type, Block.NULL_BLOCK);
return call(context, new IRubyObject[]{arg0, arg1, arg2}, binding, type, Block.NULL_BLOCK);
}

@Override
@@ -97,17 +97,19 @@ IRubyObject yieldSpecificMultiArgsCommon(ThreadContext context, IRubyObject[] ar

@Override
public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Binding binding, Type type) {
return yieldSpecificMultiArgsCommon(context, new IRubyObject[] { arg0, arg1 }, binding, type);
return yieldSpecificMultiArgsCommon(context, new IRubyObject[]{arg0, arg1}, binding, type);
}

@Override
public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Binding binding, Type type) {
return yieldSpecificMultiArgsCommon(context, new IRubyObject[] { arg0, arg1, arg2 }, binding, type);
return yieldSpecificMultiArgsCommon(context, new IRubyObject[]{arg0, arg1, arg2}, binding, type);
}

private IRubyObject[] toAry(ThreadContext context, IRubyObject value) {
IRubyObject val0 = Helpers.aryToAry(value);

if (val0.isNil()) return new IRubyObject[] { value };

if (!(val0 instanceof RubyArray)) {
throw context.runtime.newTypeError(value.getType().getName() + "#to_ary should return Array");
}
@@ -117,7 +119,12 @@ private IRubyObject[] toAry(ThreadContext context, IRubyObject value) {

protected IRubyObject doYieldLambda(ThreadContext context, IRubyObject value, Binding binding, Type type) {
// Lambda does not splat arrays even if a rest arg is present when it wants a single parameter filled.
IRubyObject[] args = signature.required() == 1 ? new IRubyObject[] { value } : toAry(context, value);
IRubyObject[] args;
if (signature.required() == 1 || signature.arityValue() == -1) {
args = new IRubyObject[] { value };
} else {
args = toAry(context, value);
}

signature.checkArity(context.runtime, args);

26 changes: 6 additions & 20 deletions core/src/main/java/org/jruby/runtime/ThreadContext.java
Original file line number Diff line number Diff line change
@@ -744,30 +744,16 @@ public BacktraceElement[] createBacktrace2(int level, boolean nativeException) {
return newTrace;
}

private static StringBuilder appendRubyBacktraceString(final StringBuilder buffer, StackTraceElement element) {
return buffer.append( element.getFileName() ).append(':')
.append( element.getLineNumber() ).append(":in `")
.append( element.getMethodName() ).append('\'');
}

public static String createRawBacktraceStringFromThrowable(final Throwable ex) {
public static String createRawBacktraceStringFromThrowable(final Throwable ex, final boolean color) {
StackTraceElement[] javaStackTrace = ex.getStackTrace();

if (javaStackTrace == null || javaStackTrace.length == 0) return "";

final StringBuilder buffer = new StringBuilder(160);

StackTraceElement element = javaStackTrace[0];
buffer.append( appendRubyBacktraceString(buffer, element) )
.append(": ").append( ex.toString() );

for (int i = 1; i < javaStackTrace.length; i++) {
element = javaStackTrace[i];
buffer.append('\n');
buffer.append("\tfrom ").append( appendRubyBacktraceString(buffer, element) );
}

return buffer.toString();
return TraceType.printBacktraceJRuby(
new BacktraceData(javaStackTrace, new BacktraceElement[0], true, false, false).getBacktraceWithoutRuby(),
ex.getClass().getName(),
ex.getLocalizedMessage(),
color);
}

private Frame pushFrameForBlock(Binding binding) {
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;

public class BacktraceData implements Serializable {
@@ -37,6 +38,10 @@ public RubyStackTraceElement[] getBacktrace(Ruby runtime) {
return backtraceElements;
}

public RubyStackTraceElement[] getBacktraceWithoutRuby() {
return constructBacktrace(Collections.EMPTY_MAP);
}

private RubyStackTraceElement[] constructBacktrace(Map<String, Map<String, String>> boundMethods) {
ArrayList<RubyStackTraceElement> trace = new ArrayList<RubyStackTraceElement>(javaTrace.length);

28 changes: 19 additions & 9 deletions core/src/main/java/org/jruby/runtime/backtrace/TraceType.java
Original file line number Diff line number Diff line change
@@ -320,30 +320,40 @@ protected static String printBacktraceMRI(RubyException exception, boolean conso
private static final String EVAL_COLOR = "\033[0;33m";
private static final String CLEAR_COLOR = "\033[0m";

public static String printBacktraceJRuby(RubyStackTraceElement[] frames, String type, String message, boolean color) {
StringBuilder buffer = new StringBuilder();

// exception line
buffer
.append(type)
.append(": ")
.append(message)
.append('\n');

if (frames == null) frames = RubyStackTraceElement.EMPTY_ARRAY;
renderBacktraceJRuby(frames, buffer, color);


return buffer.toString();
}

protected static String printBacktraceJRuby(RubyException exception, boolean console) {
final Ruby runtime = exception.getRuntime();
final ThreadContext context = runtime.getCurrentContext();

StringBuilder buffer = new StringBuilder();
boolean color = console && runtime.getInstanceConfig().getBacktraceColor();

// exception line
String message = exception.message(context).toString();
if (exception.getMetaClass() == runtime.getRuntimeError() && message.length() == 0) {
message = "No current exception";
}
buffer
.append(exception.getMetaClass().getName())
.append(": ")
.append(message)
.append('\n');
String type = exception.getMetaClass().getName();

RubyStackTraceElement[] frames = exception.getBacktraceElements();
if (frames == null) frames = RubyStackTraceElement.EMPTY_ARRAY;
renderBacktraceJRuby(frames, buffer, color);


return buffer.toString();
return printBacktraceJRuby(frames, type, message, color);
}

private static void renderBacktraceJRuby(RubyStackTraceElement[] frames, StringBuilder buffer, boolean color) {
10 changes: 5 additions & 5 deletions lib/ruby/stdlib/fileutils.rb
Original file line number Diff line number Diff line change
@@ -156,10 +156,10 @@ def uptodate?(new, old_list)
end
module_function :uptodate?

def remove_tailing_slash(dir)
def remove_trailing_slash(dir)
dir == '/' ? dir : dir.chomp(?/)
end
private_module_function :remove_tailing_slash
private_module_function :remove_trailing_slash

#
# Options: mode noop verbose
@@ -207,7 +207,7 @@ def mkdir_p(list, options = {})
fu_output_message "mkdir -p #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
return *list if options[:noop]

list.map {|path| remove_tailing_slash(path)}.each do |path|
list.map {|path| remove_trailing_slash(path)}.each do |path|
# optimize for the most common case
begin
fu_mkdir path, options[:mode]
@@ -244,7 +244,7 @@ def mkdir_p(list, options = {})
OPT_TABLE['makedirs'] = [:mode, :noop, :verbose]

def fu_mkdir(path, mode) #:nodoc:
path = remove_tailing_slash(path)
path = remove_trailing_slash(path)
if mode
Dir.mkdir path, mode
File.chmod mode, path
@@ -272,7 +272,7 @@ def rmdir(list, options = {})
return if options[:noop]
list.each do |dir|
begin
Dir.rmdir(dir = remove_tailing_slash(dir))
Dir.rmdir(dir = remove_trailing_slash(dir))
if parents
until (parent = File.dirname(dir)) == '.' or parent == dir
dir = parent
5 changes: 5 additions & 0 deletions spec/ruby/core/proc/fixtures/common.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
module ProcSpecs
class ToAryAsNil
def to_ary
nil
end
end
def self.new_proc_in_method
Proc.new
end
8 changes: 8 additions & 0 deletions spec/ruby/core/proc/shared/call.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require File.expand_path('../../fixtures/common', __FILE__)

describe :proc_call, shared: true do
it "invokes self" do
Proc.new { "test!" }.send(@method).should == "test!"
@@ -49,6 +51,12 @@
a.should == 1
end

it "will call #to_ary on argument and return self if return is nil" do
argument = ProcSpecs::ToAryAsNil.new
result = proc { |x, _| x }.send(@method, argument)
result.should == argument
end

it "substitutes nil for missing arguments when self is a proc" do
proc {|x,y| [x,y]}.send(@method).should == [nil,nil]

46 changes: 34 additions & 12 deletions spec/ruby/language/yield_spec.rb
Original file line number Diff line number Diff line change
@@ -22,24 +22,46 @@
end

describe "taking a single argument" do
it "raises a LocalJumpError when the method is not passed a block" do
lambda { @y.s(1) }.should raise_error(LocalJumpError)
describe "when no block is given" do
it "raises a LocalJumpError" do
lambda { @y.s(1) }.should raise_error(LocalJumpError)
end
end

it "passes an empty Array when the argument is an empty Array" do
@y.s([]) { |*a| a }.should == [[]]
end
describe "yielding to a literal block" do
it "passes an empty Array when the argument is an empty Array" do
@y.s([]) { |*a| a }.should == [[]]
end

it "passes nil as a value" do
@y.s(nil) { |*a| a }.should == [nil]
end
it "passes nil as a value" do
@y.s(nil) { |*a| a }.should == [nil]
end

it "passes a single value" do
@y.s(1) { |*a| a }.should == [1]
it "passes a single value" do
@y.s(1) { |*a| a }.should == [1]
end

it "passes a single, multi-value Array" do
@y.s([1, 2, 3]) { |*a| a }.should == [[1, 2, 3]]
end
end

it "passes a single, multi-value Array" do
@y.s([1, 2, 3]) { |*a| a }.should == [[1, 2, 3]]
describe "yielding to a lambda" do
it "passes an empty Array when the argument is an empty Array" do
@y.s([], &lambda { |*a| a }).should == [[]]
end

it "passes nil as a value" do
@y.s(nil, &lambda { |*a| a }).should == [nil]
end

it "passes a single value" do
@y.s(1, &lambda { |*a| a }).should == [1]
end

it "passes a single, multi-value Array" do
@y.s([1, 2, 3], &lambda { |*a| a }).should == [[1, 2, 3]]
end
end
end

1 change: 0 additions & 1 deletion spec/tags/ruby/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
fails:A block yielded a single Array assigns elements to optional arguments
fails:A block yielded a single Array assigns the last element to a non-keyword argument if #to_hash returns nil
fails:A block yielded a single Array raises a TypeError if #to_hash does not return a Hash
fails:A block yielded a single Object receives the object if #to_ary returns nil
fails:A block yielded a single Array does not treat hashes with string keys as keyword arguments
fails:A block yielded a single Array calls #to_hash on the last element when there are more arguments than parameters
fails:A block yielded a single Array assigns symbol keys from a Hash to keyword arguments
1 change: 1 addition & 0 deletions spec/truffle/tags/core/proc/call_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Proc#call on a Proc created with Kernel#lambda or Kernel#proc will call #to_ary on argument and return self if return is nil
1 change: 1 addition & 0 deletions spec/truffle/tags/core/proc/case_compare_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Proc#=== on a Proc created with Kernel#lambda or Kernel#proc will call #to_ary on argument and return self if return is nil
1 change: 1 addition & 0 deletions spec/truffle/tags/core/proc/element_reference_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Proc#call on a Proc created with Kernel#lambda or Kernel#proc will call #to_ary on argument and return self if return is nil
1 change: 1 addition & 0 deletions spec/truffle/tags/core/proc/yield_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Proc#yield on a Proc created with Kernel#lambda or Kernel#proc will call #to_ary on argument and return self if return is nil
2 changes: 1 addition & 1 deletion test/mri/excludes_truffle/TestFileUtilsDryRun.rb
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@
exclude :test_visibility_remove_entry, "needs investigation"
exclude :test_visibility_remove_entry_secure, "needs investigation"
exclude :test_visibility_remove_file, "needs investigation"
exclude :test_visibility_remove_tailing_slash, "needs investigation"
exclude :test_visibility_remove_trailing_slash, "needs investigation"
exclude :test_visibility_rename_cannot_overwrite_file, "needs investigation"
exclude :test_visibility_rm, "needs investigation"
exclude :test_visibility_rm_f, "needs investigation"
2 changes: 1 addition & 1 deletion test/mri/excludes_truffle/TestFileUtilsNoWrite.rb
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@
exclude :test_visibility_remove_entry, "needs investigation"
exclude :test_visibility_remove_entry_secure, "needs investigation"
exclude :test_visibility_remove_file, "needs investigation"
exclude :test_visibility_remove_tailing_slash, "needs investigation"
exclude :test_visibility_remove_trailing_slash, "needs investigation"
exclude :test_visibility_rename_cannot_overwrite_file, "needs investigation"
exclude :test_visibility_rm, "needs investigation"
exclude :test_visibility_rm_f, "needs investigation"
2 changes: 1 addition & 1 deletion test/mri/excludes_truffle/TestFileUtilsVerbose.rb
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@
exclude :test_visibility_remove_entry, "needs investigation"
exclude :test_visibility_remove_entry_secure, "needs investigation"
exclude :test_visibility_remove_file, "needs investigation"
exclude :test_visibility_remove_tailing_slash, "needs investigation"
exclude :test_visibility_remove_trailing_slash, "needs investigation"
exclude :test_visibility_rename_cannot_overwrite_file, "needs investigation"
exclude :test_visibility_rm, "needs investigation"
exclude :test_visibility_rm_f, "needs investigation"
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.util.ArgumentDescriptorUtils;
import org.jruby.util.StringSupport;

@CoreClass(name = "Method")
@@ -163,8 +164,7 @@ public ParametersNode(RubyContext context, SourceSection sourceSection) {
public DynamicObject parameters(DynamicObject method) {
final ArgumentDescriptor[] argsDesc = Layouts.METHOD.getMethod(method).getSharedMethodInfo().getArgumentDescriptors();

return getContext().toTruffle(Helpers.argumentDescriptorsToParameters(getContext().getRuntime(),
argsDesc, true));
return ArgumentDescriptorUtils.argumentDescriptorsToParameters(getContext(), argsDesc, true);
}

}
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.truffle.runtime.util.ArgumentDescriptorUtils;
import org.jruby.util.StringSupport;

@CoreClass(name = "Proc")
@@ -265,8 +266,7 @@ public ParametersNode(RubyContext context, SourceSection sourceSection) {
public DynamicObject parameters(DynamicObject proc) {
final ArgumentDescriptor[] argsDesc = Layouts.PROC.getSharedMethodInfo(proc).getArgumentDescriptors();

return getContext().toTruffle(Helpers.argumentDescriptorsToParameters(getContext().getRuntime(),
argsDesc, Layouts.PROC.getType(proc) == Type.LAMBDA));
return ArgumentDescriptorUtils.argumentDescriptorsToParameters(getContext(), argsDesc, Layouts.PROC.getType(proc) == Type.LAMBDA);
}

}
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.util.ArgumentDescriptorUtils;
import org.jruby.util.StringSupport;

@CoreClass(name = "UnboundMethod")
@@ -158,8 +159,7 @@ public ParametersNode(RubyContext context, SourceSection sourceSection) {
public DynamicObject parameters(DynamicObject method) {
final ArgumentDescriptor[] argsDesc = Layouts.UNBOUND_METHOD.getMethod(method).getSharedMethodInfo().getArgumentDescriptors();

return getContext().toTruffle(Helpers.argumentDescriptorsToParameters(getContext().getRuntime(),
argsDesc, true));
return ArgumentDescriptorUtils.argumentDescriptorsToParameters(getContext(), argsDesc, true);
}

}
14 changes: 1 addition & 13 deletions truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java
Original file line number Diff line number Diff line change
@@ -508,16 +508,8 @@ public org.jruby.RubyString toJRubyString(DynamicObject string) {
}

public Object toTruffle(IRubyObject object) {
if (object == runtime.getTopSelf()) {
return getCoreLibrary().getMainObject();
} else if (object == runtime.getKernel()) {
return getCoreLibrary().getKernelModule();
} else if (object instanceof RubyNil) {
if (object instanceof RubyNil) {
return getCoreLibrary().getNilObject();
} else if (object instanceof org.jruby.RubyBoolean.True) {
return true;
} else if (object instanceof org.jruby.RubyBoolean.False) {
return false;
} else if (object instanceof org.jruby.RubyFixnum) {
final long value = ((org.jruby.RubyFixnum) object).getLongValue();

@@ -533,10 +525,6 @@ public Object toTruffle(IRubyObject object) {
return Layouts.BIGNUM.createBignum(coreLibrary.getBignumFactory(), value);
} else if (object instanceof org.jruby.RubyString) {
return toTruffle((org.jruby.RubyString) object);
} else if (object instanceof org.jruby.RubySymbol) {
return getSymbolTable().getSymbol(object.toString());
} else if (object instanceof org.jruby.RubyArray) {
return toTruffle((org.jruby.RubyArray) object);
} else if (object instanceof org.jruby.RubyException) {
return toTruffle((org.jruby.RubyException) object, null);
} else {
Original file line number Diff line number Diff line change
@@ -17,13 +17,15 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Property;

import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.Entry;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.subsystems.SafepointAction;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
@@ -46,27 +48,20 @@ public void run(DynamicObject thread, Node currentNode) {
stack.add(thread);

if (Thread.currentThread() == stoppingThread) {
stack.addAll(ObjectGraph.getAdjacentObjects(context.getCoreLibrary().getGlobalVariablesObject()));
stack.addAll(context.getAtExitManager().getHandlers());
stack.addAll(context.getObjectSpaceManager().getFinalizerHandlers());
visitContextRoots(context, stack);
}

final FrameInstance currentFrame = Truffle.getRuntime().getCurrentFrame();

if (currentFrame != null) {
stack.addAll(getObjectsInFrame(currentFrame.getFrame(FrameInstance.FrameAccess.READ_ONLY, true)));
}

Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Object>() {

@Override
public Object visitFrame(FrameInstance frameInstance) {
stack.addAll(getObjectsInFrame(frameInstance
.getFrame(FrameInstance.FrameAccess.READ_ONLY, true)));

stack.addAll(getObjectsInFrame(frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY, true)));
return null;
}

});

while (!stack.isEmpty()) {
@@ -78,7 +73,6 @@ public Object visitFrame(FrameInstance frameInstance) {
}
}
}

});

return visited;
@@ -90,23 +84,27 @@ public static Set<DynamicObject> stopAndGetRootObjects(Node currentNode, final R
final Thread stoppingThread = Thread.currentThread();

context.getSafepointManager().pauseAllThreadsAndExecute(currentNode, false, new SafepointAction() {

@Override
public void run(DynamicObject thread, Node currentNode) {
objects.add(thread);

if (Thread.currentThread() == stoppingThread) {
objects.addAll(ObjectGraph.getAdjacentObjects(context.getCoreLibrary().getGlobalVariablesObject()));
objects.addAll(context.getAtExitManager().getHandlers());
objects.addAll(context.getObjectSpaceManager().getFinalizerHandlers());
visitContextRoots(context, objects);
}
}

});

return objects;
}

public static void visitContextRoots(RubyContext context, Collection<DynamicObject> stack) {
// We do not want to expose the global object
stack.addAll(ObjectGraph.getAdjacentObjects(context.getCoreLibrary().getGlobalVariablesObject()));

stack.addAll(context.getAtExitManager().getHandlers());
stack.addAll(context.getObjectSpaceManager().getFinalizerHandlers());
}

public static Set<DynamicObject> getAdjacentObjects(DynamicObject object) {
final Set<DynamicObject> reachable = new HashSet<>();

@@ -152,7 +150,6 @@ public static Set<DynamicObject> getObjectsInFrame(Frame frame) {
final Set<DynamicObject> objects = new HashSet<>();

final Frame lexicalParentFrame = RubyArguments.tryGetDeclarationFrame(frame.getArguments());

if (lexicalParentFrame != null) {
objects.addAll(getObjectsInFrame(lexicalParentFrame));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*
* Contains code modified from JRuby's org.jruby.runtime.Helpers and org.jruby.runtime.ArgumentType.
*/
package org.jruby.truffle.runtime.util;

import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.runtime.ArgumentType;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

public class ArgumentDescriptorUtils {

public static DynamicObject argumentDescriptorsToParameters(RubyContext context, ArgumentDescriptor[] argsDesc, boolean isLambda) {
final Object[] params = new Object[argsDesc.length];

for (int i = 0; i < argsDesc.length; i++) {
params[i] = toArray(context, argsDesc[i], isLambda);
}

return Layouts.ARRAY.createArray(context.getCoreLibrary().getArrayFactory(), params, params.length);
}

public static DynamicObject toArray(RubyContext context, ArgumentDescriptor argDesc, boolean isLambda) {
if ((argDesc.type == ArgumentType.req) && ! isLambda) {
return toArray(context, ArgumentType.opt, argDesc.name);
}
return toArray(context, argDesc.type, argDesc.name);
}

public static DynamicObject toArray(RubyContext context, ArgumentType argType, String name) {
final Object[] store;

if (argType.anonymous || name == null) {
store = new Object[] { context.getSymbol(argType.symbolicName) };
} else {
store = new Object[] { context.getSymbol(argType.symbolicName), context.getSymbol(name) };
}

return Layouts.ARRAY.createArray(context.getCoreLibrary().getArrayFactory(), store, store.length);
}
}

0 comments on commit 9595a68

Please sign in to comment.