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

777 Коммитов

Автор SHA1 Сообщение Дата
Jemma Issroff c1ab6ddc9a Transition complex objects to "too complex" shape
When an object becomes "too complex" (in other words it has too many
variations in the shape tree), we transition it to use a "too complex"
shape and use a hash for storing instance variables.

Without this patch, there were rare cases where shape tree growth could
"explode" and cause performance degradation on what would otherwise have
been cached fast paths.

This patch puts a limit on shape tree growth, and gracefully degrades in
the rare case where there could be a factorial growth in the shape tree.

For example:

```ruby
class NG; end

HUGE_NUMBER.times do
  NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1)
end
```

We consider objects to be "too complex" when the object's class has more
than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and
the object introduces a new variation (a new leaf node) associated with
that class.

For example, new variations on instances of the following class would be
considered "too complex" because those instances create more than 8
leaves in the shape tree:

```ruby
class Foo; end
9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) }
```

However, the following class is *not* too complex because it only has
one leaf in the shape tree:

```ruby
class Foo
  def initialize
    @a = @b = @c = @d = @e = @f = @g = @h = @i = nil
  end
end
9.times { Foo.new }
``

This case is rare, so we don't expect this change to impact performance
of most applications, but it needs to be handled.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2022-12-15 10:06:04 -08:00
Matt Valentine-House 181d4bee5e Use rb_inspect instead of +PRIsVALUE for Object.inspect
In order to preserve the values when TrueClass, FalseClass or NilClass
are stored in ivars
2022-12-09 22:11:00 +09:00
Peter Zhu 003f8ea809 Remove dead code in rb_obj_copy_ivar
The removed code is a duplicate of the code above.
2022-11-22 13:49:46 -08:00
Peter Zhu 648927d71b Refactor obj_ivar_set and vm_setivar
obj_ivar_set and vm_setivar_slowpath is essentially doing the same thing,
but the code is duplicated and not quite implemented in the same way,
which could cause bugs. This commit refactors vm_setivar_slowpath to use
obj_ivar_set.
2022-11-21 09:58:53 -05:00
Aaron Patterson 2185f0ca77
Update assertion
New T_OBJECT objects will have a T_OBJECT shape
2022-11-18 13:58:13 -08:00
Aaron Patterson 10788166e7 Differentiate T_OBJECT shapes from other objects
We would like to differentiate types of objects via their shape.  This
commit adds a special T_OBJECT shape when we allocate an instance of
T_OBJECT.  This allows us to avoid testing whether an object is an
instance of a T_OBJECT or not, we can just check the shape.
2022-11-18 08:31:56 -08:00
S-H-GAMELINKS 1f4f6c9832 Using UNDEF_P macro 2022-11-16 18:58:33 +09:00
Jemma Issroff 7ee1cacb84 Extract `rb_shape_get_parent` helper
Extract an `rb_shape_get_parent` method instead of continually calling
`rb_shape_get_shape_by_id(shape->parent_id)`
2022-11-10 13:02:50 -05:00
Jemma Issroff c726c48a3d Remove numiv from RObject
Since object shapes store the capacity of an object, we no longer
need the numiv field on RObjects. This gives us one extra slot which
we can use to give embedded objects one more instance variable (for a
total of 3 ivs). This commit removes the concept of numiv from RObject.
2022-11-10 10:11:34 -05:00
Jemma Issroff 5246f4027e Transition shape when object's capacity changes
This commit adds a `capacity` field to shapes, and adds shape
transitions whenever an object's capacity changes. Objects which are
allocated out of a bigger size pool will also make a transition from the
root shape to the shape with the correct capacity for their size pool
when they are allocated.

This commit will allow us to remove numiv from objects completely, and
will also mean we can guarantee that if two objects share shapes, their
IVs are in the same positions (an embedded and extended object cannot
share shapes). This will enable us to implement ivar sets in YJIT using
object shapes.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2022-11-10 10:11:34 -05:00
Aaron Patterson 70173a72a2
Ivar copy needs to happen _before_ setting the shape
When we copy instance variables, it is possible for the GC to be kicked
off.  The GC looks at the shape to determine what slots to mark inside
the object.  If the shape is set too soon, the GC could think that there
are more instance variables on the object than there actually are at
that moment.
2022-11-01 15:38:44 -07:00
John Hawthorn 02f1554224
Implement object shapes for T_CLASS and T_MODULE (#6637)
* Avoid RCLASS_IV_TBL in marshal.c
* Avoid RCLASS_IV_TBL for class names
* Avoid RCLASS_IV_TBL for autoload
* Avoid RCLASS_IV_TBL for class variables
* Avoid copying RCLASS_IV_TBL onto ICLASSes
* Use object shapes for Class and Module IVs
2022-10-31 14:05:37 -07:00
Jemma Issroff f2ae58119d In init_copy, set shape after copying ivars
GC uses shapes to determine IV buffer width. Since allocation can
trigger GC, we need to ensure we only set the shape once we've fully
allocated new memory for the IV buffer, otherwise the GC can end up
trying to mark invalid memory.
2022-10-21 10:57:05 -07:00
Ufuk Kayserilioglu 0378e2f4a8 Add Class#attached_object
Implements [Feature #12084]

Returns the object for which the receiver is the singleton class, or
raises TypeError if the receiver is not a singleton class.
2022-10-20 17:30:17 +02:00
Nobuyoshi Nakada 7563604fb8 [Bug #18998] Honor `#to_str` next to `#to_int` in `Kernel#Integer` 2022-10-20 15:35:31 +09:00
Jemma Issroff b54c8ba8fc Simplified rb_obj_copy_ivar implementation 2022-10-17 14:47:45 -07:00
Jemma Issroff 913979bede
Make inline cache reads / writes atomic with object shapes
Prior to this commit, we were reading and writing ivar index and
shape ID in inline caches in two separate instructions when
getting and setting ivars. This meant there was a race condition
with ractors and these caches where one ractor could change
a value in the cache while another was still reading from it.

