Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5c604ec2420f
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4ff804e944d1
Choose a head ref
  • 8 commits
  • 14 files changed
  • 1 contributor

Commits on Jun 26, 2016

  1. [Truffle] change string>symbol map to string>rope

    to avoid duplicated instances of a symbol caused by GC in the rope>symbol map
    pitr-ch committed Jun 26, 2016
    1
    Copy the full SHA
    36ae824 View commit details
  2. [Truffle] Fix overflow in LazyIntRope

    Numbers between 1000000000 and Integer.MAX_VALUE/10 will overflow on *=10
    pitr-ch committed Jun 26, 2016
    Copy the full SHA
    e8d9982 View commit details
  3. [Truffle] jtr: fix indent

    pitr-ch committed Jun 26, 2016
    Copy the full SHA
    45835a0 View commit details
  4. Copy the full SHA
    1e67538 View commit details
  5. Copy the full SHA
    ddc672c View commit details
  6. Copy the full SHA
    41c467a View commit details
  7. [Truffle] do not run CI for actionpack

    fails intermittently
    pitr-ch committed Jun 26, 2016
    Copy the full SHA
    3a45609 View commit details
  8. Copy the full SHA
    4ff804e View commit details
6 changes: 3 additions & 3 deletions lib/ruby/truffle/jruby+truffle/gem_ci/actionpack.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
has_to_succeed setup

set_result run([%w[--require-pattern test/**/*_test.rb],
(option(:exclude) ? %w[-r excluded-tests] : []),
%w[-- -I test -e nil]].flatten(1),
raise: false)
(option(:exclude) ? %w[-r excluded-tests] : []),
%w[-- -I test -e nil]].flatten(1),
raise: false)

2 changes: 1 addition & 1 deletion lib/ruby/truffle/jruby+truffle/gem_ci/travis.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
actionpack
# actionpack
activesupport
activemodel
algebrick
300 changes: 0 additions & 300 deletions lib/ruby/truffle/jruby+truffle/gem_configurations/actionpack.yaml

This file was deleted.

87 changes: 0 additions & 87 deletions lib/ruby/truffle/jruby+truffle/gem_configurations/activemodel.yaml

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions lib/ruby/truffle/jruby+truffle/gem_configurations/psd.yaml

This file was deleted.

