Граф коммитов

1113 Коммитов

Автор SHA1 Сообщение Дата
Nobuyoshi Nakada 25fbc88666
Removed non-ASCII code to suppress warnings by localized compilers 2020-06-27 23:15:13 +09:00
Kazuki Tsujimoto 600f3990d6
Cosmetic change 2020-06-27 13:53:47 +09:00
Vladimir Dementyev c9ee34a18b Add #deconstruct cache to find pattern 2020-06-27 13:51:03 +09:00
Vladimir Dementyev 5320375732 Optimize array pattern matching by caching #deconstruct value 2020-06-27 13:51:03 +09:00
Nobuyoshi Nakada 74c345c7b8 Removed no longer used flags 2020-06-27 10:55:18 +09:00
Nobuyoshi Nakada 61984d4760 Not to rewrite node while compiling
Moved this hack mark to an argument to `compile_hash`.
> Bad Hack: temporarily mark hash node with flag so
> compile_hash can compile call differently.
2020-06-27 10:55:18 +09:00
Takashi Kokubun 7561db8c00
Introduce Primitive.attr! to annotate 'inline' (#3242)
[Feature #15589]
2020-06-20 17:13:03 -07:00
Yusuke Endoh 50efa18c6c compile.c: Improve branch coverage instrumentation [Bug #16967]
Formerly, branch coverage measurement counters are generated for each
compilation traverse of the AST.  However, ensure clause node is
traversed twice; one is for normal-exit case (the resulted bytecode is
embedded in its outer scope), and the other is for exceptional case (the
resulted bytecode is used in catch table).  Two branch coverage counters
are generated for the two cases, but it is not desired.

This changeset revamps the internal representation of branch coverage
measurement.  Branch coverage counters are generated only at the first
visit of a branch node.  Visiting the same node reuses the
already-generated counter, so double counting is avoided.
2020-06-20 09:28:03 +09:00
Yusuke Endoh bc0aea0804 compile.c: pass NODE* instead of a quadruple of code location 2020-06-20 09:28:03 +09:00
Yusuke Endoh 4b523e79a0 compile.c (branch_coverage_valid_p): Refactored out 2020-06-20 09:28:03 +09:00
Yusuke Endoh 37cd877dbd compile.c: Use functions for building branch coverage instructions
instead of maros.  Just refactoring.
2020-06-20 09:28:03 +09:00
Nobuyoshi Nakada 49f0fd21e4 [Feature #16254] Allow `Primitive.func` style 2020-06-19 18:46:55 +09:00
Nobuyoshi Nakada c8703a17ce [Feature #16254] Allow `__builtin.func` style 2020-06-19 18:46:55 +09:00
Jeremy Evans aae8223c70 Dup splat array in certain cases where there is a block argument
This makes:

```ruby
  args = [1, 2, -> {}]; foo(*args, &args.pop)
```

call `foo` with 1, 2, and the lambda, in addition to passing the
lambda as a block.  This is different from the previous behavior,
which passed the lambda as a block but not as a regular argument,
which goes against the expected left-to-right evaluation order.

This is how Ruby already compiled arguments if using leading
arguments, trailing arguments, or keywords in the same call.

This works by disabling the optimization that skipped duplicating
the array during the splat (splatarray instruction argument
switches from false to true).  In the above example, the splat
call duplicates the array.  I've tested and cases where a
local variable or symbol are used do not duplicate the array,
so I don't expect this to decrease the performance of most Ruby
programs.  However, programs such as:

```ruby
  foo(*args, &bar)
```

could see a decrease in performance, if `bar` is a method call
and not a local variable.

This is not a perfect solution, there are ways to get around
this:

```ruby
  args = Struct.new(:a).new([:x, :y])
  def args.to_a; a; end
  def args.to_proc; a.pop; ->{}; end
  foo(*args, &args)
  # calls foo with 1 argument (:x)
  # not 2 arguments (:x and :y)
```

A perfect solution would require completely disabling the
optimization.

Fixes [Bug #16504]
Fixes [Bug #16500]
2020-06-18 08:19:33 -07:00
Nobuyoshi Nakada ccb7a4b9f2
Replaced accessors of `Struct` with `invokebuiltin` 2020-06-17 08:18:46 +09:00
Nobuyoshi Nakada 318d52e820
Revert "Replaced accessors of `Struct` with `invokebuiltin`"
This reverts commit 19cabe8b09,
which didn't support tool/lib/iseq_loader_checker.rb.
2020-06-16 18:44:58 +09:00
Nobuyoshi Nakada 19cabe8b09
Replaced accessors of `Struct` with `invokebuiltin` 2020-06-16 18:24:02 +09:00
Kazuki Tsujimoto ddded1157a
Introduce find pattern [Feature #16828] 2020-06-14 09:24:36 +09:00
Jeremy Evans 0ba27259d3 Fix crashes in the peephole optimizer on OpenBSD/sparc64
These crashes are due to alignment issues, casting ADJUST to INSN
and then accessing after the end of the ADJUST.  These patches
come from Stefan Sperling <stsp@apache.org>, who reported the
issue.
2020-06-08 11:11:27 -07:00
Nobuyoshi Nakada 6dcd10ce56
compile.c: Mark cursor in debug list 2020-05-31 03:07:30 +09:00
Nobuyoshi Nakada 2c711273bb
compile.c: Removed wrong conversion 2020-05-31 03:05:10 +09:00
Nobuyoshi Nakada 57fd44d374
Adjusted an indent 2020-05-30 21:20:50 +09:00
Koichi Sasada 03d7f3cdb2 add indent for debug disasm output 2020-05-29 11:25:45 +09:00
Nobuyoshi Nakada 79d9528ddc
Fixed potential memory leak
Create a wrapper object first, then buffer allocation which can
fail.
2020-05-22 06:50:29 +09:00
Aaron Patterson 891e253ee7
Use a pinning list for keeping objects alive during assembly.
The GC will not disassemble incomplete instruction sequences.  So it is
important that when instructions are being assembled, any objects the
instructions point at should not be moved.

This patch implements a fixed width array that pins its references.
When the instructions are done being assembled, the pinning array goes
away and the objects inside the iseqs are allowed to move.
2020-05-20 11:16:21 -07:00
Nobuyoshi Nakada c0cd474d4f
Prefer dedicated enum over int 2020-05-18 12:42:33 +09:00
Nobuyoshi Nakada b02c10b240
built-in method call must not have a receiver 2020-05-18 12:28:50 +09:00
卜部昌平 233c2018f1 drop varargs.h support
This header file is simply out of date (for decades since at least
1989).  It's the 21st century.  Just stop using it.
2020-05-11 14:56:51 +09:00
卜部昌平 9e41a75255 sed -i 's|ruby/impl|ruby/internal|'
To fix build failures.
2020-05-11 09:24:08 +09:00
卜部昌平 d7f4d732c1 sed -i s|ruby/3|ruby/impl|g
This shall fix compile errors.
2020-05-11 09:24:08 +09:00
Nobuyoshi Nakada 5d430c1b34
Added more NORETURN declarations 2020-05-11 00:40:14 +09:00
Kazuki Tsujimoto d6389224da
Fix pseudo code for NODE_ARYPTN, NODE_HSHPTN
Due to the change in 3893a8dd42,
there is no longer a need to put true/false.
2020-05-04 13:27:25 +09:00
Nobuyoshi Nakada 69b3e0ac59 Create succ_index_table as a part of `iseq_setup`
With compiling `CPDEBUG >= 2`, `rb_iseq_disasm` segfaults if this
table has not been created.  Also `ibf_load_iseq_each` calls
`rb_iseq_insns_info_encode_positions`.
2020-04-15 16:06:48 +09:00
Nobuyoshi Nakada 2c12d111cb
Disassemble nop-inserted list 2020-04-15 12:34:40 +09:00
Nobuyoshi Nakada de2afcbf0c
Show heading for update_catch_except_flags 2020-04-15 12:28:31 +09:00
Alan Wu 82fdffc5ec
Avoid UB with flexible array member
Accessing past the end of an array is technically UB. Use C99 flexible
array member instead to avoid the UB and simplify allocation size
calculation.

See also: DCL38-C in the SEI CERT C Coding Standard
2020-04-12 15:19:06 -04:00
Nobuyoshi Nakada e474c189da
Suppress -Wswitch warnings 2020-04-08 15:13:37 +09:00
卜部昌平 9e6e39c351
Merge pull request #2991 from shyouhei/ruby.h
Split ruby.h
2020-04-08 13:28:13 +09:00
Jeremy Evans d2c41b1bff Reduce allocations for keyword argument hashes
Previously, passing a keyword splat to a method always allocated
a hash on the caller side, and accepting arbitrary keywords in
a method allocated a separate hash on the callee side.  Passing
explicit keywords to a method that accepted a keyword splat
did not allocate a hash on the caller side, but resulted in two
hashes allocated on the callee side.

This commit makes passing a single keyword splat to a method not
allocate a hash on the caller side.  Passing multiple keyword
splats or a mix of explicit keywords and a keyword splat still
generates a hash on the caller side.  On the callee side,
if arbitrary keywords are not accepted, it does not allocate a
hash.  If arbitrary keywords are accepted, it will allocate a
hash, but this commit uses a callinfo flag to indicate whether
the caller already allocated a hash, and if so, the callee can
use the passed hash without duplicating it.  So this commit
should make it so that a maximum of a single hash is allocated
during method calls.

To set the callinfo flag appropriately, method call argument
compilation checks if only a single keyword splat is given.
If only one keyword splat is given, the VM_CALL_KW_SPLAT_MUT
callinfo flag is not set, since in that case the keyword
splat is passed directly and not mutable.  If more than one
splat is used, a new hash needs to be generated on the caller
side, and in that case the callinfo flag is set, indicating
the keyword splat is mutable by the callee.

In compile_hash, used for both hash and keyword argument
compilation, if compiling keyword arguments and only a
single keyword splat is used, pass the argument directly.

On the caller side, in vm_args.c, the callinfo flag needs to
be recognized and handled.  Because the keyword splat
argument may not be a hash, it needs to be converted to a
hash first if not.  Then, unless the callinfo flag is set,
the hash needs to be duplicated.  The temporary copy of the
callinfo flag, kw_flag, is updated if a hash was duplicated,
to prevent the need to duplicate it again.  If we are
converting to a hash or duplicating a hash, we need to update
the argument array, which can including duplicating the
positional splat array if one was passed.  CALLER_SETUP_ARG
and a couple other places needs to be modified to handle
similar issues for other types of calls.

This includes fairly comprehensive tests for different ways
keywords are handled internally, checking that you get equal
results but that keyword splats on the caller side result in
distinct objects for keyword rest parameters.

Included are benchmarks for keyword argument calls.
Brief results when compiled without optimization:

  def kw(a: 1) a end
  def kws(**kw) kw end
  h = {a: 1}

  kw(a: 1)       # about same
  kw(**h)        # 2.37x faster
  kws(a: 1)      # 1.30x faster
  kws(**h)       # 2.19x faster
  kw(a: 1, **h)  # 1.03x slower
  kw(**h, **h)   # about same
  kws(a: 1, **h) # 1.16x faster
  kws(**h, **h)  # 1.14x faster
2020-03-17 12:09:43 -07:00
Jeremy Evans ac04b778c1 Make {**{}} return unfrozen empty hash
Previously, method call keyword splats and hash keyword splats
were compiled exactly the same.  This is because parse-wise, they
operate on indentical nodes when it comes to compiling the **{}.

Fix this by using an ugly hack of temporarily modifying the
nd_brace flag in the method call keyword splat case.  Inside
compile_hash, only optimize the **{} case for hashes where the
nd_brace flag has been modified to reflect we are in the method
call keyword splat case and it is safe to do so.

Since compile_keyword_args is only called in one place, move the
keyword_node_p call out of that method to the single caller to
avoid duplicating the code.
2020-03-17 12:09:43 -07:00
Jeremy Evans 00dc8c0246 Correctly detect whether strict alignment is needed on OpenBSD
From Stefan Sperling <stsp@apache.org>
2020-03-12 15:45:03 -07:00
Koichi Sasada 31748e69c8 CI can be NULL.
Unused CI (introduced from peephole optimization, etc) can be NULL
so introduce NULL check.
2020-02-22 10:27:44 +09:00
Koichi Sasada b9007b6c54 Introduce disposable call-cache.
This patch contains several ideas:

(1) Disposable inline method cache (IMC) for race-free inline method cache
    * Making call-cache (CC) as a RVALUE (GC target object) and allocate new
      CC on cache miss.
    * This technique allows race-free access from parallel processing
      elements like RCU.
(2) Introduce per-Class method cache (pCMC)
    * Instead of fixed-size global method cache (GMC), pCMC allows flexible
      cache size.
    * Caching CCs reduces CC allocation and allow sharing CC's fast-path
      between same call-info (CI) call-sites.
(3) Invalidate an inline method cache by invalidating corresponding method
    entries (MEs)
    * Instead of using class serials, we set "invalidated" flag for method
      entry itself to represent cache invalidation.
    * Compare with using class serials, the impact of method modification
      (add/overwrite/delete) is small.
    * Updating class serials invalidate all method caches of the class and
      sub-classes.
    * Proposed approach only invalidate the method cache of only one ME.

See [Feature #16614] for more details.
2020-02-22 09:58:59 +09:00
Koichi Sasada f2286925f0 VALUE size packed callinfo (ci).
Now, rb_call_info contains how to call the method with tuple of
(mid, orig_argc, flags, kwarg). Most of cases, kwarg == NULL and
mid+argc+flags only requires 64bits. So this patch packed
rb_call_info to VALUE (1 word) on such cases. If we can not
represent it in VALUE, then use imemo_callinfo which contains
conventional callinfo (rb_callinfo, renamed from rb_call_info).

iseq->body->ci_kw_size is removed because all of callinfo is VALUE
size (packed ci or a pointer to imemo_callinfo).

To access ci information, we need to use these functions:
vm_ci_mid(ci), _flag(ci), _argc(ci), _kwarg(ci).

struct rb_call_info_kw_arg is renamed to rb_callinfo_kwarg.

rb_funcallv_with_cc() and rb_method_basic_definition_p_with_cc()
is temporary removed because cd->ci should be marked.
2020-02-22 09:58:59 +09:00
Nobuyoshi Nakada 56d33b3ea8
Fixed missing `return`
Get rid of double writing.
2020-02-20 13:39:27 +09:00
卜部昌平 7aa3f1fe69 printf can be a macro
Namely glibc has this macro on -DFORTIFY_SOURCE.  We have to prevent
macro redefinition with different macro body.
2020-02-20 11:46:54 +09:00
Nobuyoshi Nakada 0bfa479c52
Split the optimizable range item conditions 2020-02-16 13:47:18 +09:00
Masataka Pocke Kuwabara 5278294230 Reduce begin-less/end-less range allocation
```
$ cat test.yaml
prelude: |
    def endless
      1..
    end

    def beginless
      ..1
    end

    def endless_substr(str)
      str[1..]
    end

benchmark:
    endless: endless
    beginless: beginless
    endless_substr: "endless_substr('foo')"

$ RBENV_VERSION=trunk ruby -v
ruby 2.8.0dev (2020-02-15T12:52:03Z master 961630126b) [x86_64-linux]
$ RBENV_VERSION=patched ruby -v
ruby 2.8.0dev (2020-02-15T12:52:03Z origin/master 961630126b) [x86_64-linux]

$ benchmark-driver test.yaml --rbenv 'patched;trunk'
Warming up --------------------------------------
             endless    45.948M i/s -     46.076M times in 1.002782s (21.76ns/i, 26clocks/i)
           beginless    49.986M i/s -     50.237M times in 1.005037s (20.01ns/i, 24clocks/i)
      endless_substr     8.067M i/s -      8.187M times in 1.014936s (123.96ns/i, 148clocks/i)
Calculating -------------------------------------
                        patched       trunk
             endless   115.679M     21.500M i/s -    137.843M times in 1.191597s 6.411398s
           beginless   112.599M     22.060M i/s -    149.957M times in 1.331778s 6.797768s
      endless_substr     8.888M      6.760M i/s -     24.201M times in 2.722995s 3.580038s

Comparison:
                          endless
             patched: 115679391.9 i/s
               trunk:  21499711.2 i/s - 5.38x  slower

                        beginless
             patched: 112598731.5 i/s
               trunk:  22059673.0 i/s - 5.10x  slower

                   endless_substr
             patched:   8887513.1 i/s
               trunk:   6759886.2 i/s - 1.31x  slower
```
2020-02-16 02:37:12 +09:00
Jeremy Evans 7a288df7b8 Make yield in singleton class definitions in methods a SyntaxError
This behavior was deprecated in 2.7 and scheduled to be removed
in 3.0.

Calling yield in a class definition outside a method is now a
SyntaxError instead of a LocalJumpError, as well.
2020-02-11 12:44:23 -08:00
NagayamaRyoga a2845adb49 compile.c: Drop obj_list from ibf_dump
[Feature #16505]
2020-02-09 11:33:38 -05:00