* insns.def (getblockparamproxy): introduce new instruction to return
the `rb_block_param_proxy` object if possible. This object responds
to `call` method and invoke given block (completely similar to `yield`).
* method.h (OPTIMIZED_METHOD_TYPE_BLOCK_CALL): add new optimized call type
which is for `rb_block_param_proxy.cal`.
* vm_insnhelper.c (vm_call_method_each_type): ditto.
* vm_insnhelper.c (vm_call_opt_block_call): ditto.
* vm_core.h (BOP_CALL, PROC_REDEFINED_OP_FLAG): add check for `Proc#call`
redefinition.
* compile.c (iseq_compile_each0): compile to use new insn
`getblockparamproxy` for method call.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_insnhelper.c (vm_call_opt_call): do same process of `yield` instead of
invoking `Proc`.
* vm_insnhelper.c (vm_invoke_block): invoke given block handler instead of
using a block handler in the current frame.
Also do not check blcok handler here (caller should check it).
* insns.def (invokeblock): catch up this fix.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61624 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (checkkeyword): adjust argument type to
vm_check_keyword as lindex_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61420 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2.5's line coverage measurement was about two times slower than 2.4
because of two reasons; (1) vm_trace uses rb_iseq_event_flags (which
takes O(n) currently where n is the length of iseq) to get an event
type, and (2) RUBY_EVENT_LINE uses setjmp to call an event hook.
This change adds a special event for line coverage,
RUBY_EVENT_COVERAGE_LINE, and adds `tracecoverage` instructions where
the event occurs in iseq.
`tracecoverage` instruction calls an event hook without vm_trace.
And, RUBY_EVENT_COVERAGE_LINE is an internal event which does not
use setjmp.
This change also cancells lineno change due to the deletion of trace
instructions [Feature #14104]. So fixes [Bug #14191].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61350 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* tool/instruction.rb: create `trace_` prefix instructions.
* compile.c (ADD_TRACE): do not add `trace` instructions but add
TRACE link elements. TRACE elements will be unified with a next
instruction as instruction information.
* vm_trace.c (update_global_event_hook): modify all ISeqs when
hooks are enabled.
* iseq.c (rb_iseq_trace_set): added to toggle `trace_` instructions.
* vm_insnhelper.c (vm_trace): added.
This function is a body of `trace_` prefix instructions.
* vm_insnhelper.h (JUMP): save PC to a control frame.
* insns.def (trace): removed.
* vm_exec.h (INSN_ENTRY_SIG): add debug output (disabled).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60763 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Fix compile errors for OPT_CALL_THREADED_CODE (in vm_opts.h).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_insnhelper.c (vm_search_super_method): accepts `ec` instead of `th`.
Surprisingly, it doesn't use `th` (now `ec`) so this patch is for
the future extension.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60471 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
to represent execution context [Feature #14038]
* vm_core.h (rb_thread_t): rb_thread_t::ec is now a pointer.
There are many code using `th` to represent execution context
(such as cfp, VM stack and so on). To access `ec`, they need to
use `th->ec->...` (adding one indirection) so that we need to
replace them by passing `ec` instead of `th`.
* vm_core.h (GET_EC()): introduced to access current ec. Also
remove `ruby_current_thread` global variable.
* cont.c (rb_context_t): introduce rb_context_t::thread_ptr instead of
rb_context_t::thread_value.
* cont.c (ec_set_vm_stack): added to update vm_stack explicitly.
* cont.c (ec_switch): added to switch ec explicitly.
* cont.c (rb_fiber_close): added to terminate fibers explicitly.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60440 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
[Feature #14045]
* insns.def (getblockparam, setblockparam): add special access
instructions for block parameters.
getblockparam checks VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM and
if it is not set this instruction creates a Proc object from
a given blcok and set VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.
setblockparam is similar to setlocal, but set
VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.
* compile.c: use get/setblockparm instead get/setlocal instructions.
Note that they are used for method local block parameters (def m(&b)),
not for block local method parameters (iter{|&b|).
* proc.c (get_local_variable_ptr): creates Proc object for
Binding#local_variable_get/set.
* safe.c (safe_setter): we need to create Proc objects for postponed
block parameters when $SAFE is changed.
* vm_args.c (args_setup_block_parameter): used only for block local blcok
parameters.
* vm_args.c (vm_caller_setup_arg_block): if called with
VM_CALL_ARGS_BLOCKARG_BLOCKPARAM flag then passed block values should be
a block handler.
* test/ruby/test_optimization.rb: add tests.
* benchmark/bm_vm1_blockparam*: added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60397 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (intern): new instruction to turn string into symbol.
opt_call_c_function can not dump.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (iseq_compile_each0): insert to_s method call, so that
refinements activated at the caller should take place.
[Feature #13812]
* insns.def (tostring): fix up converted object to a string,
infect and fallback.
* insns.def (branchiftype): new instruction for conversion.
branches if TOS is an instance of the given type.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This is needed for passing to the hook function the measuring target
type (line/branch/method) and the site of coverage event fired.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Sometimes, size of a hash can be calcluated a priori. By providing
such info to the constructor we can avoid unnecessary internal re-
allocations. This can boost for instance creation of hash literals.
[Bug #13861]
Signed-off-by: Urabe, Shyouhei <shyouhei@ruby-lang.org>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59744 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
is_local argument was introduced on r11639 and removed on r11813.
* insns.def (getinstancevariable, setinstancevariable): Remove a not
exist argument.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_insnhelper.c (vm_stack_consistency_error): extracted from
insns.def for further info in the future.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59149 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* debug_counter.h: add the following counters:
* lvar_get: counter for lvar get.
* lvar_get_dynamic: counter for lvar get from upper frames.
* lvar_set: coutner for lvar set.
* lvar_set_dynamic: coutner for lvar set from upper frames.
* lvar_set_slowpath: counter for lavr set using slowpath.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* st.c (rb_hash_bulk_insert): new API to bulk insert entries
into a hash. Given arguments are first inserted into the
table at once, then reindexed. This is faster than inserting
things using rb_hash_aset() one by one.
This arrangement (rb_ prefixed function placed in st.c) is
unavoidable because it both touches table internal and write
barrier at once.
* internal.h: delcare the new function.
* hash.c (rb_hash_s_create): use the new function.
* vm.c (core_hash_merge): ditto.
* insns.def (newhash): ditto.
* test/ruby/test_hash.rb: more coverage on hash creation.
* test/ruby/test_literal.rb: ditto.
-----------------------------------------------------------
benchmark results:
minimum results in each 7 measurements.
Execution time (sec)
name before after
loop_whileloop2 0.136 0.137
vm2_bighash* 1.249 0.623
Speedup ratio: compare with the result of `before' (greater is better)
name after
loop_whileloop2 0.996
vm2_bighash* 2.004
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58492 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
We need to fix GC bug before merging this. Revert revisions
58452, 58435, 58434, 58428, 58427 in this order.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58463 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Same as rb_ary_tmp_new_from_values(), it reduces vm_exec_core binary
size from 26,176 bytes to 26,080 bytes. But this time, also with a
bit of optimizations:
- Because we are allocating a new hash and no back references are
introduced at all, we can safely skip write barriers.
- Also, the iteration never recurs. We can avoid complicated
function callbacks by using st_insert instead of st_update.
----
* hash.c (rb_hash_new_from_values): refactor
extract the bulk insert into a function.
* hash.c (rb_hash_new_from_object): also refactor.
* hash.c (rb_hash_s_create): use the new functions.
* insns.def (newhash): ditto.
* vm.c (core_hash_from_ary): ditto.
* iternal.h: export the new function.
-----------------------------------------------------------
benchmark results:
minimum results in each 7 measurements.
Execution time (sec)
name before after
loop_whileloop2 0.135 0.134
vm2_bighash* 1.236 0.687
Speedup ratio: compare with the result of `before' (greater is better)
name after
loop_whileloop2 1.008
vm2_bighash* 1.798
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Found a part where copy&paste can be eliminated. Reduces vm_exec_core
from 26,228 bytes to 26,176 bytes in size on my machine. I believe it
does not affect any runtime performance.
----
* array.c (rb_ary_tmp_new_from_values): extend existing
rb_ary_new_from_values function so that it can take
additional value for klass.
* array.c (rb_ary_new_from_values): use the new function.
* insns.def (toregexp): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58416 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (trace): use cast `flag` to pass compilation with clang on MacOSX.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58394 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Contemporary C compilers are good at function inlining. They fold
multiple functions into one. However they are not yet smart enough to
unfold a function into several ones. So generally speaking, it is
wiser for a C programmer to manually split C functions whenever
possible. That should make rooms for compilers to optimize at will.
Before this changeset insns.def was converted into single HUGE
function called vm_exec_core(). By moving each instruction's core
into individual functions, generated C source code is reduced from
3,428 lines to 2,847 lines. Looking at the generated assembly
however, it seems my compiler (gcc 6.2) is extraordinary smart so that
it inlines almost all functions I introduced in this changeset back
into that vm_exec_core. On my machine compiled machine binary of the
function does not shrink very much in size (28,432 bytes to 26,816
bytes, according to nm(1)).
I believe this change is zero-cost. Several benchmarks I exercised
showed no significant difference beyond error mergin. For instance
3 repeated runs of optcarrot benchmark on my machine resulted in:
before this: 28.330329285707490, 27.513378371065920, 29.40420215754537
after this: 27.107195867280414, 25.549324021385907, 30.31581919050884
in fps (greater==faster).
----
* internal.h (rb_obj_not_equal): used from vm_insnhelper.c
* insns.def: move vast majority of lines into vm_insnhelper.c
* vm_insnhelper.c: moved here.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Unfortunately this enlarges insns.def by yet another
instruction. However, it is much prettier than opt_str_freeze
in use, and maybe we can avoid having so many instructions in
the future.
[ruby-core:80368]
* insns.def (DEFINE_INSN): new instruction: opt_str_uminus (maybe temporary)
* compile.c (iseq_compile_each0): split instructions
* test/ruby/test_optimization.rb (test_string_uminus): new test
* vm.c (vm_init_redefined_flag): set redefinintion flag for uminus
* vm_core.h (enum ruby_basic_operators): add BOP_UMINUS
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58144 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
NOTE:
(1) Fixnum's LSB is always 1.
It means you can always run `x - 1` without overflow.
(2) Of course `z = x + (y-1)` may overflow.
Now z's LSB is always 1, and the MSB of true result is also 1.
You can get true result in long as `(1<<63)|(z>>1)`,
and it equals to `(z<<63)|(z>>1)` == `ror(z)`.
GCC and Clang have __builtin_add_ovewflow:
* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
* https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Patch by Eric Wong [ruby-core:78797].
I don't like the idea of making insns.def any bigger to support
a corner case, and "test_hash_aref_fstring_identity" shows
how contrived this is.
[ruby-core:78783] [Bug #12855]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57278 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (checkmatch): adjust type of the index variable, to
get rid of (potential) overflow.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (opt_case_dispatch): extract float value only if the
Float method is not redefnined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56511 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
[Bug #12628]
This patch introduce many changes.
* Introduce concept of "Block Handler (BH)" to represent
passed blocks.
* move rb_control_frame_t::flag to ep[0] (as a special local
variable). This flags represents not only frame type, but also
env flags such as escaped.
* rename `rb_block_t` to `struct rb_block`.
* Make Proc, Binding and RubyVM::Env objects wb-protected.
Check [Bug #12628] for more details.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55766 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
instead of setting rb_thread_t::cfp directly.
* vm_insnhelper.c (vm_pop_frame): return the result of
finish frame or not.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55755 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
compilers to use x86 LEA instruction (3 operand).
Even if 3 operand LEA's latency is 3 cycle after SandyBridge,
it reduces code size and can be faster because of super scalar.
* insns.def (opt_plus): calculate and use rb_int2big.
On positive Fixnum overflow, `recv - 1 + obj` doesn't carry
because recv's msb and obj's msb are 0, and resulted msb is 1.
Therefore simply rshift and cast as signed long works fine.
On negative Fixnum overflow, it will carry because both arguments'
msb are 1, and resulted msb is also 1.
In this case it needs to restore carried sign bit after rshift.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* [Feature #12005] Unify Fixnum and Bignum into Integer
* include/ruby/ruby.h (rb_class_of): Return rb_cInteger for fixnums.
* insns.def (INTEGER_REDEFINED_OP_FLAG): Unified from
FIXNUM_REDEFINED_OP_FLAG and BIGNUM_REDEFINED_OP_FLAG.
* vm_core.h: Ditto.
* vm_insnhelper.c (opt_eq_func): Use INTEGER_REDEFINED_OP_FLAG instead
of FIXNUM_REDEFINED_OP_FLAG.
* vm.c (vm_redefinition_check_flag): Use rb_cInteger instead of
rb_cFixnum and rb_cBignum.
(C): Use Integer instead of Fixnum and Bignum.
* numeric.c (fix_succ): Removed.
(Init_Numeric): Define Fixnum as Integer.
* bignum.c (bignew): Use rb_cInteger instead of Rb_cBignum.
(rb_int_coerce): replaced from rb_big_coerce and return fixnums
as-is.
(Init_Bignum): Define Bignum as Integer.
Don't define ===.
* error.c (builtin_class_name): Return "Integer" for fixnums.
* sprintf.c (ruby__sfvextra): Use rb_cInteger instead of rb_cFixnum.
* ext/-test-/testutil: New directory to test.
Currently it provides utilities for fixnum and bignum.
* ext/json/generator/generator.c: Define mInteger_to_json.
* lib/mathn.rb (Fixnum#/): Redefinition removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55024 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
superclass of a class as Object and it has another superclass.
[Bug #12367] [ruby-core:75446]
* test/ruby/test_class.rb: test for above.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54970 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
and define CONSTFUNC and PUREFUNC if available.
Note that I don't add those options as default because
it still shows many false-positive (it seems not to consider
longjmp).
* vm_eval.c (stack_check): get rb_thread_t* as an argument
to avoid duplicate call of GET_THREAD().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54952 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
x == FIXNUM_MIN && y == -1. This must be a rare case and it is
expected compiler to handle well.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54216 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
but LONG_LONG is always defined as 64bit), or there's int128_t.
* internal.h (DL2NUM): defined if DLONG is defined.
* internal.h (rb_fix_mul_fix): defined for `Fixnum * Fixnum`.
* insns.def (opt_mul): use rb_fix_mul_fix().
* numeric.c (fix_mul): ditto.
* time.c (mul): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54203 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Now `[x, y].max` is optimized so that a temporal array object is not
created in some condition.
* insns.def (opt_newarray_max, opt_newarray_min): added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54153 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* bignum.c (rb_uint128t2big): added for opt_mult.
* bignum.c (rb_uint128t2big): added for rb_uint128t2big..
* configure.in: define int128_t, uint128_t and related MACROs.
Initially introduced by r41379 but reverted by r50749.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The position of `/* fall through */` was moved by r52931.
* insns.def (opt_case_dispatch): Move a comment to the
appropriate position.
[ci skip]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53423 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Infinity cannot be written as an optimizable literal,
so it can never match a key in a CDHASH.
Avoid converting it to prevent FloatDomainError.
* insns.def (opt_case_dispatch): avoid converting Infinity
* test/ruby/test_optimization.rb (test_opt_case_dispatch_inf): new
[ruby-dev:49423] [Bug #11804]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53039 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
and a pre-compilation/runtime loader sample.
[Feature #11788]
* iseq.c: add new methods:
* RubyVM::InstructionSequence#to_binary_format(extra_data = nil)
* RubyVM::InstructionSequence.from_binary_format(binary)
* RubyVM::InstructionSequence.from_binary_format_extra_data(binary)
* compile.c: implement body of this new feature.
* load.c (rb_load_internal0), iseq.c (rb_iseq_load_iseq):
call RubyVM::InstructionSequence.load_iseq(fname) with
loading script name if this method is defined.
We can return any ISeq object as a result value.
Otherwise loading will be continue as usual.
This interface is not matured and is not extensible.
So that we don't guarantee the future compatibility of this method.
Basically, you should'nt use this method.
* iseq.h: move ISEQ_MAJOR/MINOR_VERSION (and some definitions)
from iseq.c.
* encoding.c (rb_data_is_encoding), internal.h: added.
* vm_core.h: add several supports for lazy load.
* add USE_LAZY_LOAD macro to specify enable or disable of
this feature.
* add several fields to rb_iseq_t.
* introduce new macro rb_iseq_check().
* insns.def: some check for lazy loading feature.
* vm_insnhelper.c: ditto.
* proc.c: ditto.
* vm.c: ditto.
* test/lib/iseq_loader_checker.rb: enabled iff suitable
environment variables are provided.
* test/runner.rb: enable lib/iseq_loader_checker.rb.
* sample/iseq_loader.rb: add sample compiler and loader.
$ ruby sample/iseq_loader.rb [dir]
will compile all ruby scripts in [dir].
With default setting, this compile creates *.rb.yarb files
in same directory of target .rb scripts.
$ ruby -r sample/iseq_loader.rb [app]
will run with enable to load compiled binary data.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52949 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
nil/true/false are special literals just like floats, integers,
literal strings, and symbols. Optimize when statements with
them by using a jump table, too.
target 0: a (ruby 2.3.0dev (2015-12-08 trunk 52928) [x86_64-linux]) at "/home/ew/rrrr/b/ruby"
target 1: b (ruby 2.3.0dev (2015-12-08 master 52928) [x86_64-linux]) at "/home/ew/ruby/b/ruby"
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
loop_whileloop2 0.102 0.103
vm2_case_lit* 1.657 0.549
Speedup ratio: compare with the result of `a' (greater is better)
name b
loop_whileloop2 0.988
vm2_case_lit* 3.017
* benchmark/bm_vm2_case_lit.rb: new benchmark
* compile.c (case_when_optimizable_literal): add nil/true/false
* insns.def (opt_case_dispatch): ditto
* vm.c (vm_redefinition_check_flag): ditto
* vm.c (vm_init_redefined_flag): ditto
* vm_core.h: ditto
* object.c (InitVM_Object): define === explicitly for nil/true/false
* test/ruby/test_case.rb (test_deoptimize_nil): new test
* test/ruby/test_optimization.rb (test_opt_case_dispatch): update
(test_eqq): new test
[ruby-core:71923] [Feature #11769]
Original patch by Aaron Patterson <tenderlove@ruby-lang.org>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52931 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The missing check for Float#=== redefinition was noticed while
working on enhancing optimized case dispatch for nil/true/false
in [ruby-core:71818] https://bugs.ruby-lang.org/issues/11769
So no, I don't normally redefine core classes like this :P
* insns.def (opt_case_dispatch): check Float#=== redefinition
* test/ruby/test_optimization.rb (test_opt_case_dispatch): new
[ruby-core:71920] [Bug #11784]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52928 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
strings as default.
[Feature #11725]
* insns.def (freezestring): add new instruction to support adding
debug information for dynamically constracted strings.
* compile.c (iseq_compile_each): support adding debug information
for NODE_DSTR with freezestring instruction.
* error.c (rb_error_frozen): change the debug information ID name
id_debug_created_info and this field should have a 2 element array
containing path and line information.
* defs/id.def: ditto.
* test/ruby/test_rubyoptions.rb: catch up this fix.
* test/ruby/test_iseq.rb: now frozen strings are not same.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
current cref only when cached CREF list includes singleton class.
Singleton classes have own namespaces, so that we need to check
cref as a key (#10943).
However, if current CREF list does not include singleton class,
no need to check CREF beacuse it should be same name space.
* vm_insnhelper.c (vm_get_const_key_cref): add a function returns
CREF only when it includes singleton class.
* vm_core.h: constify iseq_inline_cache_entry::ic_cref.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52371 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* internal.h (RUBY_DTRACE_CREATE_HOOK): macro to call hook at
object creation.
* vm.c (rb_source_location, rb_source_loc): retrieve source path
and line number at once.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52340 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (iseq_peephole_optimize): peephole optimization for
branchnil jumps.
* compile.c (iseq_compile_each): generate save navigation operator
code.
* insns.def (branchnil): new opcode to pop the tos and branch if
it is nil.
* parse.y (NEW_QCALL, call_op, parser_yylex): parse token '.?'.
[Feature #11537]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (compile_dstr_fragments): fix performance by omitting
the first empty string only for keeping literal encoding if
other literals are too. [ruby-core:70930] [Bug #11556]
* string.c (rb_str_append_literal): append but keep encoding non
US-ASCII.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51970 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* rb_call_info (ci) has compiled fixed information.
* if ci->flag & VM_CALL_KWARG, then rb_call_info is
also rb_call_info_with_kwarg. This technique reduce one word
for major rb_call_info data.
* rb_calling_info has temporary data (argc, blockptr, recv).
for each method dispatch. This data is allocated only on
machine stack.
* rb_call_cache is for inline method cache.
Before this patch, only rb_call_info_t data is passed.
After this patch, above three structs are passed.
This patch improves:
* data locarity (rb_call_info is now read-only data).
* reduce memory consumption (rb_call_info_with_kwarg,
rb_calling_info).
* compile.c: use above data.
* insns.def: ditto.
* iseq.c: ditto.
* vm_args.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_insnhelper.h: ditto.
* iseq.h: add iseq_compile_data::ci_index and
iseq_compile_data::ci_kw_indx.
* tool/instruction.rb: introduce TS_CALLCACHE operand type.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51903 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
All contents of previous rb_iseq_t is in rb_iseq_t::body.
Remove rb_iseq_t::self because rb_iseq_t is an object.
RubyVM::InstructionSequence is wrapper object points T_IMEMO/iseq.
So RubyVM::ISeq.of(something) method returns different wrapper
objects but they point the same T_IMEMO/iseq object.
This patch is big, but most of difference is replacement of
iseq->xxx to iseq->body->xxx.
(previous) rb_iseq_t::compile_data is also located to
rb_iseq_t::compile_data.
It was moved from rb_iseq_body::compile_data.
Now rb_iseq_t has empty two pointers.
I will split rb_iseq_body data into static data and dynamic data.
* compile.c: rename some functions/macros.
Now, we don't need to separate iseq and iseqval (only VALUE).
* eval.c (ruby_exec_internal): `n' is rb_iseq_t (T_IMEMO/iseq).
* ext/objspace/objspace.c (count_imemo_objects): count T_IMEMO/iseq.
* gc.c: check T_IMEMO/iseq.
* internal.h: add imemo_type::imemo_iseq.
* iseq.c: define RubyVM::InstructionSequnce as T_OBJECT.
Methods are implemented by functions named iseqw_....
* load.c (rb_load_internal0): rb_iseq_new_top() returns
rb_iseq_t (T_IMEMO/iesq).
* method.h (rb_add_method_iseq): accept rb_iseq_t (T_IMEMO/iseq).
* vm_core.h (GetISeqPtr): removed because it is not T_DATA now.
* vm_core.h (struct rb_iseq_body): remove padding for
[Bug #10037][ruby-core:63721].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51327 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defineclass): do not quote unprintable characters at
raising an exception.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51062 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defineclass): preserve encoding of name in error
messages for super class mismatch.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51055 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defineclass): preserve encoding of name in error
messages for non-class super.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51054 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defineclass): preserve encoding of name in error
messages when already defined but type mismatch.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
`flag' contains several categories of attributes and it makes us
confusion (at least, I had confused).
* rb_method_visibility_t (flags::visi)
* NOEX_UNDEF -> METHOD_VISI_UNDEF = 0
* NOEX_PUBLIC -> METHOD_VISI_PUBLIC = 1
* NOEX_PRIVATE -> METHOD_VISI_PRIVATE = 2
* NOEX_PROTECTED -> METHOD_VISI_PROTECTED = 3
* NOEX_SAFE(flag)) -> safe (flags::safe, 2 bits)
* NOEX_BASIC -> basic (flags::basic, 1 bit)
* NOEX_MODFUNC -> rb_scope_visibility_t in CREF
* NOEX_SUPER -> MISSING_SUPER (enum missing_reason)
* NOEX_VCALL -> MISSING_VCALL (enum missing_reason)
* NOEX_RESPONDS -> BOUND_RESPONDS (macro)
Now, NOEX_NOREDEF is not supported (I'm not sure it is needed).
Background:
I did not know what "NOEX" stands for.
I asked Matz (who made this name) and his answer was "Nothing".
"At first, it meant NO EXport (private), but the original
meaning was gone."
This is why I remove the mysterious word "NOEX" from MRI.
* vm_core.h: introduce `enum missing_reason' to represent
method_missing (NoMethodError) reason.
* eval_intern.h: introduce rb_scope_visibility_t to represent
scope visibility.
It has 3 method visibilities (public/private/protected)
and `module_function`.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50743 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Motivation and new data structure are described in [Bug #11203].
This patch also solve the following issues.
* [Bug #11200] Memory leak of method entries
* [Bug #11046] __callee__ returns incorrect method name in orphan
proc
* test/ruby/test_method.rb: add a test for [Bug #11046].
* vm_core.h: remvoe rb_control_frame_t::me. me is located at value
stack.
* vm_core.h, gc.c, vm_method.c: remove unlinked_method... codes
because method entries are simple VALUEs.
* method.h: Now, all method entries has own independent method
definititons. Strictly speaking, this change is not essential,
but for future changes.
* rb_method_entry_t::flag is move to rb_method_definition_t::flag.
* rb_method_definition_t::alias_count is now
rb_method_definition_t::alias_count_ptr, a pointer to the counter.
* vm_core.h, vm_insnhelper.c (rb_vm_frame_method_entry) added to
search the current method entry from value stack.
* vm_insnhelper.c (VM_CHECK_MODE): introduced to enable/disable
assertions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50728 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_cref_t is data type of CREF. Now, the body is still NODE.
It is easy to understand what is CREF and what is pure NODE.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_core.h, method.h: remove rb_iseq_t::cref_stack. CREF is stored
to rb_method_definition_t::body.iseq_body.cref.
* vm_insnhelper.c: modify SVAR usage.
When calling ISEQ type method, push CREF information onto method
frame, SVAR located place. Before this fix, SVAR is simply nil.
After this patch, CREF (or NULL == Qfalse for not iseq methods)
is stored at the method invocation.
When SVAR is requierd, then put NODE_IF onto SVAR location,
and NDOE_IF::nd_reserved points CREF itself.
* vm.c (vm_cref_new, vm_cref_dump, vm_cref_new_toplevel): added.
* vm_insnhelper.c (vm_push_frame): accept CREF.
* method.h, vm_method.c (rb_add_method_iseq): added. This function
accepts iseq and CREF.
* class.c (clone_method): use rb_add_method_iseq().
* gc.c (mark_method_entry): mark method_entry::body.iseq_body.cref.
* iseq.c: remove CREF related codes.
* insns.def (getinlinecache/setinlinecache): CREF should be cache key
because a different CREF has a different namespace.
* node.c (rb_gc_mark_node): mark NODE_IF::nd_reserved for SVAR.
* proc.c: catch up changes.
* struct.c: ditto.
* insns.def: ditto.
* vm_args.c (raise_argument_error): ditto.
* vm_eval.c: ditto.
* test/ruby/test_class.rb: add a test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Time#succ is a deprecated method and not frequently used, so this wastes
icache in vm_exec_core. Using bloat-o-meter in the Linux kernel source
to shows a small reduction on my x86-64 system:
$ ~/linux/scripts/bloat-o-meter ruby.before ruby.after
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-57 (-57)
function old new delta
vm_exec_core 24216 24159 -57
[Feature #10501]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
keyword arguments/parameters and a splat argument.
[Feature #10440] (Details are described in this ticket)
Most of complex part is moved to vm_args.c.
Now, ISeq#to_a does not catch up new instruction format.
* vm_core.h: change iseq data structures.
* introduce rb_call_info_kw_arg_t to represent keyword arguments.
* add rb_call_info_t::kw_arg.
* rename rb_iseq_t::arg_post_len to rb_iseq_t::arg_post_num.
* rename rb_iseq_t::arg_keywords to arg_keyword_num.
* rename rb_iseq_t::arg_keyword to rb_iseq_t::arg_keyword_bits.
to represent keyword bitmap parameter index.
This bitmap parameter shows that which keyword parameters are given
or not given (0 for given).
It is refered by `checkkeyword' instruction described bellow.
* rename rb_iseq_t::arg_keyword_check to rb_iseq_t::arg_keyword_rest
to represent keyword rest parameter index.
* add rb_iseq_t::arg_keyword_default_values to represent default
keyword values.
* rename VM_CALL_ARGS_SKIP_SETUP to VM_CALL_ARGS_SIMPLE
to represent
(ci->flag & (SPLAT|BLOCKARG)) &&
ci->blockiseq == NULL &&
ci->kw_arg == NULL.
* vm_insnhelper.c, vm_args.c: rewrite with refactoring.
* rewrite splat argument code.
* rewrite keyword arguments/parameters code.
* merge method and block parameter fitting code into one code base.
* vm.c, vm_eval.c: catch up these changes.
* compile.c (new_callinfo): callinfo requires kw_arg parameter.
* compile.c (compile_array_): check the last argument Hash object or
not. If Hash object and all keys are Symbol literals, they are
compiled to keyword arguments.
* insns.def (checkkeyword): add new instruction.
This instruction check the availability of corresponding keyword.
For example, a method "def foo k1: 'v1'; end" is cimpiled to the
following instructions.
0000 checkkeyword 2, 0 # check k1 is given.
0003 branchif 9 # if given, jump to address #9
0005 putstring "v1"
0007 setlocal_OP__WC__0 3 # k1 = 'v1'
0009 trace 8
0011 putnil
0012 trace 16
0014 leave
* insns.def (opt_send_simple): removed and add new instruction
"opt_send_without_block".
* parse.y (new_args_tail_gen): reorder variables.
Before this patch, a method "def foo(k1: 1, kr1:, k2: 2, **krest, &b)"
has parameter variables "k1, kr1, k2, &b, internal_id, krest",
but this patch reorders to "kr1, k1, k2, internal_id, krest, &b".
(locate a block variable at last)
* parse.y (vtable_pop): added.
This function remove latest `n' variables from vtable.
* iseq.c: catch up iseq data changes.
* proc.c: ditto.
* class.c (keyword_error): export as rb_keyword_error().
* common.mk: depend vm_args.c for vm.o.
* hash.c (rb_hash_has_key): export.
* internal.h: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (getlocal,setlocal): add comment to def/opt_operand.def
I spent some time thinking about the same optimization before
realizing it was already done.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
We may tag the running_thread pointer to avoid making the "once" struct
bigger than "struct iseq_inline_cache_entry".
This only saves a small amount with "valgrind ruby -e exit"
before:
total heap usage: 48,122 allocs, 19,248 frees, 8,110,149 bytes allocated
after:
total heap usage: 48,122 allocs, 19,253 frees, 8,099,197 bytes allocated
* insns.def (once): define and use fake RUNNING_THREAD_ONCE_DONE
pointer to indicate is->once.running_thread is done.
* vm_core.h (iseq_inline_storage_entry): remove done field,
allowing the union to be reduced from 24=>16 bytes on 64-bit
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47542 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (once), vm_insnhelper.c (vm_once_exec): turn the
parameter into a VALUE to get rid of type-punned pointer cast.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46478 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (opt_regexpmatch2): respect redefined match op
Thanks to Sam Rawlins for the fix.
* test/ruby/test_string.rb: test based on Tsuyoshi Sawada's report
[Bug #9581]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45318 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (opt_aref_with): new instruction to optimize Hash#[],
removing any allocation overhead when used with a string literal
key. Patch by normalperson (Eric Wong). [ruby-core:59640] [Bug #9382]
* insns.def (opt_aset_with): new instruction to optimize Hash#[]=
* compile.c (iseq_compile_each): compiler shortcuts for new
instructions
* hash.c (static VALUE rb_hash_compare_by_id_p): fix documentation for
Hash#compare_by_identity to reflect frozen string sharing
* test/ruby/test_hash.rb (class TestHash): test for new behavior
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44551 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
vm_insnhelper.c, vm_insnhelper.h, vm_method.c: Rename method_serial
to global_method_state and constant_serial to global_constant_state
after discussion with ko1.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
method is called on a static string literal with no arguments.
* defs/id.def (firstline): add freeze so idFreeze is available
* insns.def (opt_str_freeze): add opt_str_freeze instruction which
pushes a frozen string literal without allocating a new object if
String#freeze is not overriden
* string.c (Init_String): define String#freeze
* vm.c (vm_init_redefined_flag): define BOP_FREEZE on String class as
a basic operation
* vm_insnhelper.h: ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43627 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
ic_serial. This is possible because these fields are only ever used
exclusively with each other.
* insns.def: ditto
* vm_core.h: ditto
* vm_insnhelper.c: ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
before calling rb_reg_match().
* test/ruby/test_string.rb: Test for above.
* vm.c (vm_init_redefined_flag): Add BOP flag for String#=~
[ruby-core:57385] [Bug #8953]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43052 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (opt_regexpmatch2): use CALL_SIMPLE_METHOD to call =~ if
the receiver is not a T_STRING [Bug #8847] [ruby-core:56916]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42742 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (getinlinecache, once, opt_case_dispatch): refine some
English version comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42638 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Stack overflow check should be done *after* pushing a stack frame.
However, some stack overflow checking codes checked *before*
pushing a stack frame with iseq->stack_max.
To solve this problem, add a new parameter `stack_max' to specify
a possible consuming stack size.
* vm_core.h (CHECK_VM_STACK_OVERFLOW0): add to share the stack overflow
checking code.
* insns.def: catch up this change.
* vm.c, vm_eval.c: ditto.
* test/ruby/test_exception.rb: add a stack overflow test.
This code is reported by nobu.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42398 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defined): use vm_search_superclass() like as normal super
call. based on a patch <https://gist.github.com/wanabe/5520026> by
wanabe.
* vm_insnhelper.c (vm_search_superclass): return error but not raise
exceptions.
* vm_insnhelper.c (vm_search_super_method): check the result of
vm_search_superclass and raise execptions on error.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40584 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defined): get method entry from the method top level
frame, not block frame. [ruby-core:54769] [Bug #8367]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
a significant performance improvement. Thanks to @samsaffron.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
by scoped module definitions. The bug was introduced in r38495.
* test/ruby/test_module.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38772 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
compile.c (iseq_compile_each), insns.def (defineclass): change the
meaning of the third operand of defineclass as follows:
lower 3bits: the type of the defineclass
0 = class, 1 = singleton class, 2 = module
4th bit: a flag represents whether the defineclass is scoped
0 = not scoped (e.g., class Foo)
1 = scoped (e.g., class Bar::Baz)
5th bit: a flag represents whether the superclass is specified
0 = not specified (e.g., class Foo)
1 = specified (e.g., class Bar < Foo)
If the superclass is specified and is not a class, a TypeError
should be raised. [ruby-dev:46747] [Bug #7572]
* test/ruby/test_class.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (iseq_compile_each): count flip-flop state in local iseq
not in each iseqs, so that the keys can be other than hidden
strings. [ruby-core:47253] [Bug #6899]
* vm_insnhelper.c (lep_svar_get, lep_svar_set, vm_getspecial): store
flip-flop states in an array instead of a hash.
* iseq.c (set_relation): main iseq also can has local scope.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38292 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
of the receiver in module_eval and instance_eval.
* eval.c (ruby_Init_refinement): undef Class#refine.
* eval.c (ruby_Init_refinement): remove Module#using.
* eval.c (ruby_Init_refinement): main.using should be private.
* eval.c (rb_mod_refine): the argument of Module#refine should not
be a module.
* insns.def (defineclass): do not activate refinements in a class or
module.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38262 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Operand unification technique enable to combine
an instruction and specific operands and make new
instruction.
* defs/opt_operand.def: add several configuration
of operand unifications.
* insns.def: use `int' instead to suppress warning.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38173 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
path without caching the computed path. Some classes are frozen, and
will raise an exception without this.
* probes.d (cmethod-entry, cmethod-return): separate cmethods from
regular methods to match set trace func.
* probes_helper.h: refactor macros. Fix probes to avoid calling
#inspect when profiling.
* insns.def: update for use with new macros.
* vm_eval.c: ditto
* vm_insnhelper.c: ditto
* test/dtrace/test_singleton_function.rb: fix test for new output.
* test/dtrace/test_cmethod.rb: test the cmethod probes.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38099 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
(1) TracePoint#return_value which returns return
value on the :return and :c_return event.
(2) TracePoint#raised_exception which returns raised exception
value on the :raise event.
Eeach methods raise RuntimeError if it is called at unsupported
event.
Please review and give us feedback until next preview
release (Dec/2012) of Ruby 2.0.0.
* insns.def, vm.c, vm_eval.c, vm_insnhelper.c, eval.c, thread.c:
ditto.
* vm_trace.c, vm_core.h: move definition of rb_trace_arg_t from
vm_trace.c to vm_core.h.
Caller fills rb_trace_arg_t and pass the pointer of this variable.
* test/ruby/test_settracefunc.rb: fix tests to test this change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37752 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
`opt_send_simple' to the place near `send' definition.
(to take care about icache locality).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37260 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This condition will be true after r37258.
* vm_insnhelper.c (vm_caller_setup_args): remove `UNLIKELY' on
checking blockiseq (it seems `LIKELY').
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37259 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
when no need to care about block and splat.
* compile.c: use the `opt_send_simple' instruction.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37258 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
with rb_call_info_t to speedup `attr' getter and setter.
Cached index is stored in rb_call_info_t::aux::index.
`index' == 0 means not cached. `index' > 0 means cached and cached
index is `index - 1'.
* insns.def ((get|set)instancevariable): use new wrapper functions
vm_(get|set)instancevariable() defined in vm_insnhelper.c.
* vm_core.h (rb_call_info_t::aux): introduce new union data because
opt_pc can share with index.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37228 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
use only a `ci' (rb_call_info_t) parameter instead of using
parameters such as `op_id', 'op_argc', `blockiseq' and flag.
These information are stored in rb_call_info_t at the compile
time.
This technique simplifies parameter passings at related
function calls (~10% speedups for simple mehtod invocation at
my machine).
`rb_call_info_t' also has new function pointer variable `call'.
This `call' variable enables to customize method (block)
invocation process for each place. However, it always call
`vm_call_general()' at this changes.
`rb_call_info_t' also has temporary variables for method
(block) invocation.
* vm_core.h, compile.c, insns.def: introduce VM_CALL_ARGS_SKIP_SETUP
VM_CALL macro. This flag indicates that this call can skip
caller_setup (block arg and splat arg).
* compile.c: catch up above changes.
* iseq.c: catch up above changes (especially for TS_CALLINFO).
* tool/instruction.rb: catch up above chagnes.
* vm_insnhelper.c, vm_insnhelper.h: ditto. Macros and functions
parameters are changed.
* vm_eval.c (vm_call0): ditto (it will be rewriten soon).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37180 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This data structure contains information including inline method
cache. After that, `struct iseq_inline_cache_entry' does not
need to contain inline cache for method invocation.
Other information will be added to this data structure.
* vm_core.h (rb_iseq_t): add `callinfo_entries' and `callinfo_size'
members to `rb_iseq_t'.
* insns.def, compile.c: Use CALL_INFO instead of IC.
* tool/instruction.rb: support CALL_INFO as operand type.
* vm_insnhelper.c, vm_insnhelper.h: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37121 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
`bp' can be calculate by `sp' (stack pointer) of previous frame.
Now, `bp_check' field is remained for debug. You can eliminate
this field by setting VM_DEBUG_BP_CHECK as 0.
* vm_insnhelper.c (vm_base_ptr): add `vm_base_ptr(cfp).
This function calculates base pointer from cfp.
* vm_insnhelper.c (vm_setup_method): push `recv' value on top of
value stack (before method parameters).
This change is for keeping consistency with normal method dispatch.
* insns.def: fix to use vm_base_ptr().
* vm.c (vm_exec): ditto.
* vm_dump.c: remove `bp' related dumps.
* cont.c (fiber_init): fix to check VM_DEBUG_BP_CHECK.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (invokesuper): klass in cfp is not valid in at_exit and
END blocks. [ruby-core:47680] [Bug #7064]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
64bit CPU environment (sizeof(double) == sizeof(VALUE)).
flonum technique enables to avoid double object creation
if the double value d is in range about between
1.72723e-77 < |d| <= 1.15792e+77 or 0.0.
flonum Float value is immediate and their lowest two bits
are b10.
If flonum is activated, then USE_FLONUM macro is 1.
I'll write detailed in this technique on
https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/Flonum_tech
* benchmark/bmx_temp.rb: add an benchmark for simple
Float calculation.
* gc.c (id2ref, rb_obj_id): add flonum Float support.
* include/ruby/intern.h: move decl of rb_float_new(double)
to include/ruby/ruby.h.
* insns.def, vm.c, vm_insnhelper.c: add flonum optimization
and simplify source code.
* vm_insnhelper.h (FLONUM_2_P): added.
* marshal.c: support flonum output.
* numeric.c (rb_float_new_in_heap): added.
* parse.y: support flonum.
* random.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36798 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
in a thread work correctly. [ruby-core:47284] [Bug #6907]
* test/ruby/test_super.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
of the recipient class. Fixes [ruby-core:47186]
* test/ruby/test_super.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36784 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
remove checkincludearray instruction and
add new instruction checkmatch.
This change is to solve
[Bug #4438] "rescue args type check omitted".
* iseq.c: increment ISEQ_MAJOR_VERSION because removal of
checkincludearray instruction.
* vm_core.h: add several definitions for
the checkmatch instruction.
* vm_insnhelper.c (check_match): added.
* bootstraptest/test_exception.rb: add a test.
* test/ruby/test_exception.rb: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36658 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
receiver for super called in instance_eval. If such a receiver is
not found, raise NoMethodError. [ruby-dev:39772] [Bug #2402]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defined): now should use klass in the current control
frame to search superclass, not me->klass. reported by naruse.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_insnhelper.c (vm_search_normal_superclass): no longer needs
receiver, klass is always unique in the ancestors now.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_method_entry_get_with_omod() to avoid infinite loop when
super is used with refinements. [ruby-core:30450] [Bug #3351]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36612 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
vm_insnhelper.c, vm_insnhelper.h, vm_method.c: add klass to
rb_control_frame_t to implement super correctly.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_thread_s_check_interrupt): added for
Thread.control_intgerrupt and Thread.check_interrupt.
See details on rdoc.
I'll make an ticket for this feature.
* test/ruby/test_thread.rb: add a test for Thread.control_intgerrupt.
* thread.c (rb_threadptr_raise): make a new exception object
even if argc is 0.
* thread.c (rb_thread_kill): kill thread immediately if target thread
is current thread.
* vm_core.h (RUBY_VM_CHECK_INTS_BLOCKING): added.
CHECK_INTS while/after blocking operation.
* vm_core.h (RUBY_VM_CHECK_INTS): require rb_thread_t ptr.
* cont.c (fiber_switch): use replaced RUBY_VM_CHECK_INTS().
* eval.c (ruby_cleanup): ditto.
* insns.def: ditto.
* process.c (rb_waitpid): ditto.
* vm_eval.c (vm_call0): ditto.
* vm_insnhelper.c (vm_call_method): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36470 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (defined): use method entry and id in cfp for proper
superclass, since klass in iseq is shared by dynamically defined
methods from the same block. [ruby-core:45831][Bug #6644]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36369 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* eval.c (rb_frame_callee, rb_f_callee_name): fix to return the called
id.
* vm_insnhelper.c (vm_push_frame): set proper method entry.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36301 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Before this commit:
`finish frame' was place holder which indicates that VM loop
needs to return function.
If a C method calls a Ruby methods (a method written by Ruby),
then VM loop will be (re-)invoked. When the Ruby method returns,
then also VM loop should be escaped. `finish frame' has only
one instruction `finish', which returns VM loop function.
VM loop function executes `finish' instruction, then VM loop
function returns itself.
With such mechanism, `leave' instruction (which returns one
frame from current scope) doesn't need to check that this `leave'
should also return from VM loop function.
Strictly, one branch can be removed from `leave' instructon.
Consideration:
However, pushing the `finish frame' needs costs because
it needs several memory accesses. The number of pushing
`finish frame' is greater than I had assumed. Of course,
pushing `finish frame' consumes additional control frame.
Moreover, recent processors has good branch prediction,
with which we can ignore such trivial checking.
After this commit:
Finally, I decide to remove `finish frame' and `finish'
instruction. Some parts of VM depend on `finish frame',
so the new frame flag VM_FRAME_FLAG_FINISH is introduced.
If this frame should escape from VM function loop, then
the result of VM_FRAME_TYPE_FINISH_P(cfp) is true.
`leave' instruction checks this flag every time.
I measured performance on it. However on my environments,
it improves some benchmarks and slows some benchmarks down.
Maybe it is because of C compiler optimization parameters.
I'll re-visit here if this cause problems.
* insns.def (leave, finish): remove finish instruction.
* vm.c, vm_eval.c, vm_exec.c, vm_backtrace.c, vm_dump.c:
apply above changes.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36099 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
dfp (dynamic frame pointer) to ep (environment pointer).
This change make VM `normal' (similar to other interpreters).
Before this commit:
Each frame has two env pointers lfp and dfp. lfp points
local environment which is method/class/toplevel frame.
lfp[0] is block pointer.
dfp is block local frame. dfp[0] points previous (parent)
environment pointer.
lfp == dfp when frame is method/class/toplevel.
You can get lfp from dfp by traversing previous environment
pointers.
After this commit:
Each frame has only `ep' to point respective enviornoment.
If there is parent environment, then ep[0] points parent
envioenment (as dfp). If there are no more environment,
then ep[0] points block pointer (as lfp). We call such ep
as `LEP' (local EP). We add some macros to get LEP and to
detect LEP or not.
In short, we replace dfp and lfp with ep and LEP.
rb_block_t and rb_binding_t member `lfp' and `dfp' are removed
and member `ep' is added.
rename rb_thread_t's member `local_lfp' and `local_svar' to
`root_lep' and `root_svar'.
(VM_EP_PREV_EP(ep)): get previous environment pointer. This macro
assume that ep is not LEP.
(VM_EP_BLOCK_PTR(ep)): get block pointer. This macro assume
that ep is LEP.
(VM_EP_LEP_P(ep)): detect ep is LEP or not.
(VM_ENVVAL_BLOCK_PTR(ptr)): make block pointer.
(VM_ENVVAL_BLOCK_PTR_P(v)): detect v is block pointer.
(VM_ENVVAL_PREV_EP_PTR(ptr)): make prev environment pointer.
(VM_ENVVAL_PREV_EP_PTR_P(v)): detect v is prev env pointer.
* vm.c: apply above changes.
(VM_EP_LEP(ep)): get LEP.
(VM_CF_LEP(cfp)): get LEP of cfp->ep.
(VM_CF_PREV_EP(cfp)): utility function VM_EP_PREV_EP(cfp->ep).
(VM_CF_BLOCK_PTR(cfp)): utility function VM_EP_BLOCK_PTR(cfp->ep).
* vm.c, vm_eval.c, vm_insnhelper.c, vm_insnhelper.h, insns.def:
apply above changes.
* cont.c: ditto.
* eval.c, eval_intern.h: ditto.
* proc.c: ditto.
* thread.c: ditto.
* vm_dump.c: ditto.
* vm_exec.h: fix function name (on vm debug mode).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
self. since stabby lambda is a syntax, so it should not be
affected by the context. [ruby-core:42349][Bug #5966]
* insns.def (send): no special deal for FCALL. self should be put
on TOS instead.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34819 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* compile.c (iseq_compile_each): make new array with
splat. [ruby-core:21901][Feature #1125]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34633 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
ancestors only when global scope. [ruby-core:39227] [Bug #5264]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33163 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
also inherited constants for classes without superclass and
modules. [ruby-core:37698] [Bug #3423]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33157 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Manage a redefinition of special methods for each classes.
A patch from Joel Gouly <joel.gouly@gmail.com>. Thanks!
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33059 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
A patch by Magnus Holm <judofyr@gmail.com>. Thanks!
* test/ruby/test_variable.rb: add a test for above.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33045 b2dd03c8-39d4-4d8f-98ff-823fe69b080e