This commit instead reads and writes shape ID and ivar index to
inline caches atomically so there is no longer a race condition.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-10-11 08:40:56 -07:00
Jemma Issroff ad63b668e2
Revert "Revert "This commit implements the Object Shapes technique in CRuby.""
This reverts commit 9a6803c90b.
2022-10-11 08:40:56 -07:00
Jean Boussier 1a7e7bb2d1 object.c: rb_eql returns int not VALUE
It works, but assumes `Qfalse == 0`, which is true today
but might not be forever.
2022-10-10 11:35:16 +02:00
Aaron Patterson 9a6803c90b
Revert "This commit implements the Object Shapes technique in CRuby."
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
2022-09-30 16:01:50 -07:00
Jemma Issroff d594a5a8bd
This commit implements the Object Shapes technique in CRuby.
Object Shapes is used for accessing instance variables and representing the
"frozenness" of objects.  Object instances have a "shape" and the shape
represents some attributes of the object (currently which instance variables are
set and the "frozenness").  Shapes form a tree data structure, and when a new
instance variable is set on an object, that object "transitions" to a new shape
in the shape tree.  Each shape has an ID that is used for caching. The shape
structure is independent of class, so objects of different types can have the
same shape.

For example:

```ruby
class Foo
  def initialize
    # Starts with shape id 0
    @a = 1 # transitions to shape id 1
    @b = 1 # transitions to shape id 2
  end
end

class Bar
  def initialize
    # Starts with shape id 0
    @a = 1 # transitions to shape id 1
    @b = 1 # transitions to shape id 2
  end
end

foo = Foo.new # `foo` has shape id 2
bar = Bar.new # `bar` has shape id 2
```

Both `foo` and `bar` instances have the same shape because they both set
instance variables of the same name in the same order.

This technique can help to improve inline cache hits as well as generate more
efficient machine code in JIT compilers.

This commit also adds some methods for debugging shapes on objects.  See
`RubyVM::Shape` for more details.

