diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 892ec5041de7..b955ae7c1c5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,7 +192,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.6, 2.7, '3.0'] + ruby: [2.7, '3.0', 3.1] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fa2d641c1c9..8677be2ab050 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Bug fixes: * Fix capacity computation for huge `Hash` (#2635, @eregon). * Fix aliased methods to return the correct owner when method is from a superclass (@bjfish). * Fix `String#[Regexp, Integer]` when the capture group exists but is not matched (@eregon). +* Fix `File.open` mode string parsing when binary option is the third character (@bjfish). +* Fix `rb_scan_args_kw` macro to avoid shadowing variables (#2649, @aardvark179). Compatibility: @@ -22,6 +24,8 @@ Compatibility: * Implement `rb_gc_mark_maybe` and `rb_global_variable` to ensure `VALUE` stay live in C extensions (@aardvark179). * Implement `rb_imemo_tmpbuf` allocation for `ripper` (@aardvark179). * `Process.euid=` should accept String (#2615, @ngtban). +* Implement `inherit` argument for `Module#class_variables` (#2653, @bjfish). +* Fix `Float#/` when dividing by `Rational` (@bjfish). Performance: diff --git a/bench/benchmark-interface/examples/error.rb b/bench/benchmark-interface/examples/error.rb index dcc135c83263..9b55c36455e0 100644 --- a/bench/benchmark-interface/examples/error.rb +++ b/bench/benchmark-interface/examples/error.rb @@ -6,8 +6,8 @@ # GNU General Public License version 2, or # GNU Lesser General Public License version 2.1. -start = Time.now +start = BenchmarkInterface.get_time benchmark do - 1/0 if Time.now - start > 3 + 1/0 if BenchmarkInterface.get_time - start > 3 end diff --git a/bench/benchmark-interface/lib/benchmark-interface.rb b/bench/benchmark-interface/lib/benchmark-interface.rb index 9762a2e91b30..fe2488da4924 100644 --- a/bench/benchmark-interface/lib/benchmark-interface.rb +++ b/bench/benchmark-interface/lib/benchmark-interface.rb @@ -7,7 +7,9 @@ # GNU Lesser General Public License version 2.1. require 'benchmark-interface/version' +require 'benchmark-interface/timing' require 'benchmark-interface/benchmark' +require 'benchmark-interface/benchmark-api' require 'benchmark-interface/benchmark-set' require 'benchmark-interface/frontends/mri' require 'benchmark-interface/backends/simple' @@ -21,6 +23,8 @@ require 'benchmark-interface/run' module BenchmarkInterface + extend Timing + def self.benchmark(name=nil, &block) BenchmarkInterface::BenchmarkSet.current.register name, block end @@ -28,9 +32,10 @@ def self.benchmark(name=nil, &block) def self.run_n_iterations(iterations) i = 0 while i < iterations - yield + result = yield i += 1 end + result end end @@ -38,7 +43,7 @@ def benchmark(name=nil, &block) BenchmarkInterface.benchmark name, &block end -if $PROGRAM_NAME.split('/').last != 'benchmark' +if File.basename($PROGRAM_NAME) != 'benchmark' set = BenchmarkInterface::BenchmarkSet.new backend = BenchmarkInterface::Backends::Bips diff --git a/bench/benchmark-interface/lib/benchmark-interface/backends/simple.rb b/bench/benchmark-interface/lib/benchmark-interface/backends/simple.rb index 96688a5f275f..49c5bf43884b 100644 --- a/bench/benchmark-interface/lib/benchmark-interface/backends/simple.rb +++ b/bench/benchmark-interface/lib/benchmark-interface/backends/simple.rb @@ -9,22 +9,11 @@ module BenchmarkInterface module Backends module Simple - + extend BenchmarkInterface::Timing + INITIAL_ITERATIONS = 1 MAX_ITERATIONS = 2147483647 - # Accomodates Rubinius - - if defined?(Process::CLOCK_MONOTONIC) - def self.get_time - Process.clock_gettime(Process::CLOCK_MONOTONIC) - end - else - def self.get_time - Time.now - end - end - def self.run(benchmark_set, names, options) full_time = options['--time'] freq = options['--freq'] @@ -42,8 +31,9 @@ def self.run(benchmark_set, names, options) while get_time - start_time < full_time start_round_time = get_time - BenchmarkInterface.run_n_iterations(iterations, &block) + result = BenchmarkInterface.run_n_iterations(iterations, &block) round_time = get_time - start_round_time + benchmark.verify!(result) # If the round time was very low and so very imprecise then we may # get a wild number of iterations next time. diff --git a/bench/benchmark-interface/lib/benchmark-interface/backends/stable.rb b/bench/benchmark-interface/lib/benchmark-interface/backends/stable.rb index 57a06f52571d..b7993229d20f 100644 --- a/bench/benchmark-interface/lib/benchmark-interface/backends/stable.rb +++ b/bench/benchmark-interface/lib/benchmark-interface/backends/stable.rb @@ -9,6 +9,7 @@ module BenchmarkInterface module Backends module Stable + extend BenchmarkInterface::Timing def self.run(benchmark_set, names, options) full_time = options['--time'] @@ -22,16 +23,16 @@ def self.run(benchmark_set, names, options) puts benchmark.name block = benchmark.block - start_time = Time.now + start_time = get_time - while Time.now - start_time < full_time - start_round_time = Time.now + while get_time - start_time < full_time + start_round_time = get_time block.call - round_time = Time.now - start_round_time + round_time = get_time - start_round_time ips = 1 / round_time puts 1 if print_iterations - puts Time.now - start_time if elapsed + puts get_time - start_time if elapsed puts ips * inner_iterations end end diff --git a/bench/benchmark-interface/lib/benchmark-interface/benchmark-api.rb b/bench/benchmark-interface/lib/benchmark-interface/benchmark-api.rb new file mode 100644 index 000000000000..0318ddfe5f25 --- /dev/null +++ b/bench/benchmark-interface/lib/benchmark-interface/benchmark-api.rb @@ -0,0 +1,21 @@ +# Copyright (c) 2022 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 2.0, or +# GNU General Public License version 2, or +# GNU Lesser General Public License version 2.1. + +module BenchmarkInterface + class BenchmarkAPI + attr_reader :benchmark + + def initialize(benchmark) + @benchmark = benchmark + end + + def verify(&block) + @benchmark.verify_block = block + end + end +end diff --git a/bench/benchmark-interface/lib/benchmark-interface/benchmark-set.rb b/bench/benchmark-interface/lib/benchmark-interface/benchmark-set.rb index da683a997708..05eb21b85f1e 100644 --- a/bench/benchmark-interface/lib/benchmark-interface/benchmark-set.rb +++ b/bench/benchmark-interface/lib/benchmark-interface/benchmark-set.rb @@ -35,7 +35,9 @@ def load_mri_benchmarks(path, options) def register(name, code) name = implicit_name unless name - @benchmarks.push Benchmark.new(name, code) + benchmark = Benchmark.new(name, code) + @benchmarks.push benchmark + BenchmarkInterface::BenchmarkAPI.new(benchmark) end def implicit_name diff --git a/bench/benchmark-interface/lib/benchmark-interface/benchmark.rb b/bench/benchmark-interface/lib/benchmark-interface/benchmark.rb index 32d72b1e3ef8..0e197d2eddda 100644 --- a/bench/benchmark-interface/lib/benchmark-interface/benchmark.rb +++ b/bench/benchmark-interface/lib/benchmark-interface/benchmark.rb @@ -10,12 +10,23 @@ module BenchmarkInterface class Benchmark attr_reader :name, :block - + attr_writer :verify_block + def initialize(name, block) @name = name @block = block end + def verify!(result) + if @verify_block + check = @verify_block.call(result) + unless check + raise "Benchmark #{@name} did not return the correct value, " \ + "the verify block returned #{check.inspect} and the result was:\n#{result.inspect}" + end + end + end + def remove_line_numbers @name = @name.split(':')[0...-1].join(':') if @name.include? ':' end @@ -23,18 +34,21 @@ def remove_line_numbers def time_block(desired_time) iterations = 1 while true - start = Time.now + start = BenchmarkInterface.get_time if block.arity == 1 - block.call iterations + result = block.call iterations else - BenchmarkInterface.run_n_iterations(iterations, &block) + result = BenchmarkInterface.run_n_iterations(iterations, &block) end + time = BenchmarkInterface.get_time - start + + verify!(result) - time = Time.now - start return [time, iterations] if time >= desired_time iterations *= 2 end end + private :time_block def basic_iteration_time time, iterations = time_block(0.1) diff --git a/bench/benchmark-interface/lib/benchmark-interface/timing.rb b/bench/benchmark-interface/lib/benchmark-interface/timing.rb new file mode 100644 index 000000000000..f41354f31105 --- /dev/null +++ b/bench/benchmark-interface/lib/benchmark-interface/timing.rb @@ -0,0 +1,22 @@ +# Copyright (c) 2022 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 2.0, or +# GNU General Public License version 2, or +# GNU Lesser General Public License version 2.1. + +module BenchmarkInterface + module Timing + if defined?(Process::CLOCK_MONOTONIC) + def get_time + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + else + # Accomodates Rubinius + def get_time + Time.now + end + end + end +end diff --git a/bench/liquid/liquid-bibs-render.rb b/bench/liquid/liquid-bibs-render.rb index 29d49af078ce..49e7275e9d9e 100644 --- a/bench/liquid/liquid-bibs-render.rb +++ b/bench/liquid/liquid-bibs-render.rb @@ -13,5 +13,7 @@ benchmark do result = template.render!(data) dev_null.write result - raise StandardError, "Incorrect rendering result" unless result == expected_result + result +end.verify do |result| + result == expected_result end diff --git a/ci.jsonnet b/ci.jsonnet index af26f7a01e3f..029495d15258 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -10,7 +10,7 @@ # https://github.com/google/jsonnet/releases and compiled. # CONFIGURATION -local overlay = "ffb092a26e86b0b4c2ac33bdbc329d938b527942"; +local overlay = "52900f1ecd0b7b23e0bbb74e7552886e6ec29df3"; # For debugging: generated builds will be restricted to those listed in # the array. No restriction is applied when it is empty. @@ -34,6 +34,8 @@ local part_definitions = { use: { common: { + python_version: "3", # To use the correct virtualenv + environment+: { path+:: [], TRUFFLERUBY_CI: "true", @@ -676,19 +678,6 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, " "ruby-benchmarks-other-svm-graal-enterprise-multi-tier": shared + svm_other + svm_configurations["svm-graal-enterprise"] + $.use.multi_tier, } + - { - local shared = $.platform.linux + $.jdk.v11 + $.use.common + $.use.gem_test_pack + - $.benchmark.runner + $.benchmark.server + - { timelimit: "00:30:00" }, - - "ruby-benchmarks-server-mri": shared + other_rubies.mri, - "ruby-benchmarks-server-jruby": shared + other_rubies.jruby, - "ruby-benchmarks-server-graal-core": shared + graal_configurations["graal-core"] + $.use.no_multi_tier, - "ruby-benchmarks-server-graal-core-multi-tier": shared + graal_configurations["graal-core"] + $.use.multi_tier, - "ruby-benchmarks-server-graal-enterprise": shared + graal_configurations["graal-enterprise"] + $.use.no_multi_tier, - "ruby-benchmarks-server-graal-enterprise-multi-tier": shared + graal_configurations["graal-enterprise"] + $.use.multi_tier, - } + - { "ruby-metrics-truffle": $.platform.linux + $.jdk.v11 + $.use.common + $.env.jvm + $.use.build + @@ -735,6 +724,7 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, " }; { + part_definitions:: part_definitions, specVersion: "3", overlay: overlay, builds: composition_environment.builds, diff --git a/common.json b/common.json index bc1ca838a9c9..6b5da58c00f0 100644 --- a/common.json +++ b/common.json @@ -30,23 +30,18 @@ ], "deps": { - "COMMENT.common": [ - "pip:isort is a dependency of pip:pylint. The explicit dependency on the pip package works around", - "https://bugzilla.redhat.com/show_bug.cgi?id=1710221 on older Redhat-based systems, and doesn't", - "hurt on others." - ], "common": { "timelimit": "30:00", "environment": { - "MX_PYTHON": "python3" + "MX_PYTHON": "python3.8" }, "packages": { - "pip:isort": "==4.3.19", - "pip:logilab-common": "==1.4.4", - "pip:pylint": "==1.9.3", + "python3": "==3.8.10", + "pip:pylint": "==2.4.4", "pip:lazy-object-proxy": "==1.6.0", "pip:ninja_syntax": "==1.7.2" - } + }, + "python_version": "3" }, "linux": { @@ -80,6 +75,15 @@ }, "environment": { "ECLIPSE_EXE": "$ECLIPSE/eclipse" + }, + + "COMMENT.eclipse_org": [ + "Coordinates for downloading same version as above directly from eclipse.org (used by GitHub actions).", + "Template URL: https://archive.eclipse.org/eclipse/downloads/drops4/R--/eclipse-SDK--linux-gtk-x86_64.tar.gz" + ], + "eclipse_org": { + "version": "4.14", + "timestamp": "201912100610" } }, "jdt": { diff --git a/lib/cext/ABI_version.txt b/lib/cext/ABI_version.txt index 00750edc07d6..b8626c4cff28 100644 --- a/lib/cext/ABI_version.txt +++ b/lib/cext/ABI_version.txt @@ -1 +1 @@ -3 +4 diff --git a/lib/cext/include/truffleruby/truffleruby.h b/lib/cext/include/truffleruby/truffleruby.h index d63b7c25facf..7ec070e5d951 100644 --- a/lib/cext/include/truffleruby/truffleruby.h +++ b/lib/cext/include/truffleruby/truffleruby.h @@ -61,21 +61,25 @@ if (polyglot_as_boolean(polyglot_invoke(RUBY_CEXT, "warning?"))) { \ } \ }) +struct rb_tr_scan_args_parse_data { + int pre; + int optional; + bool rest; + int post; + bool kwargs; + bool block; +}; + #define rb_tr_scan_args_kw(kw_flag, argc, argv, format, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \ (RBIMPL_CONSTANT_P(format) ? \ __extension__ ({ \ - static bool evaled; \ - static int pre; \ - static int optional; \ - static bool rest; \ - static int post; \ - static bool kwargs; \ - static bool block; \ - if (!evaled) { \ - rb_tr_scan_args_kw_parse(format, &pre, &optional, &rest, &post, &kwargs, &block); \ - evaled = true; \ + static bool rb_tr_scan_args_format_str_evaled; \ + static struct rb_tr_scan_args_parse_data rb_tr_scan_data; \ + if (!rb_tr_scan_args_format_str_evaled) { \ + rb_tr_scan_args_kw_parse(format, &rb_tr_scan_data); \ + rb_tr_scan_args_format_str_evaled = true; \ } \ - rb_tr_scan_args_kw_int(kw_flag, argc, argv, pre, optional, rest, post, kwargs, block, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); \ + rb_tr_scan_args_kw_int(kw_flag, argc, argv, rb_tr_scan_data, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); \ }) : \ rb_tr_scan_args_kw_non_const(kw_flag, argc, argv, format, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)) @@ -214,10 +218,10 @@ static inline char *rb_tr_string_value_cstr(VALUE *value_pointer) { return RSTRING_PTR(string); } -void rb_tr_scan_args_kw_parse(const char *format, int *pre, int *optional, bool *rest, int *post, bool *kwargs, bool *block); +void rb_tr_scan_args_kw_parse(const char *format, struct rb_tr_scan_args_parse_data *parse_data); -ALWAYS_INLINE(static int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int pre, int optional, bool rest, int post, bool kwargs, bool block, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10)); -static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int pre, int optional, bool rest, int post, bool kwargs, bool block, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) { +ALWAYS_INLINE(static int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, struct rb_tr_scan_args_parse_data parse_data, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10)); +static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, struct rb_tr_scan_args_parse_data parse_data, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) { int keyword_given = 0; int last_hash_keyword = 0; @@ -230,12 +234,12 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int // Check we have enough arguments - if (pre + post > argc) { + if (parse_data.pre + parse_data.post > argc) { rb_raise(rb_eArgError, "not enough arguments for required"); } - const int n_mand = pre + post; - const int n_opt = optional; + const int n_mand = parse_data.pre + parse_data.post; + const int n_opt = parse_data.optional; // Read arguments @@ -256,7 +260,7 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int if (argc > 0) { VALUE last = argv[argc - 1]; - if (kwargs && n_mand < argc) { + if (parse_data.kwargs && n_mand < argc) { if (keyword_given) { if (!RB_TYPE_P(last, T_HASH)) { rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash"); @@ -271,8 +275,8 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int option hash only if it is not ambiguous; i.e. '*' is not specified and arguments are given more than sufficient. This will be removed in Ruby 3. */ - if (rest || argc <= n_mand + n_opt) { - kwargs = false; + if (parse_data.rest || argc <= n_mand + n_opt) { + parse_data.kwargs = false; erased_kwargs = true; rb_warn("The last argument is nil, treating as empty keywords"); } @@ -280,7 +284,7 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int else { hash = rb_check_hash_type(last); if (NIL_P(hash)) { - kwargs = false; + parse_data.kwargs = false; erased_kwargs = true; } } @@ -290,20 +294,20 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int if (!polyglot_as_boolean(RUBY_CEXT_INVOKE_NO_WRAP("test_kwargs", argv[argc - 1], Qfalse))) { // Does not handle the case where "The last argument is split into positional and keyword parameters" // Instead assumes that it is all one hash - kwargs = false; + parse_data.kwargs = false; erased_kwargs = true; } } } - else if (kwargs && keyword_given && n_mand == argc) { + else if (parse_data.kwargs && keyword_given && n_mand == argc) { /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */ rb_warn("Passing the keyword argument as the last hash parameter is deprecated"); } } - int trailing = post; + int trailing = parse_data.post; - if (kwargs) { + if (parse_data.kwargs) { trailing++; } @@ -312,31 +316,31 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int VALUE arg; - if (pre > 0 || optional > 0) { - if (argn - pre < argc - trailing) { + if (parse_data.pre > 0 || parse_data.optional > 0) { + if (argn - parse_data.pre < argc - trailing) { arg = argv[argn]; argn++; } else { arg = Qnil; } - if (pre > 0) { - pre--; + if (parse_data.pre > 0) { + parse_data.pre--; } else { - optional--; + parse_data.optional--; } - } else if (rest && !taken_rest) { + } else if (parse_data.rest && !taken_rest) { arg = rb_ary_new(); while (argn < argc - trailing) { rb_ary_push(arg, argv[argn]); argn++; } taken_rest = true; - } else if (post > 0) { + } else if (parse_data.post > 0) { arg = argv[argn]; argn++; - post--; - } else if (kwargs && !taken_kwargs) { + parse_data.post--; + } else if (parse_data.kwargs && !taken_kwargs) { if (argn < argc) { arg = argv[argn]; RUBY_CEXT_INVOKE_NO_WRAP("test_kwargs", arg, Qtrue); @@ -349,7 +353,7 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int } else if (erased_kwargs && !taken_kwargs) { arg = Qnil; taken_kwargs = true; - } else if (block && !taken_block) { + } else if (parse_data.block && !taken_block) { if (rb_block_given_p()) { arg = rb_block_proc(); } else { @@ -385,7 +389,7 @@ static inline int rb_tr_scan_args_kw_int(int kw_flag, int argc, VALUE *argv, int } if (argn < argc) { - rb_error_arity(argc, n_mand, rest ? UNLIMITED_ARGUMENTS : n_mand + n_opt); + rb_error_arity(argc, n_mand, parse_data.rest ? UNLIMITED_ARGUMENTS : n_mand + n_opt); } return argc; @@ -395,16 +399,11 @@ ALWAYS_INLINE(static int rb_tr_scan_args_kw_non_const(int kw_flag, int argc, VAL static inline int rb_tr_scan_args_kw_non_const(int kw_flag, int argc, VALUE *argv, const char *format, VALUE *v1, VALUE *v2, VALUE *v3, VALUE *v4, VALUE *v5, VALUE *v6, VALUE *v7, VALUE *v8, VALUE *v9, VALUE *v10) { const char *formatp = format; - int pre = 0; - int optional = 0; - bool rest; - int post = 0; - bool kwargs; - bool block; + struct rb_tr_scan_args_parse_data parse_data = {0, 0, false, 0, false, false}; - rb_tr_scan_args_kw_parse(format, &pre, &optional, &rest, &post, &kwargs, &block); + rb_tr_scan_args_kw_parse(format, &parse_data); - return rb_tr_scan_args_kw_int(kw_flag, argc, argv, pre, optional, rest, post, kwargs, block, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); + return rb_tr_scan_args_kw_int(kw_flag, argc, argv, parse_data, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } #define rb_iv_get(obj, name) \ diff --git a/mx.truffleruby/env_files.md b/mx.truffleruby/env_files.md new file mode 100644 index 000000000000..a3555163f52a --- /dev/null +++ b/mx.truffleruby/env_files.md @@ -0,0 +1,14 @@ +Here is how the various env files relate to each other: +* `jvm` + * `jvm-ce`: + Graal CE + * `jvm-ce-ntl`: + native toolchain launchers + * `jvm-ce-libgraal`: + libgraal + * `native`: + librubyvm + * `jvm-ee`: + Graal EE + * `jvm-ee-ntl`: + native toolchain launchers + * `jvm-ee-libgraal`: + libgraal + * `native-ee`: + librubyvm + * `native-ee-g1`: + Native Image G1 + * `jvm-gu`: + Graal Updater + * `jvm-js`: + Graal.js + * `jvm-py`: + GraalPython diff --git a/mx.truffleruby/jvm-ce b/mx.truffleruby/jvm-ce index de1c3a3bbeee..cb2aaf53b25a 100644 --- a/mx.truffleruby/jvm-ce +++ b/mx.truffleruby/jvm-ce @@ -1,2 +1,2 @@ -DYNAMIC_IMPORTS=/compiler,/tools -COMPONENTS=TruffleRuby,GraalVM compiler,suite:tools +DYNAMIC_IMPORTS=/tools,/compiler +COMPONENTS=TruffleRuby,suite:tools,GraalVM compiler diff --git a/mx.truffleruby/jvm-ce-libgraal b/mx.truffleruby/jvm-ce-libgraal index d887bdf894b6..414053331693 100644 --- a/mx.truffleruby/jvm-ce-libgraal +++ b/mx.truffleruby/jvm-ce-libgraal @@ -1,5 +1,3 @@ -DYNAMIC_IMPORTS=/compiler,/substratevm,/tools -COMPONENTS=TruffleRuby,GraalVM compiler,SubstrateVM,LibGraal,suite:tools -# NATIVE_IMAGES=lib:jvmcicompiler,graalvm-native-* -FORCE_BASH_LAUNCHERS=truffleruby -SKIP_LIBRARIES=false +DYNAMIC_IMPORTS=/tools,/compiler,/substratevm +COMPONENTS=TruffleRuby,suite:tools,GraalVM compiler,SubstrateVM,LibGraal +NATIVE_IMAGES=suite:sulong,lib:jvmcicompiler diff --git a/mx.truffleruby/jvm-ce-ntl b/mx.truffleruby/jvm-ce-ntl index 4e693a88f8f0..d364bb0a3188 100644 --- a/mx.truffleruby/jvm-ce-ntl +++ b/mx.truffleruby/jvm-ce-ntl @@ -1,6 +1,3 @@ -# "ntl" stands for native toolchain launchers -DYNAMIC_IMPORTS=/substratevm,/tools -COMPONENTS=TruffleRuby,SubstrateVM,suite:tools -# NATIVE_IMAGES=graalvm-native-* -FORCE_BASH_LAUNCHERS=truffleruby -DISABLE_INSTALLABLES=false +DYNAMIC_IMPORTS=/tools,/compiler,/substratevm +COMPONENTS=TruffleRuby,suite:tools,GraalVM compiler,SubstrateVM +NATIVE_IMAGES=suite:sulong diff --git a/mx.truffleruby/jvm-ee b/mx.truffleruby/jvm-ee index af58b9fd8910..ce1c3831ea87 100644 --- a/mx.truffleruby/jvm-ee +++ b/mx.truffleruby/jvm-ee @@ -1,2 +1,2 @@ -DYNAMIC_IMPORTS=/graal-enterprise,/tools -COMPONENTS=TruffleRuby,GraalVM enterprise compiler,suite:tools +DYNAMIC_IMPORTS=/tools,/graal-enterprise +COMPONENTS=TruffleRuby,suite:tools,GraalVM enterprise compiler diff --git a/mx.truffleruby/jvm-ee-libgraal b/mx.truffleruby/jvm-ee-libgraal index b8f9ee591857..a19bac6ef4b5 100644 --- a/mx.truffleruby/jvm-ee-libgraal +++ b/mx.truffleruby/jvm-ee-libgraal @@ -1,5 +1,3 @@ -DYNAMIC_IMPORTS=/graal-enterprise,/substratevm-enterprise,/tools -COMPONENTS=TruffleRuby,GraalVM enterprise compiler,SubstrateVM Enterprise,LibGraal,suite:tools -# NATIVE_IMAGES=lib:jvmcicompiler,graalvm-native-* -FORCE_BASH_LAUNCHERS=truffleruby -SKIP_LIBRARIES=false +DYNAMIC_IMPORTS=/tools,/graal-enterprise,/substratevm-enterprise +COMPONENTS=TruffleRuby,suite:tools,GraalVM enterprise compiler,SubstrateVM Enterprise,LibGraal +NATIVE_IMAGES=suite:sulong,lib:jvmcicompiler diff --git a/mx.truffleruby/jvm-ee-ntl b/mx.truffleruby/jvm-ee-ntl new file mode 100644 index 000000000000..dcb14707ed35 --- /dev/null +++ b/mx.truffleruby/jvm-ee-ntl @@ -0,0 +1,3 @@ +DYNAMIC_IMPORTS=/tools,/graal-enterprise,/substratevm-enterprise +COMPONENTS=TruffleRuby,suite:tools,GraalVM enterprise compiler,SubstrateVM Enterprise +NATIVE_IMAGES=suite:sulong diff --git a/mx.truffleruby/jvm-gu b/mx.truffleruby/jvm-gu index 69c5cc09dc44..98da521b9f24 100644 --- a/mx.truffleruby/jvm-gu +++ b/mx.truffleruby/jvm-gu @@ -1,2 +1,2 @@ -DYNAMIC_IMPORTS=/vm,/tools -COMPONENTS=TruffleRuby,gu,suite:tools +DYNAMIC_IMPORTS=/tools,/vm +COMPONENTS=TruffleRuby,suite:tools,gu diff --git a/mx.truffleruby/jvm-js b/mx.truffleruby/jvm-js index 3d35b01e18e4..a51398c1cb65 100644 --- a/mx.truffleruby/jvm-js +++ b/mx.truffleruby/jvm-js @@ -1,2 +1,2 @@ DYNAMIC_IMPORTS=/tools,/graal-js -COMPONENTS=TruffleRuby,Graal.js,suite:tools +COMPONENTS=TruffleRuby,suite:tools,Graal.js diff --git a/mx.truffleruby/jvm-py b/mx.truffleruby/jvm-py index d9c097b25416..5179668c2560 100644 --- a/mx.truffleruby/jvm-py +++ b/mx.truffleruby/jvm-py @@ -1,2 +1,2 @@ DYNAMIC_IMPORTS=/tools,graalpython -COMPONENTS=TruffleRuby,Graal.Python,suite:tools +COMPONENTS=TruffleRuby,suite:tools,Graal.Python diff --git a/mx.truffleruby/native b/mx.truffleruby/native index ce798f751f6e..9fa3f5ab3613 100644 --- a/mx.truffleruby/native +++ b/mx.truffleruby/native @@ -1,4 +1,5 @@ -DYNAMIC_IMPORTS=/substratevm,/tools -COMPONENTS=TruffleRuby,SubstrateVM,suite:tools -NATIVE_IMAGES=true +DYNAMIC_IMPORTS=/tools,/compiler,/substratevm +COMPONENTS=TruffleRuby,suite:tools,GraalVM compiler,SubstrateVM +NATIVE_IMAGES=suite:sulong,lib:rubyvm +# To also create the standalone DISABLE_INSTALLABLES=false diff --git a/mx.truffleruby/native-ee b/mx.truffleruby/native-ee index 7f1f4e069e5f..710ab073d1d2 100644 --- a/mx.truffleruby/native-ee +++ b/mx.truffleruby/native-ee @@ -1,5 +1,6 @@ -DYNAMIC_IMPORTS=/substratevm-enterprise,/tools -COMPONENTS=TruffleRuby,SubstrateVM Enterprise,suite:tools -NATIVE_IMAGES=true +DYNAMIC_IMPORTS=/tools,/graal-enterprise,/substratevm-enterprise +COMPONENTS=TruffleRuby,suite:tools,GraalVM enterprise compiler,SubstrateVM Enterprise +NATIVE_IMAGES=suite:sulong,lib:rubyvm EXTRA_IMAGE_BUILDER_ARGUMENTS=rubyvm:-H:+AuxiliaryEngineCache rubyvm:-H:ReservedAuxiliaryImageBytes=1073741824 +# To also create the standalone DISABLE_INSTALLABLES=false diff --git a/mx.truffleruby/native-ee-g1 b/mx.truffleruby/native-ee-g1 index 0858d456b18b..b3cbb9eb63ac 100644 --- a/mx.truffleruby/native-ee-g1 +++ b/mx.truffleruby/native-ee-g1 @@ -1,5 +1,6 @@ -DYNAMIC_IMPORTS=/substratevm-enterprise,substratevm-enterprise-gcs,/tools -COMPONENTS=TruffleRuby,SubstrateVM Enterprise,SubstrateVM Enterprise GC,suite:tools -NATIVE_IMAGES=true +DYNAMIC_IMPORTS=/tools,/graal-enterprise,/substratevm-enterprise,substratevm-enterprise-gcs +COMPONENTS=TruffleRuby,suite:tools,GraalVM enterprise compiler,SubstrateVM Enterprise,SubstrateVM Enterprise GC +NATIVE_IMAGES=suite:sulong,lib:rubyvm EXTRA_IMAGE_BUILDER_ARGUMENTS=rubyvm:-H:+UseG1GC +# To also create the standalone DISABLE_INSTALLABLES=false diff --git a/mx.truffleruby/suite.py b/mx.truffleruby/suite.py index eb2c77942f06..e1b009016567 100644 --- a/mx.truffleruby/suite.py +++ b/mx.truffleruby/suite.py @@ -1,5 +1,5 @@ suite = { - "mxversion": "5.309.0", + "mxversion": "6.0.1", "name": "truffleruby", "imports": { @@ -7,7 +7,7 @@ { "name": "regex", "subdir": True, - "version": "ee11f21138f4ce3b4d4a178436dc5e7c5ed3264f", + "version": "bccc6d539bfde23d1d4ed7b4d3f647777c5560db", "urls": [ {"url": "https://github.com/oracle/graal.git", "kind": "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -16,7 +16,7 @@ { "name": "sulong", "subdir": True, - "version": "ee11f21138f4ce3b4d4a178436dc5e7c5ed3264f", + "version": "bccc6d539bfde23d1d4ed7b4d3f647777c5560db", "urls": [ {"url": "https://github.com/oracle/graal.git", "kind": "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb index c7dd34d5c61d..172978057029 100644 --- a/spec/ruby/core/file/open_spec.rb +++ b/spec/ruby/core/file/open_spec.rb @@ -494,6 +494,14 @@ File.open(@file, "w") { |f| f.puts "testing" } File.size(@file).should > 0 File.open(@file, "rb+") do |f| + f.binmode?.should == true + f.external_encoding.should == Encoding::ASCII_8BIT + f.pos.should == 0 + f.should_not.eof? + end + File.open(@file, "r+b") do |f| + f.binmode?.should == true + f.external_encoding.should == Encoding::ASCII_8BIT f.pos.should == 0 f.should_not.eof? end diff --git a/spec/ruby/core/float/divide_spec.rb b/spec/ruby/core/float/divide_spec.rb index d8f71a6b982c..72ab7527bd52 100644 --- a/spec/ruby/core/float/divide_spec.rb +++ b/spec/ruby/core/float/divide_spec.rb @@ -36,4 +36,8 @@ -> { 13.0 / "10" }.should raise_error(TypeError) -> { 13.0 / :symbol }.should raise_error(TypeError) end + + it "divides correctly by Rational numbers" do + (1.2345678901234567 / Rational(1, 10000000000000000000)).should == 1.2345678901234567e+19 + end end diff --git a/spec/ruby/core/integer/fdiv_spec.rb b/spec/ruby/core/integer/fdiv_spec.rb index d99a19eb0f99..d9ea2fdf8d57 100644 --- a/spec/ruby/core/integer/fdiv_spec.rb +++ b/spec/ruby/core/integer/fdiv_spec.rb @@ -55,6 +55,11 @@ num.fdiv(den).should == -0.5555555555555556 end + it "rounds to the correct float for bignum denominators" do + 1.fdiv(10**324).should == 0.0 + 1.fdiv(10**323).should == 1.0e-323 + end + it "performs floating-point division between self and a Float" do 8.fdiv(9.0).should be_close(0.888888888888889, TOLERANCE) end diff --git a/spec/ruby/core/module/class_variables_spec.rb b/spec/ruby/core/module/class_variables_spec.rb index fd7aa93aa8ba..e155f1deac25 100644 --- a/spec/ruby/core/module/class_variables_spec.rb +++ b/spec/ruby/core/module/class_variables_spec.rb @@ -23,4 +23,12 @@ c.extend ModuleSpecs::MVars c.class_variables.should_not include(:@@mvar) end + + it "returns the correct class variables when inherit is given" do + ModuleSpecs::SubCVars.class_variables(false).should == [:@@sub] + ModuleSpecs::SubCVars.new.singleton_class.class_variables(false).should == [] + + ModuleSpecs::SubCVars.class_variables(true).should == [:@@sub, :@@cls, :@@meta] + ModuleSpecs::SubCVars.new.singleton_class.class_variables(true).should == [:@@sub, :@@cls, :@@meta] + end end diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb index 40777cdbbdc2..a64f672b2f1a 100644 --- a/spec/ruby/core/module/fixtures/classes.rb +++ b/spec/ruby/core/module/fixtures/classes.rb @@ -352,6 +352,10 @@ def meta end end + class SubCVars < CVars + @@sub = :sub + end + module MVars @@mvar = :mvar end diff --git a/src/main/c/cext/args.c b/src/main/c/cext/args.c index 85bfb6d54b34..ff1b6acd025d 100644 --- a/src/main/c/cext/args.c +++ b/src/main/c/cext/args.c @@ -103,43 +103,43 @@ int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optiona return extracted; } -void rb_tr_scan_args_kw_parse(const char *format, int *pre, int *optional, bool *rest, int *post, bool *kwargs, bool *block) { +void rb_tr_scan_args_kw_parse(const char *format, struct rb_tr_scan_args_parse_data *parse_data) { const char *formatp = format; if (isdigit(*formatp)) { - *pre = *formatp - '0'; + parse_data->pre = *formatp - '0'; formatp++; if (isdigit(*formatp)) { - *optional = *formatp - '0'; + parse_data->optional = *formatp - '0'; formatp++; } } if (*formatp == '*') { - *rest = true; + parse_data->rest = true; formatp++; } else { - *rest = false; + parse_data->rest = false; } if (isdigit(*formatp)) { - *post = *formatp - '0'; + parse_data->post = *formatp - '0'; formatp++; } if (*formatp == ':') { - *kwargs = true; + parse_data->kwargs = true; formatp++; } else { - *kwargs = false; + parse_data->kwargs = false; } if (*formatp == '&') { - *block = true; + parse_data->block = true; formatp++; } else { - *block = false; + parse_data->block = false; } if (*formatp != '\0') { diff --git a/src/main/java/org/truffleruby/core/module/ModuleNodes.java b/src/main/java/org/truffleruby/core/module/ModuleNodes.java index a64abeb9d338..24bc62e02252 100644 --- a/src/main/java/org/truffleruby/core/module/ModuleNodes.java +++ b/src/main/java/org/truffleruby/core/module/ModuleNodes.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -884,15 +885,22 @@ protected Object setClassVariable(RubyModule module, String name, Object value, } - @CoreMethod(names = "class_variables") - public abstract static class ClassVariablesNode extends CoreMethodArrayArgumentsNode { + @CoreMethod(names = "class_variables", optional = 1) + @NodeChild(value = "module", type = RubyNode.class) + @NodeChild(value = "inherit", type = RubyBaseNodeWithExecute.class) + public abstract static class ClassVariablesNode extends CoreMethodNode { + + @CreateCast("inherit") + protected RubyBaseNodeWithExecute coerceToBoolean(RubyBaseNodeWithExecute inherit) { + return BooleanCastWithDefaultNode.create(true, inherit); + } @TruffleBoundary @Specialization - protected RubyArray getClassVariables(RubyModule module) { - final Set variables = new HashSet<>(); + protected RubyArray getClassVariables(RubyModule module, boolean inherit) { + final Set variables = new LinkedHashSet<>(); - ModuleOperations.classVariableLookup(module, m -> { + ModuleOperations.classVariableLookup(module, inherit, m -> { final ClassVariableStorage classVariableStorage = m.fields.getClassVariables(); for (Object key : classVariableStorage.getShape().getKeys()) { variables.add(getSymbol((String) key)); diff --git a/src/main/java/org/truffleruby/core/module/ModuleOperations.java b/src/main/java/org/truffleruby/core/module/ModuleOperations.java index a1fbcc7dc7cc..60ca23fd0e7e 100644 --- a/src/main/java/org/truffleruby/core/module/ModuleOperations.java +++ b/src/main/java/org/truffleruby/core/module/ModuleOperations.java @@ -664,6 +664,7 @@ public static void setClassVariable(RubyLanguage language, RubyContext context, private static boolean trySetClassVariable(RubyModule topModule, String name, Object value) { return classVariableLookup( topModule, + true, module -> module.fields.getClassVariables().putIfPresent( name, value, @@ -689,13 +690,17 @@ public static Object removeClassVariable(ModuleFields fields, RubyContext contex } @TruffleBoundary - public static R classVariableLookup(RubyModule module, Function action) { + public static R classVariableLookup(RubyModule module, boolean inherit, Function action) { // Look in the current module R result = action.apply(module); if (result != null) { return result; } + if (!inherit) { + return null; + } + // If singleton class of a module, check the attached module. if (module instanceof RubyClass) { RubyClass klass = (RubyClass) module; diff --git a/src/main/java/org/truffleruby/core/numeric/IntegerNodes.java b/src/main/java/org/truffleruby/core/numeric/IntegerNodes.java index 4404c0935182..d1afce7ba7cf 100644 --- a/src/main/java/org/truffleruby/core/numeric/IntegerNodes.java +++ b/src/main/java/org/truffleruby/core/numeric/IntegerNodes.java @@ -286,7 +286,7 @@ protected Object mul(Object a, Object b, } - @Primitive(name = "interger_fdiv") + @Primitive(name = "integer_fdiv") public abstract static class FDivNode extends PrimitiveArrayArgumentsNode { @Specialization @@ -302,19 +302,19 @@ protected double fDivLongLong(long num, long den) { @TruffleBoundary @Specialization protected double fDivLongBig(long num, RubyBignum den) { - return new BigDecimal(num).divide(new BigDecimal(den.value), 17, RoundingMode.HALF_UP).doubleValue(); + return new BigDecimal(num).divide(new BigDecimal(den.value), 323, RoundingMode.HALF_UP).doubleValue(); } @TruffleBoundary @Specialization protected double fDivBigLong(RubyBignum num, long den) { - return new BigDecimal(num.value).divide(new BigDecimal(den), 17, RoundingMode.HALF_UP).doubleValue(); + return new BigDecimal(num.value).divide(new BigDecimal(den), 323, RoundingMode.HALF_UP).doubleValue(); } @TruffleBoundary @Specialization protected double fDivBigBig(RubyBignum num, RubyBignum den) { - return new BigDecimal(num.value).divide(new BigDecimal(den.value), 17, RoundingMode.HALF_UP).doubleValue(); + return new BigDecimal(num.value).divide(new BigDecimal(den.value), 323, RoundingMode.HALF_UP).doubleValue(); } } diff --git a/src/main/java/org/truffleruby/language/arguments/SplatToArgsNode.java b/src/main/java/org/truffleruby/language/arguments/SplatToArgsNode.java index 4a9490313670..e3c435b1e790 100644 --- a/src/main/java/org/truffleruby/language/arguments/SplatToArgsNode.java +++ b/src/main/java/org/truffleruby/language/arguments/SplatToArgsNode.java @@ -26,7 +26,7 @@ public SplatToArgsNode() { stores = ArrayStoreLibrary.getFactory().createDispatched(ArrayGuards.storageStrategyLimit()); } - public Object[] execute(Object receiver, Object[] rubyArgs, RubyArray splatted) { + public Object[] execute(Object receiver, RubyArray splatted) { int size = splatSizeProfile.profile(splatted.size); Object store = splatted.store; final Object[] newArgs = RubyArguments.allocate(size); diff --git a/src/main/java/org/truffleruby/language/dispatch/DispatchNode.java b/src/main/java/org/truffleruby/language/dispatch/DispatchNode.java index e728bb9f2702..9d99fdccf872 100644 --- a/src/main/java/org/truffleruby/language/dispatch/DispatchNode.java +++ b/src/main/java/org/truffleruby/language/dispatch/DispatchNode.java @@ -10,6 +10,7 @@ package org.truffleruby.language.dispatch; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.interop.TruffleObject; @@ -82,7 +83,7 @@ public static DispatchNode getUncached() { @Child protected ToSymbolNode toSymbol; protected final ConditionProfile methodMissing; - protected final BranchProfile methodMissingMissing; + @CompilationFinal private boolean methodMissingMissingProfile; protected DispatchNode( DispatchConfiguration config, @@ -96,7 +97,6 @@ protected DispatchNode( this.methodLookup = methodLookup; this.callNode = callNode; this.methodMissing = methodMissing; - this.methodMissingMissing = methodMissingMissing; } protected DispatchNode(DispatchConfiguration config) { @@ -280,14 +280,24 @@ public final Object dispatch(Frame frame, Object receiver, String methodName, Ob return dispatch(frame, receiver, methodName, rubyArgs, null); } - public final Object dispatch(Frame frame, Object receiver, String methodName, Object[] rubyArgs, + public Object dispatch(Frame frame, Object receiver, String methodName, Object[] rubyArgs, LiteralCallNode literalCallNode) { + return dispatchInternal(frame, receiver, methodName, rubyArgs, literalCallNode, + metaclassNode, methodLookup, methodMissing, callNode); + } + + protected final Object dispatchInternal(Frame frame, Object receiver, String methodName, Object[] rubyArgs, + LiteralCallNode literalCallNode, + MetaClassNode metaClassNode, + LookupMethodNode lookupMethodNode, + ConditionProfile methodMissingProfile, + CallInternalMethodNode callNode) { assert RubyArguments.getSelf(rubyArgs) == receiver; - final RubyClass metaclass = metaclassNode.execute(receiver); - final InternalMethod method = methodLookup.execute(frame, metaclass, methodName, config); + final RubyClass metaclass = metaClassNode.execute(receiver); + final InternalMethod method = lookupMethodNode.execute(frame, metaclass, methodName, config); - if (methodMissing.profile(method == null || method.isUndefined())) { + if (methodMissingProfile.profile(method == null || method.isUndefined())) { switch (config.missingBehavior) { case RETURN_MISSING: return MISSING; @@ -320,7 +330,7 @@ private Object callMethodMissing(Frame frame, Object receiver, String methodName literalCallNode); if (result == MISSING) { - methodMissingMissing.enter(); + methodMissingMissingProfileEnter(); throw new RaiseException(getContext(), coreExceptions().noMethodErrorFromMethodMissing( ExceptionFormatter.NO_METHOD_ERROR, receiver, @@ -359,6 +369,13 @@ protected DispatchNode getMethodMissingNode() { return callMethodMissing; } + protected void methodMissingMissingProfileEnter() { + if (!methodMissingMissingProfile) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + methodMissingMissingProfile = true; + } + } + protected RubySymbol nameToSymbol(String methodName) { if (toSymbol == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -404,13 +421,17 @@ private static final class Uncached extends DispatchNode { } protected Uncached(DispatchConfiguration config) { - super( - config, + super(config, null, null, null, null, null); + } + + @Override + public Object dispatch(Frame frame, Object receiver, String methodName, Object[] rubyArgs, + LiteralCallNode literalCallNode) { + return dispatchInternal(frame, receiver, methodName, rubyArgs, literalCallNode, MetaClassNodeGen.getUncached(), LookupMethodNodeGen.getUncached(), - CallInternalMethodNodeGen.getUncached(), ConditionProfile.getUncached(), - BranchProfile.getUncached()); + CallInternalMethodNodeGen.getUncached()); } @Override @@ -423,6 +444,10 @@ protected DispatchNode getMethodMissingNode() { return DispatchNode.getUncached(DispatchConfiguration.PRIVATE_RETURN_MISSING_IGNORE_REFINEMENTS); } + @Override + protected void methodMissingMissingProfileEnter() { + } + @Override protected RubySymbol nameToSymbol(String methodName) { return ToSymbolNode.getUncached().execute(methodName); diff --git a/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java b/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java index ff012e88d9af..e20db9eab6c8 100644 --- a/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java +++ b/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java @@ -66,7 +66,14 @@ protected InternalRespondToNode(DispatchConfiguration config) { this(config, MetaClassNode.create(), LookupMethodNode.create()); } - public final boolean execute(Frame frame, Object receiver, String methodName) { + public boolean execute(Frame frame, Object receiver, String methodName) { + return executeInternal(frame, receiver, methodName, config, metaclassNode, methodLookup); + } + + protected static boolean executeInternal(Frame frame, Object receiver, String methodName, + DispatchConfiguration config, + MetaClassNode metaclassNode, + LookupMethodNode methodLookup) { final RubyClass metaclass = metaclassNode.execute(receiver); final InternalMethod method = methodLookup.execute(frame, metaclass, methodName, config); return method != null && method.isDefined() && method.isImplemented(); @@ -83,7 +90,14 @@ private static final class Uncached extends InternalRespondToNode { } protected Uncached(DispatchConfiguration config) { - super(config, MetaClassNodeGen.getUncached(), LookupMethodNodeGen.getUncached()); + super(config, null, null); + } + + public boolean execute(Frame frame, Object receiver, String methodName) { + return executeInternal(frame, receiver, methodName, + config, + MetaClassNodeGen.getUncached(), + LookupMethodNodeGen.getUncached()); } @Override diff --git a/src/main/java/org/truffleruby/language/dispatch/RubyCallNode.java b/src/main/java/org/truffleruby/language/dispatch/RubyCallNode.java index a44e1c9e2419..49febfcb4445 100644 --- a/src/main/java/org/truffleruby/language/dispatch/RubyCallNode.java +++ b/src/main/java/org/truffleruby/language/dispatch/RubyCallNode.java @@ -192,7 +192,7 @@ private Object[] splatArgs(Object receiverObject, Object[] rubyArgs) { splatToArgs = insert(new SplatToArgsNode()); } - return splatToArgs.execute(receiverObject, rubyArgs, (RubyArray) RubyArguments.getArgument(rubyArgs, 0)); + return splatToArgs.execute(receiverObject, (RubyArray) RubyArguments.getArgument(rubyArgs, 0)); } @Override diff --git a/src/main/java/org/truffleruby/language/objects/MetaClassNode.java b/src/main/java/org/truffleruby/language/objects/MetaClassNode.java index 6ef359d85229..126da39a63e7 100644 --- a/src/main/java/org/truffleruby/language/objects/MetaClassNode.java +++ b/src/main/java/org/truffleruby/language/objects/MetaClassNode.java @@ -9,6 +9,7 @@ */ package org.truffleruby.language.objects; +import com.oracle.truffle.api.dsl.TypeSystemReference; import org.truffleruby.core.encoding.RubyEncoding; import org.truffleruby.core.klass.RubyClass; import org.truffleruby.core.numeric.RubyBignum; @@ -16,6 +17,7 @@ import org.truffleruby.core.symbol.RubySymbol; import org.truffleruby.core.string.ImmutableRubyString; import org.truffleruby.language.Nil; +import org.truffleruby.language.NoImplicitCastsToLong; import org.truffleruby.language.RubyBaseNode; import org.truffleruby.language.RubyDynamicObject; @@ -24,6 +26,7 @@ import com.oracle.truffle.api.dsl.Specialization; @GenerateUncached +@TypeSystemReference(NoImplicitCastsToLong.class) public abstract class MetaClassNode extends RubyBaseNode { public static MetaClassNode create() { diff --git a/src/main/java/org/truffleruby/language/objects/classvariables/LookupClassVariableStorageNode.java b/src/main/java/org/truffleruby/language/objects/classvariables/LookupClassVariableStorageNode.java index eec33aa020d2..a83d1e4d8850 100644 --- a/src/main/java/org/truffleruby/language/objects/classvariables/LookupClassVariableStorageNode.java +++ b/src/main/java/org/truffleruby/language/objects/classvariables/LookupClassVariableStorageNode.java @@ -36,7 +36,7 @@ protected ClassVariableStorage lookupClassVariable(RubyModule module, String nam @Specialization(replaces = "lookupClassVariable") @TruffleBoundary protected ClassVariableStorage uncachedLookupClassVariable(RubyModule module, String name) { - return ModuleOperations.classVariableLookup(module, m -> { + return ModuleOperations.classVariableLookup(module, true, m -> { final ClassVariableStorage classVariables = m.fields.getClassVariables(); if (classVariables.getShape().hasProperty(name)) { return classVariables; diff --git a/src/main/ruby/truffleruby/core/integer.rb b/src/main/ruby/truffleruby/core/integer.rb index 0c2d00893235..16c7a96cece5 100644 --- a/src/main/ruby/truffleruby/core/integer.rb +++ b/src/main/ruby/truffleruby/core/integer.rb @@ -111,7 +111,7 @@ def divmod(b) def fdiv(n) if Primitive.object_kind_of?(n, Integer) - Primitive.interger_fdiv(self, n) + Primitive.integer_fdiv(self, n) else redo_coerced :fdiv, n end diff --git a/src/main/ruby/truffleruby/core/io.rb b/src/main/ruby/truffleruby/core/io.rb index 01f7e5df2628..bca52752b7b1 100644 --- a/src/main/ruby/truffleruby/core/io.rb +++ b/src/main/ruby/truffleruby/core/io.rb @@ -648,8 +648,8 @@ def self.normalize_options(mode, perm, options) mode, external, internal = mode.split(':') raise ArgumentError, 'invalid access mode' unless mode - binary = true if mode[1] === ?b - binary = false if mode[1] === ?t + binary = true if mode.include?(?b) + binary = false if mode.include?(?t) elsif mode binary = true if (mode & BINARY) != 0 end diff --git a/tool/jt.rb b/tool/jt.rb index 21c53847f6cb..c2c192e3a6c7 100755 --- a/tool/jt.rb +++ b/tool/jt.rb @@ -2330,11 +2330,11 @@ def bootstrap_toolchain with_color(TERM_COLOR_RED) do puts "\nNOTE: Set env variable JT_IMPORTS_DONT_ASK to always answer 'no' to this prompt.\n\n" puts scheckimports_output - input = '' - until %w(y n).include? input + begin print 'Do you want to checkout the supported version of graal as specified in truffleruby\'s suite.py? (runs `mx sforceimports`) [y/n] ' + STDOUT.flush input = STDIN.gets.chomp - end + end until %w(y n).include? input puts '' input == 'y' end