Skip to content

Commit

Permalink
Showing 38 changed files with 630 additions and 308 deletions.
2 changes: 1 addition & 1 deletion core/pom.rb
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@
jar 'com.github.jnr:jnr-x86asm:1.0.2', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-unixsocket:0.8', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-posix:3.0.15', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-constants:0.9.0-SNAPSHOT', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-constants:0.9.0', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-ffi:2.0.3'
jar 'com.github.jnr:jffi:${jffi.version}'
jar 'com.github.jnr:jffi:${jffi.version}:native'
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-constants</artifactId>
<version>0.9.0-SNAPSHOT</version>
<version>0.9.0</version>
<exclusions>
<exclusion>
<artifactId>jnr-ffi</artifactId>
6 changes: 1 addition & 5 deletions core/src/main/java/org/jruby/parser/ParserSupport.java
Original file line number Diff line number Diff line change
@@ -42,7 +42,6 @@
import java.util.List;
import org.jcodings.Encoding;
import org.jruby.RubyBignum;
import org.jruby.RubyEncoding;
import org.jruby.RubyRegexp;
import org.jruby.ast.*;
import org.jruby.ast.types.ILiteralNode;
@@ -53,7 +52,6 @@
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.lexer.yacc.ISourcePositionHolder;
import org.jruby.lexer.yacc.RubyLexer;
import org.jruby.lexer.yacc.SyntaxException;
import org.jruby.lexer.yacc.SyntaxException.PID;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Signature;
@@ -1378,9 +1376,7 @@ public String internalId() {
return "";
}

private static final String TRUFFLE_CORE_LOAD_PATH = Options.TRUFFLE_CORE_LOAD_PATH.load();