For more context on Object Shapes, see [Feature: #18776]

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-09-28 08:26:21 -07:00
Aaron Patterson 06abfa5be6
Revert this until we can figure out WB issues or remove shapes from GC
Revert "* expand tabs. [ci skip]"

This reverts commit 830b5b5c35.

Revert "This commit implements the Object Shapes technique in CRuby."

This reverts commit 9ddfd2ca00.
2022-09-26 16:10:11 -07:00
Jemma Issroff 9ddfd2ca00 This commit implements the Object Shapes technique in CRuby.
Object Shapes is used for accessing instance variables and representing the
"frozenness" of objects.  Object instances have a "shape" and the shape
represents some attributes of the object (currently which instance variables are
set and the "frozenness").  Shapes form a tree data structure, and when a new
instance variable is set on an object, that object "transitions" to a new shape
in the shape tree.  Each shape has an ID that is used for caching. The shape
structure is independent of class, so objects of different types can have the
same shape.

For example:

```ruby
class Foo
  def initialize
    # Starts with shape id 0
    @a = 1 # transitions to shape id 1
    @b = 1 # transitions to shape id 2
  end
end

class Bar
  def initialize
    # Starts with shape id 0
    @a = 1 # transitions to shape id 1
    @b = 1 # transitions to shape id 2
  end
end

foo = Foo.new # `foo` has shape id 2
bar = Bar.new # `bar` has shape id 2
```

Both `foo` and `bar` instances have the same shape because they both set
instance variables of the same name in the same order.

This technique can help to improve inline cache hits as well as generate more
efficient machine code in JIT compilers.

This commit also adds some methods for debugging shapes on objects.  See
`RubyVM::Shape` for more details.

For more context on Object Shapes, see [Feature: #18776]

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-09-26 09:21:30 -07:00
Nobuyoshi Nakada 332d29df53
[DOC] non-positive `base` in `Kernel#Integer` and `String#to_i` 2022-09-08 11:52:16 +09:00
S-H-GAMELINKS fc5382d465 Reuse rb_class_new_instance_kw function 2022-08-20 12:25:01 +09:00
Nobuyoshi Nakada f42230ff22
Adjust styles [ci skip] 2022-07-27 18:42:27 +09:00
Takashi Kokubun 5b21e94beb Expand tabs [ci skip]
[Misc #18891]
2022-07-21 09:42:04 -07:00
Peter Zhu 7424ea184f Implement Objects on VWA
This commit implements Objects on Variable Width Allocation. This allows
Objects with more ivars to be embedded (i.e. contents directly follow the
object header) which improves performance through better cache locality.
2022-07-15 09:21:07 -04:00
Nobuyoshi Nakada a58611dfb1 Allow to just warn as bool expected, without an exception 2022-06-20 19:35:12 +09:00
Jemma Issroff fc484be5e5 Add assertion for embedded to embedded ivar copy 2022-06-10 13:47:42 -07:00
Jeremy Evans 7cda7fbbdc
Add Module#undefined_instance_methods
Implements [Feature #12655]

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2022-06-06 09:57:32 -07:00
Burdette Lamar ac75c710cc
Link from printf methods to format spec doc (#5886) 2022-05-05 09:01:12 -05:00
Burdette Lamar f553180a86
[DOC] Enhanced RDoc for Kernel (#5847)
Treats #Integer; fixes an error in #String.
2022-04-27 06:00:22 -05:00
John Hawthorn a8541475d1 Faster rb_class_superclass
This uses the RCLASS_SUPERCLASSES array to quickly find the next
SUPERCLASS of klass which is a T_CLASS.
2022-04-26 14:08:55 -07:00
Burdette Lamar 5ce0d2aa35
[DOC] Enhanced RDoc for Kernel (#5846)
Treats:
    #Array
    #Hash
    #String
2022-04-25 15:59:09 -05:00
Akshay Birajdar 8751c5c267 [DOC] Enhance documentation for `Module#<` & `Module#>` 2022-04-14 08:52:22 -04:00
Nobuyoshi Nakada 295030969c
[DOC] Prefer RDOCLINK to the method name 2022-04-14 14:57:39 +09:00
Nobuyoshi Nakada 2ff41e97fa
[DOC] Now underscore methods can cross-reference 2022-04-14 12:55:44 +09:00
Nobuyoshi Nakada 0bca029d2f
[DOC] Use simple references to operator methods
Method references is not only able to be marked up as code, also
reflects `--show-hash` option.
The bug that prevented the old rdoc from correctly parsing these
methods was fixed last month.
2022-03-30 10:54:52 +09:00
Burdette Lamar c8e1ae4db7
[DOC] Repair format of What's Here sections in object.c (#5722)
* Repair format of What's Here sections in object.c
2022-03-29 06:19:51 -05:00
John Hawthorn b8e72bd2e9 Revert "Faster rb_class_superclass"
This reverts commit 29b68b89a0.
2022-03-17 11:56:49 -07:00
John Hawthorn 29b68b89a0 Faster rb_class_superclass
This uses the RCLASS_SUPERCLASSES array to quickly find the next
SUPERCLASS of klass which is a T_CLASS.
2022-03-17 11:48:39 -07:00
John Hawthorn d76ba1c219 Fast rb_class_inherited_p
This uses the superclass table recently introduced to implement fast
inheritance checking between classes (ex. Foo < Bar).

This is almost identical to what we do in class_search_class_ancestor
(as called by rb_obj_is_kind_of) except that we are checking both
directions: ie. both whether Foo < Bar and whether Bar < Foo.
2022-03-15 08:49:53 -07:00
John Hawthorn 4d8f76286b Fast object is iclass checks
Calling rb_obj_is_kind_of with an ICLASS returns the same result as
calling it with the ICLASS's original Module.

Most of the time we encounter an ICLASS here checking the validity of a
protected method or super call, which we expect to return true (or raise
a slow exception anyways). We can take advantage of this by performing a
fast class inheritance check on the ICLASS's "includer" in hopes that it
returns true.

If the includer class check returns false we still have to fallback to
the full inheritance chain scan for the module's inclusion, but this
should be less common.
2022-03-11 10:36:19 -08:00
John Hawthorn 82dea29073 Revert "Fast object is iclass checks"
This reverts commit 1b15756d24.
2022-03-10 11:06:42 -08:00
John Hawthorn 1b15756d24 Fast object is iclass checks
Calling rb_obj_is_kind_of with an ICLASS returns the same result as
calling it with the ICLASS's original Module.

Most of the time we encounter an ICLASS here checking the validity of a
protected method or super call, which we expect to return true (or raise
a slow exception anyways). We can take advantage of this by performing a
fast class inheritance check on the ICLASS's "includer" in hopes that it
returns true.

If the includer class check returns false we still have to fallback to
the full inheritance chain scan for the module's inclusion, but this
should be less common.
2022-03-10 09:34:08 -08:00
John Hawthorn b13a7c8e36 Constant time class to class ancestor lookup
Previously when checking ancestors, we would walk all the way up the
ancestry chain checking each parent for a matching class or module.

I believe this was especially unfriendly to CPU cache since for each
step we need to check two cache lines (the class and class ext).

This check is used quite often in:
* case statements
* rescue statements
* Calling protected methods
* Class#is_a?
* Module#===
* Module#<=>

I believe it's most common to check a class against a parent class, to
this commit aims to improve that (unfortunately does not help checking
for an included Module).

This is done by storing on each class the number and an array of all
parent classes, in order (BasicObject is at index 0). Using this we can
check whether a class is a subclass of another in constant time since we
know the location to expect it in the hierarchy.
2022-02-23 19:57:42 -08:00
John Hawthorn 764e4fa850 Never call kind_of with klass=0 2022-02-23 19:57:42 -08:00
Burdette Lamar e9a2b30744
Enhanced RDoc concerning command injection (#5537)
Clarifies security vulnerabilities for commands.

Treats:

    Kernel.system
    Kernel.` (backtick)
    IO.popen
    IO.read
    IO.write
    IO.binread
    IO.binwrite
    IO.readlines
    IO.foreach
2022-02-18 06:46:04 -06:00
Nobuyoshi Nakada 50c972a1ae
[DOC] Simplify operator method references 2022-02-12 12:38:36 +09:00