Commit graph

158 commits

Author SHA1 Message Date
Nobuyoshi Nakada
aad9fa2853
Use RB_VM_LOCKING 2025-05-25 15:22:43 +09:00
Jean Boussier
52da5f8bbc Refactor rb_shape_transition_remove_ivar
Move the fields management logic in `rb_ivar_delete`, and keep
shape managment logic in `rb_shape_transition_remove_ivar`.
2025-05-23 17:33:17 +02:00
Jean Boussier
a6435befa7 variable.c: Refactor rb_obj_field_* to take shape_id_t 2025-05-13 10:35:34 +02:00
Jean Boussier
f2e5f6dbb6 Allow T_CLASS and generic types to be too_complex
The intial complex shape implementation never allowed objects
other than T_OBJECT to become too complex, unless we run out of
shapes.

I don't see any reason to prevent that.

Ref: https://github.com/ruby/ruby/pull/6931
2025-05-11 19:35:58 +02:00
Satoshi Tagomori
382645d440 namespace on read 2025-05-11 23:32:50 +09:00
Jean Boussier
3135eddb4e Refactor FIRST_T_OBJECT_SHAPE_ID to not be used outside shape.c 2025-05-09 20:45:48 +02:00
Jean Boussier
ea77250847 Rename RB_OBJ_SHAPE -> rb_obj_shape
As well as `RB_OBJ_SHAPE_ID` -> `rb_obj_shape_id`
and `RSHAPE` is now a simple alias for `rb_shape_lookup`.

I tried to turn all these into `static inline` but I'm having
trouble with `RUBY_EXTERN rb_shape_tree_t *rb_shape_tree_ptr;`
not being exposed as I'd expect.
2025-05-09 10:22:51 +02:00
Jean Boussier
0b81359b3f Stop exposing rb_shape_frozen_shape_p 2025-05-09 10:22:51 +02:00
Jean Boussier
a970d35de2 Get rid of rb_shape_get_parent. 2025-05-09 10:22:51 +02:00
Jean Boussier
5782561fc1 Rename rb_shape_get_shape_id -> RB_OBJ_SHAPE_ID
And `rb_shape_get_shape` -> `RB_OBJ_SHAPE`.
2025-05-09 10:22:51 +02:00
Jean Boussier
a007575497 Remove unused rb_shape_object_id_index 2025-05-09 10:22:51 +02:00
Jean Boussier
c9b08882b7 Refactor rb_shape_get_next to return an ID
Also rename it, and change parameters to be consistent with
other transition functions.
2025-05-09 10:22:51 +02:00
Jean Boussier
e0200cfba0 Refactor rb_shape_transition_shape_remove_ivar to not take a shape pointer
It's more consistent with other transition functions.
2025-05-09 10:22:51 +02:00
Jean Boussier
3f7c0af051 Rename rb_shape_obj_too_complex -> rb_shape_obj_too_complex_p 2025-05-09 10:22:51 +02:00
Jean Boussier
677d075c29 Refactor rb_shape_transition_too_complex to return an ID. 2025-05-09 10:22:51 +02:00
Jean Boussier
f82523f14b Refactor rb_shape_transition_frozen to return a shape_id. 2025-05-09 10:22:51 +02:00
Jean Boussier
334ebba221 Rename rb_shape_get_shape_by_id -> RSHAPE 2025-05-09 10:22:51 +02:00
Jean Boussier
9966de11fb Refactor rb_shape_get_next_iv_shape to take and return ids. 2025-05-09 10:22:51 +02:00
Jean Boussier
e4f97ce387 Refactor rb_shape_depth to take an ID rather than a pointer.
As well as `rb_shape_edges_count` and `rb_shape_memsize`.
2025-05-09 10:22:51 +02:00
Jean Boussier
f8b3fc520f Refactor rb_shape_traverse_from_new_root to not expose rb_shape_t 2025-05-09 10:22:51 +02:00
Jean Boussier
7116b0a7f1 Extract rb_shape_free_all 2025-05-09 10:22:51 +02:00
Jean Boussier
b67711b17a Fix remove_instance_variable on complex objects
Introduced in: https://github.com/ruby/ruby/pull/13159

Now that there is no longer a unique TOO_COMPLEX shape with
no children, checking `shape->type == TOO_COMPLEX` is incorrect.
2025-05-08 21:48:35 +02:00
Jean Boussier
f48e45d1e9 Move object_id in object fields.
And get rid of the `obj_to_id_tbl`

