summaryrefslogtreecommitdiff
path: root/compile.c
AgeCommit message (Collapse)Author
2022-03-24Add ISEQ_BODY macroPeter Zhu
Use ISEQ_BODY macro to get the rb_iseq_constant_body of the ISeq. Using this macro will make it easier for us to change the allocation strategy of rb_iseq_constant_body when using Variable Width Allocation. Notes: Merged: https://github.com/ruby/ruby/pull/5698
2022-03-02Using macros to check iseq elementS.H
Notes: Merged: https://github.com/ruby/ruby/pull/5558 Merged-By: nobu <nobu@ruby-lang.org>
2022-02-03Fix indents [ci skip]Nobuyoshi Nakada
2022-02-02Treat TS_ICVARC cache as separate from TS_IVC cacheJemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/5519
2022-01-14Fix constant assignment evaluation orderJeremy Evans
Previously, the right hand side was always evaluated before the left hand side for constant assignments. For the following: ```ruby lhs::C = rhs ``` rhs was evaluated before lhs, which is inconsistant with attribute assignment (lhs.m = rhs), and apparently also does not conform to JIS 3017:2013 11.4.2.2.3. Fix this by changing evaluation order. Previously, the above compiled to: ``` 0000 putself ( 1)[Li] 0001 opt_send_without_block <calldata!mid:rhs, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 dup 0004 putself 0005 opt_send_without_block <calldata!mid:lhs, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0007 setconstant :C 0009 leave ``` After this change: ``` 0000 putself ( 1)[Li] 0001 opt_send_without_block <calldata!mid:lhs, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 putself 0004 opt_send_without_block <calldata!mid:rhs, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0006 swap 0007 topn 1 0009 swap 0010 setconstant :C 0012 leave ``` Note that if expr is not a module/class, then a TypeError is not raised until after the evaluation of rhs. This is because that error is raised by setconstant. If we wanted to raise TypeError before evaluation of rhs, we would have to add a VM instruction for calling vm_check_if_namespace. Changing assignment order for single assignments caused problems in the multiple assignment code, revealing that the issue also affected multiple assignment. Fix the multiple assignment code so left-to-right evaluation also works for constant assignments. Do some refactoring of the multiple assignment code to reduce duplication after adding support for constants. Rename struct masgn_attrasgn to masgn_lhs_node, since it now handles both constants and attributes. Add add_masgn_lhs_node static function for adding data for lhs attribute and constant setting. Fixes [Bug #15928] Notes: Merged: https://github.com/ruby/ruby/pull/4450
2021-12-13Remove `NODE_DASGN_CURR` [Feature #18406]Nobuyoshi Nakada
This `NODE` type was used in pre-YARV implementation, to improve the performance of assignment to dynamic local variable defined at the innermost scope. It has no longer any actual difference with `NODE_DASGN`, except for the node dump. Notes: Merged: https://github.com/ruby/ruby/pull/5251
2021-12-07Avoid Array allocation when appending to args array (#5211)John Hawthorn
* Use duparray when possible for argspush ARGSPUSH is the node we see with a single value pushed to the end of a splatted array. ARGSCAT is similar, but is used when multiple values are being concatenated to the list. Previously only ARGSCAT had an optimization where when all the values were static it would use duparray instead of newarray to create the intermediate array. This commit adds similar behaviour for ARGSPUSH, using duparray instead of putobject/newarray. * Replace duparray with putobject before concatarray When performing duparray/concatarray we know we'll never use the intermediate array being created by duparray, so we should be able to use it as a temporary object. This avoids an extra array allocation for NODE_ARGSPUSH (ex. [*foo, 1]) and NODE_ARGSCAT (ex. [*foo, 1, 2]). Notes: Merged-By: jhawthorn <john@hawthorn.email>
2021-12-04Add `nd_type_p` macroS.H
Notes: Merged: https://github.com/ruby/ruby/pull/5091 Merged-By: nobu <nobu@ruby-lang.org>
2021-11-23Assign temporary ID to anonymous ID [Bug #18250]Nobuyoshi Nakada
Dumped iseq binary can not have unnamed symbols/IDs, and ID 0 is stored instead. As `struct rb_id_table` disallows ID 0, also for the distinction, re-assign a new temporary ID based on the local variable table index when loading from the binary, as well as the parser. Notes: Merged: https://github.com/ruby/ruby/pull/5157
2021-11-21Refactor hacky ID tables to struct rb_ast_id_table_tYusuke Endoh
The implementation of a local variable tables was represented as `ID*`, but it was very hacky: the first element is not an ID but the size of the table, and, the last element is (sometimes) a link to the next local table only when the id tables are a linked list. This change converts the hacky implementation to a normal struct. Notes: Merged: https://github.com/ruby/ruby/pull/5136
2021-11-19optimize `Struct` getter/setterKoichi Sasada
Introduce new optimized method type `OPTIMIZED_METHOD_TYPE_STRUCT_AREF/ASET` with index information. Notes: Merged: https://github.com/ruby/ruby/pull/5131
2021-11-18Optimize dynamic string interpolation for symbol/true/false/nil/0-9Jeremy Evans
This provides a significant speedup for symbol, true, false, nil, and 0-9, class/module, and a small speedup in most other cases. Speedups (using included benchmarks): :symbol :: 60% 0-9 :: 50% Class/Module :: 50% nil/true/false :: 20% integer :: 10% [] :: 10% "" :: 3% One reason this approach is faster is it reduces the number of VM instructions for each interpolated value. Initial idea, approach, and benchmarks from Eric Wong. I applied the same approach against the master branch, updating it to handle the significant internal changes since this was first proposed 4 years ago (such as CALL_INFO/CALL_CACHE -> CALL_DATA). I also expanded it to optimize true/false/nil/0-9/class/module, and added handling of missing methods, refined methods, and RUBY_DEBUG. This renames the tostring insn to anytostring, and adds an objtostring insn that implements the optimization. This requires making a few functions non-static, and adding some non-static functions. This disables 4 YJIT tests. Those tests should be reenabled after YJIT optimizes the new objtostring insn. Implements [Feature #13715] Co-authored-by: Eric Wong <e@80x24.org> Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Co-authored-by: Yusuke Endoh <mame@ruby-lang.org> Co-authored-by: Koichi Sasada <ko1@atdot.net> Notes: Merged: https://github.com/ruby/ruby/pull/5002 Merged-By: jeremyevans <code@jeremyevans.net>
2021-11-18compile.c: remove dead codeYusuke Endoh
2021-11-18compile.c: Fix typoYusuke Endoh
2021-11-15`Primitive.mandatory_only?` for fast pathKoichi Sasada
Compare with the C methods, A built-in methods written in Ruby is slower if only mandatory parameters are given because it needs to check the argumens and fill default values for optional and keyword parameters (C methods can check the number of parameters with `argc`, so there are no overhead). Passing mandatory arguments are common (optional arguments are exceptional, in many cases) so it is important to provide the fast path for such common cases. `Primitive.mandatory_only?` is a special builtin function used with `if` expression like that: ```ruby def self.at(time, subsec = false, unit = :microsecond, in: nil) if Primitive.mandatory_only? Primitive.time_s_at1(time) else Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in)) end end ``` and it makes two ISeq, ``` def self.at(time, subsec = false, unit = :microsecond, in: nil) Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in)) end def self.at(time) Primitive.time_s_at1(time) end ``` and (2) is pointed by (1). Note that `Primitive.mandatory_only?` should be used only in a condition of an `if` statement and the `if` statement should be equal to the methdo body (you can not put any expression before and after the `if` statement). A method entry with `mandatory_only?` (`Time.at` on the above case) is marked as `iseq_overload`. When the method will be dispatch only with mandatory arguments (`Time.at(0)` for example), make another method entry with ISeq (2) as mandatory only method entry and it will be cached in an inline method cache. The idea is similar discussed in https://bugs.ruby-lang.org/issues/16254 but it only checks mandatory parameters or more, because many cases only mandatory parameters are given. If we find other cases (optional or keyword parameters are used frequently and it hurts performance), we can extend the feature. Notes: Merged: https://github.com/ruby/ruby/pull/5112
2021-10-29Fix script_lines in loaded iseq as nilNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/5047
2021-10-24suppress warnings for probable NULL dererefencesNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/5015
2021-10-21`RubyVM.keep_script_lines`Koichi Sasada
`RubyVM.keep_script_lines` enables to keep script lines for each ISeq and AST. This feature is for debugger/REPL support. ```ruby RubyVM.keep_script_lines = true RubyVM::keep_script_lines = true eval("def foo = nil\ndef bar = nil") pp RubyVM::InstructionSequence.of(method(:foo)).script_lines ``` Notes: Merged: https://github.com/ruby/ruby/pull/4913
2021-10-20Simplify code for YJIT const cache in compile.cAlan Wu
Since opt_getinlinecache and opt_setinlinecache point to the same cache struct, there is no need to track the index of the get instruction and then store it on the cache struct later when processing the set instruction. Setting it when processing the get instruction works just as well. This change reduces our diff.
2021-10-20Fix changes from rebaseNoah Gibbs
2021-10-20Simpler fix for -DUSE_EMBED_CI=0Alan Wu
Nobu pointed out that saving the old ci to a local is enough to keep it reachable.
2021-10-20Revert "Fix use-after-free on USE_EMBED_CI=0"Alan Wu
This reverts commit 1e0f2e4b09ca9443524acf4b50ffd50a80f330f3.
2021-10-20Fix use-after-free on USE_EMBED_CI=0Alan Wu
The old code didn't keep old_operands[0] reachable while allocating. You can crash it by requiring erb under GC stress mode.
2021-10-20YJIT: Fancier opt_getinlinecacheAlan Wu
Make sure `opt_getinlinecache` is in a block all on its own, and invalidate it from the interpreter when `opt_setinlinecache`. It will recompile with a filled cache the second time around. This lets YJIT runs well when the IC for constant is cold.
2021-10-20Refactor uJIT code into more files for readabilityMaxime Chevalier-Boisvert
2021-10-20MicroJIT: compile after ten callsAlan Wu
2021-10-20Implement the --disable-ujit command line optionAlan Wu
2021-10-20Avoid triggering GC while translating threaded codeAlan Wu
2021-10-20Avoid recompiling overlapping instruction sequences in ujitMaxime Chevalier-Boisvert
2021-10-20Generate multiple copies of native code for `pop`Alan Wu
Insert generated addresses into st_table for mapping native code addresses back to info about VM instructions. Export `encoded_insn_data` to do this. Also some style fixes.
2021-10-20Add new files, ujit_compile.c, ujit_compile.hMaxime Chevalier-Boisvert
2021-10-20Added shift instructionsMaxime Chevalier-Boisvert
2021-10-20Yeah, this actually works!Alan Wu
2021-10-20Cast to void pointer for `%p` in commented out code [ci skip]Nobuyoshi Nakada
2021-10-07Dump outer variables tables when dumping an iseq to binaryAaron Patterson
This commit dumps the outer variables table when dumping an iseq to binary. This fixes a case where Ractors aren't able to tell what outer variables belong to a lambda after the lambda is loaded via ISeq.load_from_binary [Bug #18232] [ruby-core:105504] Notes: Merged: https://github.com/ruby/ruby/pull/4942
2021-10-03Using NIL_P macro instead of `== Qnil`S.H
Notes: Merged: https://github.com/ruby/ruby/pull/4925 Merged-By: nobu <nobu@ruby-lang.org>
2021-09-12Using RB_FLOAT_TYPE_P macroS-H-GAMELINKS
Notes: Merged: https://github.com/ruby/ruby/pull/4821
2021-09-11Using SYMBOL_P macroS-H-GAMELINKS
Notes: Merged: https://github.com/ruby/ruby/pull/4798
2021-09-10Remove unused argumentNobuyoshi Nakada
2021-09-10suppress GCC's -Wsuggest-attribute=format卜部昌平
I was not aware of this because I use clang these days. Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-09-05Replace RBOOL macroS-H-GAMELINKS
Notes: Merged: https://github.com/ruby/ruby/pull/4791
2021-09-01Extract compile_attrasgn from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_kw_arg from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_errinfo from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_dots from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_colon3 from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_colon2 from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_match from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_yield from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795
2021-09-01Extract compile_super from iseq_compile_each0Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4795