To pass `false` as `freeze:` keyword argument, `kw_splat` argument
should be true. Also `rb_keyword_given_p()` should return true
here as `false` has been given as a keyword argument.
This makes it possible to initialize_clone to correctly not freeze
internal state if the freeze: false keyword is passed to clone.
If clone is called with freeze: true or no keyword, do not pass
a second argument to initialize_clone to keep backwards
compatibility.
This makes it so that external libraries that override
initialize_clone but do not support the freeze keyword will fail
with ArgumentError if passing freeze: false to clone. I think that
is better than the current behavior, which succeeds but results in
an unfrozen object with frozen internals.
Fix related issues in set and delegate in stdlib.
Fixes [Bug #14266]
This removes the warnings added in 2.7, and changes the behavior
so that a final positional hash is not treated as keywords or
vice-versa.
To handle the arg_setup_block splat case correctly with keyword
arguments, we need to check if we are taking a keyword hash.
That case didn't have a test, but it affects real-world code,
so add a test for it.
This removes rb_empty_keyword_given_p() and related code, as
that is not needed in Ruby 3. The empty keyword case is the
same as the no keyword case in Ruby 3.
This changes rb_scan_args to implement keyword argument
separation for C functions when the : character is used.
For backwards compatibility, it returns a duped hash.
This is a bad idea for performance, but not duping the hash
breaks at least Enumerator::ArithmeticSequence#inspect.
Instead of having RB_PASS_CALLED_KEYWORDS be a number,
simplify the code by just making it be rb_keyword_given_p().
Saves comitters' daily life by avoid #include-ing everything from
internal.h to make each file do so instead. This would significantly
speed up incremental builds.
We take the following inclusion order in this changeset:
1. "ruby/config.h", where _GNU_SOURCE is defined (must be the very
first thing among everything).
2. RUBY_EXTCONF_H if any.
3. Standard C headers, sorted alphabetically.
4. Other system headers, maybe guarded by #ifdef
5. Everything else, sorted alphabetically.
Exceptions are those win32-related headers, which tend not be self-
containing (headers have inclusion order dependencies).
This removes the related tests, and puts the related specs behind
version guards. This affects all code in lib, including some
libraries that may want to support older versions of Ruby.
If defined in Ruby, dig would be defined as def dig(arg, *rest) end,
it would not use keywords. If the last dig argument was an empty
hash, it could be treated as keyword arguments by the next dig
method. Allow dig to pass along the empty keyword flag if called
with an empty keyword, to suppress the previous behavior and force
treating the hash as a positional argument and not keywords.
Also handle the case where dig calls method_missing, passing the
empty keyword flag to that as well.
This requires adding rb_check_funcall_with_hook_kw functions, so
that dig can specify how arguments are treated. It also adds
kw_splat arguments to a couple static functions.
It is not safe to set this in C functions that can be called from
other C functions, as in the non argument-delegation case, you
can end up calling a Ruby method with a flag indicating keywords
are set without passing keywords.
Introduce some new *_kw functions that take a kw_splat flag and
use these functions to set RB_PASS_CALLED_KEYWORDS in places where
we know we are delegating methods (e.g. Class#new, Method#call)
We can check the function pointer passed to rb_define_private_method
like how we do so in rb_define_method. Doing so revealed some
problematic usages of rb_obj_dummy. They had to be split according
to their arity.
We can check the function pointer passed to rb_define_global_function
like we do so in rb_define_method. It turns out that almost anybody
is misunderstanding the API.
Object#=~ always returns nil. This behavior is not only unuseful but
also troublesome because it may hide a type error.
This change deprecates Object#=~. For compatibility, NilClass#=~ is
newly introduced. [Feature #15231]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65989 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_f_integer): prefer `base` optional argument over
keyword arguments. this issue should be resolved more generally
by separating keyword arguments from hashes in the future.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64015 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (mutable_obj_clone): `Kernel#clone` should not copy
FL_USER* flags because they are copied unexpectedly.
Unexpected copy will break internal data consistency.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63912 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_cstr_to_dbl_raise): do not ignore exponent part
when the input string longer than internal buffer contains
underscore(s). [ruby-core:86836] [Bug #14731]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63322 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Support `exception:` keyword argument in `Kernel#Float()`.
If `exception:` is `false`, `Kernel#Float()` returns `nil` if the given
value cannot be interpreted as a float value.
The default value of `exception:` is `true`.
This is part of [Feature #12732].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Support `exception:` keyword argument in Kernel#Integer().
If `exception:` is `false`, `Kernel#Integer()` returns `nil` if the given
value cannot be interpreted as an integer value.
The default value of `exception:` is `true`.
This is part of [Feature #12732].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62757 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
For checking whether an object is an Integer, because a subclass of
Integer is meaningless in Ruby, RB_INTEGER_TYPE_P is better than
rb_obj_is_kind_of for speed.
* object.c (rb_to_integer): Use RB_INTEGER_TYPE_P instead of rb_obj_is_kind_of.
* object.c (rb_check_to_integer): ditto.
* range.c (range_max): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62582 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
which has been developed by Takashi Kokubun <takashikkbn@gmail> as
YARV-MJIT. Many of its bugs are fixed by wanabe <s.wanabe@gmail.com>.
This JIT compiler is designed to be a safe migration path to introduce
JIT compiler to MRI. So this commit does not include any bytecode
changes or dynamic instruction modifications, which are done in original
MJIT.
This commit even strips off some aggressive optimizations from
YARV-MJIT, and thus it's slower than YARV-MJIT too. But it's still
fairly faster than Ruby 2.5 in some benchmarks (attached below).
Note that this JIT compiler passes `make test`, `make test-all`, `make
test-spec` without JIT, and even with JIT. Not only it's perfectly safe
with JIT disabled because it does not replace VM instructions unlike
MJIT, but also with JIT enabled it stably runs Ruby applications
including Rails applications.
I'm expecting this version as just "initial" JIT compiler. I have many
optimization ideas which are skipped for initial merging, and you may
easily replace this JIT compiler with a faster one by just replacing
mjit_compile.c. `mjit_compile` interface is designed for the purpose.
common.mk: update dependencies for mjit_compile.c.
internal.h: declare `rb_vm_insn_addr2insn` for MJIT.
vm.c: exclude some definitions if `-DMJIT_HEADER` is provided to
compiler. This avoids to include some functions which take a long time
to compile, e.g. vm_exec_core. Some of the purpose is achieved in
transform_mjit_header.rb (see `IGNORED_FUNCTIONS`) but others are
manually resolved for now. Load mjit_helper.h for MJIT header.
mjit_helper.h: New. This is a file used only by JIT-ed code. I'll
refactor `mjit_call_cfunc` later.
vm_eval.c: add some #ifdef switches to skip compiling some functions
like Init_vm_eval.
win32/mkexports.rb: export thread/ec functions, which are used by MJIT.
include/ruby/defines.h: add MJIT_FUNC_EXPORTED macro alis to clarify
that a function is exported only for MJIT.
array.c: export a function used by MJIT.
bignum.c: ditto.
class.c: ditto.
compile.c: ditto.
error.c: ditto.
gc.c: ditto.
hash.c: ditto.
iseq.c: ditto.
numeric.c: ditto.
object.c: ditto.
proc.c: ditto.
re.c: ditto.
st.c: ditto.
string.c: ditto.
thread.c: ditto.
variable.c: ditto.
vm_backtrace.c: ditto.
vm_insnhelper.c: ditto.
vm_method.c: ditto.
I would like to improve maintainability of function exports, but I
believe this way is acceptable as initial merging if we clarify the
new exports are for MJIT (so that we can use them as TODO list to fix)
and add unit tests to detect unresolved symbols.
I'll add unit tests of JIT compilations in succeeding commits.
Author: Takashi Kokubun <takashikkbn@gmail.com>
Contributor: wanabe <s.wanabe@gmail.com>
Part of [Feature #14235]
---
* Known issues
* Code generated by gcc is faster than clang. The benchmark may be worse
in macOS. Following benchmark result is provided by gcc w/ Linux.
* Performance is decreased when Google Chrome is running
* JIT can work on MinGW, but it doesn't improve performance at least
in short running benchmark.
* Currently it doesn't perform well with Rails. We'll try to fix this
before release.
---
* Benchmark reslts
Benchmarked with:
Intel 4.0GHz i7-4790K with 16GB memory under x86-64 Ubuntu 8 Cores
- 2.0.0-p0: Ruby 2.0.0-p0
- r62186: Ruby trunk (early 2.6.0), before MJIT changes
- JIT off: On this commit, but without `--jit` option
- JIT on: On this commit, and with `--jit` option
** Optcarrot fps
Benchmark: https://github.com/mame/optcarrot
| |2.0.0-p0 |r62186 |JIT off |JIT on |
|:--------|:--------|:--------|:--------|:--------|
|fps |37.32 |51.46 |51.31 |58.88 |
|vs 2.0.0 |1.00x |1.38x |1.37x |1.58x |
** MJIT benchmarks
Benchmark: https://github.com/benchmark-driver/mjit-benchmarks
(Original: https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch/MJIT-benchmarks)
| |2.0.0-p0 |r62186 |JIT off |JIT on |
|:----------|:--------|:--------|:--------|:--------|
|aread |1.00 |1.09 |1.07 |2.19 |
|aref |1.00 |1.13 |1.11 |2.22 |
|aset |1.00 |1.50 |1.45 |2.64 |
|awrite |1.00 |1.17 |1.13 |2.20 |
|call |1.00 |1.29 |1.26 |2.02 |
|const2 |1.00 |1.10 |1.10 |2.19 |
|const |1.00 |1.11 |1.10 |2.19 |
|fannk |1.00 |1.04 |1.02 |1.00 |
|fib |1.00 |1.32 |1.31 |1.84 |
|ivread |1.00 |1.13 |1.12 |2.43 |
|ivwrite |1.00 |1.23 |1.21 |2.40 |
|mandelbrot |1.00 |1.13 |1.16 |1.28 |
|meteor |1.00 |2.97 |2.92 |3.17 |
|nbody |1.00 |1.17 |1.15 |1.49 |
|nest-ntimes|1.00 |1.22 |1.20 |1.39 |
|nest-while |1.00 |1.10 |1.10 |1.37 |
|norm |1.00 |1.18 |1.16 |1.24 |
|nsvb |1.00 |1.16 |1.16 |1.17 |
|red-black |1.00 |1.02 |0.99 |1.12 |
|sieve |1.00 |1.30 |1.28 |1.62 |
|trees |1.00 |1.14 |1.13 |1.19 |
|while |1.00 |1.12 |1.11 |2.41 |
** Discourse's script/bench.rb
Benchmark: https://github.com/discourse/discourse/blob/v1.8.7/script/bench.rb
NOTE: Rails performance was somehow a little degraded with JIT for now.
We should fix this.
(At least I know opt_aref is performing badly in JIT and I have an idea
to fix it. Please wait for the fix.)
*** JIT off
Your Results: (note for timings- percentile is first, duration is second in millisecs)
categories_admin:
50: 17
75: 18
90: 22
99: 29
home_admin:
50: 21
75: 21
90: 27
99: 40
topic_admin:
50: 17
75: 18
90: 22
99: 32
categories:
50: 35
75: 41
90: 43
99: 77
home:
50: 39
75: 46
90: 49
99: 95
topic:
50: 46
75: 52
90: 56
99: 101
*** JIT on
Your Results: (note for timings- percentile is first, duration is second in millisecs)
categories_admin:
50: 19
75: 21
90: 25
99: 33
home_admin:
50: 24
75: 26
90: 30
99: 35
topic_admin:
50: 19
75: 20
90: 25
99: 30
categories:
50: 40
75: 44
90: 48
99: 76
home:
50: 42
75: 48
90: 51
99: 89
topic:
50: 49
75: 55
90: 58
99: 99
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62197 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* array.c (rb_check_to_array): conversion to array by to_a method.
returns nil if not possible.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62072 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
FrozenError will be used instead of RuntimeError for exceptions
raised when there is an attempt to modify a frozen object. The
reason for this change is to differentiate exceptions related
to frozen objects from generic exceptions such as those generated
by Kernel#raise without an exception class.
From: Jeremy Evans <code@jeremyevans.net>
Signed-off-by: Urabe Shyouhei <shyouhei@ruby-lang.org>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61131 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Array(arg) does more than just call to_ary or to_a on the argument.
It also falls back to returning [arg] if neither method is available.
This patch extends the description and adds a few examples of how it
handles common types of arguments, including an integer
(which does not implement to_ary or to_a).
Extend Kernel#Array doc to mention TypeError
patched by ragesoss (Sage Ross) [fix GH-1663]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60327 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (convert_type_with_id): fix failure message for
explicit conversion. rb_convert_type_with_id and
rb_check_convert_type_with_id are not only for implicit
conversions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59919 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Ensure space for the terminating NUL byte. Note that this code path is
reachable only when Ruby is compiled with SHARABLE_MIDDLE_SUBSTRING=1.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
To convert the object implicitly, it has had two parts in convert_type() which are
1. lookink up the method's id
2. calling the method
Seems that strncmp() and strcmp() in convert_type() are slightly heavy to look up
the method's id for type conversion.
This patch will add and use internal APIs (rb_convert_type_with_id, rb_check_convert_type_with_id)
to call the method without looking up the method's id when convert the object.
Array#flatten -> 19 % up
Array#+ -> 3 % up
[ruby-dev:50024] [Bug #13341] [Fix GH-1537]
### Before
Array#flatten 104.119k (± 1.1%) i/s - 525.690k in 5.049517s
Array#+ 1.993M (± 1.8%) i/s - 10.010M in 5.024258s
### After
Array#flatten 124.005k (± 1.0%) i/s - 624.240k in 5.034477s
Array#+ 2.058M (± 4.8%) i/s - 10.302M in 5.019328s
### Test Code
require 'benchmark/ips'
class Foo
def to_ary
[1,2,3]
end
end
Benchmark.ips do |x|
ary = []
100.times { |i| ary << i }
array = [ary]
x.report "Array#flatten" do |i|
i.times { array.flatten }
end
x.report "Array#+" do |i|
obj = Foo.new
i.times { array + obj }
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58978 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c: [DOC] add an example for Object#yield_self that
better illustrates its purpose; other small improvements.
Reported by Vitaly Tatarintsev (ck3g). Patch by Marcus Stollsteimer.
[Fix GH-1637]
* object.c: [DOC] improve docs for Object#{itself,tap}.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58972 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This improvement is similar with https://github.com/ruby/ruby/pull/1552
internal.h: add declaration of rb_eql_opt() API.
vm_insnhelper.c (rb_eql_opt): add rb_eql_opt() API which provides optimized
path for #eql? method such as rb_equal_opt().
object.c (rb_eql): optimize using rb_eql_opt() such as rb_equal().
Array#eql? and some methods have used rb_eql() and Array#eql? will be faster
around 20%.
[ruby-core:80761] [Bug #13447] [Fix GH-#1589]
### Before
user system total real
1.570000 0.000000 1.570000 ( 1.569754)
### After
user system total real
1.300000 0.000000 1.300000 ( 1.303624)
### Test code
require 'benchmark'
Benchmark.bmbm do |x|
ary1 = Array.new(1000) { rand(1000) }
ary2 = Array.new(1000) { rand(1000) }
x.report do
5000000.times do
ary1.eql?(ary2)
end
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58881 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_equal): add optimized path to compare the objects using
rb_equal_opt(). Previously, if not same objects were given, rb_equal() would
call `==' method via rb_funcall() which took a long time.
rb_equal_opt() has provided faster comparing for Fixnum/Float/String objects.
Now, Time#eql? uses rb_equal() to compare with argument object and it will
be faster around 40% on 64-bit environment.
* array.c (rb_ary_index): remove redundant rb_equal_opt() calling.
Now, rb_equal() was optimized using rb_equal_opt().
If rb_equal_opt() returns Qundef, it will invoke rb_equal() -> rb_equal_opt(),
and it will cause the performance regression.
So, this patch will remove first redundant rb_equal_opt() calling.
* array.c (rb_ary_rindex): ditto.
* array.c (rb_ary_includes): ditto.
[ruby-core:80360] [Bug #13365] [Fix GH-#1552]
### Before
Time#eql? with other 7.309M (± 1.4%) i/s - 36.647M in 5.014964s
Array#index(val) 1.433M (± 1.2%) i/s - 7.207M in 5.030942s
Array#rindex(val) 1.418M (± 1.6%) i/s - 7.103M in 5.009164s
Array#include?(val) 1.451M (± 0.9%) i/s - 7.295M in 5.026392s
### After
Time#eql? with other 10.321M (± 1.9%) i/s - 51.684M in 5.009203s
Array#index(val) 1.474M (± 0.9%) i/s - 7.433M in 5.044384s
Array#rindex(val) 1.449M (± 1.7%) i/s - 7.292M in 5.034436s
Array#include?(val) 1.466M (± 1.7%) i/s - 7.373M in 5.030047s
### Test code
require 'benchmark/ips'
Benchmark.ips do |x|
t1 = Time.now
t2 = Time.now
x.report "Time#eql? with other" do |i|
i.times { t1.eql?(t2) }
end
# Benchmarks to check whether it didn't introduce the regression
obj = Object.new
x.report "Array#index(val)" do |i|
ary = [1, 2, true, false, obj]
i.times { ary.index(obj) }
end
x.report "Array#rindex(val)" do |i|
ary = [1, 2, true, false, obj].reverse
i.times { ary.rindex(obj) }
end
x.report "Array#include?(val)" do |i|
ary = [1, 2, true, false, obj]
i.times { ary.include?(obj) }
end
end
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58880 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_obj_size): The #yield_self Enumerator instance
always has a #count of `1`. This provides a lazy #size of `1`
to match the count instead of `nil`. [Fix GH-1615]
Author: Shannon Skipper <shannonskipper@gmail.com>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_obj_yield_self): new method which yields the
receiver and returns the result.
[ruby-core:46320] [Feature #6721]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58528 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_cstr_to_dbl): stop at successive underscores, as
well as Float literals. [ruby-core:80098] [Bug #13105]
* `_` should be within digits
* only one `_` allowed between digits
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is auto-generated using following command:
svn diff -r57807:57788 include internal.h bignum.c numeric.c compile.c insns.def object.c sprintf.c | patch -p0
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57818 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Looking at the source code, FIXABLE tends to be just before LOING2FIX
to check applicability of that operation. Why not try computing first
then check for overflow, which should be optimial.
I also tried the same thing for unsigned types but resulted in slower
execution. It seems RB_POSFIXABLE() is fast enough on modern CPUs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57789 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* numeric.c (num_clone, num_dup): no longer raises TypeError,
returns the receiver instead as well as Integer and Float.
[ruby-core:79636] [Bug #13237]
* object.c (rb_immutable_obj_clone): immutable object clone with
freeze optional keyword argument.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57682 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_obj_clone2): extract option for clone, and split by
whether the object is immutable or mutable.
* object.c (rb_obj_clone): no arguments, return immutable object
immediately.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (special_object_p): uninterned Symbol also should not
raise a TypeError but return itself instead, as well as interned
Symbols. [ruby-core:79216] [Bug #13145]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* object.c (rb_obj_alloc): add pathological check of klass for
extension libraries which do not check given arguments properly.
[ruby-core:78934] [Bug #13093]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57250 b2dd03c8-39d4-4d8f-98ff-823fe69b080e