Skip to content

Commit

Permalink
Merge branch 'master' into truffle-head
Browse files Browse the repository at this point in the history
Conflicts:
	truffle/src/main/java/org/jruby/truffle/nodes/control/TraceNode.java
	truffle/src/main/java/org/jruby/truffle/nodes/core/TruffleInteropNodes.java
	truffle/src/main/java/org/jruby/truffle/nodes/interop/InteropNode.java
	truffle/src/main/java/org/jruby/truffle/runtime/core/StringForeignAccessFactory.java
	truffle/src/main/java/org/jruby/truffle/runtime/subsystems/AttachmentsManager.java
	truffle/src/main/java/org/jruby/truffle/runtime/subsystems/TraceManager.java
	truffle/src/main/java/org/jruby/truffle/translator/BodyTranslator.java
chrisseaton committed Jul 10, 2015
2 parents bc78332 + 34c3d90 commit 1317665
Showing 138 changed files with 2,837 additions and 1,388 deletions.
2 changes: 1 addition & 1 deletion core/pom.rb
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@
jar 'com.github.jnr:jnr-enxio:0.9'
jar 'com.github.jnr:jnr-x86asm:1.0.2'
jar 'com.github.jnr:jnr-unixsocket:0.8'
jar 'com.github.jnr:jnr-posix:3.0.15-SNAPSHOT'
jar 'com.github.jnr:jnr-posix:3.0.15'
jar 'com.github.jnr:jnr-constants:0.8.8'
jar 'com.github.jnr:jnr-ffi:2.0.3'
jar 'com.github.jnr:jffi:${jffi.version}'
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -112,7 +112,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-posix</artifactId>
<version>3.0.15-SNAPSHOT</version>
<version>3.0.15</version>
</dependency>
<dependency>
<groupId>com.github.jnr</groupId>
18 changes: 14 additions & 4 deletions core/src/main/java/org/jruby/RubyProcess.java
Original file line number Diff line number Diff line change
@@ -627,16 +627,23 @@ public static IRubyObject waitpid(ThreadContext context, IRubyObject recv, IRuby
}

public static IRubyObject waitpid(Ruby runtime, IRubyObject[] args) {
int pid = -1;
long pid = -1;
int flags = 0;
if (args.length > 0) {
pid = (int)args[0].convertToInteger().getLongValue();
pid = args[0].convertToInteger().getLongValue();
}
if (args.length > 1) {
flags = (int)args[1].convertToInteger().getLongValue();
}

return runtime.newFixnum(waitpid(runtime, pid, flags));
pid = waitpid(runtime, pid, flags);

if (pid == 0) {
runtime.getCurrentContext().setLastExitStatus(runtime.getNil());
return runtime.getNil();
}

return runtime.newFixnum(pid);
}

public static long waitpid(Ruby runtime, long pid, int flags) {
@@ -645,7 +652,10 @@ public static long waitpid(Ruby runtime, long pid, int flags) {
pid = runtime.getPosix().waitpid(pid, status, flags);
raiseErrnoIfSet(runtime, ECHILD);

runtime.getCurrentContext().setLastExitStatus(RubyProcess.RubyStatus.newProcessStatus(runtime, status[0], pid));
if (pid > 0) {
runtime.getCurrentContext().setLastExitStatus(RubyProcess.RubyStatus.newProcessStatus(runtime, status[0], pid));
}

return pid;
}

4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/ext/socket/RubySocket.java
Original file line number Diff line number Diff line change
@@ -464,7 +464,9 @@ private void initDomain(Ruby runtime, IRubyObject domain) {
}

soDomain = family;
soProtocolFamily = ProtocolFamily.valueOf("PF" + soDomain.name().substring(2));
String name = soDomain.name();
if (name.startsWith("pseudo_")) name = name.substring(7);
soProtocolFamily = ProtocolFamily.valueOf("PF" + name.substring(2));
}