239 changes: 239 additions & 0 deletions lib/ruby/truffle/jruby+truffle/lib/truffle/actionpack_exclusions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
---
ActionDispatch::Journey::GTG::TestGeneralizedTable:
- test_to_svg # blocking
ActionPackAssertionsControllerTest:
- test_render_file_absolute_path
- test_render_file_relative_path
AssertTemplateTest:
- test_assert_template_reset_between_requests
- test_fails_with_repeated_name_in_path
- test_file_with_absolute_path_success
- test_file_with_relative_path_success
- test_with_file_failure
FunctionalFragmentCachingTest:
- test_fragment_caching
- test_fragment_caching_with_variant
IntegrationProcessTest:
- test_cookie_persist_to_next_request
- test_https_and_port_via_host_and_https!
- test_https_and_port_via_process
- test_port_via_host!
- test_port_via_process
- test_cookie_persist_to_next_request_on_another_domain
- test_get
- test_get_with_parameters
- test_get_with_query_string
- test_get_xml_rss_atom
- test_head
- test_post
- test_redirect
- test_request_with_bad_format
- test_respect_removal_of_default_headers_by_a_controller_action
- test_response_cookies_are_added_to_the_cookie_jar_for_the_next_request
- test_xml_http_request_get
ApplicationIntegrationTest:
- test_missing_route_helper_after_controller_access
- test_missing_route_helper_before_controller_access
ActionController::SSETest:
- test_basic_sse
- test_sse_with_event_name
- test_sse_with_id
- test_sse_with_multiple_line_message
- test_sse_with_retry
ActionController::LiveStreamTest:
- test_abort_with_full_buffer
- test_async_stream
- test_bad_request_in_controller_before_streaming
- test_exception_callback_when_committed
- test_exception_handling_html
- test_exception_handling_plain_text
- test_exception_in_controller_before_streaming
- test_exceptions_raised_handling_exceptions_and_committed
- test_ignore_client_disconnect
- test_live_stream_default_header
- test_render_text
- test_set_cookie
- test_stale_with_etag
- test_stale_without_etag
- test_thread_locals_get_copied
- test_write_to_stream
ExpiresInRenderTest:
- test_dynamic_render_with_file
- test_permitted_dynamic_render_file_hash
RequestForgeryProtectionControllerUsingResetSessionTest:
- test_should_emit_a_csrf-param_meta_tag_and_a_csrf-token_meta_tag
- test_should_render_button_to_with_token_tag
- test_should_render_form_with_token_tag
- test_should_render_form_with_token_tag_if_remote_and_authenticity_token_requested
- test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested
- test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested_and_embedding_is_on
- test_should_render_form_with_token_tag_with_authenticity_token_requested
RequestForgeryProtectionControllerUsingExceptionTest:
- test_should_render_button_to_with_token_tag
- test_should_render_form_with_token_tag
- test_should_render_form_with_token_tag_if_remote_and_authenticity_token_requested
- test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested
- test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested_and_embedding_is_on
- test_should_render_form_with_token_tag_with_authenticity_token_requested
FreeCookieControllerTest:
- test_should_not_render_button_to_with_token_tag
- test_should_not_render_form_with_token_tag
RescueControllerTest:
- test_block_rescue_handler_with_argument
- test_block_rescue_handler_with_argument_as_string
- test_proc_rescue_handle_with_argument
- test_proc_rescue_handle_with_argument_as_string
SendFileTest:
- test_send_file_with_action_controller_live
TestCaseTest:
- test_assert_select_with_body
- test_assert_select_without_body
- test_should_not_impose_childless_html_tags_in_xml
MimeControllerLayoutsTest:
- test_format_with_inherited_layouts
- test_missing_layout_renders_properly
RespondToControllerTest:
- test_html_type_with_layout
ContentNegotiation::TestContentNegotiation:
- test_A_*/*_Accept_header_will_return_HTML
RenderAction::RenderActionTest:
- test_rendering_an_action_using_'<action>'
- test_rendering_an_action_using_'<action>'_and_options
- test_rendering_an_action_using_:action
- test_rendering_an_action_using_:action_=>_:hello_world
- test_rendering_an_action_using_:action_=>_<String>
RenderAction::RenderLayoutTest:
- test_rendering_with_layout_=>_'greetings'
- test_rendering_with_layout_=>_:nil
- test_rendering_with_layout_=>_false
- test_rendering_with_layout_=>_true
RenderActionWithApplicationLayout::LayoutTest:
- test_rendering_implicit_application.html.erb_as_layout
- test_rendering_with_layout_=>_'greetings'
- test_rendering_with_layout_=>_:nil
- test_rendering_with_layout_=>_false
- test_rendering_with_layout_=>_true
RenderActionWithApplicationLayout::TestLayout:
- test_builder_works_with_layouts
RenderActionWithControllerLayout::ControllerLayoutTest:
- test_render_hello_world_and_implicitly_use_<controller_path>.html.erb_as_a_layout.
- test_rendering_with_layout_=>_:nil
- test_rendering_with_layout_=>_false
- test_rendering_with_layout_=>_true
RenderActionWithBothLayouts::ControllerLayoutTest:
- test_rendering_implicitly_use_<controller_path>.html.erb_over_application.html.erb_as_a_layout
- test_rendering_with_layout_=>_:nil
- test_rendering_with_layout_=>_false
- test_rendering_with_layout_=>_true
RenderBody::RenderBodyTest:
- test_rendering_body_with_layout:_'greetings'
- test_rendering_body_with_layout:_true
RenderContext::RenderContextTest:
- test_rendering_using_the_controller_as_context
- test_rendering_using_the_controller_as_context_with_layout
RenderHtml::RenderHtmlTest:
- test_rendering_text_with_layout:_'greetings'
- test_rendering_text_with_layout:_true
RenderImplicitAction::RenderImplicitActionTest:
- test_available_action?_returns_true_for_implicit_actions
- test_render_a_simple_action_with_new_explicit_call_to_render
- test_render_an_action_called_not_implemented
- test_render_an_action_with_a_missing_method_and_has_special_characters
ControllerLayouts::RenderLayoutTest:
- test_overriding_an_implicit_layout_with_render_:layout_option
- test_rendering_a_normal_template,_but_using_an_implicit_NAMED_layout
- test_rendering_a_normal_template,_but_using_the_implicit_layout
ControllerLayouts::LayoutOptionsTest:
- test_rendering_with_:layout_=>_false_leaves_out_the_implicit_layout
ControllerLayouts::MismatchFormatTest:
- test_a_layout_for_JS_is_ignored_even_if_explicitly_provided_for_HTML
- test_if_XML_is_implicitly_selected,_an_HTML_template_is_not_also_selected
- test_if_XML_is_selected,_an_HTML_template_is_not_also_selected
ControllerLayouts::FalseLayoutMethodTest:
- test_access_false_layout_returned_by_a_method/proc
RenderPartial::TestPartial:
- test_rendering_a_partial_in_ActionView_doesn't_pull_the_ivars_again_from_the_controller
- test_rendering_a_template_with_renders_another_partial_with_other_format_that_renders_other_partial_in_the_same_format
RenderPartial::TestInheritedPartial:
- test_partial_from_child_controller_gets_picked
- test_partial_from_parent_controller_gets_picked_if_missing_in_child_one
RenderPlain::RenderPlainTest:
- test_rendering_text_with_layout:_'greetings'
- test_rendering_text_with_layout:_true
RenderStreaming::StreamingTest:
- test_do_not_stream_on_HTTP/1.0
- test_rendering_with_layout_exception
- test_rendering_with_streaming_do_not_override_explicit_cache_control_given_to_render
- test_rendering_with_streaming_enabled_at_the_class_level
- test_rendering_with_streaming_given_to_render
- test_rendering_with_streaming_no_layout
- test_rendering_with_template_exception
- test_rendering_with_template_exception_logs_the_exception
- test_skip_rendering_with_streaming_at_render_level
RenderTemplate::TestWithoutLayout:
- test_rendering_a_builder_template
- test_rendering_a_normal_template_with_full_path_without_layout
- test_rendering_a_normal_template_with_full_path_without_layout_without_key
- test_rendering_a_template_not_in_a_subdirectory
- test_rendering_a_template_not_in_a_subdirectory_with_a_leading_slash
- test_rendering_a_template_not_in_a_subdirectory_with_a_leading_slash_without_key
- test_rendering_a_template_with_<%=raw_stuff_%>
- test_rendering_a_template_with_error_properly_excerts_the_code
- test_rendering_a_template_with_local_variables
- test_rendering_a_template_with_local_variables_without_key
- test_rendering_a_template_with_renders_another_template_with_other_format_that_renders_other_template_in_the_same_format
RenderTemplate::TestWithLayout:
- test_rendering_layout_=>_'greetings'
- test_rendering_with_implicit_layout
- test_rendering_with_layout_=>_:false
- test_rendering_with_layout_=>_:nil
- test_rendering_with_layout_=>_:true
RenderTemplate::Compatibility::TestTemplateRenderWithForwardSlash:
- test_rendering_a_normal_template_with_full_path_starting_with_a_leading_slash
Render::RenderTest:
- test_render_with_blank
Render::TestOnlyRenderPublicActions:
- test_raises_an_exception_when_a_method_of_Object_is_called
- test_raises_an_exception_when_a_private_method_is_called
Render::TestVariousObjectsAvailableInView:
- test_The_action_name_is_accessible_in_the_view
- test_The_controller_name_is_accessible_in_the_view
- test_The_request_object_is_accessible_in_the_view
Render::TestViewInheritance:
- test_Template_from_child_controller_gets_picked_over_parent_one
- test_Template_from_child_controller_with_custom_view_paths_appended_gets_picked_over_parent_one
- test_Template_from_child_controller_with_custom_view_paths_prepended_gets_picked_over_parent_one
- test_Template_from_parent_controller_gets_picked_if_missing_in_child_controller
RenderText::RenderTextTest:
- test_rendering_text_with_layout:_'greetings'
- test_rendering_text_with_layout:_true
CookiesTest:
- test_encrypted_cookie_using_custom_digest
- test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_hybrid_jar_if_both_secret_token_and_secret_key_base_are_set
- test_legacy_signed_cookie_is_read_and_transparently_upgraded_by_signed_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
DebugExceptionsTest:
- test_debug_exceptions_app_shows_user_code_that_caused_the_error_in_source_view
- test_display_backtrace_on_template_missing_errors
- test_display_backtrace_when_error_type_is_SyntaxError
- test_display_backtrace_when_error_type_is_SyntaxError_wrapped_by_ActionView::Template::Error
- test_displays_request_and_response_info_when_a_RoutingError_occurs
- test_rescue_with_diagnostics_message
- test_rescue_with_text_error_for_xhr_request
- test_show_registered_original_exception_for_wrapped_exceptions
TestGenerationPrefix::WithMountedEngine:
- test_[ENGINE]_absolute_path_redirect_doesn't_use_SCRIPT_NAME_from_request
- test_[ENGINE]_absolute_path_root_doesn't_use_SCRIPT_NAME_from_request
- test_[ENGINE]_relative_path_redirect_uses_SCRIPT_NAME_from_request
TestRoutingMapper:
- test_redirect_modulo
TestRedirectInterpolation:
- test_path_redirect_escapes_interpolated_parameters_correctly
- test_redirect_escapes_interpolated_parameters_with_redirect_proc
TestGlobRoutingMapper:
- test_glob_constraint
QueryStringParsingTest:
- test_query_string_with_many_ampersands
CookieStoreTest:
- test_deserializes_unloaded_classes_on_get_id
- test_deserializes_unloaded_classes_on_get_value
210 changes: 210 additions & 0 deletions lib/ruby/truffle/jruby+truffle/lib/truffle/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
require 'pp'
require 'yaml'

stubs = {
# TODO (pitr-ch 23-Jun-2016): remove? it's not used any more
minitest: dedent(<<-RUBY),
require 'minitest'
# mock load_plugins as it loads rubygems
def Minitest.load_plugins
end
RUBY

activesupport_isolation: dedent(<<-RUBY),
require 'active_support/testing/isolation'
module ActiveSupport
module Testing
module Isolation
def run
with_info_handler do
time_it do
capture_exceptions do
before_setup; setup; after_setup
skip 'isolation not supported'
end
%w{ before_teardown teardown after_teardown }.each do |hook|
capture_exceptions do
self.send hook
end
end
end
end
return self # per contract
end
end
end
end
RUBY

bcrypt: dedent(<<-RUBY),
require 'bcrypt'
module BCrypt
class Engine
def self.hash_secret(secret, salt, _ = nil)
if valid_secret?(secret)
if valid_salt?(salt)
Truffle::Gem::BCrypt.hashpw(secret.to_s, salt.to_s)
else
raise Errors::InvalidSalt.new("invalid salt")
end
else
raise Errors::InvalidSecret.new("invalid secret")
end
end
def self.generate_salt(cost = self.cost)
cost = cost.to_i
if cost > 0
if cost < MIN_COST
cost = MIN_COST
end
Truffle::Gem::BCrypt.gensalt(cost)
else
raise Errors::InvalidCost.new("cost must be numeric and > 0")
end
end
end
end
RUBY

html_sanitizer: dedent(<<-RUBY),
require 'action_view'
require 'action_view/helpers'
require 'action_view/helpers/sanitize_helper'
module ActionView
module Helpers
module SanitizeHelper
def sanitize(html, options = {})
html
end
def sanitize_css(style)
style
end
def strip_tags(html)
html
end
def strip_links(html)
html
end
module ClassMethods #:nodoc:
attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
def sanitized_allowed_tags
[]
end
def sanitized_allowed_attributes
[]
end
end
end
end
end
RUBY

}.reduce({}) do |h, (k, v)|
file_name = "stub-#{k}"
h.update k => { setup: { file: { "#{file_name}.rb" => v } },
run: { require: [file_name] } }
end

replacements = {
bundler: dedent(<<-RUBY),
module Bundler
BundlerError = Class.new(Exception)
def self.setup
end
end
RUBY
:'bundler/gem_tasks' => nil,
java: nil,
bcrypt_ext: nil,
method_source: nil,
:'rails-html-sanitizer' => nil,
nokogiri: nil
}.reduce({}) do |h, (k, v)|
h.update k => { setup: { file: { "#{k}.rb" => v || %[puts "loaded '#{k}.rb' an empty replacement"] } } }
end

# add required replacements to stubs
deep_merge!(stubs.fetch(:bcrypt),
replacements.fetch(:java),
replacements.fetch(:bcrypt_ext))
deep_merge!(stubs.fetch(:html_sanitizer),
replacements.fetch(:'rails-html-sanitizer'),
replacements.fetch(:nokogiri))

def exclusion_file(gem_name)
data = YAML.load_file(__dir__ + "/#{gem_name}_exclusions.yaml")
data.pretty_inspect
end

rails_common =
deep_merge replacements.fetch(:bundler),
setup: { without: %w(db job) },
run: { environment: { 'N' => 1 },
require: %w(rubygems date bigdecimal pathname openssl-stubs) }

config :activesupport,
deep_merge(
rails_common,
stubs.fetch(:activesupport_isolation),
replacements.fetch(:method_source))

config :activemodel,
deep_merge(
rails_common,
stubs.fetch(:activesupport_isolation),
stubs.fetch(:bcrypt))

# TODO (pitr-ch 23-Jun-2016): investigate, fails intermittently
config :actionpack,
deep_merge(
rails_common,
stubs.fetch(:html_sanitizer),
setup: { file: { 'excluded-tests.rb' => format(dedent(<<-RUBY), exclusion_file(:actionpack)),
failures = %s
require 'truffle/exclude_rspec_examples'
Truffle.exclude_rspec_examples failures
RUBY
} })

config :'concurrent-ruby',
setup: { file: { "stub-processor_number.rb" => dedent(<<-RUBY) } },
# stub methods calling #system
require 'concurrent'
module Concurrent
module Utility
class ProcessorCounter
def compute_processor_count
2
end
def compute_physical_processor_count
2
end
end
end
end
RUBY
run: { require: %w(stub-processor_number) }

config :monkey_patch,
replacements.fetch(:bundler)

config :openweather,
replacements.fetch(:'bundler/gem_tasks')

config :psd,
replacements.fetch(:nokogiri)
222 changes: 167 additions & 55 deletions lib/ruby/truffle/jruby+truffle/lib/truffle/runner.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,21 @@
require 'rubygems'
require 'bundler'

class String
def pretty_print(q)
lines = self.lines
if lines.size > 1
q.group(0, '', '') do
q.seplist(lines, lambda { q.text ' +'; q.breakable }) do |v|
q.pp v
end
end
else
q.text inspect
end
end
end

module Truffle
class Runner
module Utils
@@ -61,10 +76,20 @@ def print_cmd(cmd, dir, print)
command.map { |v| Shellwords.escape v }
end

puts '$ ' + [*formatted_env, *formatted_cmd].compact.join(' ') + (dir ? " (in #{dir})" : '')
log '$ ' + [*formatted_env, *formatted_cmd].compact.join(' ') + (dir ? " (in #{dir})" : '')
return cmd
end

def dig(data, *keys)
return data if keys.empty?

if data.respond_to?(:[])
dig data[keys[0]], keys[1..-1]
else
raise ArgumentError, "#{data.inspect} does not have :[] method to apply key: #{keys[0]}"
end
end

def dig_deep(data, selection)
return data if selection.nil?

@@ -87,6 +112,59 @@ def dig_deep(data, selection)
end
end

def deep_merge!(a, b, *rest)
[a, b, *rest].reduce { |a, b| deep_merge2! a, b }
end

def deep_merge(a, b, *rest)
[a, b, *rest].reduce { |a, b| deep_merge2 a, b }
end

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

if Array === a
if Array === b
return a.concat b
else
return a
end
end

b
end

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

if Array === a
if Array === b
return a + b
else
return a
end
end

b
end

def log(message)
puts 'jtr: ' + message
end

extend self
end

include Utils
@@ -113,7 +191,7 @@ module OptionBlocks
apply_pattern = -> (pattern, old, options) do
Dir.glob(pattern) do |file|
if options[:exclude_pattern].any? { |p| /#{p}/ =~ file }
puts "skipped: #{file}" if verbose?
log "skipped: #{file}" if verbose?
next
end
options[:require] << File.expand_path(file)
@@ -149,6 +227,8 @@ module OptionBlocks
STORE_NEW_VALUE, true],
bundle_options: ['--bundle-options OPTIONS', 'bundle options separated by space', STORE_NEW_VALUE, ''],
configuration: ['--config GEM_NAME', 'Load configuration for specified gem', STORE_NEW_VALUE, nil],
configuration_file: ['--config-file PATH', 'Path to a file defining configuration of gems',
STORE_NEW_VALUE, ROOT.join('lib', 'truffle', 'config.rb')],
dir: ['--dir DIRECTORY', 'Set working directory', STORE_NEW_VALUE, nil],
},
setup: { help: ['-h', '--help', 'Show this message', STORE_NEW_VALUE, false],
@@ -271,9 +351,24 @@ def initialize(argv, options = {})
@subcommand, *argv_after_global = @option_parsers[:global].order argv
@called_from_dir = Dir.pwd
@options[:global][:dir] = File.expand_path(@options[:global][:dir] || @called_from_dir)
@config = Config.new

Dir.chdir @options[:global][:dir] do
puts "pwd: #{Dir.pwd}" if verbose?
log "pwd is #{Dir.pwd}" if verbose?

@config.load @options[:global][:configuration_file].to_s

@gem_name = if @options[:global][:configuration]
@options[:global][:configuration].to_sym
else
candidates = Dir['*.gemspec']
if candidates.size == 1
gem_name, _ = candidates.first.split('.')
gem_name.to_sym
end
end

log "detected gem/app: #{@gem_name}" if @gem_name

load_gem_configuration
load_local_configuration
@@ -296,14 +391,14 @@ def initialize(argv, options = {})

def run
Dir.chdir @options[:global][:dir] do
log "executing #{@subcommand}"
send "subcommand_#{@subcommand}", @argv_after_subcommand
end
end

def print_options
if verbose?
puts 'Options:'
pp @options
log "Options are\n" + @options.pretty_inspect
end
end

@@ -339,14 +434,13 @@ def build_option_parser(parser_options, options_hash)
end

def load_gem_configuration
candidates = @options[:global][:configuration] ? [@options[:global][:configuration]] : Dir['*.gemspec']

if candidates.size == 1
gem_name, _ = candidates.first.split('.')
yaml_path = ROOT.join 'gem_configurations', "#{gem_name}.yaml"
if @gem_name
if (c = @config.for(@gem_name))
apply_hash_to_configuration c
log "loading configuration for #{@gem_name}"
log "configuration is:\n#{c.pretty_inspect}" if verbose?
end
end

apply_yaml_to_configuration(yaml_path)
end

def load_local_configuration
@@ -357,11 +451,16 @@ def load_local_configuration
def apply_yaml_to_configuration(yaml_path)
if yaml_path && File.exist?(yaml_path)
yaml_data = YAML.load_file(yaml_path)
@options = deep_merge @options, yaml_data
puts "loading #{yaml_path}"
apply_hash_to_configuration(yaml_data)
log "loading YAML configuration #{yaml_path}"
end
end

def apply_hash_to_configuration(yaml_data)
# pp '--------', @options, yaml_data, deep_merge(@options, yaml_data)
@options = deep_merge! @options, yaml_data
end

def construct_default_options
OPTION_DEFINITIONS.each_with_object({}) do |(group, group_options), options|
options[group] = default_option_values(group_options)
@@ -392,34 +491,14 @@ def help(key = nil)
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.concat b
else
return a
end
end

b
end

BUNDLER_EVAL_ENV = Object.new

def BUNDLER_EVAL_ENV.gem(name, options)
[name, options]
end

def BUNDLER_EVAL_ENV.process(line)
eval line
def parse_gemfile_line(line)
BUNDLER_EVAL_ENV.send :eval, line
end

def gemfile_use_path!(gems_path)
@@ -428,7 +507,7 @@ def gemfile_use_path!(gems_path)
new_lines = File.read(gemfile).lines.map do |line|
if line =~ /^( +)gem.*git:/
space = $1
gem_name, options = BUNDLER_EVAL_ENV.process(line)
gem_name, options = parse_gemfile_line(line)
repo_name = options[:git].split('/').last
repo_match = "#{gems_path}/bundler/gems/#{repo_name}-*"
repo_path = Dir[repo_match].first
@@ -452,36 +531,36 @@ def subcommand_setup(rest)
bundle_options = @options[:global][:bundle_options].split(' ')
bundle_path = File.expand_path(@options[:global][:truffle_bundle_path])
execute_all = lambda do |cmd|
execute_cmd([{ 'JRUBY_BIN' => JRUBY_BIN.to_s }, cmd])
case cmd
when Proc
cmd.call
when Array, String
execute_cmd([{ 'JRUBY_BIN' => JRUBY_BIN.to_s }, cmd])
else
raise
end
end

real_path = File.join(bundle_path, RUBY_ENGINE)
target_gem_path = File.join(bundle_path, RUBY_ENGINE, '2.3.0')
target_gem_path_22 = File.join(bundle_path, RUBY_ENGINE, '2.2.0')
jruby_truffle_path = File.join(bundle_path, 'jruby+truffle')
mock_path = File.join(bundle_path, @options[:global][:mock_load_path])

FileUtils.mkpath real_path
FileUtils.mkpath mock_path

FileUtils.ln_s RUBY_ENGINE,
jruby_truffle_path,
verbose: verbose?,
force: true
File.symlink RUBY_ENGINE, jruby_truffle_path unless File.exist? jruby_truffle_path

if @options[:setup][:offline]
FileUtils.rmtree target_gem_path
FileUtils.ln_s @options[:setup][:offline_gem_path],
target_gem_path,
verbose: verbose?
File.symlink @options[:setup][:offline_gem_path], target_gem_path
else
File.delete target_gem_path if File.symlink?(target_gem_path)
FileUtils.mkpath target_gem_path
end

FileUtils.ln_s '2.3.0',
File.join(bundle_path, RUBY_ENGINE, '2.2.0'),
verbose: verbose?,
force: true
File.symlink '2.3.0', target_gem_path_22 unless File.exist? target_gem_path_22

@options[:setup][:before].each(&execute_all)

@@ -498,7 +577,7 @@ def subcommand_setup(rest)
print_always: true)

@options[:setup][:file].each do |name, content|
puts "creating file: #{mock_path}/#{name}" if verbose?
log "creating file: #{mock_path}/#{name}" if verbose?
FileUtils.mkpath File.dirname("#{mock_path}/#{name}")
File.write "#{mock_path}/#{name}", content
end
@@ -511,7 +590,7 @@ def subcommand_setup(rest)

true
rescue => e
puts format('%s: %s\n%s', e.class, e.message, e.backtrace.join("\n"))
log format('%s: %s\n%s', e.class, e.message, e.backtrace.join("\n"))
false
end

@@ -544,7 +623,7 @@ def subcommand_run(rest)
core_load_path = jruby_path.join 'truffle/src/main/ruby'

missing_core_load_path = !File.exists?(core_load_path)
puts "Core load path: #{core_load_path} does not exist, fallbacking to --no-use-fs-core" if missing_core_load_path
log "Core load path: #{core_load_path} does not exist, fallbacking to --no-use-fs-core" if missing_core_load_path

truffle_options = [
'-X+T',
@@ -603,7 +682,8 @@ def subcommand_ci(rest)
end

results = batch.each_line.map do |line|
next if line =~ /^#/ || line.strip.empty?
# commented lines result in true
next true if line =~ /^#/ || line.strip.empty?

options = {}
option_parser = build_option_parser OPTION_DEFINITIONS[:ci], options
@@ -635,6 +715,38 @@ def execute_cmd(cmd, dir: nil, raise: true, print_always: false)
super cmd, dir: dir, raise: raise, print: verbose? || print_always
end

class Config
def initialize
@configurations = {}
end

def load(path)
content = File.read path
eval content, binding, path, 1
end

def dedent(string)
indent = string.lines[0] =~ /[^ ]/
string.lines.map { |l| l[indent..-1] }.join
end

def config(gem_name, configuration)
@configurations[gem_name] = configuration
end

def deep_merge(a, b, *rest)
Utils.deep_merge a, b, *rest
end

def deep_merge!(a, b, *rest)
Utils.deep_merge! a, b, *rest
end

def for(gem_name)
@configurations[gem_name]
end
end

class CIEnvironment
include Utils
include OptionBlocks
@@ -687,12 +799,12 @@ def do_definition(name, raise: true)
ci_file = Dir.glob(ROOT.join('gem_ci', "{#{name}}.rb")).first
return false if ci_file.nil?

puts "Using CI definition: #{ci_file}"
log "Using CI definition: #{ci_file}"
catch :cancel_ci! do
begin
instance_eval File.read(ci_file), ci_file, 1
rescue => e
puts format('%s: %s\n%s', e.class, e.message, e.backtrace.join("\n"))
log format('%s: %s\n%s', e.class, e.message, e.backtrace.join("\n"))
end
end

29 changes: 16 additions & 13 deletions truffle/src/main/java/org/jruby/truffle/core/rope/LazyIntRope.java
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
package org.jruby.truffle.core.rope;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import org.jcodings.Encoding;
import org.jcodings.specific.USASCIIEncoding;

@@ -30,8 +29,9 @@ protected LazyIntRope(int value, Encoding encoding, int length) {
assert Integer.toString(value).length() == length;
}

@ExplodeLoop
private static int length(int value) {
final int sign;

if (value < 0) {
/*
* We can't represent -Integer.MIN_VALUE, and we're about to multiple by 10 to add the space needed for the
@@ -43,25 +43,28 @@ private static int length(int value) {
}

value = -value;
value *= 10;
}

// If values were evenly distributed it would make more sense to do this in the reverse order, but they aren't

for (int n = 1, limit = 10; n < 10; n++, limit *= 10) {
if (value < limit) {
return n;
}
sign = 1;
} else {
sign = 0;
}

return 10;
return sign + (value < 1E5 ?
value < 1E2 ?
value < 1E1 ? 1 : 2 :
value < 1E3 ? 3 :
value < 1E4 ? 4 : 5 :
value < 1E7 ?
value < 1E6 ? 6 : 7 :
value < 1E8 ? 8 :
value < 1E9 ? 9 : 10);
}

@Override
public Rope withEncoding(Encoding newEncoding, CodeRange newCodeRange) {
if (newCodeRange != getCodeRange()) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new UnsupportedOperationException("Cannot fast-path updating encoding with different code range.");
throw new UnsupportedOperationException(
"Cannot fast-path updating encoding with different code range.");
}

return new LazyIntRope(value, newEncoding, length(value));
Original file line number Diff line number Diff line change
@@ -36,57 +36,47 @@ public class SymbolTable {

private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final WeakHashMap<Rope, WeakReference<DynamicObject>> symbolsTable = new WeakHashMap<>();
private final WeakHashMap<String, WeakReference<DynamicObject>> symbolsTableByString = new WeakHashMap<>();
private final WeakHashMap<String, WeakReference<Rope>> ropesTableByString = new WeakHashMap<>();

public SymbolTable(RubyContext context) {
this.context = context;
}

@CompilerDirectives.TruffleBoundary
@TruffleBoundary
public DynamicObject getSymbol(String string) {
lock.readLock().lock();

Rope rope = null;
try {
final WeakReference<DynamicObject> symbolReference = symbolsTableByString.get(string);

if (symbolReference != null) {
final DynamicObject symbol = symbolReference.get();

if (symbol != null) {
return symbol;
}
}
rope = readRope(string);
} finally {
lock.readLock().unlock();
}

final Rope rope = StringOperations.createRope(string, USASCIIEncoding.INSTANCE);
final DynamicObject symbol = getSymbol(rope);

lock.writeLock().lock();
if (rope == null) {
rope = StringOperations.createRope(string, USASCIIEncoding.INSTANCE);

try {
symbolsTableByString.put(string, new WeakReference<>(symbol));
// we do not need to ensure that the map does not have the string key,
// it may write different objects but logically it writes equal key, value

return symbol;
} finally {
lock.writeLock().unlock();
lock.writeLock().lock();
try {
ropesTableByString.put(string, new WeakReference<>(rope));
} finally {
lock.writeLock().unlock();
}
}

return getSymbol(rope);
}

@CompilerDirectives.TruffleBoundary
@TruffleBoundary
public DynamicObject getSymbol(Rope rope) {
lock.readLock().lock();

try {
final WeakReference<DynamicObject> symbolReference = symbolsTable.get(rope);

if (symbolReference != null) {
final DynamicObject symbol = symbolReference.get();

if (symbol != null) {
return symbol;
}
final DynamicObject symbol = readSymbol(rope);
if (symbol != null) {
return symbol;
}
} finally {
lock.readLock().unlock();
@@ -97,12 +87,9 @@ public DynamicObject getSymbol(Rope rope) {
try {
final WeakReference<DynamicObject> symbolReference = symbolsTable.get(rope);

if (symbolReference != null) {
final DynamicObject symbol = symbolReference.get();

if (symbol != null) {
return symbol;
}
final DynamicObject symbol = readSymbol(rope);
if (symbol != null) {
return symbol;
}

final DynamicObject symbolClass = context.getCoreLibrary().getSymbolClass();
@@ -122,7 +109,17 @@ public DynamicObject getSymbol(Rope rope) {
}
}

@CompilerDirectives.TruffleBoundary
private Rope readRope(String string) {
final WeakReference<Rope> ropeReference = ropesTableByString.get(string);
return ropeReference != null ? ropeReference.get() : null;
}

private DynamicObject readSymbol(Rope rope) {
final WeakReference<DynamicObject> ropeReference = symbolsTable.get(rope);
return ropeReference != null ? ropeReference.get() : null;
}

@TruffleBoundary
public Collection<DynamicObject> allSymbols() {
final Collection<WeakReference<DynamicObject>> symbolReferences;