It's no longer needed, the `object_id` is now stored inline
in the object alongside instance variables.

We still need the inverse table in case `_id2ref` is invoked, but
we lazily build it by walking the heap if that happens.

The `object_id` concern is also no longer a GC implementation
concern, but a generic implementation.

Co-Authored-By: Matt Valentine-House <matt@eightbitraptor.com>
2025-05-08 07:58:05 +02:00
Jean Boussier
d34c150547 shape.c: refactor frozen shape to no longer be final
This opens the door to store more informations in shapes, such
as the `object_id` or object address in case it has been observed
and the object has to be moved.
2025-05-08 07:58:05 +02:00
Jean Boussier
6c9b3ac232 Refactor OBJ_TOO_COMPLEX_SHAPE_ID to not be referenced outside shape.h
Also refactor checks for `->type == SHAPE_OBJ_TOO_COMPLEX`.
2025-05-08 07:58:05 +02:00
Jean Boussier
0ea210d1ea Rename ivptr -> fields, next_iv_index -> next_field_index
Ivars will longer be the only thing stored inline
via shapes, so keeping the `iv_index` and `ivptr` names
would be confusing.

Instance variables won't be the only thing stored inline
via shapes, so keeping the `ivptr` name would be confusing.

`field` encompass anything that can be stored in a VALUE array.

Similarly, `gen_ivtbl` becomes `gen_fields_tbl`.
2025-05-08 07:58:05 +02:00
Jean Boussier
53ae558042 Improve style consistency of rb_shape_t * 2025-05-05 14:44:49 +02:00
Jean Boussier
c65991978b get_next_shape_internal: Skip VM lock for single child case
If the shape has only one child, we check it lock-free without
compromising thread safety.

I haven't computed hard data as to how often that it the case,
but we can assume that it's not too rare for shapes to have
a single child that is often requested, typically when freezing
and object.
2025-04-30 23:32:33 +02:00
Jean Boussier
18dac125cb Improve syntax style consistency in shape.c and shape.h
Most of this code use the `type * name` style, while the
overwhemling majority of the rest of ruby use the `type *name`
style.

This is a cosmetic change, but helps with readability.
2025-04-30 08:10:55 +02:00
Nobuyoshi Nakada
13e6fe9bbc
[DOC] Hide RubyVM::Shape that is for debug from RDoc totally 2024-12-24 21:31:52 +09:00
Kunshan Wang
8ae7c22972 Annotate anonymous mmap
Use PR_SET_VMA_ANON_NAME to set human-readable names for anonymous
virtual memory areas mapped by `mmap()` when compiled and run on Linux
5.17 or higher.  This makes it convenient for developers to debug mmap.
2024-11-21 13:48:05 -05:00
Matt Valentine-House
8e7df4b7c6 Rename size_pool -> heap
Now that we've inlined the eden_heap into the size_pool, we should
rename the size_pool to heap. So that Ruby contains multiple heaps, with
different sized objects.

The term heap as a collection of memory pages is more in memory
management nomenclature, whereas size_pool was a name chosen out of
necessity during the development of the Variable Width Allocation
features of Ruby.

The concept of size pools was introduced in order to facilitate
different sized objects (other than the default 40 bytes). They wrapped
the eden heap and the tomb heap, and some related state, and provided a
reasonably simple way of duplicating all related concerns, to provide
multiple pools that all shared the same structure but held different
objects.

Since then various changes have happend in Ruby's memory layout:

* The concept of tomb heaps has been replaced by a global free pages list,
  with each page having it's slot size reconfigured at the point when it
  is resurrected
* the eden heap has been inlined into the size pool itself, so that now
  the size pool directly controls the free_pages list, the sweeping
  page, the compaction cursor and the other state that was previously
  being managed by the eden heap.

Now that there is no need for a heap wrapper, we should refer to the
collection of pages containing Ruby objects as a heap again rather than
a size pool
2024-10-03 21:20:09 +01:00
Nobuyoshi Nakada
196d59f690
Parenthesize macro arguments 2024-08-16 15:43:43 +09:00
Nobuyoshi Nakada
129b4936bf
Simplify and clarify bitmask calculation 2024-08-16 15:43:43 +09:00
Raed Rizqie
018bd07f07
Fix some warnings
* Fix unused functions when no `mmap`.

  ```
  shape.c:285:1: warning: unused function 'redblack_insert' [-Wunused-function]
    285 | redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value)
        | ^~~~~~~~~~~~~~~
  ```