public static boolean skipTruffleRubiniusWarnings(RubyLexer lexer) {
return lexer.getFile().startsWith(TRUFFLE_CORE_LOAD_PATH);
return lexer.getFile().startsWith(Options.TRUFFLE_CORE_LOAD_PATH.load());
}
}
63 changes: 31 additions & 32 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -126,35 +126,6 @@ public class Options {
public static final Option<Boolean> IR_WRITING_DEBUG = bool(IR, "ir.writing.debug", false, "Debug writing JRuby IR file.");
public static final Option<String> IR_INLINE_COMPILER_PASSES = string(IR, "ir.inline_passes", "Specify comma delimeted list of passes to run after inlining a method.");

public static final Option<String> TRUFFLE_CORE_LOAD_PATH = string(TRUFFLE, "truffle.core.load_path", "truffle:/jruby-truffle", "Directory to load the Truffle core library from.");

public static final Option<Integer> TRUFFLE_DISPATCH_POLYMORPHIC_MAX = integer(TRUFFLE, "truffle.dispatch.polymorphic.max", 8, "Maximum size of a polymorphic call site cache.");
public static final Option<Integer> TRUFFLE_ARRAYS_UNINITIALIZED_SIZE = integer(TRUFFLE, "truffle.arrays.uninitialized_size", 32, "How large an array to allocate when we have no other information to go on.");
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_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.");
public static final Option<String> TRUFFLE_TRANSLATOR_PRINT_PARSE_TREE = string(TRUFFLE, "truffle.translator.print_parse_trees", "", "Comma delimited list of method names to print the JRuby parse tree of before translation.");
public static final Option<Boolean> TRUFFLE_EXCEPTIONS_PRINT_JAVA = bool(TRUFFLE, "truffle.exceptions.print_java", false, "Print Java exceptions at the point of translating them to Ruby exceptions.");
public static final Option<Boolean> TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA = bool(TRUFFLE, "truffle.exceptions.print_uncaught_java", false, "Print uncaught Java exceptions at the point of translating them to Ruby exceptions.");
public static final Option<Boolean> TRUFFLE_COVERAGE = bool(TRUFFLE, "truffle.coverage", false, "Enable coverage (will be enabled by default in the future - currently has some bugs");

public static final Option<Boolean> TRUFFLE_BACKTRACES_HIDE_CORE_FILES = bool(TRUFFLE, "truffle.backtraces.hide_core_files", true, "Hide core source files in backtraces, like MRI does.");

public static final Option<Boolean> TRUFFLE_INLINER_ALWAYS_CLONE_YIELD = bool(TRUFFLE, "truffle.inliner.always_clone_yield", true, "Always clone yield call targets.");
public static final Option<Boolean> TRUFFLE_INLINER_ALWAYS_INLINE_YIELD = bool(TRUFFLE, "truffle.inliner.always_inline_yield", true, "Always inline yield call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED = bool(TRUFFLE, "truffle.dispatch.metaprogramming_always_uncached", false, "Always use uncached dispatch for the metaprogramming methods #__send__, #send and #respond_to?, and for any call site that has to use #method_missing or #const_missing.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT = bool(TRUFFLE, "truffle.dispatch.metaprogramming_always_indirect", false, "Always use indirect calls for the metaprogramming methods #__send__ and #send, and for any call site that has to use #method_missing or #const_missing.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED = bool(TRUFFLE, "truffle.call.method_missing_always_cloned", true, "Always clone #method_missing call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED = bool(TRUFFLE, "truffle.call.method_missing_always_inlined", true, "Always inline #method_missing call targets.");

public static final Option<Boolean> TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = bool(TRUFFLE, "truffle.set_trace_func.include_core_file_callers", false, "Include internal core library calls in set_trace_func output.");

public static final Option<Boolean> TRUFFLE_METRICS_TIME = bool(TRUFFLE, "truffle.metrics.time", false, "Print the time at various stages of VM operation.");
public static final Option<Boolean> TRUFFLE_METRICS_MEMORY_USED_ON_EXIT = bool(TRUFFLE, "truffle.metrics.memory_used_on_exit", false, "Print the size of heap memory in use on exit.");

public static final Option<Boolean> NATIVE_ENABLED = bool(NATIVE, "native.enabled", true, "Enable/disable native code, including POSIX features and C exts.");
public static final Option<Boolean> NATIVE_VERBOSE = bool(NATIVE, "native.verbose", false, "Enable verbose logging of native extension loading.");
public static final Option<Boolean> FFI_COMPILE_DUMP = bool(NATIVE, "ffi.compile.dump", false, "Dump bytecode-generated FFI stubs to console.");
@@ -171,15 +142,15 @@ public class Options {
public static final Option<Boolean> OBJECTSPACE_ENABLED = bool(MISCELLANEOUS, "objectspace.enabled", false, "Enable or disable ObjectSpace.each_object.");
public static final Option<Boolean> SIPHASH_ENABLED = bool(MISCELLANEOUS, "siphash.enabled", false, "Enable or disable SipHash for String hash function.");
public static final Option<Boolean> LAUNCH_INPROC = bool(MISCELLANEOUS, "launch.inproc", false, "Set in-process launching of e.g. system('ruby ...').");
public static final Option<String> BYTECODE_VERSION = string(MISCELLANEOUS, "bytecode.version", new String[]{"1.5","1.6","1.7"}, SafePropertyAccessor.getProperty("java.specification.version", "1.5"), "Specify the major Java bytecode version.");
public static final Option<String> BYTECODE_VERSION = string(MISCELLANEOUS, "bytecode.version", new String[]{"1.5", "1.6", "1.7"}, SafePropertyAccessor.getProperty("java.specification.version", "1.5"), "Specify the major Java bytecode version.");
public static final Option<Boolean> MANAGEMENT_ENABLED = bool(MISCELLANEOUS, "management.enabled", false, "Set whether JMX management is enabled.");
public static final Option<Boolean> JUMP_BACKTRACE = bool(MISCELLANEOUS, "jump.backtrace", false, "Make non-local flow jumps generate backtraces.");
public static final Option<Boolean> PROCESS_NOUNWRAP = bool(MISCELLANEOUS, "process.noUnwrap", false, "Do not unwrap process streams (issue on some recent JVMs).");
public static final Option<Boolean> REIFY_CLASSES = bool(MISCELLANEOUS, "reify.classes", false, "Before instantiation, stand up a real Java class for every Ruby class.");
public static final Option<Boolean> REIFY_LOGERRORS = bool(MISCELLANEOUS, "reify.logErrors", false, "Log errors during reification (reify.classes=true).");
public static final Option<Boolean> REFLECTED_HANDLES = bool(MISCELLANEOUS, "reflected.handles", false, "Use reflection for binding methods, not generated bytecode.");
public static final Option<Boolean> BACKTRACE_COLOR = bool(MISCELLANEOUS, "backtrace.color", false, "Enable colorized backtraces.");
public static final Option<String> BACKTRACE_STYLE = string(MISCELLANEOUS, "backtrace.style", new String[]{"normal","raw","full","mri"}, "normal", "Set the style of exception backtraces.");
public static final Option<String> BACKTRACE_STYLE = string(MISCELLANEOUS, "backtrace.style", new String[]{"normal", "raw", "full", "mri"}, "normal", "Set the style of exception backtraces.");
public static final Option<Boolean> BACKTRACE_MASK = bool(MISCELLANEOUS, "backtrace.mask", false, "Mask .java lines in Ruby backtraces.");
public static final Option<String> THREAD_DUMP_SIGNAL = string(MISCELLANEOUS, "thread.dump.signal", new String[]{"USR1", "USR2", "etc"}, "USR2", "Set the signal used for dumping thread stacks.");
public static final Option<Boolean> NATIVE_NET_PROTOCOL = bool(MISCELLANEOUS, "native.net.protocol", false, "Use native impls for parts of net/protocol.");
@@ -204,7 +175,7 @@ public class Options {
public static final Option<Boolean> LOG_BACKTRACES = bool(DEBUG, "log.backtraces", false, "Log every time an exception backtrace is generated.");
public static final Option<Boolean> LOG_CALLERS = bool(DEBUG, "log.callers", false, "Log every time a Kernel#caller backtrace is generated.");
public static final Option<Boolean> LOG_WARNINGS = bool(DEBUG, "log.warnings", false, "Log every time a built-in warning backtrace is generated.");
public static final Option<String> LOGGER_CLASS = string(DEBUG, "logger.class", new String[] {"class name"}, "org.jruby.util.log.StandardErrorLogger", "Use specified class for logging.");
public static final Option<String> LOGGER_CLASS = string(DEBUG, "logger.class", new String[]{"class name"}, "org.jruby.util.log.StandardErrorLogger", "Use specified class for logging.");
public static final Option<Boolean> DUMP_INSTANCE_VARS = bool(DEBUG, "dump.variables", false, "Dump class + instance var names on first new of Object subclasses.");
public static final Option<Boolean> REWRITE_JAVA_TRACE = bool(DEBUG, "rewrite.java.trace", true, "Rewrite stack traces from exceptions raised in Java calls.");

@@ -246,6 +217,34 @@ public class Options {
public static final Option<Boolean> CLI_RUBYOPT_ENABLE = bool(CLI, "cli.rubyopt.enable", true, "Enable/disable RUBYOPT processing at start.");
public static final Option<Boolean> CLI_STRIP_HEADER = bool(CLI, "cli.strip.header", false, "Strip text before shebang in script. Same as -x.");
public static final Option<Boolean> CLI_LOAD_GEMFILE = bool(CLI, "cli.load.gemfile", false, "Load a bundler Gemfile in cwd before running. Same as -G.");

public static final Option<String> TRUFFLE_CORE_LOAD_PATH = string(TRUFFLE, "truffle.core.load_path", "truffle:/jruby-truffle", "Directory to load the Truffle core library from.");

public static final Option<Integer> TRUFFLE_DISPATCH_POLYMORPHIC_MAX = integer(TRUFFLE, "truffle.dispatch.polymorphic.max", 8, "Maximum size of a polymorphic call site cache.");
public static final Option<Integer> TRUFFLE_ARRAYS_UNINITIALIZED_SIZE = integer(TRUFFLE, "truffle.arrays.uninitialized_size", 32, "How large an array to allocate when we have no other information to go on.");
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_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<Boolean> TRUFFLE_EXCEPTIONS_PRINT_JAVA = bool(TRUFFLE, "truffle.exceptions.print_java", false, "Print Java exceptions at the point of translating them to Ruby exceptions.");
public static final Option<Boolean> TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA = bool(TRUFFLE, "truffle.exceptions.print_uncaught_java", false, "Print uncaught Java exceptions at the point of translating them to Ruby exceptions.");
public static final Option<Boolean> TRUFFLE_COVERAGE = bool(TRUFFLE, "truffle.coverage", false, "Enable coverage (will be enabled by default in the future - currently has some bugs");

public static final Option<Boolean> TRUFFLE_BACKTRACES_HIDE_CORE_FILES = bool(TRUFFLE, "truffle.backtraces.hide_core_files", true, "Hide core source files in backtraces, like MRI does.");

public static final Option<Boolean> TRUFFLE_INLINER_ALWAYS_CLONE_YIELD = bool(TRUFFLE, "truffle.inliner.always_clone_yield", true, "Always clone yield call targets.");
public static final Option<Boolean> TRUFFLE_INLINER_ALWAYS_INLINE_YIELD = bool(TRUFFLE, "truffle.inliner.always_inline_yield", true, "Always inline yield call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED = bool(TRUFFLE, "truffle.dispatch.metaprogramming_always_uncached", false, "Always use uncached dispatch for the metaprogramming methods #__send__, #send and #respond_to?, and for any call site that has to use #method_missing or #const_missing.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT = bool(TRUFFLE, "truffle.dispatch.metaprogramming_always_indirect", false, "Always use indirect calls for the metaprogramming methods #__send__ and #send, and for any call site that has to use #method_missing or #const_missing.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED = bool(TRUFFLE, "truffle.call.method_missing_always_cloned", true, "Always clone #method_missing call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED = bool(TRUFFLE, "truffle.call.method_missing_always_inlined", true, "Always inline #method_missing call targets.");

public static final Option<Integer> TRUFFLE_PACK_UNROLL_LIMIT = integer(TRUFFLE, "truffle.pack.unroll", 4, "If a pack expression has a loop less than this many iterations, unroll it.");

public static final Option<Boolean> TRUFFLE_METRICS_TIME = bool(TRUFFLE, "truffle.metrics.time", false, "Print the time at various stages of VM operation.");
public static final Option<Boolean> TRUFFLE_METRICS_MEMORY_USED_ON_EXIT = bool(TRUFFLE, "truffle.metrics.memory_used_on_exit", false, "Print the size of heap memory in use on exit.");

public static final Option<Boolean> TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = bool(TRUFFLE, "truffle.set_trace_func.include_core_file_callers", false, "Include internal core library calls in set_trace_func output.");

public static String dump() {
return "# JRuby configuration options with current values\n" +
4 changes: 4 additions & 0 deletions tool/truffle/jruby_truffle_runner/bin/jruby+truffle
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

require_relative '../lib/jruby+truffle_runner.rb'
JRubyTruffleRunner.new
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
:global:
# default ../jruby/bin/ruby won't work since activesupport is one more dir deeper
:jruby_truffle_path: '../../jruby/bin/jruby'
:graal_path: '../../graalvm-jdk1.8.0/bin/java'
:setup:
:file:
shims.rb: |
require 'minitest'
# mock diff, it calls not fully supported Kernel#system
module Minitest
module Assertions
def self.diff
nil
end
end
end
# mock load_plugins as it loads rubygems
def Minitest.load_plugins
end
bundler.rb: "module Bundler; def self.setup; end; end"
# mock method_source gem
method_source.rb: nil
# do not let bundler to install db gem group
:without:
- db
:run:
:require:
- shims
4 changes: 4 additions & 0 deletions tool/truffle/jruby_truffle_runner/gem_configurations/psd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
:setup:
:file:
nokogiri.rb: nil
17 changes: 17 additions & 0 deletions tool/truffle/jruby_truffle_runner/jruby+truffle_runner.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Gem::Specification.new do |s|
s.name = 'jruby+truffle_runner'
s.version = '0.0.1'
s.platform = Gem::Platform::RUBY
s.authors = ['Petr Chalupa']
s.email = ['git@pitr.ch']
s.homepage = 'https://github.com/jruby/jruby'
s.summary = 'Temporary JRuby+Truffle runner'
s.description = 'Until JRuby+Truffle is more complete, allows to run apps/gems simply on JRuby+Truffle.'

s.required_rubygems_version = '>= 1.3.6'

s.files = Dir['{lib}/**/*.rb', 'bin/*', 'gem_configurations/*.yaml', 'LICENSE', '*.md']
s.require_path = 'lib'

s.executables = ['jruby+truffle']
end
308 changes: 308 additions & 0 deletions tool/truffle/jruby_truffle_runner/lib/jruby+truffle_runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
# 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

require 'optparse'
require 'pp'
require 'yaml'
require 'fileutils'

# TODO (pitr 01-Sep-2015): add pre stored run options combinations like -S irb, -I test

class JRubyTruffleRunner
attr_reader :options

EXECUTABLE = 'jruby+truffle'
LOCAL_CONFIG_FILE = '.jruby+truffle.yaml'

begin
assign_new_value = -> (new, old) { new }
add_to_array = -> (new, old) { old << new }
merge_hash = -> ((k, v), old) { old.merge k => v }

# Format:
# subcommand_name: {
# :'option_name (also used as a key in yaml)' => [option_parser_on_method_args,
# -> (new_value, old_value) { result_of_this_block_is_stored },
# default_value]
# }
OPTION_DEFINITIONS = {
global: {
verbose: ['-v', '--verbose', 'Run verbosely (prints options)', assign_new_value, false],
help: ['-h', '--help', 'Show this message', assign_new_value, false],
debug_port: ['--debug-port PORT', 'Debug port', assign_new_value, '51819'],
debug_option: ['--debug-option OPTION', 'Debug JVM option', assign_new_value,
'-J-agentlib:jdwp=transport=dt_socket,server=y,address=%d,suspend=y'],
truffle_bundle_path: ['--truffle-bundle-path NAME', 'Bundle path', assign_new_value, 'jruby+truffle_bundle'],
jruby_truffle_path: ['--jruby-truffle-path PATH', 'Path to JRuby+Truffle bin/jruby', assign_new_value,
'../jruby/bin/jruby'],
graal_path: ['--graal-path PATH', 'Path to Graal', assign_new_value, '../graalvm-jdk1.8.0/bin/java'],
mock_load_path: ['--mock-load-path PATH', 'Root path for all mocks/monkey-patches which is prepended in $:',
assign_new_value, 'mocks']
},
setup: {
help: ['-h', '--help', 'Show this message', assign_new_value, false],
after: ['--after SH_CMD', 'Commands to execute after setup', add_to_array, []],
file: ['--file NAME,CONTENT', Array, 'Create file in truffle_bundle_path', merge_hash, {}],
without: ['--without GROUP', 'Do not install listed gem group by bundler', add_to_array, []]
},
run: {
help: ['-h', '--help', 'Show this message', assign_new_value, false],
test: ['-t', '--test', 'Do not use Truffle use plain JRuby', assign_new_value, false],
graal: ['-g', '--graal', 'Run on graal', assign_new_value, false],
debug: ['-d', '--debug', 'JVM remote debugging', assign_new_value, false],
require: ['-r', '--require FILE', 'Files to require, same as Ruby\'s -r', add_to_array, []],
load_path: ['-I', '--load-path LOAD_PATH', 'Paths to add to load path, same as Ruby\'s -I', add_to_array, []],
# TODO (pitr 01-Sep-2015): add option for prepended load paths to be able to replace ugly echo in the yaml file
jexception: ['--jexception', 'print Java exceptions', assign_new_value, false]
},
clean: {
help: ['-h', '--help', 'Show this message', assign_new_value, false]
}
}
end

begin
global_help = <<-TXT.gsub(/^ {6}/, '')
Usage: #{EXECUTABLE} [options] [subcommand [subcommand-options]]
Subcommands are: #{(OPTION_DEFINITIONS.keys - [:global]).map(&:to_s).join(', ')}
Allows to execute gem/app on JRuby+Truffle until it's more complete. Environment
has to be set up first with setup subcommand then run subcommand can be used.
Options can be set on commandline or in local directory in #{LOCAL_CONFIG_FILE} file.
Tha data in yaml file follow same structure as OPTION_DEFINITIONS what, its values
are deep-merged with default values, then command-line options are applied.
This tool contains default configurations for gems in gem_configurations directory.
They are copied when there is no configuration present.
TXT

setup_help = <<-TXT.gsub(/^ {6}/, '')
Usage: #{EXECUTABLE} [options] setup [subcommand-options]
Creates environment for running gem/app on JRuby+Truflle.
TXT

run_help = <<-TXT.gsub(/^ {6}/, '')
Usage: #{EXECUTABLE} [options] run [subcommand-options] -- [ruby-options]
Runs file, -e expr, etc in setup environment on JRuby+Truffle
Examples: #{EXECUTABLE} run -- a_file.rb
#{EXECUTABLE} run -- -S irb
#{EXECUTABLE} run -- -e 'puts :v'
#{EXECUTABLE} --verbose run -- -Itest test/a_test_file_test.rb
TXT

clean_help = <<-TXT.gsub(/^ {6}/, '')
Usage: #{EXECUTABLE} [options] clean [subcommand-options]
Deletes all files created by setup subcommand.
TXT

HELP = { global: global_help, setup: setup_help, run: run_help, clean: clean_help }
end


def initialize(argv = ARGV)
construct_default_options
load_local_yaml_configuration
build_option_parsers

subcommand, *argv_after_global = @option_parsers[:global].order argv

if subcommand.nil?
print_options
help
end

subcommand = subcommand.to_sym

subcommand_option_parser = @option_parsers[subcommand] || raise("unknown subcommand: #{subcommand}")
argv_after_subcommand = subcommand_option_parser.order argv_after_global

print_options
help subcommand if @options[subcommand][:help]

send "subcommand_#{subcommand}", argv_after_subcommand
end

def print_options
if verbose?
puts 'Options:'
pp @options
end
end

private

def verbose?
@options[:global][:verbose]
end

def build_option_parsers
@option_parsers = OPTION_DEFINITIONS.each_with_object({}) do |(group, group_options), parsers|
parsers[group] = OptionParser.new do |option_parser|
group_options.each do |option, data|
*args, description, block, default = data

option_parser.on(*args, description + " (default: #{default.inspect})") do |new_value|
old_value = @options[group][option]
@options[group][option] = block.call new_value, old_value
end
end
end
end

@option_parsers.each { |key, option_parser| option_parser.banner = HELP[key] }
end

def load_local_yaml_configuration
yaml_path = File.join Dir.pwd, LOCAL_CONFIG_FILE

unless File.exist? yaml_path
candidates = Dir['*.gemspec']
if candidates.size == 1
gem_name, _ = candidates.first.split('.')

default_configuration_file_path = File.dirname(__FILE__) + "/../gem_configurations/#{gem_name}.yaml"
if File.exist?(default_configuration_file_path)
puts "Copying default #{LOCAL_CONFIG_FILE} for #{gem_name}."
FileUtils.cp default_configuration_file_path, LOCAL_CONFIG_FILE
end
end
end

yaml_data = YAML.load_file(yaml_path) if File.exist?(yaml_path)
@options = deep_merge @options, yaml_data
end

def construct_default_options
@options = OPTION_DEFINITIONS.each_with_object({}) do |(group, group_options), options|
group_options.each_with_object(options[group] = {}) do |(option, data), group_option_defaults|
*args, block, default = data
group_option_defaults[option] = default
end
end
end

def help(key = nil)
parsers = if key
[@option_parsers[key]]
else
@option_parsers.values
end
puts *parsers
exit
end

def deep_merge(a, b)
if Hash === a
if Hash === b
return a.merge(b) { |k, ov, nv| deep_merge ov, nv }
else
return a
end
end

if Array === a
if Array === b
return a + b.map { |v| eval_yaml_strings v }
else
return a
end
end

eval_yaml_strings b
end

def eval_yaml_strings(value)
if String === value
begin
eval('"' + value.gsub(/\\#|"|\\/, '\#' => '\#', '"' => '\"', '\\' => '\\\\') + '"')
rescue => e
p value
raise e
end
else
value
end
end

def subcommand_setup(rest)
bundle_path = File.expand_path @options[:global][:truffle_bundle_path]
bundle_installed = execute_cmd 'command -v bundle 2>/dev/null', fail: false

execute_cmd 'gem install bundler' unless bundle_installed

execute_cmd ['bundle install --standalone',
"--path #{bundle_path}",
("--without #{@options[:setup][:without].join(' ')}" unless @options[:setup][:without].empty?)
].join(' ')

link_path = "#{bundle_path}/jruby+truffle"
FileUtils.rm link_path if File.exist? link_path
execute_cmd "ln -s #{bundle_path}/#{RUBY_ENGINE} #{link_path}"

mock_path = "#{bundle_path}/#{@options[:global][:mock_load_path]}"
FileUtils.mkpath mock_path

@options[:setup][:file].each do |name, content|
puts "creating file: #{mock_path}/#{name}" if verbose?
File.write "#{mock_path}/#{name}", content
end

File.open("#{bundle_path}/bundler/setup.rb", 'a') do |f|
f.write %[$:.unshift "\#{path}/../#{@options[:global][:mock_load_path]}"]
end

@options[:setup][:after].each do |cmd|
execute_cmd cmd
end
end

def subcommand_run(rest)
cmd_options = [
('-X+T' unless @options[:run][:test]),
(format(@options[:global][:debug_option], @options[:global][:debug_port]) if @options[:run][:debug]),
('-Xtruffle.exceptions.print_java=true' if @options[:run][:jexception]),
"-r ./#{@options[:global][:truffle_bundle_path]}/bundler/setup.rb",
*@options[:run][:load_path].map { |v| '-I ' + v },
*@options[:run][:require].map { |v| '-r ' + v }
].compact.join(' ')

cmd = [("JAVACMD=#{@options[:global][:graal_path]}" if @options[:run][:graal]),
@options[:global][:jruby_truffle_path],
cmd_options,
*rest
].compact.join(' ')

exit execute_cmd(cmd, fail: false, print_always: true)
end

def subcommand_clean(rest)
FileUtils.rm_rf @options[:global][:truffle_bundle_path]
end

def print_cmd(cmd, print_always)
puts '$ ' + cmd if verbose? || print_always
cmd
end

def execute_cmd(cmd, fail: true, print_always: false)
result = system(print_cmd(cmd, print_always))
ensure
raise 'command failed' if fail && !result
end
end
6 changes: 3 additions & 3 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -25,9 +25,9 @@
import jnr.posix.POSIX;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.RubyString;
import org.jruby.truffle.nodes.dispatch.DispatchNode;
import org.jruby.truffle.nodes.instrument.RubyWrapperNode;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -172,8 +172,8 @@ protected NativeSockets nativeSockets() {
return getContext().getNativeSockets();
}

protected static int getCacheLimit() {
return DispatchNode.DISPATCH_POLYMORPHIC_MAX;
protected int getCacheLimit() {
return getContext().getOptions().DISPATCH_POLYMORPHIC_MAX;
}

// Helper methods for caching
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
import org.jruby.truffle.runtime.layouts.Layouts;

/*
* TODO(CS): could probably unify this with SplatCastNode with some final configuration options.
* TODO(CS): could probably unify this with SplatCastNode with some final configuration getContext().getOptions().
*/
@NodeChild("child")
public abstract class ArrayCastNode extends RubyNode {
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
import org.jruby.truffle.nodes.objects.AllocateObjectNodeGen;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -234,10 +235,10 @@ public SendNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);

dispatchNode = new CallDispatchHeadNode(context, true,
DispatchNode.DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT,
getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT,
MissingBehavior.CALL_METHOD_MISSING);

if (DispatchNode.DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
if ((boolean) getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
dispatchNode.forceUncached();
}
}
Original file line number Diff line number Diff line change
@@ -1432,10 +1432,10 @@ public PublicSendNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);

dispatchNode = new CallDispatchHeadNode(context, false,
DispatchNode.DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT,
getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT,
MissingBehavior.CALL_METHOD_MISSING);

if (DispatchNode.DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
if ((boolean) getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
dispatchNode.forceUncached();
}
}
@@ -1611,7 +1611,7 @@ public RespondToNode(RubyContext context, SourceSection sourceSection) {
dispatch = new DoesRespondDispatchHeadNode(context, false, false, MissingBehavior.RETURN_MISSING, null);
dispatchIgnoreVisibility = new DoesRespondDispatchHeadNode(context, true, false, MissingBehavior.RETURN_MISSING, null);

if (DispatchNode.DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
if ((boolean) getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
dispatch.forceUncached();
dispatchIgnoreVisibility.forceUncached();
}
Original file line number Diff line number Diff line change
@@ -14,11 +14,11 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.cli.Options;

import java.util.Arrays;

@@ -29,8 +29,6 @@

public abstract class ArrayBuilderNode extends Node {

public static final int ARRAYS_UNINITIALIZED_SIZE = Options.TRUFFLE_ARRAYS_UNINITIALIZED_SIZE.load();

private final RubyContext context;

public ArrayBuilderNode(RubyContext context) {
@@ -67,7 +65,7 @@ public void resume(Object[] store) {
@Override
public Object start() {
CompilerDirectives.transferToInterpreter();
return new Object[ARRAYS_UNINITIALIZED_SIZE];
return new Object[getContext().getOptions().ARRAYS_UNINITIALIZED_SIZE];
}

@Override
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@
import org.jruby.truffle.pack.runtime.PackResult;
import org.jruby.truffle.pack.runtime.exceptions.*;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayMirror;
@@ -64,15 +65,12 @@
import org.jruby.util.ByteList;
import org.jruby.util.Memo;
import org.jruby.util.StringSupport;
import org.jruby.util.cli.Options;

import java.util.Arrays;

@CoreClass(name = "Array")
public abstract class ArrayNodes {

public static final int ARRAYS_SMALL = Options.TRUFFLE_ARRAYS_SMALL.load();

@CoreMethod(names = "allocate", constructor = true)
public abstract static class AllocateNode extends CoreMethodArrayArgumentsNode {

@@ -4193,9 +4191,9 @@ public DynamicObject sortVeryShortIntegerFixnum(VirtualFrame frame, DynamicObjec

// Selection sort - written very carefully to allow PE

for (int i = 0; i < ARRAYS_SMALL; i++) {
for (int i = 0; i < getContext().getOptions().ARRAYS_SMALL; i++) {
if (i < size) {
for (int j = i + 1; j < ARRAYS_SMALL; j++) {
for (int j = i + 1; j < getContext().getOptions().ARRAYS_SMALL; j++) {
if (j < size) {
if (castSortValue(compareDispatchNode.call(frame, store[j], "<=>", null, store[i])) < 0) {
final int temp = store[j];
@@ -4221,9 +4219,9 @@ public DynamicObject sortVeryShortLongFixnum(VirtualFrame frame, DynamicObject a

// Selection sort - written very carefully to allow PE

for (int i = 0; i < ARRAYS_SMALL; i++) {
for (int i = 0; i < getContext().getOptions().ARRAYS_SMALL; i++) {
if (i < size) {
for (int j = i + 1; j < ARRAYS_SMALL; j++) {
for (int j = i + 1; j < getContext().getOptions().ARRAYS_SMALL; j++) {
if (j < size) {
if (castSortValue(compareDispatchNode.call(frame, store[j], "<=>", null, store[i])) < 0) {
final long temp = store[j];
@@ -4283,8 +4281,8 @@ private int castSortValue(Object value) {
throw new RaiseException(getContext().getCoreLibrary().argumentError("expecting a Fixnum to sort", this));
}

protected static boolean isSmall(DynamicObject array) {
return Layouts.ARRAY.getSize(array) <= ARRAYS_SMALL;
protected boolean isSmall(DynamicObject array) {
return Layouts.ARRAY.getSize(array) <= getContext().getOptions().ARRAYS_SMALL;
}

}
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.objects.IsFrozenNode;
import org.jruby.truffle.nodes.objects.IsFrozenNodeGen;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.BucketsStrategy;
import org.jruby.truffle.runtime.hash.Entry;
@@ -56,7 +57,7 @@ public RubyNode getValue(int index) {
public static HashLiteralNode create(RubyContext context, SourceSection sourceSection, RubyNode[] keyValues) {
if (keyValues.length == 0) {
return new EmptyHashLiteralNode(context, sourceSection);
} else if (keyValues.length <= PackedArrayStrategy.MAX_ENTRIES * 2) {
} else if (keyValues.length <= context.getOptions().HASH_PACKED_ARRAY_MAX * 2) {
return new SmallHashLiteralNode(context, sourceSection, keyValues);
} else {
return new GenericHashLiteralNode(context, sourceSection, keyValues);
@@ -101,7 +102,7 @@ public SmallHashLiteralNode(RubyContext context, SourceSection sourceSection, Ru
@ExplodeLoop
@Override
public Object execute(VirtualFrame frame) {
final Object[] store = PackedArrayStrategy.createStore();
final Object[] store = PackedArrayStrategy.createStore(getContext());

int size = 0;

152 changes: 62 additions & 90 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/hash/HashNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
import org.jruby.truffle.nodes.core.BasicObjectNodesFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.*;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -59,14 +60,14 @@ public SetNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = { "isNullHash(hash)", "!isRubyString(key)" })
public Object setNull(VirtualFrame frame, DynamicObject hash, Object key, Object value, boolean byIdentity) {
Object store = PackedArrayStrategy.createStore(hashNode.hash(frame, key), key, value);
assert HashOperations.verifyStore(store, 1, null, null);
Object store = PackedArrayStrategy.createStore(getContext(), hashNode.hash(frame, key), key, value);
assert HashOperations.verifyStore(getContext(), store, 1, null, null);
Layouts.HASH.setStore(hash, store);
Layouts.HASH.setSize(hash, 1);
Layouts.HASH.setFirstInSequence(hash, null);
Layouts.HASH.setLastInSequence(hash, null);

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);
return value;
}

@@ -83,14 +84,14 @@ public Object setNullNotByIdentity(VirtualFrame frame, DynamicObject hash, Dynam
@ExplodeLoop
@Specialization(guards = {"isPackedHash(hash)", "!isRubyString(key)"})
public Object setPackedArray(VirtualFrame frame, DynamicObject hash, Object key, Object value, boolean byIdentity) {
assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);

final int hashed = hashNode.hash(frame, key);

final Object[] store = (Object[]) Layouts.HASH.getStore(hash);
final int size = Layouts.HASH.getSize(hash);

for (int n = 0; n < PackedArrayStrategy.MAX_ENTRIES; n++) {
for (int n = 0; n < getContext().getOptions().HASH_PACKED_ARRAY_MAX; n++) {
if (n < size) {
if (hashed == PackedArrayStrategy.getHashed(store, n)) {
final boolean equal;
@@ -103,7 +104,7 @@ public Object setPackedArray(VirtualFrame frame, DynamicObject hash, Object key,

if (equal) {
PackedArrayStrategy.setValue(store, n, value);
assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);
return value;
}
}
@@ -112,16 +113,16 @@ public Object setPackedArray(VirtualFrame frame, DynamicObject hash, Object key,

extendProfile.enter();

if (strategyProfile.profile(size + 1 <= PackedArrayStrategy.MAX_ENTRIES)) {
if (strategyProfile.profile(size + 1 <= getContext().getOptions().HASH_PACKED_ARRAY_MAX)) {
PackedArrayStrategy.setHashedKeyValue(store, size, hashed, key, value);
Layouts.HASH.setSize(hash, size + 1);
return value;
} else {
PackedArrayStrategy.promoteToBuckets(hash, store, size);
BucketsStrategy.addNewEntry(hash, hashed, key, value);
PackedArrayStrategy.promoteToBuckets(getContext(), hash, store, size);
BucketsStrategy.addNewEntry(getContext(), hash, hashed, key, value);
}

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);

return value;
}
@@ -144,7 +145,7 @@ public Object setPackedArrayNotByIdentity(VirtualFrame frame, DynamicObject hash

@Specialization(guards = {"isBucketHash(hash)", "!isRubyString(key)"})
public Object setBuckets(VirtualFrame frame, DynamicObject hash, Object key, Object value, boolean byIdentity) {
assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);

if (lookupEntryNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -184,13 +185,13 @@ public Object setBuckets(VirtualFrame frame, DynamicObject hash, Object key, Obj
// TODO CS 11-May-15 could store the next size for resize instead of doing a float operation each time

if (resizeProfile.profile(newSize / (double) entries.length > BucketsStrategy.LOAD_FACTOR)) {
BucketsStrategy.resize(hash);
BucketsStrategy.resize(getContext(), hash);
}
} else {
entry.setKeyValue(result.getHashed(), key, value);
}

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(getContext(), hash);

return value;
}
Original file line number Diff line number Diff line change
@@ -19,18 +19,15 @@
import com.oracle.truffle.api.object.Shape;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.util.cli.Options;

public class CachedBoxedMethodMissingDispatchNode extends CachedDispatchNode {

private static final boolean DISPATCH_METHODMISSING_ALWAYS_CLONED = Options.TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED.load();
private static final boolean DISPATCH_METHODMISSING_ALWAYS_INLINED = Options.TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED.load();

private final Shape expectedShape;
private final Assumption unmodifiedAssumption;
private final InternalMethod method;
@@ -66,12 +63,12 @@ public CachedBoxedMethodMissingDispatchNode(
*/

if (callNode.isCallTargetCloningAllowed()
&& (DISPATCH_METHODMISSING_ALWAYS_CLONED || method.getSharedMethodInfo().shouldAlwaysSplit())) {
&& (getContext().getOptions().DISPATCH_METHODMISSING_ALWAYS_CLONED || method.getSharedMethodInfo().shouldAlwaysSplit())) {
insert(callNode);
callNode.cloneCallTarget();
}

if (callNode.isInlinable() && DISPATCH_METHODMISSING_ALWAYS_INLINED) {
if (callNode.isInlinable() && getContext().getOptions().DISPATCH_METHODMISSING_ALWAYS_INLINED) {
insert(callNode);
callNode.forceInlining();
}
Original file line number Diff line number Diff line change
@@ -19,14 +19,9 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.util.cli.Options;

public abstract class DispatchNode extends RubyNode {

public static final int DISPATCH_POLYMORPHIC_MAX = Options.TRUFFLE_DISPATCH_POLYMORPHIC_MAX.load();
public static final boolean DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED = Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED.load();
public static final boolean DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT = Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT.load();

private final DispatchAction dispatchAction;

private static final class Missing {
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
import com.oracle.truffle.api.object.Shape;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.objects.SingletonClassNode;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
@@ -83,7 +84,7 @@ public DispatchNode call() throws Exception {

final DispatchNode newDispathNode;

if (depth == DISPATCH_POLYMORPHIC_MAX) {
if (depth == getContext().getOptions().DISPATCH_POLYMORPHIC_MAX) {
newDispathNode = new UncachedDispatchNode(getContext(), ignoreVisibility, getDispatchAction(), missingBehavior);
} else {
depth++;
@@ -229,12 +230,12 @@ private DispatchNode createMethodMissingNode(
receiverObject.toString() + " didn't have a #method_missing", this));
}

if (DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
if ((boolean) getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED) {
return new UncachedDispatchNode(getContext(), ignoreVisibility, getDispatchAction(), missingBehavior);
}

return new CachedBoxedMethodMissingDispatchNode(getContext(), methodName, first, shape,
getContext().getCoreLibrary().getMetaClass(receiverObject), method, DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT, getDispatchAction());
getContext().getCoreLibrary().getMetaClass(receiverObject), method, getContext().getOptions().DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT, getDispatchAction());
}

default: {
Original file line number Diff line number Diff line change
@@ -20,21 +20,18 @@
import org.jruby.exceptions.MainExitException;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.ThreadExitException;
import org.jruby.truffle.runtime.control.TruffleFatalException;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.cli.Options;

import java.util.Arrays;

public class ExceptionTranslatingNode extends RubyNode {

private static final boolean PRINT_JAVA_EXCEPTIONS = Options.TRUFFLE_EXCEPTIONS_PRINT_JAVA.load();
private static final boolean PRINT_UNCAUGHT_JAVA_EXCEPTIONS = Options.TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA.load();

private final UnsupportedOperationBehavior unsupportedOperationBehavior;

@Child private RubyNode child;
@@ -93,15 +90,15 @@ public Object execute(VirtualFrame frame) {
}

private DynamicObject translate(ArithmeticException exception) {
if (PRINT_JAVA_EXCEPTIONS) {
if (getContext().getOptions().EXCEPTIONS_PRINT_JAVA) {
exception.printStackTrace();
}

return getContext().getCoreLibrary().zeroDivisionError(this);
}

private DynamicObject translate(UnsupportedSpecializationException exception) {
if (PRINT_JAVA_EXCEPTIONS) {
if (getContext().getOptions().EXCEPTIONS_PRINT_JAVA) {
exception.printStackTrace();
}

@@ -166,7 +163,7 @@ private DynamicObject translate(UnsupportedSpecializationException exception) {
}

public DynamicObject translate(Throwable throwable) {
if (PRINT_JAVA_EXCEPTIONS || PRINT_UNCAUGHT_JAVA_EXCEPTIONS) {
if (getContext().getOptions().EXCEPTIONS_PRINT_JAVA || (boolean) getContext().getOptions().EXCEPTIONS_PRINT_UNCAUGHT_JAVA) {
throwable.printStackTrace();
}

Original file line number Diff line number Diff line change
@@ -39,11 +39,12 @@ public int getPrimitiveArity() {

@Override
public RubyNode createCallPrimitiveNode(RubyContext context, SourceSection sourceSection, ReturnID returnID) {
return CallNodeFactory.create(context, sourceSection, new RubyNode[] {
new LiteralNode(context, sourceSection, method),
new ReadAllArgumentsNode(context, sourceSection),
new ReadBlockNode(context, sourceSection, NotProvided.INSTANCE)
});
return new CallRubiniusPrimitiveNode(context, sourceSection,
CallNodeFactory.create(context, sourceSection, new RubyNode[] {
new LiteralNode(context, sourceSection, method),
new ReadAllArgumentsNode(context, sourceSection),
new ReadBlockNode(context, sourceSection, NotProvided.INSTANCE)
}), returnID);
}

@Override
Original file line number Diff line number Diff line change
@@ -10,10 +10,10 @@
package org.jruby.truffle.nodes.yield;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.cli.Options;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
@@ -36,9 +36,6 @@
})
public abstract class CallBlockNode extends RubyNode {

private static final boolean INLINER_ALWAYS_CLONE_YIELD = Options.TRUFFLE_INLINER_ALWAYS_CLONE_YIELD.load();
private static final boolean INLINER_ALWAYS_INLINE_YIELD = Options.TRUFFLE_INLINER_ALWAYS_INLINE_YIELD.load();

// Allowing the child to be Node.replace()'d.
static class CallNodeWrapperNode extends Node {
@Child DirectCallNode child;
@@ -88,10 +85,10 @@ protected CallNodeWrapperNode createBlockCallNode(CallTarget callTarget) {
final DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(callTarget);
final CallNodeWrapperNode callNodeWrapperNode = new CallNodeWrapperNode(callNode);

if (INLINER_ALWAYS_CLONE_YIELD && callNode.isCallTargetCloningAllowed()) {
if (getContext().getOptions().INLINER_ALWAYS_CLONE_YIELD && callNode.isCallTargetCloningAllowed()) {
callNode.cloneCallTarget();
}
if (INLINER_ALWAYS_INLINE_YIELD && callNode.isInlinable()) {
if (getContext().getOptions().INLINER_ALWAYS_INLINE_YIELD && callNode.isInlinable()) {
callNode.forceInlining();
}
return callNodeWrapperNode;
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import org.jruby.truffle.pack.nodes.PackNode;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;

/**
@@ -41,7 +42,7 @@ public NNode(RubyContext context, int repeats, PackNode child) {
public Object execute(VirtualFrame frame) {
if (CompilerDirectives.inCompiledCode()
&& CompilerDirectives.isCompilationConstant(repeats)
&& repeats <= 4) {
&& repeats <= getContext().getOptions().PACK_UNROLL_LIMIT) {
return executeExploded(frame);
}

39 changes: 39 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/runtime/Options.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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
*/
package org.jruby.truffle.runtime;

public class Options {

public final String CORE_LOAD_PATH = org.jruby.util.cli.Options.TRUFFLE_CORE_LOAD_PATH.load();

public final int DISPATCH_POLYMORPHIC_MAX = org.jruby.util.cli.Options.TRUFFLE_DISPATCH_POLYMORPHIC_MAX.load();
public final int ARRAYS_UNINITIALIZED_SIZE = org.jruby.util.cli.Options.TRUFFLE_ARRAYS_UNINITIALIZED_SIZE.load();
public final int ARRAYS_SMALL = org.jruby.util.cli.Options.TRUFFLE_ARRAYS_SMALL.load();
public final int HASH_PACKED_ARRAY_MAX = org.jruby.util.cli.Options.TRUFFLE_HASH_PACKED_ARRAY_MAX.load();

public final int INSTRUMENTATION_SERVER_PORT = org.jruby.util.cli.Options.TRUFFLE_INSTRUMENTATION_SERVER_PORT.load();
public final boolean EXCEPTIONS_PRINT_JAVA = org.jruby.util.cli.Options.TRUFFLE_EXCEPTIONS_PRINT_JAVA.load();
public final boolean EXCEPTIONS_PRINT_UNCAUGHT_JAVA = org.jruby.util.cli.Options.TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA.load();
public final boolean COVERAGE = org.jruby.util.cli.Options.TRUFFLE_COVERAGE.load();

public final boolean BACKTRACES_HIDE_CORE_FILES = org.jruby.util.cli.Options.TRUFFLE_BACKTRACES_HIDE_CORE_FILES.load();

public final boolean INLINER_ALWAYS_CLONE_YIELD = org.jruby.util.cli.Options.TRUFFLE_INLINER_ALWAYS_CLONE_YIELD.load();
public final boolean INLINER_ALWAYS_INLINE_YIELD = org.jruby.util.cli.Options.TRUFFLE_INLINER_ALWAYS_INLINE_YIELD.load();
public final boolean DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED = org.jruby.util.cli.Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED.load();
public final boolean DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT = org.jruby.util.cli.Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT.load();
public final boolean DISPATCH_METHODMISSING_ALWAYS_CLONED = org.jruby.util.cli.Options.TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED.load();
public final boolean DISPATCH_METHODMISSING_ALWAYS_INLINED = org.jruby.util.cli.Options.TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED.load();

public final int PACK_UNROLL_LIMIT = org.jruby.util.cli.Options.TRUFFLE_PACK_UNROLL_LIMIT.load();

public final boolean INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = org.jruby.util.cli.Options.TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC.load();

}
19 changes: 12 additions & 7 deletions truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java
Original file line number Diff line number Diff line change
@@ -61,7 +61,6 @@
import org.jruby.truffle.translator.TranslatorDriver;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
import org.jruby.util.cli.Options;

import java.io.File;
import java.io.IOException;
@@ -81,11 +80,10 @@ public class RubyContext extends ExecutionContext implements TruffleContextInter

private static volatile RubyContext latestInstance;

private static final boolean TRUFFLE_COVERAGE = Options.TRUFFLE_COVERAGE.load();
private static final int INSTRUMENTATION_SERVER_PORT = Options.TRUFFLE_INSTRUMENTATION_SERVER_PORT.load();

private final Ruby runtime;

private final Options options;

private final POSIX posix;
private final NativeSockets nativeSockets;

@@ -121,6 +119,8 @@ public RubyContext(Ruby runtime) {
}

public RubyContext(Ruby runtime, TruffleLanguage.Env env) {
options = new Options();

latestInstance = this;

assert runtime != null;
@@ -141,7 +141,7 @@ public RubyContext(Ruby runtime, TruffleLanguage.Env env) {

// TODO(CS, 28-Jan-15) this is global
// TODO(CS, 28-Jan-15) maybe not do this for core?
if (TRUFFLE_COVERAGE) {
if (options.COVERAGE) {
coverageTracker = new CoverageTracker();
} else {
coverageTracker = null;
@@ -177,8 +177,8 @@ public RubyContext(Ruby runtime, TruffleLanguage.Env env) {
rubiniusPrimitiveManager = new RubiniusPrimitiveManager();
rubiniusPrimitiveManager.addAnnotatedPrimitives();

if (INSTRUMENTATION_SERVER_PORT != 0) {
instrumentationServerManager = new InstrumentationServerManager(this, INSTRUMENTATION_SERVER_PORT);
if (options.INSTRUMENTATION_SERVER_PORT != 0) {
instrumentationServerManager = new InstrumentationServerManager(this, options.INSTRUMENTATION_SERVER_PORT);
instrumentationServerManager.start();
} else {
instrumentationServerManager = null;
@@ -690,4 +690,9 @@ public Object importObject(DynamicObject name) {

return env.importSymbol(name.toString());
}

public Options getOptions() {
return options;
}

}
Original file line number Diff line number Diff line change
@@ -12,12 +12,12 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.loader.SourceLoader;
import org.jruby.util.cli.Options;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -38,7 +38,7 @@ public enum FormattingFlags {
public static BacktraceFormatter createDefaultFormatter(RubyContext context) {
final EnumSet<FormattingFlags> flags = EnumSet.noneOf(FormattingFlags.class);

if (!Options.TRUFFLE_BACKTRACES_HIDE_CORE_FILES.load()) {
if (!context.getOptions().BACKTRACES_HIDE_CORE_FILES) {
flags.add(FormattingFlags.INCLUDE_CORE_FILES);
}

Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import org.jruby.truffle.nodes.rubinius.ByteArrayNodesFactory;
import org.jruby.truffle.nodes.rubinius.PosixNodesFactory;
import org.jruby.truffle.nodes.rubinius.RubiniusTypeNodesFactory;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.BacktraceFormatter;
@@ -59,7 +60,6 @@
import org.jruby.truffle.runtime.signal.SignalOperations;
import org.jruby.truffle.translator.NodeWrapper;
import org.jruby.util.StringSupport;
import org.jruby.util.cli.Options;
import org.jruby.util.cli.OutputStrings;

import java.io.File;
@@ -72,9 +72,7 @@

public class CoreLibrary {

public static final String CORE_LOAD_PATH = getCoreLoadPath();

private static final String CLI_RECORD_SEPARATOR = Options.CLI_RECORD_SEPARATOR.load();
private static final String CLI_RECORD_SEPARATOR = org.jruby.util.cli.Options.CLI_RECORD_SEPARATOR.load();

private final RubyContext context;

@@ -179,8 +177,8 @@ public class CoreLibrary {

@CompilationFinal private InternalMethod basicObjectSendMethod;

private static String getCoreLoadPath() {
String path = Options.TRUFFLE_CORE_LOAD_PATH.load();
public String getCoreLoadPath() {
String path = context.getOptions().CORE_LOAD_PATH;

while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
@@ -673,7 +671,7 @@ public void initializeAfterMethodsAdded() {

state = State.LOADING_RUBY_CORE;
try {
context.load(context.getSourceCache().getSource(CoreLibrary.CORE_LOAD_PATH + "/core.rb"), node, NodeWrapper.IDENTITY);
context.load(context.getSourceCache().getSource(getCoreLoadPath() + "/core.rb"), node, NodeWrapper.IDENTITY);
} catch (IOException e) {
throw new RuntimeException(e);
}
Original file line number Diff line number Diff line change
@@ -124,9 +124,9 @@ public static int getBucketIndex(int hashed, int bucketsCount) {
return (hashed & SIGN_BIT_MASK) % bucketsCount;
}

public static void addNewEntry(DynamicObject hash, int hashed, Object key, Object value) {
public static void addNewEntry(RubyContext context, DynamicObject hash, int hashed, Object key, Object value) {
assert HashGuards.isBucketHash(hash);
assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(context, hash);

final Entry[] buckets = (Entry[]) Layouts.HASH.getStore(hash);

@@ -157,13 +157,13 @@ public static void addNewEntry(DynamicObject hash, int hashed, Object key, Objec

Layouts.HASH.setSize(hash, Layouts.HASH.getSize(hash) + 1);

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(context, hash);
}

@TruffleBoundary
public static void resize(DynamicObject hash) {
public static void resize(RubyContext context, DynamicObject hash) {
assert HashGuards.isBucketHash(hash);
assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(context, hash);

final int bucketsCount = capacityGreaterThan(Layouts.HASH.getSize(hash)) * OVERALLOCATE_FACTOR;
final Entry[] newEntries = new Entry[bucketsCount];
@@ -191,13 +191,13 @@ public static void resize(DynamicObject hash) {
int size = Layouts.HASH.getSize(hash);
Entry firstInSequence = Layouts.HASH.getFirstInSequence(hash);
Entry lastInSequence = Layouts.HASH.getLastInSequence(hash);
assert HashOperations.verifyStore(newEntries, size, firstInSequence, lastInSequence);
assert HashOperations.verifyStore(context, newEntries, size, firstInSequence, lastInSequence);
Layouts.HASH.setStore(hash, newEntries);
Layouts.HASH.setSize(hash, size);
Layouts.HASH.setFirstInSequence(hash, firstInSequence);
Layouts.HASH.setLastInSequence(hash, lastInSequence);

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(context, hash);
}

public static Iterator<Map.Entry<Object, Object>> iterateKeyValues(final Entry firstInSequence) {
@@ -261,12 +261,12 @@ public Iterator<Map.Entry<Object, Object>> iterator() {
};
}

public static void copyInto(DynamicObject from, DynamicObject to) {
public static void copyInto(RubyContext context, DynamicObject from, DynamicObject to) {
assert RubyGuards.isRubyHash(from);
assert HashGuards.isBucketHash(from);
assert HashOperations.verifyStore(from);
assert HashOperations.verifyStore(context, from);
assert RubyGuards.isRubyHash(to);
assert HashOperations.verifyStore(to);
assert HashOperations.verifyStore(context, to);

final Entry[] newEntries = new Entry[((Entry[]) Layouts.HASH.getStore(from)).length];

@@ -298,7 +298,7 @@ public static void copyInto(DynamicObject from, DynamicObject to) {
}

int size = Layouts.HASH.getSize(from);
assert HashOperations.verifyStore(newEntries, size, firstInSequence, lastInSequence);
assert HashOperations.verifyStore(context, newEntries, size, firstInSequence, lastInSequence);
Layouts.HASH.setStore(to, newEntries);
Layouts.HASH.setSize(to, size);
Layouts.HASH.setFirstInSequence(to, firstInSequence);
Original file line number Diff line number Diff line change
@@ -13,6 +13,8 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.hash.HashGuards;
import org.jruby.truffle.runtime.Options;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

import java.util.Collections;
@@ -21,11 +23,11 @@

public abstract class HashOperations {

public static boolean verifyStore(DynamicObject hash) {
return verifyStore(Layouts.HASH.getStore(hash), Layouts.HASH.getSize(hash), Layouts.HASH.getFirstInSequence(hash), Layouts.HASH.getLastInSequence(hash));
public static boolean verifyStore(RubyContext context, DynamicObject hash) {
return verifyStore(context, Layouts.HASH.getStore(hash), Layouts.HASH.getSize(hash), Layouts.HASH.getFirstInSequence(hash), Layouts.HASH.getLastInSequence(hash));
}

public static boolean verifyStore(Object store, int size, Entry firstInSequence, Entry lastInSequence) {
public static boolean verifyStore(RubyContext context, Object store, int size, Entry firstInSequence, Entry lastInSequence) {
assert store == null || store instanceof Object[] || store instanceof Entry[];

if (store == null) {
@@ -86,11 +88,11 @@ public static boolean verifyStore(Object store, int size, Entry firstInSequence,

assert foundSizeSequence == size : String.format("%d %d", foundSizeSequence, size);
} else if (store instanceof Object[]) {
assert ((Object[]) store).length == PackedArrayStrategy.MAX_ENTRIES * PackedArrayStrategy.ELEMENTS_PER_ENTRY : ((Object[]) store).length;
assert ((Object[]) store).length == context.getOptions().HASH_PACKED_ARRAY_MAX * PackedArrayStrategy.ELEMENTS_PER_ENTRY : ((Object[]) store).length;

final Object[] packedStore = (Object[]) store;

for (int n = 0; n < PackedArrayStrategy.MAX_ENTRIES; n++) {
for (int n = 0; n < context.getOptions().HASH_PACKED_ARRAY_MAX; n++) {
if (n < size) {
assert packedStore[n * 2] != null;
assert packedStore[n * 2 + 1] != null;
Original file line number Diff line number Diff line change
@@ -11,32 +11,30 @@

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.cli.Options;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

public abstract class PackedArrayStrategy {

public static final int MAX_ENTRIES = Options.TRUFFLE_HASH_PACKED_ARRAY_MAX.load();
public static final int ELEMENTS_PER_ENTRY = 3;
public static final int MAX_ELEMENTS = MAX_ENTRIES * ELEMENTS_PER_ENTRY;

public static Object[] createStore(int hashed, Object key, Object value) {
final Object[] store = createStore();
public static Object[] createStore(RubyContext context, int hashed, Object key, Object value) {
final Object[] store = createStore(context);
setHashedKeyValue(store, 0, hashed, key, value);
return store;
}

public static Object[] createStore() {
return new Object[MAX_ELEMENTS];
public static Object[] createStore(RubyContext context) {
return new Object[context.getOptions().HASH_PACKED_ARRAY_MAX * ELEMENTS_PER_ENTRY];
}

public static Object[] copyStore(Object[] store) {
final Object[] copied = createStore();
System.arraycopy(store, 0, copied, 0, MAX_ELEMENTS);
public static Object[] copyStore(RubyContext context, Object[] store) {
final Object[] copied = createStore(context);
System.arraycopy(store, 0, copied, 0, context.getOptions().HASH_PACKED_ARRAY_MAX * ELEMENTS_PER_ENTRY);
return copied;
}

@@ -70,21 +68,21 @@ public static void setHashedKeyValue(Object[] store, int n, int hashed, Object k
setValue(store, n, value);
}

public static void removeEntry(Object[] store, int n) {
for (int i = 0; i < MAX_ELEMENTS; i += ELEMENTS_PER_ENTRY) {
public static void removeEntry(RubyContext context, Object[] store, int n) {
for (int i = 0; i < context.getOptions().HASH_PACKED_ARRAY_MAX * ELEMENTS_PER_ENTRY; i += ELEMENTS_PER_ENTRY) {
assert store[i] == null || store[i] instanceof Integer;
}

final int index = n * ELEMENTS_PER_ENTRY;
System.arraycopy(store, index + ELEMENTS_PER_ENTRY, store, index, MAX_ELEMENTS - ELEMENTS_PER_ENTRY - index);
System.arraycopy(store, index + ELEMENTS_PER_ENTRY, store, index, context.getOptions().HASH_PACKED_ARRAY_MAX * ELEMENTS_PER_ENTRY - ELEMENTS_PER_ENTRY - index);

for (int i = 0; i < MAX_ELEMENTS; i += ELEMENTS_PER_ENTRY) {
for (int i = 0; i < context.getOptions().HASH_PACKED_ARRAY_MAX * ELEMENTS_PER_ENTRY; i += ELEMENTS_PER_ENTRY) {
assert store[i] == null || store[i] instanceof Integer;
}
}

@TruffleBoundary
public static void promoteToBuckets(DynamicObject hash, Object[] store, int size) {
public static void promoteToBuckets(RubyContext context, DynamicObject hash, Object[] store, int size) {
final Entry[] buckets = new Entry[BucketsStrategy.capacityGreaterThan(size)];

Entry firstInSequence = null;
@@ -120,13 +118,13 @@ public static void promoteToBuckets(DynamicObject hash, Object[] store, int size
}
}

assert HashOperations.verifyStore(buckets, size, firstInSequence, lastInSequence);
assert HashOperations.verifyStore(context, buckets, size, firstInSequence, lastInSequence);
Layouts.HASH.setStore(hash, buckets);
Layouts.HASH.setSize(hash, size);
Layouts.HASH.setFirstInSequence(hash, firstInSequence);
Layouts.HASH.setLastInSequence(hash, lastInSequence);

assert HashOperations.verifyStore(hash);
assert HashOperations.verifyStore(context, hash);
}

@TruffleBoundary
Original file line number Diff line number Diff line change
@@ -29,7 +29,6 @@
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.loader.SourceLoader;
import org.jruby.util.StringSupport;
import org.jruby.util.cli.Options;

import java.util.ArrayList;
import java.util.Collection;
@@ -38,8 +37,6 @@

public class TraceManager {

public static final boolean INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = Options.TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC.load();

private final RubyContext context;

private Collection<Instrument> instruments;
@@ -112,7 +109,7 @@ public Object executeRoot(Node node, VirtualFrame frame) {
final String filename = sourceSection.getSource().getName();
final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(filename, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

if (! INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC && filename.startsWith(SourceLoader.TRUFFLE_SCHEME)) {
if (!context.getOptions().INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC && filename.startsWith(SourceLoader.TRUFFLE_SCHEME)) {
return context.getCoreLibrary().getNilObject();
}

Original file line number Diff line number Diff line change
@@ -432,7 +432,7 @@ public RubyNode visitCallNode(CallNode node) {
}
} else if (receiver instanceof VCallNode // undefined.equal?(obj)
&& ((VCallNode) receiver).getName().equals("undefined")
&& sourceSection.getSource().getPath().startsWith(CoreLibrary.CORE_LOAD_PATH + "/core/")
&& sourceSection.getSource().getPath().startsWith(context.getCoreLibrary().getCoreLoadPath() + "/core/")
&& methodName.equals("equal?")) {
RubyNode argument = translateArgumentsAndBlock(sourceSection, null, node.getArgsNode(), null, methodName).getArguments()[0];
final RubyNode ret = new IsRubiniusUndefinedNode(context, sourceSection, argument);
@@ -988,7 +988,7 @@ public RubyNode visitConstNode(org.jruby.ast.ConstNode node) {

final String name = ConstantReplacer.replacementName(sourceSection, node.getName());

if (name.equals("Rubinius") && sourceSection.getSource().getPath().startsWith(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius")) {
if (name.equals("Rubinius") && sourceSection.getSource().getPath().startsWith(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius")) {
final RubyNode ret = new org.jruby.ast.Colon3Node(node.getPosition(), name).accept(this);
return addNewlineIfNeeded(node, ret);
}
@@ -1506,7 +1506,7 @@ public RubyNode visitGlobalVarNode(org.jruby.ast.GlobalVarNode node) {
RubyNode readNode = environment.findLocalVarNode(name, sourceSection);

if (name.equals("$_")) {
if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/regexp.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/regexp.rb")) {
readNode = new RubiniusLastStringReadNode(context, sourceSection);
} else {
readNode = GetFromThreadLocalNodeGen.create(context, sourceSection, readNode);
@@ -1607,7 +1607,7 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
// Also note the check for frozen.
final RubyNode self = new RaiseIfFrozenNode(new SelfNode(context, sourceSection));

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/time.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/time.rb")) {
if (name.equals("@is_gmt")) {
final RubyNode ret = TimeNodesFactory.InternalSetGMTNodeFactory.create(context, sourceSection, self, rhs);
return addNewlineIfNeeded(node, ret);
@@ -1617,7 +1617,7 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/hash.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/hash.rb")) {
if (name.equals("@default")) {
final RubyNode ret = HashNodesFactory.SetDefaultValueNodeFactory.create(context, sourceSection, self, rhs);
return addNewlineIfNeeded(node, ret);
@@ -1627,16 +1627,16 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/bootstrap/string.rb") ||
sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/string.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/bootstrap/string.rb") ||
sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/string.rb")) {

if (name.equals("@hash")) {
final RubyNode ret = StringNodesFactory.ModifyBangNodeFactory.create(context, sourceSection, new RubyNode[]{});
return addNewlineIfNeeded(node, ret);
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/range.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/range.rb")) {
if (name.equals("@begin")) {
final RubyNode ret = RangeNodesFactory.InternalSetBeginNodeGen.create(context, sourceSection, self, rhs);
return addNewlineIfNeeded(node, ret);
@@ -1650,7 +1650,7 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
}

// TODO (pitr 08-Aug-2015): values of predefined OM properties should be casted to defined types automatically
if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/io.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/io.rb")) {
if (name.equals("@start") || name.equals("@used") || name.equals("@total") || name.equals("@lineno")) {
// Cast int-fitting longs back to int
return addNewlineIfNeeded(
@@ -1679,8 +1679,8 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
* self, and @start to be 0.
*/

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/array.rb") ||
sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/api/shims/array.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/array.rb") ||
sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/api/shims/array.rb")) {

if (name.equals("@total")) {
final RubyNode ret = new RubyCallNode(context, sourceSection, "size", self, null, false);
@@ -1694,7 +1694,7 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/regexp.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/regexp.rb")) {
if (name.equals("@source")) {
final RubyNode ret = MatchDataNodesFactory.RubiniusSourceNodeGen.create(context, sourceSection, self);
return addNewlineIfNeeded(node, ret);
@@ -1711,8 +1711,8 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/bootstrap/string.rb") ||
sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/string.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/bootstrap/string.rb") ||
sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/string.rb")) {

if (name.equals("@num_bytes")) {
final RubyNode ret = StringNodesFactory.ByteSizeNodeFactory.create(context, sourceSection, new RubyNode[] { self });
@@ -1726,7 +1726,7 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/time.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/time.rb")) {
if (name.equals("@is_gmt")) {
final RubyNode ret = TimeNodesFactory.InternalGMTNodeFactory.create(context, sourceSection, self);
return addNewlineIfNeeded(node, ret);
@@ -1736,7 +1736,7 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/hash.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/hash.rb")) {
if (name.equals("@default")) {
final RubyNode ret = HashNodesFactory.DefaultValueNodeFactory.create(context, sourceSection, self);
return addNewlineIfNeeded(node, ret);
@@ -1749,8 +1749,8 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
}
}

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/range.rb") ||
sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/api/shims/range.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/range.rb") ||
sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/api/shims/range.rb")) {

if (name.equals("@begin")) {
final RubyNode ret = RangeNodesFactory.BeginNodeFactory.create(context, sourceSection, new RubyNode[] { self });
@@ -2753,7 +2753,7 @@ public RubyNode visitUntilNode(org.jruby.ast.UntilNode node) {
@Override
public RubyNode visitVCallNode(org.jruby.ast.VCallNode node) {
final SourceSection sourceSection = translate(node.getPosition());
if (node.getName().equals("undefined") && sourceSection.getSource().getPath().startsWith(CoreLibrary.CORE_LOAD_PATH + "/core/")) {
if (node.getName().equals("undefined") && sourceSection.getSource().getPath().startsWith(context.getCoreLibrary().getCoreLoadPath() + "/core/")) {
final RubyNode ret = new LiteralNode(context, sourceSection, context.getCoreLibrary().getRubiniusUndefined());
return addNewlineIfNeeded(node, ret);
}
Original file line number Diff line number Diff line change
@@ -215,26 +215,11 @@ public MethodDefinitionNode compileMethodNode(SourceSection sourceSection, Strin
final RubyRootNode rootNode = new RubyRootNode(
context, sourceSection, environment.getFrameDescriptor(), environment.getSharedMethodInfo(), body, environment.needsDeclarationFrame());

if (PRINT_AST_METHOD_NAMES.contains(methodName)) {
System.err.println(sourceSection + " " + methodName);
NodeUtil.printCompactTree(System.err, rootNode);
}

if (PRINT_FULL_AST_METHOD_NAMES.contains(methodName)) {
System.err.println(sourceSection + " " + methodName);
NodeUtil.printTree(System.err, rootNode);
}

final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
return new MethodDefinitionNode(context, sourceSection, methodName, environment.getSharedMethodInfo(), callTarget);
}

private ParameterCollector declareArguments(SourceSection sourceSection, String methodName, SharedMethodInfo sharedMethodInfo) {
if (PRINT_PARSE_TREE_METHOD_NAMES.contains(methodName)) {
System.err.println(sourceSection + " " + methodName);
System.err.println(sharedMethodInfo.getParseTree().toString(true, 0));
}

final ParameterCollector parameterCollector = new ParameterCollector();
argsNode.accept(parameterCollector);

Original file line number Diff line number Diff line change
@@ -83,11 +83,11 @@ public RubyNode visitDefnNode(org.jruby.ast.DefnNode node) {
String methodName = node.getName();
boolean rubiniusMethodRename = false;

if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/array.rb")) {
if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/array.rb")) {
rubiniusMethodRename = methodName.equals("zip");
} else if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/float.rb")) {
} else if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/float.rb")) {
rubiniusMethodRename = methodName.equals("round");
} else if (sourceSection.getSource().getPath().equals(CoreLibrary.CORE_LOAD_PATH + "/core/rubinius/common/range.rb")) {
} else if (sourceSection.getSource().getPath().equals(context.getCoreLibrary().getCoreLoadPath() + "/core/rubinius/common/range.rb")) {
rubiniusMethodRename = methodName.equals("each") || methodName.equals("step") || methodName.equals("to_a");
}

Original file line number Diff line number Diff line change
@@ -16,15 +16,11 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.literal.NilNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.cli.Options;

import java.util.*;

public abstract class Translator extends org.jruby.ast.visitor.AbstractNodeVisitor<RubyNode> {

public static final Set<String> PRINT_AST_METHOD_NAMES = new HashSet<>(Arrays.asList(Options.TRUFFLE_TRANSLATOR_PRINT_AST.load().split(",")));
public static final Set<String> PRINT_FULL_AST_METHOD_NAMES = new HashSet<>(Arrays.asList(Options.TRUFFLE_TRANSLATOR_PRINT_FULL_AST.load().split(",")));
public static final Set<String> PRINT_PARSE_TREE_METHOD_NAMES = new HashSet<>(Arrays.asList(Options.TRUFFLE_TRANSLATOR_PRINT_PARSE_TREE.load().split(",")));
public static final Set<String> ALWAYS_DEFINED_GLOBALS = new HashSet<>(Arrays.asList("$~"));
public static final Set<String> FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_", "$+", "$&", "$`", "$'"));

Original file line number Diff line number Diff line change
@@ -179,21 +179,6 @@ private RubyRootNode parse(Node currentNode, RubyContext context, Source source,

// Shell result

if (MethodTranslator.PRINT_PARSE_TREE_METHOD_NAMES.contains("main")) {
System.err.println(source.getShortName() + " main");
System.err.println(sharedMethodInfo.getParseTree().toString(true, 0));
}

if (MethodTranslator.PRINT_AST_METHOD_NAMES.contains("main")) {
System.err.println(source.getShortName() + " main");
NodeUtil.printCompactTree(System.err, truffleNode);
}

if (MethodTranslator.PRINT_FULL_AST_METHOD_NAMES.contains("main")) {
System.err.println(source.getShortName() + " main");
NodeUtil.printTree(System.err, truffleNode);
}

return new RubyRootNode(context, truffleNode.getSourceSection(), environment.getFrameDescriptor(), sharedMethodInfo, truffleNode, environment.needsDeclarationFrame());
}

0 comments on commit b69d25d

Please sign in to comment.