private void doConnectNonblock(ThreadContext context, Channel channel, SocketAddress addr) {
7 changes: 4 additions & 3 deletions core/src/main/java/org/jruby/ext/stringio/StringIO.java
Original file line number Diff line number Diff line change
@@ -1126,10 +1126,11 @@ public IRubyObject write(ThreadContext context, IRubyObject arg) {

enc = ptr.string.getEncoding();
enc2 = str.getEncoding();
final ByteList strByteList = str.getByteList();
if (enc != enc2 && enc != EncodingUtils.ascii8bitEncoding(runtime)
// this is a hack because we don't seem to handle incoming ASCII-8BIT properly in transcoder
&& enc2 != ASCIIEncoding.INSTANCE) {
str = runtime.newString(EncodingUtils.strConvEnc(context, str.getByteList(), enc2, enc));
str = runtime.newString(EncodingUtils.strConvEnc(context, strByteList, enc2, enc));
}
len = str.size();
if (len == 0) return RubyFixnum.zero(runtime);
@@ -1139,11 +1140,11 @@ public IRubyObject write(ThreadContext context, IRubyObject arg) {
ptr.pos = olen;
}
if (ptr.pos == olen) {
EncodingUtils.encStrBufCat(runtime, ptr.string, str.getByteList(), enc);
EncodingUtils.encStrBufCat(runtime, ptr.string, strByteList, enc);
} else {
strioExtend(ptr.pos, len);
ByteList ptrByteList = ptr.string.getByteList();
System.arraycopy(str.getByteList().getUnsafeBytes(), str.getByteList().getBegin(), ptrByteList.getUnsafeBytes(), ptrByteList.begin + ptr.pos, len);
System.arraycopy(strByteList.getUnsafeBytes(), strByteList.getBegin(), ptrByteList.getUnsafeBytes(), ptrByteList.begin() + ptr.pos, len);
}
ptr.string.infectBy(str);
ptr.string.infectBy(this);
13 changes: 7 additions & 6 deletions core/src/main/java/org/jruby/ext/timeout/Timeout.java
Original file line number Diff line number Diff line change
@@ -85,13 +85,11 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
public static class TimeoutToplevel {
@JRubyMethod(required = 1, optional = 1, visibility = PRIVATE)
public static IRubyObject timeout(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
final RubyModule timeout = context.runtime.getModule("Timeout");

switch (args.length) {
case 1:
return Timeout.timeout(context, timeout, args[0], block);
return Timeout.timeout(context, self, args[0], block);
case 2:
return Timeout.timeout(context, timeout, args[0], args[1], block);
return Timeout.timeout(context, self, args[0], args[1], block);
default:
Arity.raiseArgumentError(context.runtime, args.length, 1, 2);
return context.runtime.getNil();
@@ -100,7 +98,9 @@ public static IRubyObject timeout(ThreadContext context, IRubyObject self, IRuby
}

@JRubyMethod(module = true)
public static IRubyObject timeout(final ThreadContext context, IRubyObject timeout, IRubyObject seconds, Block block) {
public static IRubyObject timeout(final ThreadContext context, IRubyObject recv, IRubyObject seconds, Block block) {
IRubyObject timeout = context.runtime.getModule("Timeout");

// No seconds, just yield
if ( nilOrZeroSeconds(context, seconds) ) {
return block.yieldSpecific(context);
@@ -129,7 +129,8 @@ public static IRubyObject timeout(final ThreadContext context, IRubyObject timeo
}

@JRubyMethod(module = true)
public static IRubyObject timeout(final ThreadContext context, IRubyObject timeout, IRubyObject seconds, IRubyObject exceptionType, Block block) {
public static IRubyObject timeout(final ThreadContext context, IRubyObject recv, IRubyObject seconds, IRubyObject exceptionType, Block block) {
IRubyObject timeout = context.runtime.getModule("Timeout");
// No seconds, just yield
if ( nilOrZeroSeconds(context, seconds) ) {
return block.yieldSpecific(context);
Original file line number Diff line number Diff line change
@@ -89,7 +89,6 @@ protected void pre(InterpreterContext ic, ThreadContext context, IRubyObject sel
if (ic.pushNewDynScope()) {
context.pushScope(DynamicScope.newDynamicScope(ic.getStaticScope()));
}
context.setCurrentVisibility(getVisibility());
}

// FIXME: for subclasses we should override this method since it can be simple get
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/JRubyFile.java
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@ private static FileResource createResource(Ruby runtime, String cwd, String path

public static String normalizeSeps(String path) {
if (Platform.IS_WINDOWS) {
return path.replace('/', File.separatorChar);
return path.replace(File.separatorChar, '/');
} else {
return path;
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ public class Options {
public static final Option<Integer> TRUFFLE_ARRAYS_SMALL = integer(TRUFFLE, "truffle.arrays.small", 3, "Maximum size of an Array to consider small for optimisations.");
public static final Option<Integer> TRUFFLE_HASH_PACKED_ARRAY_MAX = integer(TRUFFLE, "truffle.hash.packed_array_max", 3, "Maximum size of a Hash to use with the packed array storage strategy.");

public static final Option<Integer> TRUFFLE_PASSALOT = integer(TRUFFLE, "truffle.passalot", 0, "Probabilty between 0 and 100 to randomly insert Thread.pass at a given line.");
public static final Option<Boolean> TRUFFLE_YIELDS = bool(TRUFFLE, "truffle.yields", false, "Insert GIL yieldpoints");
public static final Option<Integer> TRUFFLE_INSTRUMENTATION_SERVER_PORT = integer(TRUFFLE, "truffle.instrumentation_server_port", 0, "Port number to run an HTTP server on that provides instrumentation services");
public static final Option<String> TRUFFLE_TRANSLATOR_PRINT_AST = string(TRUFFLE, "truffle.translator.print_asts", "", "Comma delimited list of method names to print the AST of after translation.");
public static final Option<String> TRUFFLE_TRANSLATOR_PRINT_FULL_AST = string(TRUFFLE, "truffle.translator.print_full_asts", "", "Comma delimited list of method names to print the full AST of after translation.");
9 changes: 4 additions & 5 deletions core/src/test/java/org/jruby/test/TestKernel.java
Original file line number Diff line number Diff line change
@@ -31,7 +31,8 @@
***** END LICENSE BLOCK *****/
package org.jruby.test;

import java.io.File;
import java.util.ArrayList;

import org.jruby.Ruby;
import org.jruby.RubyException;
import org.jruby.RubyFixnum;
@@ -60,16 +61,14 @@ public void testLoad() throws Exception {
assertEquals("load did not load the same file several times", "1", eval("load '../test/loadTest.rb'"));
}


public void testRequire() throws Exception {
char s = File.separatorChar;
//reset the $loadTestvar
eval("$loadTest = nil");
assertEquals("failed to load the file test/loadTest", "0", eval("require '../test/loadTest'"));
assertEquals("incorrectly reloaded the file test/loadTest", "", eval("require '../test/loadTest'"));
assertEquals("incorrect value for $\" variable", "true", eval("print $\"[-1].end_with?('test" + s + "loadTest.rb')"));
}

assertEquals("incorrect value for $\" variable", "true", eval("print $\"[-1].end_with?('test/loadTest.rb')"));
}

public void testPrintf() throws Exception {
assertEquals("hello", eval("printf(\"%s\", \"hello\")"));
1,247 changes: 1,246 additions & 1 deletion lib/ruby/truffle/mri/rubygems.rb

Large diffs are not rendered by default.

96 changes: 95 additions & 1 deletion lib/ruby/truffle/mri/thread.rb
Original file line number Diff line number Diff line change
@@ -26,7 +26,101 @@ class ThreadError < StandardError
Thread.abort_on_exception = true
end

# Truffle: ConditionVariable is defined in Java.
#
# ConditionVariable objects augment class Mutex. Using condition variables,
# it is possible to suspend while in the middle of a critical section until a
# resource becomes available.
#
# Example:
#
# require 'thread'
#
# mutex = Mutex.new
# resource = ConditionVariable.new
#
# a = Thread.new {
# mutex.synchronize {
# # Thread 'a' now needs the resource
# resource.wait(mutex)
# # 'a' can now have the resource
# }
# }
#
# b = Thread.new {
# mutex.synchronize {
# # Thread 'b' has finished using the resource
# resource.signal
# }
# }
#
class ConditionVariable
#
# Creates a new ConditionVariable
#
def initialize
@waiters = {}
@waiters_mutex = Mutex.new
end

#
# Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
#
# If +timeout+ is given, this method returns after +timeout+ seconds passed,
# even if no other thread has signaled.
#
def wait(mutex, timeout=nil)
Thread.handle_interrupt(StandardError => :never) do
begin
Thread.handle_interrupt(StandardError => :on_blocking) do
@waiters_mutex.synchronize do
@waiters[Thread.current] = true
end
mutex.sleep timeout
end
ensure
@waiters_mutex.synchronize do
@waiters.delete(Thread.current)
end
end
end
self
end

#
# Wakes up the first thread in line waiting for this lock.
#
def signal
Thread.handle_interrupt(StandardError => :on_blocking) do
begin
t, _ = @waiters_mutex.synchronize { @waiters.shift }
t.run if t
rescue ThreadError
retry # t was already dead?
end
end
self
end

#
# Wakes up all threads waiting for this lock.
#
def broadcast
Thread.handle_interrupt(StandardError => :on_blocking) do
threads = nil
@waiters_mutex.synchronize do
threads = @waiters.keys
@waiters.clear
end
for t in threads
begin
t.run
rescue ThreadError
end
end
end
self
end
end

#
# This class provides a way to synchronize communication between threads.
4 changes: 2 additions & 2 deletions maven/jruby-jars/DEV_INSTRUCTIONS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
In order to build a new jruby-jars gem, here is the process:

* cd ../../
* mvn -Pjruby-jars
* ./mvnw -Pjruby-jars

the gem will be in ./pkg directory
the gem will be in ./pkg directory
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@ private void collectTests(ScriptingContainer container, String index) throws Exc
" next if filename =~ /psych\\/test_nil.rb/\n" +
// TODO file an issue or so
" next if filename =~ /test_load_compiled_ruby.rb/\n" +
" next if filename =~ /compiler\\/test_jrubyc.rb/\n" +
// TODO remove the following after fix of #2215
" next if filename =~ /test_jar_on_load_path.rb/\n" +
" next if filename =~ /test_file.rb/\n" +
@@ -86,11 +87,10 @@ private void runIt(String index, String script) throws Exception {
// runIt(null, "require '/home/christian/projects/active/maven/jruby/test/jruby/test_command_line_switches.rb'");
// }

// does not seem to pass at all
// @Test
// public void testObjectspace() throws Exception {
// runIt("objectspace");
// }
@Test
public void testObjectspace() throws Exception {
runIt("objectspace");
}

@Test
public void testMRI() throws Exception {
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ private void collectTests(ScriptingContainer container, String index) throws Exc
" next if filename =~ /psych\\/test_nil.rb/\n" +
// TODO file an issue or so
" next if filename =~ /test_load_compiled_ruby.rb/\n" +
" next if filename =~ /compiler\\/test_jrubyc.rb/\n" +
// TODO remove the following after fix of #2215
" next if filename =~ /test_jar_on_load_path.rb/\n" +
" next if filename =~ /test_file.rb/\n" +
@@ -88,11 +89,10 @@ private void runIt(String index, String script) throws Exception {
// runIt(null, "require '/home/christian/projects/active/maven/jruby/test/jruby/test_command_line_switches.rb'");
// }

// does not seem to pass at all
// @Test
// public void testObjectspace() throws Exception {
// runIt("objectspace");
// }
@Test
public void testObjectspace() throws Exception {
runIt("objectspace");
}

@Test
public void testMRI() throws Exception {
4 changes: 4 additions & 0 deletions pom.rb
Original file line number Diff line number Diff line change
@@ -289,6 +289,10 @@
build do
default_goal :deploy
end

plugin(:source, '2.1.2') do
execute_goals('jar-no-fork', :id => 'attach-sources')
end
end

profile 'single invoker test' do
14 changes: 14 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -835,6 +835,20 @@ DO NOT MODIFIY - GENERATED CODE
</activation>
<build>
<defaultGoal>deploy</defaultGoal>
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
5 changes: 5 additions & 0 deletions spec/ruby/core/process/waitpid_spec.rb
Original file line number Diff line number Diff line change
@@ -2,4 +2,9 @@

describe "Process.waitpid" do
it "needs to be reviewed for spec completeness"

it "returns nil when the process has not yet completed and WNOHANG is specified" do
pid = spawn("sleep 5")
Process.waitpid(pid, Process::WNOHANG).should == nil
end
end
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/kernel/__dir___tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
fails:Kernel#__dir__ returns the name of the directory containing the currently-executing file
fails:Kernel#__dir__ when used in eval with top level binding returns the name of the directory containing the currently-executing file
fails:Kernel#__dir__ returns the real name of the directory containing the currently-executing file
fails:Kernel#__dir__ when used in eval with top level binding returns the real name of the directory containing the currently-executing file
13 changes: 0 additions & 13 deletions spec/truffle/tags/core/kernel/public_send_tags.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
fails:Kernel#public_send invokes the named public method
fails:Kernel#public_send invokes the named alias of a public method
fails:Kernel#public_send invokes the named method
fails:Kernel#public_send accepts a String method name
fails:Kernel#public_send invokes a class method if called on a class
fails:Kernel#public_send raises an ArgumentError if called with fewer arguments than required parameters
fails:Kernel#public_send succeeds if passed an arbitrary number of arguments as a splat parameter
fails:Kernel#public_send succeeds when passing 1 or more arguments as a required and a splat parameter
fails:Kernel#public_send succeeds when passing 0 arguments to a method with one parameter with a default
fails:Kernel#public_send has an arity of -1
fails:Kernel#public_send raises a NoMethodError if the method is protected
fails:Kernel#public_send raises a NoMethodError if the named method is private
fails:Kernel#public_send raises a NoMethodError if the named method is an alias of a private method
fails:Kernel#public_send raises a NoMethodError if the named method is an alias of a protected method
fails:Kernel#public_send raises a NameError if the corresponding method can't be found
fails:Kernel#public_send raises a NameError if the corresponding singleton method can't be found
1 change: 0 additions & 1 deletion spec/truffle/tags/core/module/autoload_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fails:Module#autoload ignores the autoload request if the file is already loaded
fails:Module#autoload does not remove the constant from the constant table if the loaded files does not define it
fails:Module#autoload calls #to_path on non-string filenames
fails:Module#autoload calls #to_path on non-String filename arguments
5 changes: 0 additions & 5 deletions spec/truffle/tags/core/module/remove_class_variable_tags.txt

This file was deleted.

1 change: 1 addition & 0 deletions spec/truffle/tags/core/process/waitpid_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Process.waitpid returns nil when the process has not yet completed and WNOHANG is specified
39 changes: 19 additions & 20 deletions test/jruby/compiler/test_jrubyc.rb
Original file line number Diff line number Diff line change
@@ -86,12 +86,11 @@ def test_require
File.delete("test_file1.class") rescue nil
end

def test_signature_with_arg_named_result
if RbConfig::CONFIG['bindir'].match( /!\//) || RbConfig::CONFIG['bindir'].match( /:\//)
skip( 'only filesystem installations of jruby can compile ruby to java' )
end
$compile_test = false
File.open("test_file2.rb", "w") {|file| file.write(<<-RUBY
# only filesystem installations of jruby can compile ruby to java
if !(RbConfig::CONFIG['bindir'].match( /!\//) || RbConfig::CONFIG['bindir'].match( /:\//))
def test_signature_with_arg_named_result
$compile_test = false
File.open("test_file2.rb", "w") {|file| file.write(<<-RUBY
class C
java_signature 'public int f(int result)'
def f(arg)
@@ -100,19 +99,19 @@ def f(arg)
end
C.new.f(0)
RUBY
)}

JRuby::Compiler::compile_argv(["--verbose", "--java", "--javac", "test_file2.rb"])
output = File.read(@tempfile_stderr.path)

assert_equal("", output)

assert_nothing_raised { require 'test_file2' }
assert($compile_test)
ensure
File.delete("test_file2.rb") rescue nil
File.delete("C.java") rescue nil
File.delete("C.class") rescue nil
RUBY
)}

JRuby::Compiler::compile_argv(["--verbose", "--java", "--javac", "test_file2.rb"])
output = File.read(@tempfile_stderr.path)
assert_equal("", output)
assert_nothing_raised { require 'test_file2' }
assert($compile_test)
ensure
File.delete("test_file2.rb") rescue nil
File.delete("C.java") rescue nil
File.delete("C.class") rescue nil
end
end
end
4 changes: 2 additions & 2 deletions test/jruby/test_load_compiled_ruby.rb
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ def test_load_compiled_ruby
assert !(File.exist? FILENAME)
assert File.exist? COMPILED

$:.unshift('.')
$:.unshift(File.dirname(File.expand_path(FILENAME)))
load FILENAME
assert $test_load_compiled_ruby
ensure
@@ -26,4 +26,4 @@ def test_load_compiled_ruby
FileUtils.rm_f(COMPILED)
end
end
end
end
4 changes: 2 additions & 2 deletions test/jruby/test_load_compiled_ruby_class_from_classpath.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@

require 'jruby/compiler'

class LoadCompiledRubyClassFromClasspathTest < Test::Unit::TestCase
class TestLoadCompiledRubyClassFromClasspath < Test::Unit::TestCase
include TestHelper

RubyName = "runner"
@@ -46,7 +46,7 @@ def test_loading_compiled_ruby_class_from_classpath
result = nil

FileUtils.cd("..") do
result = jruby("-Xaot.loadClasses=true -r#{RubyName} -e '1'")
result = jruby("-r#{RubyName} -e '1'", 'jruby.aot.loadClasses' => 'true' )
end
assert_equal 0, $?.exitstatus, "did not get 0 for exit status from running jruby against the class"
assert_equal "hello from runner", result, "wrong text from runner"
6 changes: 2 additions & 4 deletions test/pom.rb
Original file line number Diff line number Diff line change
@@ -170,9 +170,7 @@ def truffle_spec_config(spec_type, generate_report)
jar 'org.jruby:jruby-complete', '${project.version}', :scope => :provided

plugin :antrun do
# objectspace seems not to work at all here
# [ 'mri', 'jruby','objectspace', 'slow' ].each do |index|
[ 'mri', 'jruby', 'slow' ].each do |index|
[ 'mri', 'jruby','objectspace', 'slow' ].each do |index|
files = ""
File.open(File.join(basedir, index + '.index')) do |f|
f.each_line.each do |line|
@@ -190,7 +188,7 @@ def truffle_spec_config(spec_type, generate_report)
execute_goals( 'run',
:id => 'jruby_complete_jar_' + index,
:phase => 'test',
:configuration => [ xml( "<target><exec dir='${jruby.home}' executable='java' failonerror='true'><arg value='-cp'/><arg value='core/target/test-classes:test/target/test-classes:maven/jruby-complete/target/jruby-complete-${project.version}.jar'/><arg value='org.jruby.Main'/><arg value='-I.'/><arg value='-Itest/mri/ruby'/><arg value='-Itest/mri'/><arg value='-Itest'/><arg value='-rtest/mri_test_env'/><arg value='lib/ruby/stdlib/rake/rake_test_loader.rb'/>#{files}<arg value='-v'/></exec></target>" ) ] )
:configuration => [ xml( "<target><exec dir='${jruby.home}' executable='java' failonerror='true'><arg value='-cp'/><arg value='core/target/test-classes:test/target/test-classes:maven/jruby-complete/target/jruby-complete-${project.version}.jar'/><arg value='-Djruby.aot.loadClasses=true'/><arg value='org.jruby.Main'/><arg value='-I.'/><arg value='-Itest/mri/ruby'/><arg value='-Itest/mri'/><arg value='-Itest'/><arg value='-rtest/mri_test_env'/><arg value='lib/ruby/stdlib/rake/rake_test_loader.rb'/>#{files}<arg value='-v'/></exec></target>" ) ] )
end
end

44 changes: 44 additions & 0 deletions tool/jruby_eclipse
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/ruby
# A JRuby launcher, in Ruby, and using the class files from Eclipse
# Currently needs the core and stdlib jar, so build them again when they change.

JRUBY = File.expand_path('../..', __FILE__)
TRUFFLEJAR = "#{Dir.home}/.m2/repository/com/oracle/truffle/0.7/truffle-0.7.jar"

java = ENV["JAVACMD"] || "java"

bootclasspath = "-Xbootclasspath/a"
[
"#{JRUBY}/lib/jruby.jar",
TRUFFLEJAR,
"#{JRUBY}/lib/jruby-stdlib-9.0.0.0-SNAPSHOT.jar",
"#{JRUBY}/truffle/build.eclipse",
"#{JRUBY}/truffle/src/main/ruby"
].each { |path| bootclasspath << ":#{path}" }

args = [java]
args << "-Djffi.boot.library.path=#{JRUBY}/lib/jni"
args << bootclasspath

args << "-Djruby.home=#{JRUBY}"
args << "-Djruby.lib=#{JRUBY}/lib"
args << "-Djruby.script=jruby"
args << "-Djruby.shell=/bin/sh"

java_flags = []
rest = []
ARGV.each { |arg|
if arg.start_with?("-Xmx") or arg == "-ea"
java_flags << arg
elsif arg.start_with?("-J")
java_flags << arg[2..-1]
else
rest << arg
end
}

args += java_flags
args << "org.jruby.Main"
args += rest

exec(*args)
31 changes: 20 additions & 11 deletions tool/jt.rb
Original file line number Diff line number Diff line change
@@ -155,11 +155,16 @@ def mvn(*args)

def mspec(command, *args)
env_vars = {}
mspec_env env_vars, command, *args
end
if command.is_a?(Hash)
env_vars = command
command, *args = args
end

if ENV["JRUBY_ECLIPSE"] == "true"
args.unshift "-ttool/jruby_eclipse"
end

def mspec_env(env, command, *args)
sh env, 'ruby', 'spec/mspec/bin/mspec', command, '--config', 'spec/truffle/truffle.mspec', *args
sh env_vars, 'ruby', 'spec/mspec/bin/mspec', command, '--config', 'spec/truffle/truffle.mspec', *args
end
end

@@ -227,9 +232,7 @@ def clean
end

def irb(*args)
env_vars = {}
jruby_args = %w[-X+T -S irb]
raw_sh(env_vars, "#{JRUBY_DIR}/bin/jruby", *jruby_args, *args)
run(*%w[-S irb], *args)
end

def rebuild
@@ -272,7 +275,13 @@ def run(*args)
jruby_args += %w[-J-G:Dump=TrufflePartialEscape]
end

raw_sh env_vars, "#{JRUBY_DIR}/bin/jruby", *jruby_args, *args
if ENV["JRUBY_ECLIPSE"] == "true"
jruby_bin = "#{JRUBY_DIR}/tool/jruby_eclipse"
else
jruby_bin = "#{JRUBY_DIR}/bin/jruby"
end

raw_sh env_vars, jruby_bin, *jruby_args, *args
end
alias ruby run

@@ -292,14 +301,14 @@ def test_mri(*args)
env_vars = {
"EXCLUDES" => "test/mri/excludes_truffle"
}
jruby_args = %w[-J-Xmx2G -X+T -Xtruffle.exceptions.print_java]
jruby_args = %w[-J-Xmx2G -Xtruffle.exceptions.print_java]

if args.empty?
args = File.readlines("#{JRUBY_DIR}/test/mri_truffle.index").grep(/^[^#]\w+/).map(&:chomp)
end

command = %w[test/mri/runner.rb -v --color=never --tty=no -q]
raw_sh(env_vars, "#{JRUBY_DIR}/bin/jruby", *jruby_args, *command, *args)
run(env_vars, *jruby_args, *command, *args)
end
private :test_mri

@@ -350,7 +359,7 @@ def test_specs(*args)
options << "-T#{JEXCEPTION}"
end

mspec_env env_vars, 'run', *options, *args
mspec env_vars, 'run', *options, *args
end
private :test_specs

1 change: 0 additions & 1 deletion truffle/src/main/java/org/jruby/truffle/Main.java
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public class Main {

4 changes: 4 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyGuards.java
Original file line number Diff line number Diff line change
@@ -154,6 +154,10 @@ public static boolean isRubiniusByteArray(RubyBasicObject value) {
return value.getDynamicObject().getShape().getObjectType() == ByteArrayNodes.BYTE_ARRAY_TYPE;
}

public static boolean isRubyProc(Object value) {
return value instanceof RubyProc;
}

// Internal types

public static boolean isThreadLocal(Object value) {
13 changes: 2 additions & 11 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
import jnr.ffi.provider.MemoryManager;
import jnr.posix.POSIX;
import org.jcodings.Encoding;
import org.jruby.truffle.nodes.core.BindingNodes;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.dispatch.DispatchNode;
@@ -140,16 +141,6 @@ public double executeDouble(VirtualFrame frame) throws UnexpectedResultException
}
}

public RubyString executeRubyString(VirtualFrame frame) throws UnexpectedResultException {
final Object value = execute(frame);

if (value instanceof RubyString) {
return (RubyString) value;
} else {
throw new UnexpectedResultException(value);
}
}

public RubyRegexp executeRubyRegexp(VirtualFrame frame) throws UnexpectedResultException {
final Object value = execute(frame);

@@ -339,7 +330,7 @@ protected Object ruby(VirtualFrame frame, String expression, Object... arguments
protected Object rubyWithSelf(VirtualFrame frame, Object self, String expression, Object... arguments) {
final MaterializedFrame evalFrame = setupFrame(RubyArguments.getSelf(frame.getArguments()), arguments);

final RubyBinding binding = new RubyBinding(
final RubyBasicObject binding = BindingNodes.createRubyBinding(
getContext().getCoreLibrary().getBindingClass(),
self,
evalFrame);
Original file line number Diff line number Diff line change
@@ -33,7 +33,6 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

/**
* This is a port of MRI's rb_cmpint, as taken from RubyComparable and broken out into specialized nodes.
@@ -53,7 +52,7 @@ public CmpIntNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract int executeCmpInt(VirtualFrame frame, Object cmpResult, RubyString a, Object b);
public abstract int executeCmpInt(VirtualFrame frame, Object cmpResult, Object a, Object b);

@Specialization
public int cmpInt(int value, Object receiver, Object other) {
Original file line number Diff line number Diff line change
@@ -12,9 +12,9 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ProcNodes;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.InternalMethod;

public class LambdaNode extends RubyNode {
@@ -34,7 +34,7 @@ public Object execute(VirtualFrame frame) {

// TODO(CS): not sure we're closing over the correct state here

return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA,
return ProcNodes.createRubyProc(getContext().getCoreLibrary().getProcClass(), ProcNodes.Type.LAMBDA,
method.getSharedMethodInfo(), method.getCallTarget(), method.getCallTarget(), method.getCallTarget(),
method.getDeclarationFrame(), method, RubyArguments.getSelf(frame.getArguments()), null);
}
Original file line number Diff line number Diff line change
@@ -38,14 +38,14 @@ public RubyBasicObject doNil(Object nil) {
return nil();
}

@Specialization
public RubyProc doRubyProc(RubyProc proc) {
@Specialization(guards = "isRubyProc(proc)")
public RubyBasicObject doRubyProc(RubyBasicObject proc) {
return proc;
}

@Specialization
public RubyProc doObject(VirtualFrame frame, RubyBasicObject object) {
return (RubyProc) toProc.call(frame, object, "to_proc", null);
public Object doObject(VirtualFrame frame, RubyBasicObject object) {
return toProc.call(frame, object, "to_proc", null);
}

}
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyProc;

@NodeChild(value = "child", type = RubyNode.class)
@@ -25,26 +26,21 @@ public ProcOrNullNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract RubyProc executeProcOrNull(Object proc);
public abstract RubyBasicObject executeProcOrNull(Object proc);

@Specialization
public RubyProc doNotProvided(NotProvided proc) {
public RubyBasicObject doNotProvided(NotProvided proc) {
return null;
}

@Specialization(guards = "isNil(nil)")
public RubyProc doNil(Object nil) {
public RubyBasicObject doNil(Object nil) {
return null;
}

@Specialization
public RubyProc doProc(RubyProc proc) {
@Specialization(guards = "isRubyProc(proc)")
public RubyBasicObject doProc(RubyBasicObject proc) {
return proc;
}

@Override
public final RubyProc executeRubyProc(VirtualFrame frame) {
return (RubyProc) execute(frame);
}

}
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

/**
* Creates a symbol from a string.
@@ -27,8 +26,8 @@ public StringToSymbolNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public RubyBasicObject doString(RubyString string) {
@Specialization(guards = "isRubyString(string)")
public RubyBasicObject doString(RubyBasicObject string) {
return getSymbol(string.toString());
}

17 changes: 7 additions & 10 deletions truffle/src/main/java/org/jruby/truffle/nodes/cast/ToSNode.java
Original file line number Diff line number Diff line change
@@ -15,14 +15,14 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.KernelNodes;
import org.jruby.truffle.nodes.core.KernelNodesFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(type = RubyNode.class)
public abstract class ToSNode extends RubyNode {
@@ -43,20 +43,17 @@ protected RubyBasicObject kernelToS(VirtualFrame frame, Object object) {
return kernelToSNode.executeToS(frame, object);
}

@Override
public abstract RubyString executeRubyString(VirtualFrame frame);

@Specialization
public RubyBasicObject toS(RubyString string) {
@Specialization(guards = "isRubyString(string)")
public RubyBasicObject toS(RubyBasicObject string) {
return string;
}

@Specialization(guards = "!isRubyString(object)", rewriteOn = UnexpectedResultException.class)
public RubyBasicObject toS(VirtualFrame frame, Object object) throws UnexpectedResultException {
final Object value = callToSNode.call(frame, object, "to_s", null);

if (value instanceof RubyString) {
return (RubyString) value;
if (RubyGuards.isRubyString(value)) {
return (RubyBasicObject) value;
}

throw new UnexpectedResultException(value);
@@ -66,8 +63,8 @@ public RubyBasicObject toS(VirtualFrame frame, Object object) throws UnexpectedR
public RubyBasicObject toSFallback(VirtualFrame frame, Object object) {
final Object value = callToSNode.call(frame, object, "to_s", null);

if (value instanceof RubyString) {
return (RubyString) value;
if (RubyGuards.isRubyString(value)) {
return (RubyBasicObject) value;
} else {
return kernelToS(frame, object);
}
Original file line number Diff line number Diff line change
@@ -15,14 +15,14 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

/**
* Take a Symbol or some object accepting #to_str
@@ -45,8 +45,8 @@ public String coerceRubySymbol(RubyBasicObject symbol) {
return SymbolNodes.getString(symbol);
}

@Specialization
public String coerceRubyString(RubyString string) {
@Specialization(guards = "isRubyString(string)")
public String coerceRubyString(RubyBasicObject string) {
return string.toString();
}

@@ -65,7 +65,7 @@ public String coerceObject(VirtualFrame frame, Object object) {
}
}

if (coerced instanceof RubyString) {
if (RubyGuards.isRubyString(coerced)) {
return coerced.toString();
} else {
CompilerDirectives.transferToInterpreter();
Original file line number Diff line number Diff line change
@@ -15,13 +15,13 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

/**
* Take a Symbol or some object accepting #to_str
@@ -44,8 +44,8 @@ public RubyBasicObject coerceRubySymbol(RubyBasicObject symbol) {
return symbol;
}

@Specialization
public RubyBasicObject coerceRubyString(RubyString string) {
@Specialization(guards = "isRubyString(string)")
public RubyBasicObject coerceRubyString(RubyBasicObject string) {
return string;
}

@@ -64,8 +64,8 @@ public RubyBasicObject coerceObject(VirtualFrame frame, Object object) {
}
}

if (coerced instanceof RubyString) {
return (RubyString) coerced;
if (RubyGuards.isRubyString(coerced)) {
return (RubyBasicObject) coerced;
} else {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorBadCoercion(object, "String", "to_str", coerced, this));
Original file line number Diff line number Diff line change
@@ -15,13 +15,13 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(value = "child", type = RubyNode.class)
public abstract class ToStrNode extends RubyNode {
@@ -33,10 +33,10 @@ public ToStrNode(RubyContext context, SourceSection sourceSection) {
toStrNode = DispatchHeadNodeFactory.createMethodCall(context);
}

public abstract RubyString executeRubyString(VirtualFrame frame, Object object);
public abstract RubyBasicObject executeToStr(VirtualFrame frame, Object object);

@Specialization
public RubyBasicObject coerceRubyString(RubyString string) {
@Specialization(guards = "isRubyString(string)")
public RubyBasicObject coerceRubyString(RubyBasicObject string) {
return string;
}

@@ -57,8 +57,8 @@ public RubyBasicObject coerceObject(VirtualFrame frame, Object object) {
}
}

if (coerced instanceof RubyString) {
return (RubyString) coerced;
if (RubyGuards.isRubyString(coerced)) {
return (RubyBasicObject) coerced;
} else {
CompilerDirectives.transferToInterpreter();

Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.util.IdUtil;

@NodeChildren({
@@ -53,7 +52,7 @@ protected Object getConstant(RubyModule module, String name, RubyConstant consta
protected Object autoloadConstant(VirtualFrame frame, RubyModule module, String name, RubyConstant constant,
@Cached("createRequireNode()") RequireNode requireNode) {

requireNode.require((RubyString) constant.getValue());
requireNode.require((RubyBasicObject) constant.getValue());

// retry
return this.executeGetConstant(frame, module, name);
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@
import org.jruby.truffle.nodes.core.SymbolNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(value="child", type=RubyNode.class)
public abstract class ToJavaStringNode extends RubyNode {
@@ -33,13 +32,13 @@ public ToJavaStringNode(RubyContext context, SourceSection sourceSection) {

@TruffleBoundary
@Specialization(guards = "isRubySymbol(symbol)")
protected String toJavaString(RubyBasicObject symbol) {
protected String toJavaStringSymbol(RubyBasicObject symbol) {
return SymbolNodes.getString(symbol);
}

@TruffleBoundary
@Specialization
protected String toJavaString(RubyString string) {
@Specialization(guards = "isRubyString(string)")
protected String toJavaStringString(RubyBasicObject string) {
return string.toString();
}

Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(value="child", type=RubyNode.class)
public abstract class ToSymbolNode extends RubyNode {
@@ -31,12 +30,12 @@ public ToSymbolNode(RubyContext context, SourceSection sourceSection) {
// TODO(CS): cache the conversion to a symbol? Or should the user do that themselves?

@Specialization(guards = "isRubySymbol(symbol)")
protected RubyBasicObject toSymbol(RubyBasicObject symbol) {
protected RubyBasicObject toSymbolSymbol(RubyBasicObject symbol) {
return symbol;
}

@Specialization
protected RubyBasicObject toSymbol(RubyString string) {
@Specialization(guards = "isRubyString(string)")
protected RubyBasicObject toSymbolString(RubyBasicObject string) {
return getSymbol(StringNodes.getByteList(string));
}

Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.core.RubyString;

@CoreClass(name = "BasicObject")
public abstract class BasicObjectNodes {
@@ -177,10 +176,9 @@ public InstanceEvalNode(RubyContext context, SourceSection sourceSection) {
yield = new YieldDispatchHeadNode(context);
}

@Specialization
public Object instanceEval(VirtualFrame frame, Object receiver, RubyString string, NotProvided block) {
CompilerDirectives.transferToInterpreter();

@CompilerDirectives.TruffleBoundary
@Specialization(guards = "isRubyString(string)")
public Object instanceEval(Object receiver, RubyBasicObject string, NotProvided block) {
return getContext().instanceEval(StringNodes.getByteList(string), receiver, this);
}

Original file line number Diff line number Diff line change
@@ -30,35 +30,57 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.InternalMethod;

@CoreClass(name = "Binding")
public abstract class BindingNodes {

public static RubyBasicObject createRubyBinding(RubyClass bindingClass) {
return createRubyBinding(bindingClass, null, null);
}

public static RubyBasicObject createRubyBinding(RubyClass bindingClass, Object self, MaterializedFrame frame) {
return new RubyBinding(bindingClass, self, frame);
}

public static void setSelfAndFrame(RubyBasicObject binding, Object self, MaterializedFrame frame) {
((RubyBinding) binding).self = self;
((RubyBinding) binding).frame = frame;
}

public static Object getSelf(RubyBasicObject binding) {
return ((RubyBinding) binding).self;
}

public static MaterializedFrame getFrame(RubyBasicObject binding) {
return ((RubyBinding) binding).frame;
}

@CoreMethod(names = "initialize_copy", required = 1)
public abstract static class InitializeCopyNode extends CoreMethodArrayArgumentsNode {

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

@Specialization
public Object initializeCopy(RubyBinding self, RubyBinding from) {
@Specialization(guards = "isRubyBinding(from)")
public Object initializeCopy(RubyBasicObject self, RubyBasicObject from) {
if (self == from) {
return self;
}

final Object[] arguments = from.getFrame().getArguments();
final Object[] arguments = getFrame(from).getArguments();
final InternalMethod method = RubyArguments.getMethod(arguments);
final Object boundSelf = RubyArguments.getSelf(arguments);
final RubyProc boundBlock = RubyArguments.getBlock(arguments);
final Object[] userArguments = RubyArguments.extractUserArguments(arguments);

final Object[] copiedArguments = RubyArguments.pack(method, from.getFrame(), boundSelf, boundBlock, userArguments);
final Object[] copiedArguments = RubyArguments.pack(method, getFrame(from), boundSelf, boundBlock, userArguments);
final MaterializedFrame copiedFrame = Truffle.getRuntime().createMaterializedFrame(copiedArguments);

self.initialize(from.getSelf(), copiedFrame);
setSelfAndFrame(self, getSelf(from), copiedFrame);

return self;
}
@@ -82,7 +104,7 @@ public LocalVariableGetNode(RubyContext context, SourceSection sourceSection) {
"getFrameDescriptor(binding) == cachedFrameDescriptor"

})
public Object localVariableGetCached(RubyBinding binding, RubyBasicObject symbol,
public Object localVariableGetCached(RubyBasicObject binding, RubyBasicObject symbol,
@Cached("symbol") RubyBasicObject cachedSymbol,
@Cached("getFrameDescriptor(binding)") FrameDescriptor cachedFrameDescriptor,
@Cached("findFrameSlot(binding, symbol)") FrameSlot cachedFrameSlot,
@@ -91,14 +113,14 @@ public Object localVariableGetCached(RubyBinding binding, RubyBasicObject symbol
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorLocalVariableNotDefined(SymbolNodes.getString(symbol), binding, this));
} else {
return readLocalVariableNode.executeRead(binding.getFrame());
return readLocalVariableNode.executeRead(getFrame(binding));
}
}

@TruffleBoundary
@Specialization(guards = {"isRubySymbol(symbol)", "!isLastLine(symbol)"})
public Object localVariableGetUncached(RubyBinding binding, RubyBasicObject symbol) {
final MaterializedFrame frame = binding.getFrame();
public Object localVariableGetUncached(RubyBasicObject binding, RubyBasicObject symbol) {
final MaterializedFrame frame = getFrame(binding);
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));

if (frameSlot == null) {
@@ -110,8 +132,8 @@ public Object localVariableGetUncached(RubyBinding binding, RubyBasicObject symb

@TruffleBoundary
@Specialization(guards = {"isRubySymbol(symbol)", "isLastLine(symbol)"})
public Object localVariableGetLastLine(RubyBinding binding, RubyBasicObject symbol) {
final MaterializedFrame frame = binding.getFrame();
public Object localVariableGetLastLine(RubyBasicObject binding, RubyBasicObject symbol) {
final MaterializedFrame frame = getFrame(binding);
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));

if (frameSlot == null) {
@@ -126,16 +148,18 @@ public Object localVariableGetLastLine(RubyBinding binding, RubyBasicObject symb
}
}

protected FrameDescriptor getFrameDescriptor(RubyBinding binding) {
return binding.getFrame().getFrameDescriptor();
protected FrameDescriptor getFrameDescriptor(RubyBasicObject binding) {
assert RubyGuards.isRubyBinding(binding);
return getFrame(binding).getFrameDescriptor();
}

protected FrameSlot findFrameSlot(RubyBinding binding, RubyBasicObject symbol) {
protected FrameSlot findFrameSlot(RubyBasicObject binding, RubyBasicObject symbol) {
assert RubyGuards.isRubyBinding(binding);
assert RubyGuards.isRubySymbol(symbol);

final String symbolString = SymbolNodes.getString(symbol);

MaterializedFrame frame = binding.getFrame();
MaterializedFrame frame = getFrame(binding);

while (frame != null) {
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbolString);
@@ -180,41 +204,43 @@ public LocalVariableSetNode(RubyContext context, SourceSection sourceSection) {
"getFrameDescriptor(binding) == cachedFrameDescriptor",
"symbol == cachedSymbol"
})
public Object localVariableSetCached(RubyBinding binding, RubyBasicObject symbol, Object value,
public Object localVariableSetCached(RubyBasicObject binding, RubyBasicObject symbol, Object value,
@Cached("symbol") RubyBasicObject cachedSymbol,
@Cached("getFrameDescriptor(binding)") FrameDescriptor cachedFrameDescriptor,
@Cached("createWriteNode(findFrameSlot(binding, symbol))") WriteFrameSlotNode writeLocalVariableNode) {
return writeLocalVariableNode.executeWrite(binding.getFrame(), value);
return writeLocalVariableNode.executeWrite(getFrame(binding), value);
}

@TruffleBoundary
@Specialization(guards = {"isRubySymbol(symbol)", "!isLastLine(symbol)"})
public Object localVariableSetUncached(RubyBinding binding, RubyBasicObject symbol, Object value) {
final MaterializedFrame frame = binding.getFrame();
public Object localVariableSetUncached(RubyBasicObject binding, RubyBasicObject symbol, Object value) {
final MaterializedFrame frame = getFrame(binding);
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));
frame.setObject(frameSlot, value);
return value;
}

@TruffleBoundary
@Specialization(guards = {"isRubySymbol(symbol)", "isLastLine(symbol)"})
public Object localVariableSetLastLine(RubyBinding binding, RubyBasicObject symbol, Object value) {
final MaterializedFrame frame = binding.getFrame();
public Object localVariableSetLastLine(RubyBasicObject binding, RubyBasicObject symbol, Object value) {
final MaterializedFrame frame = getFrame(binding);
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(SymbolNodes.getString(symbol));
frame.setObject(frameSlot, ThreadLocalObject.wrap(getContext(), value));
return value;
}

protected FrameDescriptor getFrameDescriptor(RubyBinding binding) {
return binding.getFrame().getFrameDescriptor();
protected FrameDescriptor getFrameDescriptor(RubyBasicObject binding) {
assert RubyGuards.isRubyBinding(binding);
return getFrame(binding).getFrameDescriptor();
}

protected FrameSlot findFrameSlot(RubyBinding binding, RubyBasicObject symbol) {
protected FrameSlot findFrameSlot(RubyBasicObject binding, RubyBasicObject symbol) {
assert RubyGuards.isRubyBinding(binding);
assert RubyGuards.isRubySymbol(symbol);

final String symbolString = SymbolNodes.getString(symbol);

MaterializedFrame frame = binding.getFrame();
MaterializedFrame frame = getFrame(binding);

while (frame != null) {
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbolString);
@@ -226,7 +252,7 @@ protected FrameSlot findFrameSlot(RubyBinding binding, RubyBasicObject symbol) {
frame = RubyArguments.getDeclarationFrame(frame.getArguments());
}

return binding.getFrame().getFrameDescriptor().addFrameSlot(symbolString);
return getFrame(binding).getFrameDescriptor().addFrameSlot(symbolString);
}

protected WriteFrameSlotNode createWriteNode(FrameSlot frameSlot) {
@@ -247,10 +273,10 @@ public LocalVariablesNode(RubyContext context, SourceSection sourceSection) {

@TruffleBoundary
@Specialization
public RubyBasicObject localVariables(RubyBinding binding) {
public RubyBasicObject localVariables(RubyBasicObject binding) {
final RubyBasicObject array = createEmptyArray();

MaterializedFrame frame = binding.getFrame();
MaterializedFrame frame = getFrame(binding);

while (frame != null) {
for (Object name : frame.getFrameDescriptor().getIdentifiers()) {

This file was deleted.

Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyEncoding;
import org.jruby.truffle.runtime.core.RubyRegexp;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.util.ByteList;

@CoreClass(name = "Encoding")
@@ -56,8 +55,8 @@ public CompatibleQueryNode(RubyContext context, SourceSection sourceSection) {
}

@TruffleBoundary
@Specialization
public Object isCompatible(RubyString first, RubyString second) {
@Specialization(guards = {"isRubyString(first)", "isRubyString(second)"})
public Object isCompatibleStringString(RubyBasicObject first, RubyBasicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getCodeRangeable(first), StringNodes.getCodeRangeable(second));

if (compatibleEncoding != null) {
@@ -69,7 +68,7 @@ public Object isCompatible(RubyString first, RubyString second) {

@TruffleBoundary
@Specialization
public Object isCompatible(RubyEncoding first, RubyEncoding second) {
public Object isCompatibleEncodingEncoding(RubyEncoding first, RubyEncoding second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first.getEncoding(), second.getEncoding());

if (compatibleEncoding != null) {
@@ -80,8 +79,8 @@ public Object isCompatible(RubyEncoding first, RubyEncoding second) {
}

@TruffleBoundary
@Specialization
public Object isCompatible(RubyString first, RubyRegexp second) {
@Specialization(guards = "isRubyString(first)")
public Object isCompatibleStringRegexp(RubyBasicObject first, RubyRegexp second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getByteList(first).getEncoding(), second.getRegex().getEncoding());

if (compatibleEncoding != null) {
@@ -92,8 +91,8 @@ public Object isCompatible(RubyString first, RubyRegexp second) {
}

@TruffleBoundary
@Specialization
public Object isCompatible(RubyRegexp first, RubyString second) {
@Specialization(guards = "isRubyString(second)")
public Object isCompatibleRegexpString(RubyRegexp first, RubyBasicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first.getRegex().getEncoding(), StringNodes.getByteList(second).getEncoding());

if (compatibleEncoding != null) {
@@ -105,7 +104,7 @@ public Object isCompatible(RubyRegexp first, RubyString second) {

@TruffleBoundary
@Specialization
public Object isCompatible(RubyRegexp first, RubyRegexp second) {
public Object isCompatibleRegexpRegexp(RubyRegexp first, RubyRegexp second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first.getRegex().getEncoding(), second.getRegex().getEncoding());

if (compatibleEncoding != null) {
@@ -117,7 +116,7 @@ public Object isCompatible(RubyRegexp first, RubyRegexp second) {

@TruffleBoundary
@Specialization(guards = "isRubySymbol(second)")
public Object isCompatible(RubyRegexp first, RubyBasicObject second) {
public Object isCompatibleRegexpSymbol(RubyRegexp first, RubyBasicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first.getRegex().getEncoding(), SymbolNodes.getByteList(second).getEncoding());

if (compatibleEncoding != null) {
@@ -129,7 +128,7 @@ public Object isCompatible(RubyRegexp first, RubyBasicObject second) {

@TruffleBoundary
@Specialization(guards = "isRubySymbol(first)")
public Object isCompatible(RubyBasicObject first, RubyRegexp second) {
public Object isCompatibleSymbolRegexp(RubyBasicObject first, RubyRegexp second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(SymbolNodes.getByteList(first).getEncoding(), second.getRegex().getEncoding());

if (compatibleEncoding != null) {
@@ -140,8 +139,8 @@ public Object isCompatible(RubyBasicObject first, RubyRegexp second) {
}

@TruffleBoundary
@Specialization(guards = "isRubySymbol(second)")
public Object isCompatible(RubyString first, RubyBasicObject second) {
@Specialization(guards = {"isRubyString(first)", "isRubySymbol(second)"})
public Object isCompatibleStringSymbol(RubyBasicObject first, RubyBasicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getCodeRangeable(first), SymbolNodes.getCodeRangeable(second));

if (compatibleEncoding != null) {
@@ -153,7 +152,7 @@ public Object isCompatible(RubyString first, RubyBasicObject second) {

@TruffleBoundary
@Specialization(guards = {"isRubySymbol(first)", "isRubySymbol(second)"})
public Object isCompatible(RubyBasicObject first, RubyBasicObject second) {
public Object isCompatibleSymbolSymbol(RubyBasicObject first, RubyBasicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(SymbolNodes.getCodeRangeable(first), SymbolNodes.getCodeRangeable(second));

if (compatibleEncoding != null) {
@@ -164,8 +163,8 @@ public Object isCompatible(RubyBasicObject first, RubyBasicObject second) {
}

@TruffleBoundary
@Specialization
public Object isCompatible(RubyString first, RubyEncoding second) {
@Specialization(guards = "isRubyString(first)")
public Object isCompatibleStringEncoding(RubyBasicObject first, RubyEncoding second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getByteList(first).getEncoding(), second.getEncoding());

if (compatibleEncoding != null) {
@@ -196,8 +195,8 @@ public RubyEncoding defaultExternal(RubyEncoding encoding) {
return encoding;
}

@Specialization
public RubyEncoding defaultExternal(RubyString encodingString) {
@Specialization(guards = "isRubyString(encodingString)")
public RubyEncoding defaultExternal(RubyBasicObject encodingString) {
CompilerDirectives.transferToInterpreter();

final RubyEncoding rubyEncoding = RubyEncoding.getEncoding(encodingString.toString());
@@ -218,7 +217,7 @@ public RubyEncoding defaultExternal(VirtualFrame frame, Object encoding) {
toStrNode = insert(ToStrNodeGen.create(getContext(), getSourceSection(), null));
}

return defaultExternal(toStrNode.executeRubyString(frame, encoding));
return defaultExternal(toStrNode.executeToStr(frame, encoding));
}

}
@@ -260,7 +259,7 @@ public RubyBasicObject defaultInternal(VirtualFrame frame, Object encoding) {
toStrNode = insert(ToStrNodeGen.create(getContext(), getSourceSection(), null));
}

final RubyString encodingName = toStrNode.executeRubyString(frame, encoding);
final RubyBasicObject encodingName = toStrNode.executeToStr(frame, encoding);
getContext().getRuntime().setDefaultInternalEncoding(RubyEncoding.getEncoding(encodingName.toString()).getEncoding());

return encodingName;
Original file line number Diff line number Diff line change
@@ -16,18 +16,18 @@
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyRegexp;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.translator.BodyTranslator;
import org.jruby.util.RegexpOptions;

public class InteroplatedRegexpNode extends RubyNode {
public class InterpolatedRegexpNode extends RubyNode {

@Children private final RubyNode[] children;
private final RegexpOptions options;
@Child private CallDispatchHeadNode toS;

public InteroplatedRegexpNode(RubyContext context, SourceSection sourceSection, RubyNode[] children, RegexpOptions options) {
public InterpolatedRegexpNode(RubyContext context, SourceSection sourceSection, RubyNode[] children, RegexpOptions options) {
super(context, sourceSection);
this.children = children;
this.options = options;
@@ -42,7 +42,7 @@ public RubyRegexp executeRubyRegexp(VirtualFrame frame) {

for (int n = 0; n < children.length; n++) {
final Object child = children[n].execute(frame);
strings[n] = org.jruby.RubyString.newString(getContext().getRuntime(), StringNodes.getByteList(((RubyString) toS.call(frame, child, "to_s", null))));
strings[n] = org.jruby.RubyString.newString(getContext().getRuntime(), StringNodes.getByteList((RubyBasicObject) toS.call(frame, child, "to_s", null)));
}

final org.jruby.RubyString preprocessed = org.jruby.RubyRegexp.preprocessDRegexp(getContext().getRuntime(), strings, options);
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.cast.ToSNode;
import org.jruby.truffle.nodes.objects.IsTaintedNode;
@@ -23,7 +24,6 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyString;

/**
* A list of expressions to build up into a string.
@@ -47,39 +47,41 @@ public InterpolatedStringNode(RubyContext context, SourceSection sourceSection,
@ExplodeLoop
@Override
public Object execute(VirtualFrame frame) {
final RubyString[] strings = new RubyString[children.length];
final Object[] strings = new Object[children.length];

boolean tainted = false;

for (int n = 0; n < children.length; n++) {
final RubyString toInterpolate = children[n].executeRubyString(frame);
final Object toInterpolate = children[n].execute(frame);
strings[n] = toInterpolate;
tainted |= isTaintedNode.isTainted(toInterpolate);
tainted |= isTaintedNode.executeIsTainted(toInterpolate);
}

final RubyBasicObject string = concat(strings);
final Object string = concat(strings);

if (taintProfile.profile(tainted)) {
taintNode.taint(string);
taintNode.executeTaint(string);
}

return string;
}

@TruffleBoundary
private RubyBasicObject concat(RubyString[] strings) {
private RubyBasicObject concat(Object[] strings) {
// TODO(CS): there is a lot of copying going on here - and I think this is sometimes inner loop stuff

org.jruby.RubyString builder = null;

for (RubyString string : strings) {
for (Object string : strings) {
assert RubyGuards.isRubyString(string);

if (builder == null) {
builder = getContext().toJRuby(string);
builder = getContext().toJRubyString((RubyBasicObject) string);
} else {
try {
builder.append19(getContext().toJRuby(string));
} catch (org.jruby.exceptions.RaiseException e) {
throw new RaiseException(getContext().getCoreLibrary().encodingCompatibilityErrorIncompatible(builder.getEncoding().getCharsetName(), StringNodes.getByteList(string).getEncoding().getCharsetName(), this));
throw new RaiseException(getContext().getCoreLibrary().encodingCompatibilityErrorIncompatible(builder.getEncoding().getCharsetName(), StringNodes.getByteList((RubyBasicObject) string).getEncoding().getCharsetName(), this));
}
}
}
162 changes: 106 additions & 56 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -29,7 +29,6 @@
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyMatchData;
import org.jruby.truffle.runtime.core.RubyRange;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.util.ByteList;

import java.util.Arrays;
@@ -71,7 +70,7 @@ public Object getIndex(RubyMatchData matchData, int index, int length) {
}

@Specialization(guards = "isRubySymbol(index)")
public Object getIndex(RubyMatchData matchData, RubyBasicObject index, NotProvided length) {
public Object getIndexSymbol(RubyMatchData matchData, RubyBasicObject index, NotProvided length) {
CompilerDirectives.transferToInterpreter();

try {
@@ -86,8 +85,8 @@ public Object getIndex(RubyMatchData matchData, RubyBasicObject index, NotProvid
}
}

@Specialization
public Object getIndex(RubyMatchData matchData, RubyString index, NotProvided length) {
@Specialization(guards = "isRubyString(index)")
public Object getIndexString(RubyMatchData matchData, RubyBasicObject index, NotProvided length) {
CompilerDirectives.transferToInterpreter();

try {
Original file line number Diff line number Diff line change
@@ -273,9 +273,9 @@ public ToProcNode(RubyContext context, SourceSection sourceSection) {
public RubyProc toProc(RubyBasicObject methodObject) {
final InternalMethod method = getMethod(methodObject);

return new RubyProc(
return ProcNodes.createRubyProc(
getContext().getCoreLibrary().getProcClass(),
RubyProc.Type.LAMBDA,
ProcNodes.Type.LAMBDA,
method.getSharedMethodInfo(),
method.getCallTarget(),
method.getCallTarget(),
105 changes: 60 additions & 45 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -52,8 +52,11 @@
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyModule.MethodFilter;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.Arity;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
@@ -518,6 +521,7 @@ public abstract static class AutoloadNode extends CoreMethodNode {
@Child private StringNodes.EmptyNode emptyNode;
private final ConditionProfile invalidConstantName = ConditionProfile.createBinaryProfile();
private final ConditionProfile emptyFilename = ConditionProfile.createBinaryProfile();
private final ConditionProfile alreadyLoaded = ConditionProfile.createBinaryProfile();

public AutoloadNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -528,17 +532,19 @@ public AutoloadNode(RubyContext context, SourceSection sourceSection) {
return ToStrNodeGen.create(getContext(), getSourceSection(), filename);
}

@Specialization(guards = "isRubySymbol(name)")
public RubyBasicObject autoloadSymbol(RubyModule module, RubyBasicObject name, RubyString filename) {
@Specialization(guards = {"isRubySymbol(name)", "isRubyString(filename)"})
public RubyBasicObject autoloadSymbol(RubyModule module, RubyBasicObject name, RubyBasicObject filename) {
return autoload(module, SymbolNodes.getString(name), filename);
}

@Specialization(guards = "isRubyString(name)")
public RubyBasicObject autoloadString(RubyModule module, RubyBasicObject name, RubyString filename) {
@Specialization(guards = {"isRubyString(name)", "isRubyString(filename)"})
public RubyBasicObject autoloadString(RubyModule module, RubyBasicObject name, RubyBasicObject filename) {
return autoload(module, name.toString(), filename);
}

private RubyBasicObject autoload(RubyModule module, String name, RubyString filename) {
private RubyBasicObject autoload(RubyModule module, String name, RubyBasicObject filename) {
assert RubyGuards.isRubyString(filename);

if (invalidConstantName.profile(!IdUtil.isValidConstantName19(name))) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameError(String.format("autoload must be constant name: %s", name), name, this));
@@ -549,6 +555,10 @@ private RubyBasicObject autoload(RubyModule module, String name, RubyString file
throw new RaiseException(getContext().getCoreLibrary().argumentError("empty file name", this));
}

if (alreadyLoaded.profile(module.getConstants().get(name) != null)) {
return nil();
}

module.setAutoloadConstant(this, name, filename);

return nil();
@@ -599,35 +609,37 @@ protected RubyBasicObject toStr(VirtualFrame frame, Object object) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toStrNode = insert(ToStrNodeGen.create(getContext(), getSourceSection(), null));
}
return toStrNode.executeRubyString(frame, object);
return toStrNode.executeToStr(frame, object);
}

@Specialization
public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, code, "(eval)");
@Specialization(guards = "isRubyString(code)")
public Object classEval(RubyModule module, RubyBasicObject code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, "(eval)");
}

@Specialization
public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, RubyString file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, code, file.toString());
@Specialization(guards = {"isRubyString(code)", "isRubyString(file)"})
public Object classEval(RubyModule module, RubyBasicObject code, RubyBasicObject file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, file.toString());
}

@Specialization
public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, RubyString file, int line, NotProvided block) {
return classEvalSource(frame, module, code, file.toString());
@Specialization(guards = {"isRubyString(code)", "isRubyString(file)"})
public Object classEval(RubyModule module, RubyBasicObject code, RubyBasicObject file, int line, NotProvided block) {
return classEvalSource(module, code, file.toString());
}

@Specialization(guards = "wasProvided(code)")
public Object classEval(VirtualFrame frame, RubyModule module, Object code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, (RubyString) toStr(frame, code), file.toString());
return classEvalSource(module, toStr(frame, code), file.toString());
}

@Specialization(guards = "wasProvided(file)")
public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, Object file, NotProvided line, NotProvided block) {
return classEvalSource(frame, module, code, toStr(frame, file).toString());
@Specialization(guards = {"isRubyString(code)", "wasProvided(file)"})
public Object classEval(VirtualFrame frame, RubyModule module, RubyBasicObject code, Object file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, toStr(frame, file).toString());
}

private Object classEvalSource(VirtualFrame frame, RubyModule module, RubyString code, String file) {
private Object classEvalSource(RubyModule module, RubyBasicObject code, String file) {
assert RubyGuards.isRubyString(code);

final MaterializedFrame callerFrame = RubyCallStack.getCallerFrame(getContext())
.getFrame(FrameInstance.FrameAccess.MATERIALIZE, false).materialize();
Encoding encoding = StringNodes.getByteList(code).getEncoding();
@@ -900,24 +912,24 @@ public Object getConstant(VirtualFrame frame, RubyModule module, RubyBasicObject
}

@Specialization(guards = {"!inherit", "isRubySymbol(name)"})
public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, RubyBasicObject name, boolean inherit) {
public Object getConstantNoInherit(RubyModule module, RubyBasicObject name, boolean inherit) {
return getConstantNoInherit(module, SymbolNodes.getString(name), this);
}

// String
@Specialization(guards = { "inherit", "!isScoped(name)" })
public Object getConstant(VirtualFrame frame, RubyModule module, RubyString name, boolean inherit) {
@Specialization(guards = { "inherit", "isRubyString(name)", "!isScoped(name)" })
public Object getConstantString(VirtualFrame frame, RubyModule module, RubyBasicObject name, boolean inherit) {
return getConstantNode.executeGetConstant(frame, module, name.toString());
}

@Specialization(guards = { "!inherit", "!isScoped(name)" })
public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, RubyString name, boolean inherit) {
@Specialization(guards = { "!inherit", "isRubyString(name)", "!isScoped(name)" })
public Object getConstantNoInheritString(RubyModule module, RubyBasicObject name, boolean inherit) {
return getConstantNoInherit(module, name.toString(), this);
}

// Scoped String
@Specialization(guards = "isScoped(fullName)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, RubyString fullName, boolean inherit) {
@Specialization(guards = {"isRubyString(fullName)", "isScoped(fullName)"})
public Object getConstantScoped(RubyModule module, RubyBasicObject fullName, boolean inherit) {
return getConstantScoped(module, fullName.toString(), inherit);
}

@@ -945,7 +957,8 @@ private Object getConstantScoped(RubyModule module, String fullName, boolean inh
}

@TruffleBoundary
boolean isScoped(RubyString name) {
boolean isScoped(RubyBasicObject name) {
assert RubyGuards.isRubyString(name);
// TODO (eregon, 27 May 2015): Any way to make this efficient?
return name.toString().contains("::");
}
@@ -1067,9 +1080,9 @@ public RubyBasicObject defineMethod(VirtualFrame frame, RubyModule module, Strin
private RubyBasicObject defineMethod(RubyModule module, String name, RubyProc proc) {
CompilerDirectives.transferToInterpreter();

final CallTarget modifiedCallTarget = proc.getCallTargetForLambdas();
final SharedMethodInfo info = proc.getSharedMethodInfo().withName(name);
final InternalMethod modifiedMethod = new InternalMethod(info, name, module, Visibility.PUBLIC, false, modifiedCallTarget, proc.getDeclarationFrame());
final CallTarget modifiedCallTarget = ProcNodes.getCallTargetForLambdas(proc);
final SharedMethodInfo info = ProcNodes.getSharedMethodInfo(proc).withName(name);
final InternalMethod modifiedMethod = new InternalMethod(info, name, module, Visibility.PUBLIC, false, modifiedCallTarget, ProcNodes.getDeclarationFrame(proc));

return addMethod(module, name, modifiedMethod);
}
@@ -1202,8 +1215,8 @@ public RubyBasicObject includedModules(RubyModule module) {

final List<RubyModule> modules = new ArrayList<>();

for (RubyModule included : module.parentAncestors()) {
if (included.isOnlyAModule()) {
for (RubyModule included : module.ancestors()) {
if (included.isOnlyAModule() && included != module) {
modules.add(included);
}
}
@@ -1735,24 +1748,26 @@ public RubyModule doProtected(VirtualFrame frame, RubyModule module, Object[] na
}

@CoreMethod(names = "remove_class_variable", required = 1)
public abstract static class RemoveClassVariableNode extends CoreMethodArrayArgumentsNode {
@NodeChildren({
@NodeChild(type = RubyNode.class, value = "module"),
@NodeChild(type = RubyNode.class, value = "name")
})
public abstract static class RemoveClassVariableNode extends CoreMethodNode {

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

@TruffleBoundary
@Specialization(guards = "isRubyString(name)")
public RubyModule removeClassVariableString(RubyModule module, RubyBasicObject name) {
module.removeClassVariable(this, name.toString());
return module;
@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
return NameToJavaStringNodeGen.create(getContext(), getSourceSection(), name);
}

@TruffleBoundary
@Specialization(guards = "isRubySymbol(name)")
public RubyModule removeClassVariableSymbol(RubyModule module, RubyBasicObject name) {
module.removeClassVariable(this, SymbolNodes.getString(name));
return module;
@Specialization
public Object removeClassVariableString(RubyModule module, String name) {
RubyContext.checkClassVariableName(getContext(), name, this);
return module.removeClassVariable(this, name);
}

}
135 changes: 124 additions & 11 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
@@ -17,25 +18,129 @@
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
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.RubyGuards;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.util.Memo;

@CoreClass(name = "Proc")
public abstract class ProcNodes {

public static Type getType(RubyProc proc) {
return proc.type;
}

public static SharedMethodInfo getSharedMethodInfo(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).sharedMethodInfo;
}

public static CallTarget getCallTargetForBlocks(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).callTargetForBlocks;
}

public static CallTarget getCallTargetForProcs(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).callTargetForProcs;
}

public static CallTarget getCallTargetForLambdas(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).callTargetForLambdas;
}

public static MaterializedFrame getDeclarationFrame(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).declarationFrame;
}

public static InternalMethod getMethod(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).method;
}

public static Object getSelfCapturedInScope(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).self;
}

public static RubyBasicObject getBlockCapturedInScope(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
return ((RubyProc) proc).block;
}

public static CallTarget getCallTargetForType(RubyBasicObject proc) {
assert RubyGuards.isRubyProc(proc);
switch (((RubyProc) proc).type) {
case BLOCK:
return ((RubyProc) proc).callTargetForBlocks;
case PROC:
return ((RubyProc) proc).callTargetForProcs;
case LAMBDA:
return ((RubyProc) proc).callTargetForLambdas;
}

throw new UnsupportedOperationException(((RubyProc) proc).type.toString());
}

public static Object rootCall(RubyBasicObject proc, Object... args) {
assert RubyGuards.isRubyProc(proc);

return getCallTargetForType(proc).call(RubyArguments.pack(
getMethod(proc),
getDeclarationFrame(proc),
getSelfCapturedInScope(proc),
getBlockCapturedInScope(proc),
args));
}

public static void initialize(RubyBasicObject proc, SharedMethodInfo sharedMethodInfo, CallTarget callTargetForBlocks, CallTarget callTargetForProcs,
CallTarget callTargetForLambdas, MaterializedFrame declarationFrame, InternalMethod method,
Object self, RubyBasicObject block) {
assert RubyGuards.isRubyProc(proc);

((RubyProc) proc).sharedMethodInfo = sharedMethodInfo;
((RubyProc) proc).callTargetForBlocks = callTargetForBlocks;
((RubyProc) proc).callTargetForProcs = callTargetForProcs;
((RubyProc) proc).callTargetForLambdas = callTargetForLambdas;
((RubyProc) proc).declarationFrame = declarationFrame;
((RubyProc) proc).method = method;
((RubyProc) proc).self = self;
assert block == null || RubyGuards.isRubyProc(block);
((RubyProc) proc).block = block;
}

public static RubyProc createRubyProc(RubyClass procClass, Type type) {
return new RubyProc(procClass, type);
}

public static RubyProc createRubyProc(RubyClass procClass, Type type, SharedMethodInfo sharedMethodInfo, CallTarget callTargetForBlocks,
CallTarget callTargetForProcs, CallTarget callTargetForLambdas, MaterializedFrame declarationFrame,
InternalMethod method, Object self, RubyBasicObject block) {
return new RubyProc(procClass, type, sharedMethodInfo, callTargetForBlocks, callTargetForProcs, callTargetForLambdas, declarationFrame, method, self, block);
}

public enum Type {
BLOCK, PROC, LAMBDA
}

@CoreMethod(names = "arity")
public abstract static class ArityNode extends CoreMethodArrayArgumentsNode {

@@ -45,7 +150,7 @@ public ArityNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public int arity(RubyProc proc) {
return proc.getSharedMethodInfo().getArity().getArityNumber();
return getSharedMethodInfo(proc).getArity().getArityNumber();
}

}
@@ -59,9 +164,9 @@ public BindingNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public Object binding(RubyProc proc) {
final MaterializedFrame frame = proc.getDeclarationFrame();
final MaterializedFrame frame = getDeclarationFrame(proc);

return new RubyBinding(getContext().getCoreLibrary().getBindingClass(),
return BindingNodes.createRubyBinding(getContext().getCoreLibrary().getBindingClass(),
RubyArguments.getSelf(frame.getArguments()),
frame);
}
@@ -99,9 +204,9 @@ public InitializeNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public RubyBasicObject initialize(RubyProc proc, RubyProc block) {
proc.initialize(block.getSharedMethodInfo(), block.getCallTargetForProcs(),
block.getCallTargetForProcs(), block.getCallTargetForLambdas(), block.getDeclarationFrame(),
block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope());
ProcNodes.initialize(proc, getSharedMethodInfo(block), getCallTargetForProcs(block),
getCallTargetForProcs(block), getCallTargetForLambdas(block), getDeclarationFrame(block),
getMethod(block), getSelfCapturedInScope(block), getBlockCapturedInScope(block));

return nil();
}
@@ -150,7 +255,7 @@ public LambdaNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public boolean lambda(RubyProc proc) {
return proc.getType() == RubyProc.Type.LAMBDA;
return getType(proc) == Type.LAMBDA;
}

}
@@ -165,12 +270,12 @@ public ParametersNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public RubyBasicObject parameters(RubyProc proc) {
final ArgsNode argsNode = proc.getSharedMethodInfo().getParseTree().findFirstChild(ArgsNode.class);
final ArgsNode argsNode = getSharedMethodInfo(proc).getParseTree().findFirstChild(ArgsNode.class);

final ArgumentDescriptor[] argsDesc = Helpers.argsNodeToArgumentDescriptors(argsNode);

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

}
@@ -185,7 +290,7 @@ public SourceLocationNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public Object sourceLocation(RubyProc proc) {
SourceSection sourceSection = proc.getSharedMethodInfo().getSourceSection();
SourceSection sourceSection = getSharedMethodInfo(proc).getSourceSection();

if (sourceSection instanceof NullSourceSection) {
return nil();
@@ -198,4 +303,12 @@ public Object sourceLocation(RubyProc proc) {

}

public static class ProcAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return createRubyProc(rubyClass, Type.PROC);
}

}
}
23 changes: 10 additions & 13 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpNodes.java
Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyMatchData;
import org.jruby.truffle.runtime.core.RubyRegexp;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.util.ByteList;

import java.util.Iterator;
@@ -46,8 +45,8 @@ public MatchOperatorNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public Object match(RubyRegexp regexp, RubyString string) {
@Specialization(guards = "isRubyString(string)")
public Object match(RubyRegexp regexp, RubyBasicObject string) {
return regexp.matchCommon(string, true, true);
}

@@ -58,7 +57,7 @@ public Object match(VirtualFrame frame, RubyRegexp regexp, RubyBasicObject symbo
toSNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return match(regexp, (RubyString) toSNode.call(frame, symbol, "to_s", null));
return match(regexp, (RubyBasicObject) toSNode.call(frame, symbol, "to_s", null));
}

@Specialization(guards = "isNil(nil)")
@@ -73,7 +72,7 @@ public Object matchGeneric(VirtualFrame frame, RubyRegexp regexp, RubyBasicObjec
toStrNode = insert(ToStrNodeGen.create(getContext(), getSourceSection(), null));
}

return match(regexp, toStrNode.executeRubyString(frame, other));
return match(regexp, toStrNode.executeToStr(frame, other));
}

}
@@ -85,11 +84,9 @@ public EscapeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract RubyBasicObject executeEscape(VirtualFrame frame, RubyString pattern);

@TruffleBoundary
@Specialization
public RubyBasicObject escape(RubyString pattern) {
@Specialization(guards = "isRubyString(pattern)")
public RubyBasicObject escape(RubyBasicObject pattern) {
return createString(org.jruby.RubyRegexp.quote19(new ByteList(StringNodes.getByteList(pattern)), true).toString());
}

@@ -118,8 +115,8 @@ public MatchStartNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public Object matchStart(RubyRegexp regexp, RubyString string, int startPos) {
@Specialization(guards = "isRubyString(string)")
public Object matchStart(RubyRegexp regexp, RubyBasicObject string, int startPos) {
final Object matchResult = regexp.matchCommon(string, false, false, startPos);
if (matchResult instanceof RubyMatchData && ((RubyMatchData) matchResult).getNumberOfRegions() > 0
&& ((RubyMatchData) matchResult).getRegion().beg[0] == startPos) {
@@ -158,8 +155,8 @@ public SearchFromNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public Object searchFrom(RubyRegexp regexp, RubyString string, int startPos) {
@Specialization(guards = "isRubyString(string)")
public Object searchFrom(RubyRegexp regexp, RubyBasicObject string, int startPos) {
return regexp.matchCommon(string, false, false, startPos);
}
}
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.truffle.runtime.core.RubyBasicObject;

public class SetTopLevelBindingNode extends RubyNode {

@@ -24,7 +24,7 @@ public SetTopLevelBindingNode(RubyContext context, SourceSection sourceSection)

@Override
public Object execute(VirtualFrame frame) {
final RubyBinding binding = new RubyBinding(getContext().getCoreLibrary().getBindingClass(), RubyArguments.getSelf(frame.getArguments()), frame.materialize());
final RubyBasicObject binding = BindingNodes.createRubyBinding(getContext().getCoreLibrary().getBindingClass(), RubyArguments.getSelf(frame.getArguments()), frame.materialize());
getContext().getCoreLibrary().getObjectClass().setConstant(this, "TOPLEVEL_BINDING", binding);
return nil();
}
Original file line number Diff line number Diff line change
@@ -11,38 +11,46 @@
package org.jruby.truffle.nodes.core;

import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.util.CodeRangeSupport;
import org.jruby.util.StringSupport;

public class StringGuards {

public static boolean isSingleByteOptimizable(RubyString string) {
public static boolean isSingleByteOptimizable(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringSupport.isSingleByteOptimizable(StringNodes.getCodeRangeable(string), StringNodes.getByteList(string).getEncoding());
}

public static boolean isAsciiCompatible(RubyString string) {
public static boolean isAsciiCompatible(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.getByteList(string).getEncoding().isAsciiCompatible();
}

public static boolean isSingleByteOptimizableOrAsciiOnly(RubyString string) {
public static boolean isSingleByteOptimizableOrAsciiOnly(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
// TODO (nirvdrnum 08-Jun-15) Rubinius tracks whether a String is ASCII-only via a field in the String.
return isSingleByteOptimizable(string);
}

public static boolean isSingleByte(RubyString string) {
public static boolean isSingleByte(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.getByteList(string).getEncoding().isSingleByte();
}

public static boolean isValidOr7BitEncoding(RubyString string) {
public static boolean isValidOr7BitEncoding(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.isCodeRangeValid(string) || CodeRangeSupport.isCodeRangeAsciiOnly(StringNodes.getCodeRangeable(string));
}

public static boolean isFixedWidthEncoding(RubyString string) {
public static boolean isFixedWidthEncoding(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.getByteList(string).getEncoding().isFixedWidth();
}

public static boolean isValidUtf8(RubyString string) {
public static boolean isValidUtf8(RubyBasicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.isCodeRangeValid(string) && StringNodes.getByteList(string).getEncoding() instanceof UTF8Encoding;
}
}
Loading

0 comments on commit 1317665

Please sign in to comment.