* Fix unknown warning group '-Wmaybe-uninitialized' with clang.

  ```
  thread_win32.c:596:1: warning: unknown warning group '-Wmaybe-uninitialized', ignored [-Wunknown-warning-option]
    596 | COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized)
        | ^
  ```

Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com>
2024-08-16 14:51:21 +09:00
Jean Boussier
f7b53a75b6 Do not emit shape transition warnings when YJIT is compiling
[Bug #20522]

If `Warning.warn` is redefined in Ruby, emitting a warning would invoke
Ruby code, which can't safely be done when YJIT is compiling.
2024-06-04 19:21:01 +02:00
Nobuyoshi Nakada
d224bfdc32
redblack_cache_ancestors is enabled only when mmap is available 2024-05-09 10:11:18 +09:00
Peter Zhu
49753cd082 Use xcalloc for allocating shape tree
The GC is initialized by this point, so we can use xcalloc instead of
ruby_mimcalloc.
2024-04-25 17:11:34 -04:00
Peter Zhu
214811974b Add ruby_mimcalloc
Many places call ruby_mimmalloc then MEMZERO. This can be reduced by
using ruby_mimcalloc instead.
2024-04-24 15:30:43 -04:00
Aaron Patterson
9579cf45d5 If we have a shape cache we should use it
If there is a shape cache, then we should believe the results instead of
doing a linear search for non-existent items

This fixes a case where checking the index of an undefined ivar would
result in an O(n) search. Now we get O(log n).

Benchmark is as follows:

```ruby
N = ARGV[0].to_i

class ManyIVs
  class_eval "def initialize;" +
    N.times.map { "@a#{_1} = #{_1}" }.join("\n") +
    "end"

  def check
    defined?(@not)
  end
end

class Subclass < ManyIVs
  def initialize
    super
    @foo = 123
  end
end

def t
  s = Process.clock_gettime Process::CLOCK_MONOTONIC
  yield
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - s
end

def test
  a = ManyIVs.new
  b = Subclass.new
  t { 200000.times { a.check; b.check } }
end

puts "#{N},#{test}"
```

On the master branch:

```
$ for i in (seq 1 3 32); ./miniruby test.rb $i; end
1,0.015619999991031364
4,0.013061000005109236
7,0.013365999999223277
10,0.015474999992875382
13,0.017674999980954453
16,0.020055999979376793
19,0.02260500000556931
22,0.0254080000158865
25,0.02806599999894388
28,0.031244999991031364
31,0.034568000002764165
```

On this branch:

```
$ for i in (seq 1 3 32); ./miniruby test.rb $i; end
1,0.015848999988520518
4,0.013225000002421439
7,0.013049000001046807
10,0.010697999998228624
13,0.010902000009082258
16,0.011448000004747882
19,0.01151199999731034
22,0.011539999977685511
25,0.01173300002119504
28,0.011900000012246892
31,0.012278999987756833
```
2024-03-30 19:24:36 -07:00
Peter Zhu
42bfbe9aa6 Remove unused size_pool_edge_names 2024-03-13 14:50:44 -04:00
Peter Zhu
c6089b5654 Don't allow SHAPE_T_OBJECT in rb_shape_alloc_new_child 2024-03-13 09:55:52 -04:00
Peter Zhu
3896f9940e Make special const and too complex shapes before T_OBJECT shapes 2024-03-13 09:55:52 -04:00
Peter Zhu
6b0434c0f7 Don't create per size pool shapes for non-T_OBJECT 2024-03-13 09:55:52 -04:00
Peter Zhu
6ad347a105 Don't directly read the SIZE_POOL_COUNT in shapes
This removes the assumption about SIZE_POOL_COUNT for shapes.
2024-03-13 09:55:52 -04:00
Peter Zhu
df5b8ea4db Remove unneeded RUBY_FUNC_EXPORTED 2024-02-23 10:24:21 -05:00
Aaron Patterson
8b8dcc7af1 Handle mmap failures for redblack tree cache
The redblack tree cache is totally optional, so if we can't allocate
room for the cache, then just pretend as if the cache is full if mmap
fails
2024-01-12 09:31:36 -08:00
Jean Boussier
7c2d819862 Fix a grammar issue in the shape performance warning message 2023-12-20 09:28:45 +01:00
Jean Boussier
f6ad49b87c Use #initialize instead of initialize in shape perf warning
This is more consistent with other messages.
2023-12-18 13:42:02 +01:00
Nobuyoshi Nakada
40fc9b070c
[DOC] No document for internal or debug methods 2023-12-18 20:17:45 +09:00