Age | Commit message (Collapse) | Author |
|
When transitioning generic instance variable objects to too complex, we
set the shape first before performing inserting the new gen_ivtbl. The
st_insert for the new gen_ivtbl could allocate and cause a GC. If that
happens, then it will crash because the object will have a too complex
shape but not yet be backed by a st_table.
This commit changes the order so that the insert happens first before
the new shape is set.
The following script reproduces the issue:
```
o = []
o.instance_variable_set(:@a, 1)
i = 0
o = Object.new
while RubyVM::Shape.shapes_available > 0
o.instance_variable_set(:"@i#{i}", 1)
i += 1
end
ary = 1_000.times.map { [] }
GC.stress = true
ary.each do |o|
o.instance_variable_set(:@a, 1)
o.instance_variable_set(:@b, 1)
end
```
|
|
|
|
|
|
That function is a bit too low level to called from multiple
places. It's always used in tandem with `rb_shape_set_too_complex`
and both have to know how the object is laid out to update the
`iv_ptr`.
So instead we can provide two higher level function:
- `rb_obj_copy_ivs_to_hash_table` to prepare a `st_table` from an
arbitrary oject.
- `rb_obj_convert_to_too_complex` to assign the new `st_table`
to the old object, and safely free the old `iv_ptr`.
Unfortunately both can't be combined into one, because `rb_obj_copy_ivar`
need `rb_obj_copy_ivs_to_hash_table` to copy from one object
to another.
|
|
It's only used to allocate the table with the right size,
but in some case we were passing `rb_shape_get_shape_by_id(SHAPE_OBJ_TOO_COMPLEX)`
which `next_iv_index` is a bit undefined.
So overall we're better to just allocate a table the size of the existing
object, it should be close enough in the vast majority of cases,
and that's already a de-optimizaton path anyway.
|
|
This reverts commit 5f3fb4f4e397735783743fe52a7899b614bece20.
|
|
|
|
This reverts commit f6910a61122931e4193bcc0fad18d839c319b720.
We're seeing crashes in the test suite of Shopify's core monolith after
this change.
|
|
We don't need to create a shape to transition capacity as we can
transition the capacity when the capacity of the SHAPE_IVAR changes.
|
|
Right now the `rb_shape_get_next` shape caller need to
first check if there is capacity left, and if not call
`rb_shape_transition_shape_capa` before it can call `rb_shape_get_next`.
And on each of these it needs to checks if we got a TOO_COMPLEX
back.
All this logic is duplicated in the interpreter, YJIT and RJIT.
Instead we can have `rb_shape_get_next` do the capacity transition
when needed. The caller can compare the old and new shapes capacity
to know if resizing is needed. It also can check for TOO_COMPLEX
only once.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This commit changes generic ivars to respect the capacity transition in
shapes rather than growing the capacity independently.
|
|
It was assuming only objects can be complex.
|
|
This commit changes class ivars to respect the capacity transition in
shapes rather than growing the capacity independently.
|
|
This commit makes every initial size pool shape a root shape and assigns
it a capacity of 0.
|
|
|
|
There is a duplicated check for the object is too complex.
|
|
|
|
|
|
|
|
`remove_shape_recursive` wasn't considering that if we run out of
shapes, it might have to transition to SHAPE_TOO_COMPLEX.
When this happens, we now return with an error and the caller
initiates the evacuation.
|
|
|
|
|
|
|
|
On 32-bit systems, we must store the shape ID in the gen_ivtbl to not
lose the shape. If we directly store the ST table into the generic
ivar table, then we lose the shape. This makes it impossible to
determine the shape of the object and whether it is too complex or not.
|
|
|
|
We weren't taking in to account that objects with generic IV tables
could go "too complex" in the IV set code. This commit takes that in to
account and also ensures FL_EXIVAR is set when a geniv object
transitions to "too complex"
Co-Authored-By: Jean Boussier <[email protected]>
|
|
|
|
If it runs out of shapes, or new variations aren't allowed, it will
return "too complex"
|
|
|
|
|
|
This way the groth factor is encapsulated, which allows
rb_shape_transition_shape_capa to be smarter about ideal sizes.
|
|
We don't really need obj_ivar_heap_alloc and obj_ivar_heap_realloc since
they're just one liners.
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/7942
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/8035
|
|
Co-authored-by: Nobuyoshi Nakada <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/8035
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/7983
|
|
http://ci.rvm.jp/results/trunk-random1@ruby-sp2-docker/4612360
|
|
Introduce `Module#set_temporary_name` for setting identifiers for otherwise
anonymous modules/classes.
Notes:
Merged-By: ioquatix <[email protected]>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/7962
|
|
This reverts commit 10621f7cb9a0c70e568f89cce47a02e878af6778.
This was reverted because the gc integrity build started failing. We
have figured out a fix so I'm reopening the PR.
Original commit message:
Fix cvar caching when class is cloned
The class variable cache that was added in
ruby#4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.
This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.
To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.
This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.
We also added a marking function which was missing.
Fixes [Bug #19379]
Co-authored-by: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/7900
|
|
This reverts commit 77d1b082470790c17c24a2f406b4fec5d522636b.
|
|
The class variable cache that was added in
https://github.com/ruby/ruby/pull/4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.
This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.
To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.
This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.
We also added a marking function which was missing.
Fixes [Bug #19379]
Co-authored-by: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/7265
|