Commit graph

1067 commits

Author SHA1 Message Date
Jeremy Evans
4b14b2902a Uncomment code to raise LocalJumpError for yield across thread through enum
Not sure if this is the correct fix.  It does raise LocalJumpError in
the yielding thread as you would expect, but the value yielded to the calling
thread is still yielded without an exception.

Fixes [Bug #18649]
2022-04-21 20:48:27 -07:00
Jeremy Evans
0b091fdac6
Raise RuntimeError if Kernel#binding is called from a non-Ruby frame
Check whether the current or previous frame is a Ruby frame in
call_trace_func and rb_tracearg_binding before attempting to
create a binding for the frame.

Fixes [Bug #18487]

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2022-04-06 19:14:03 -07:00
Kevin Newton
8ee4a82e8c
RubyVM.stat constant cache metrics (#5766)
Before the new constant cache behavior, caches were invalidated by a
single global variable. You could inspect the value of this variable
with RubyVM.stat(:global_constant_state). This was mostly useful to
verify the behavior of the VM or to test constant loading like in Rails.

With the new constant cache behavior, we introduced
RubyVM.stat(:constant_cache) which returned a hash with symbol keys and
integer values that represented the number of live constant caches
associated with the given symbol. Additionally, we removed the old
RubyVM.stat(:global_constant_state).

This was proven to be not very useful, so it doesn't help you diagnose
constant loading issues. So, instead we added the global constant state
back into the RubyVM output. However, that number can be misleading as
now when you invalidate something like `Foo::Bar::Baz` you're actually
invalidating 3 different lists of inline caches.

This commit attempts to get the best of both worlds. We remove
RubyVM.stat(:global_constant_state) like we did originally, as it
doesn't have the same semantic meaning and it could be confusing going
forward. Instead we add RubyVM.stat(:constant_cache_invalidations) and
RubyVM.stat(:constant_cache_misses). These two metrics should provide
enough information to diagnose any constant loading issues, as well as
provide a replacement for the old global constant state.
2022-04-05 16:37:00 -04:00
Kevin Newton
42000664be Bring back RubyVM.stat(:global_constant_state)
This was removed as part of [Feature #18589]. But some applications were relying on this behavior. So bringing this back to make it better for backward compatibility going forward.
2022-04-04 20:41:05 +02:00
Kevin Newton
6068da8937 Finer-grained constant cache invalidation (take 2)
This commit reintroduces finer-grained constant cache invalidation.
After 8008fb7 got merged, it was causing issues on token-threaded
builds (such as on Windows).

The issue was that when you're iterating through instruction sequences
and using the translator functions to get back the instruction structs,
you're either using `rb_vm_insn_null_translator` or
`rb_vm_insn_addr2insn2` depending if it's a direct-threading build.
`rb_vm_insn_addr2insn2` does some normalization to always return to
you the non-trace version of whatever instruction you're looking at.
`rb_vm_insn_null_translator` does not do that normalization.

This means that when you're looping through the instructions if you're
trying to do an opcode comparison, it can change depending on the type
of threading that you're using. This can be very confusing. So, this
commit creates a new translator function
`rb_vm_insn_normalizing_translator` to always return the non-trace
version so that opcode comparisons don't have to worry about different
configurations.

[Feature #18589]
2022-04-01 14:48:22 -04:00
Jeremy Evans
d1d48cb690 Revert "Raise RuntimeError if Kernel#binding is called from a non-Ruby frame"
This reverts commit 343ea9967e.

This causes an assertion failure with -DRUBY_DEBUG=1 -DRGENGC_CHECK_MODE=2
2022-04-01 07:22:49 -07:00
Nobuyoshi Nakada
42a0bed351
Prefix ccan headers (#4568)
* Prefixed ccan headers

* Remove unprefixed names in ccan/build_assert

* Remove unprefixed names in ccan/check_type

* Remove unprefixed names in ccan/container_of

* Remove unprefixed names in ccan/list

Co-authored-by: Samuel Williams <samuel.williams@oriontransfer.co.nz>
2022-03-30 20:36:31 +13:00
Nobuyoshi Nakada
69967ee64e
Revert "Finer-grained inline constant cache invalidation"
This reverts commits for [Feature #18589]:
* 8008fb7352
  "Update formatting per feedback"
* 8f6eaca2e1
  "Delete ID from constant cache table if it becomes empty on ISEQ free"
* 629908586b
  "Finer-grained inline constant cache invalidation"

MSWin builds on AppVeyor have been crashing since the merger.
2022-03-25 20:29:09 +09:00
Jeremy Evans
343ea9967e Raise RuntimeError if Kernel#binding is called from a non-Ruby frame
Check whether the current or previous frame is a Ruby frame in
call_trace_func before attempting to create a binding for the frame.

Fixes [Bug #18487]

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2022-03-24 12:31:07 -07:00
Kevin Newton
629908586b Finer-grained inline constant cache invalidation
Current behavior - caches depend on a global counter. All constant mutations cause caches to be invalidated.

```ruby
class A
  B = 1
end

def foo
  A::B # inline cache depends on global counter
end

foo # populate inline cache
foo # hit inline cache

C = 1 # global counter increments, all caches are invalidated

foo # misses inline cache due to `C = 1`
```

Proposed behavior - caches depend on name components. Only constant mutations with corresponding names will invalidate the cache.

```ruby
class A
  B = 1
end

def foo
  A::B # inline cache depends constants named "A" and "B"
end

foo # populate inline cache
foo # hit inline cache

C = 1 # caches that depend on the name "C" are invalidated

foo # hits inline cache because IC only depends on "A" and "B"
```

Examples of breaking the new cache:

```ruby
module C
  # Breaks `foo` cache because "A" constant is set and the cache in foo depends
  # on "A" and "B"
  class A; end
end

B = 1
```

We expect the new cache scheme to be invalidated less often because names aren't frequently reused. With the cache being invalidated less, we can rely on its stability more to keep our constant references fast and reduce the need to throw away generated code in YJIT.
2022-03-24 09:14:38 -07:00
Peter Zhu
5f10bd634f Add ISEQ_BODY macro
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.
2022-03-24 10:03:51 -04:00
Yuta Saito
dff70b50d0 [wasm] vm.c: stop unwinding to main for every vm_exec call by setjmp
the original rb_wasm_setjmp implementation always unwinds to the root
call frame to have setjmp compatible interface, and simulate sjlj's
undefined behavior. Therefore, every vm_exec call unwinds to main, and
a deep call stack makes setjmp call very expensive. The following
snippet from optcarrot takes 5s even though it takes less than 0.3s on
native.

```
[0x0, 0x4, 0x8, 0xc].map do |attr|
  (0..7).map do |j|
    (0...0x10000).map do |i|
      clr = i[15 - j] * 2 + i[7 - j]
      clr != 0 ? attr | clr : 0
    end
  end
end
```

This patch adds a WASI specialized vm_exec which uses lightweight
try-catch API without unwinding to the root frame. After this patch, the
above snippet takes only 0.5s.
2022-02-18 18:28:18 +09:00
Kazuhiro NISHIYAMA
c00e360bc0
Fix error: old-style function definition
20220122T050018Z.log.html.gz#miniruby
```
compiling vm_trace.c
vm_trace.c: In function 'rb_vm_memsize_postponed_job_buffer':
vm_trace.c:1599:1: error: old-style function definition [-Werror=old-style-definition]
 1599 | rb_vm_memsize_postponed_job_buffer()
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
2022-01-22 15:48:05 +09:00
Kevin Newton
fc6fd4c31e Accurately report VM memsize
Currently the calculation only counts the size of the struct. This commit adds the size of the associated st tables, id tables, and linked lists.

Still missing is the size of the ractors and (potentially) the size of the object space.
2022-01-21 14:34:53 -08:00
Koichi Sasada
7e21b77dc6 T#dup (T < Proc) should return T's object
T#dup (T < Proc) returns Proc object (not T) from Ruby 1.9.
[Bug #17545]
2022-01-13 17:43:14 +09:00
Sutou Kouhei
c9396a3520 Show the target Proc on Ractor::IsolationError
It's useful for debug.
2021-12-22 11:10:20 +09:00
Koichi Sasada
ad450c9fe5 make overloaded_cme_table truly weak key map
`overloaded_cme_table` keeps cme -> monly_cme pairs to manage
corresponding `monly_cme` for `cme`. The lifetime of the `monly_cme`
should be longer than `monly_cme`, but the previous patch losts the
reference to the living `monly_cme`.

Now `overloaded_cme_table` values are always root (keys are only weak
reference), it means `monly_cme` does not freed until corresponding
`cme` is invalidated.

To make managing easy, move `overloaded_cme_table` to `rb_vm_t`.
2021-12-21 15:21:30 +09:00
Takashi Kokubun
02ba0bda7e
Remove RubyVM::JIT (#5275)
[Feature #18349] reverts [Feature #17490]
2021-12-15 20:02:30 -08:00
John Hawthorn
e307627b6c Don't invalidate BOPs when aliases redefined
Previously when redefining an alias of a BOP, we would unnecessarily
invalidate the bop. For example:

    class String
      alias len length
      private :len
    end

This commit avoids this by checking that the called_id on the method
entry matches the original_id on the definition.
2021-12-14 15:22:51 -08:00
John Hawthorn
b7ae08992f YJIT: Avoid unnecessary BOP invalidation
Previously we would invalidate BOPs in YJIT when the method registered
as a BOP was redefined on a subclass.
2021-12-14 15:22:51 -08:00
Takashi Kokubun
1a63468831
Prepare for removing RubyVM::JIT (#5262) 2021-12-13 23:07:46 -08:00
Koichi Sasada
cce331272b Ractor.make_shareable checks proc's sefl
`Ractor.make_shareable(proc_obj)` raises an `IsolationError`
if the self of `proc_obj` is not a shareable object.

[Bug #18243]
2021-12-09 16:20:04 +09:00
John Hawthorn
733500e9d0
Lazily create singletons on instance_{exec,eval} (#5146)
* Lazily create singletons on instance_{exec,eval}

Previously when instance_exec or instance_eval was called on an object,
that object would be given a singleton class so that method
definitions inside the block would be added to the object rather than
its class.

This commit aims to improve performance by delaying the creation of the
singleton class unless/until one is needed for method definition. Most
of the time instance_eval is used without any method definition.

This was implemented by adding a flag to the cref indicating that it
represents a singleton of the object rather than a class itself. In this
case CREF_CLASS returns the object's existing class, but in cases that
we are defining a method (either via definemethod or
VM_SPECIAL_OBJECT_CBASE which is used for undef and alias).

This also happens to fix what I believe is a bug. Previously
instance_eval behaved differently with regards to constant access for
true/false/nil than for all other objects. I don't think this was
intentional.

    String::Foo = "foo"
    "".instance_eval("Foo")   # => "foo"
    Integer::Foo = "foo"
    123.instance_eval("Foo")  # => "foo"
    TrueClass::Foo = "foo"
    true.instance_eval("Foo") # NameError: uninitialized constant Foo

This also slightly changes the error message when trying to define a method
through instance_eval on an object which can't have a singleton class.

Before:

    $ ruby -e '123.instance_eval { def foo; end }'
    -e:1:in `block in <main>': no class/module to add method (TypeError)

After:

    $ ./ruby -e '123.instance_eval { def foo; end }'
    -e:1:in `block in <main>': can't define singleton (TypeError)

IMO this error is a small improvement on the original and better matches
the (both old and new) message when definging a method using `def self.`

    $ ruby -e '123.instance_eval{ def self.foo; end }'
    -e:1:in `block in <main>': can't define singleton (TypeError)

Co-authored-by: Matthew Draper <matthew@trebex.net>

* Remove "under" argument from yield_under

* Move CREF_SINGLETON_SET into vm_cref_new

* Simplify vm_get_const_base

* Fix leaf VM_SPECIAL_OBJECT_CONST_BASE

Co-authored-by: Matthew Draper <matthew@trebex.net>
2021-12-02 15:53:39 -08:00
Alan Wu
9121e57a5f Rework tracing for blocks running as methods
The main impetus for this change is to fix [Bug #13392]. Previously, we
fired the "return" TracePoint event after popping the stack frame for
the block running as method (BMETHOD). This gave undesirable source
location outputs as the return event normally fires right before the
frame going away.

The iseq for each block can run both as a block and as a method. To
accommodate that, this commit makes vm_trace() fire call/return events for
instructions that have b_call/b_return events attached when the iseq is
running as a BMETHOD. The logic for rewriting to "trace_*" instruction
is tweaked so that when the user listens to call/return events,
instructions with b_call/b_return become trace variants.

To continue to provide the return value for non-local returns done using
the "return" or "break" keyword inside BMETHODs, the stack unwinding
code is tweaked. b_return events now provide the same return value as
return events for these non-local cases. A pre-existing test deemed not
providing a return value for these b_return events as a limitation.

This commit removes the checks for call/return TracePoint events that
happen when calling into BMETHODs when no TracePoints are active.
Technically, migrating just the return event is enough to fix the bug,
but migrating both call and return removes our reliance on
`VM_FRAME_FLAG_FINISH` and re-entering the interpreter when the caller
is already in the interpreter.
2021-12-01 17:42:33 -05:00
Yusuke Endoh
feda058531 Refactor hacky ID tables to struct rb_ast_id_table_t
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.
2021-11-21 08:59:24 +09:00
Koichi Sasada
be71c95b88 rb_method_optimized_t for further extension
Now `rb_method_optimized_t optimized` field is added to represent
optimized method type.
2021-11-19 08:32:39 +09:00
Koichi Sasada
b2255153cf vm_empty_cc_for_super
Same as `vm_empty_cc`, introduce a global variable which has
`.call_ = vm_call_super_method`. Use it if the `cme == NULL` on
`vm_search_super_method`.
2021-11-17 22:21:42 +09:00
Nobuyoshi Nakada
833c69ee82
Convert IDs to Integers
As the ID serial is 32bit value and internal IDs created in the
parser are assigned from its maximum value, Symbol converted from
it will exceed 32bit and overflow on 32bit platforms.
2021-11-08 15:14:34 +09:00
Nobuyoshi Nakada
ec657f44dc Refine the error message for hidden variables 2021-11-07 12:40:27 +09:00
Nobuyoshi Nakada
5e52fd4bd1
Preserve the encoding of message from outer local variable
In the case of read-only but refering an unshareable object.
2021-10-29 21:40:11 +09:00
Nobuyoshi Nakada
ec2e04c90d Preserve the encoding of message from outer local variables 2021-10-29 18:53:57 +09:00
Yusuke Endoh
86e3d77abb
Make Coverage suspendable (#4856)
* Make Coverage suspendable

Add `Coverage.suspend`, `Coverage.resume` and some methods.

[Feature #18176] [ruby-core:105321]
2021-10-25 20:00:51 +09:00
Nobuyoshi Nakada
7459a32af3 suppress warnings for probable NULL dererefences 2021-10-24 19:24:50 +09:00
Nobuyoshi Nakada
e5c2bf55d0 Suppress sign-compare warning 2021-10-24 19:24:50 +09:00
Shugo Maeda
6606597109
Deprecate include/prepend in refinements and add Refinement#import_methods instead
Refinement#import_methods imports methods from modules.
Unlike Module#include, it copies methods and adds them into the refinement,
so the refinement is activated in the imported methods.

[Bug #17429] [ruby-core:101639]
2021-10-21 16:31:54 +09:00
Koichi Sasada
c7550537f1 RubyVM.keep_script_lines
`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
```
2021-10-21 16:17:39 +09:00
Alan Wu
454fbe1046 Expand tabs 2021-10-20 18:19:43 -04:00
Alan Wu
7c08538aa3 Cleanup diff against upstream. Add comments
I did a `git diff --stat` against upstream and looked at all the files
that are outside of YJIT to come up with these minor changes.
2021-10-20 18:19:42 -04:00
Noah Gibbs
be06112d48 Fix changes from rebase 2021-10-20 18:19:42 -04:00
Alan Wu
4b58d698b1 Count interpreter instructions when -DYJIT_STATS=1
The interpreter instruction count was enabled based on RUBY_DEBUG as
opposed to YJIT_STATS. In builds with YJIT_STATS=1 but RUBY_DEBUG=0,
the count was not available.

Move YJIT_STATS in yjit.h where declarations are expoed to code outside
of YJIT. Also reduce the changes made to the interpreter for calling
into YJIT's instruction counting function.
2021-10-20 18:19:40 -04:00
Jose Narvaez
4e2eb7695e Yet Another Ruby JIT!
Renaming uJIT to YJIT. AKA s/ujit/yjit/g.
2021-10-20 18:19:31 -04:00
Maxime Chevalier-Boisvert
9d8cc01b75 WIP JIT-to-JIT returns 2021-10-20 18:19:28 -04:00
Aaron Patterson
9453267689 add bop to redefinition callback 2021-10-20 18:19:28 -04:00
Aaron Patterson
863ff14997 Add a callback in to microjit when a BOP is redefined
This commit adds a callback `rb_ujit_bop_redefined` when a basic
operation is redefined.
2021-10-20 18:19:28 -04:00
Alan Wu
b7f93e81df Implement --ujit-stats and instructoin counting
VM and ujit instruction counting in debug builds.

shopify/ruby#19
2021-10-20 18:19:27 -04:00
Nobuyoshi Nakada
1b35808a13
Moved the common code 2021-10-13 13:00:57 +09:00
Nobuyoshi Nakada
d0268c5ec2
Collect symbols instead of strings and get rid of rb_str_intern 2021-10-08 11:01:51 +09:00
Alan Wu
7622819147
Fix Ractor.make_shareable changing locals for Procs
env_copy() uses rb_ary_delete_at() with a loop counting up while
iterating through the list of read only locals. rb_ary_delete_at() can
shift elements in the array to an index lesser than the loop index,
causing locals to be missed and set to Qfalse in the returned
environment.

Iterate through the locals in reverse instead, this way the shifting
never happens for locals that are yet to be visited and we process all
the locals in the array.

[Bug #18023]
2021-10-06 15:38:33 -04:00
S.H
dc9112cf10
Using NIL_P macro instead of == Qnil 2021-10-03 22:34:45 +09:00
Jeremy Evans
79a4484a07 Do not load file with same realpath twice when requiring
This fixes issues with paths being loaded twice in certain cases
when symlinks are used.

It took me multiple attempts to get this working.  My original
attempt tried to convert paths to realpaths before adding them
to $LOADED_FEATURES.  Unfortunately, this doesn't work well
with the loaded feature index, which is based off load paths
and not realpaths. While I was able to get require working, I'm
fairly sure the loaded feature index was not being used as
expected, which would have significant performance implications.
Additionally, I was never able to get that approach working with
autoload when autoloading a non-realpath file. It also broke
some specs.

This takes a more conservative approach. Directly before loading the
file, if the file with the same realpath has been required, the
loading of the file is skipped. The realpaths are stored as
fstrings in a hidden hash.

When rebuilding the loaded feature index, the hash of realpaths
is also rebuilt.  I'm guessing this makes rebuilding process
slower, but I don think that is a hot path. In general, modifying
loaded features is only done when reloading, and that tends to be
in non-production environments.

Change test_require_with_loaded_features_pop test to use 30 threads
and 300 iterations, instead of 4 threads and 1000 iterations.
I saw only sporadic failures with 4/1000, but consistent failures
30/300 threads. These failures were due to the fact that the
concurrent deletions from $LOADED_FEATURES in other threads can
result in rb_ary_entry returning nil when rebuilding the loaded
features index.

To avoid concurrency issues when rebuilding the loaded features
index, the building of the index itself is left alone, and
afterwards, a separate loop is done on a copy of the loaded feature
snapshot in order to rebuild the realpaths hash.

Fixes [Bug #17885]
2021-10-02 05:51:29 -09:00