| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
New T_OBJECT objects will have a T_OBJECT shape
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Extract an `rb_shape_get_parent` method instead of continually calling
`rb_shape_get_shape_by_id(shape->parent_id)`
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
* 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
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
|
|
|
|
|
| |
It works, but assumes `Qfalse == 0`, which is true today
but might not be forever.
|
|
|
|
| |
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
| |
Revert "* expand tabs. [ci skip]"
This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275.
Revert "This commit implements the Object Shapes technique in CRuby."
This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
| |
|
| |
|
| |
|
|
|
|
| |
[Misc #18891]
|
|
|
|
|
|
| |
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.
|
| |
|
| |
|
|
|
|
|
| |
Implements [Feature #12655]
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
|
| |
|
|
|
| |
Treats #Integer; fixes an error in #String.
|
|
|
|
|
| |
This uses the RCLASS_SUPERCLASSES array to quickly find the next
SUPERCLASS of klass which is a T_CLASS.
|
|
|
|
|
|
|
| |
Treats:
#Array
#Hash
#String
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
* Repair format of What's Here sections in object.c
|
|
|
|
| |
This reverts commit 29b68b89a0c0ea7de46c058fab746550398151f0.
|
|
|
|
|
| |
This uses the RCLASS_SUPERCLASSES array to quickly find the next
SUPERCLASS of klass which is a T_CLASS.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
This reverts commit 1b15756d24c11ed6bfddb5ae53402a071a20ea97.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Clarifies security vulnerabilities for commands.
Treats:
Kernel.system
Kernel.` (backtick)
IO.popen
IO.read
IO.write
IO.binread
IO.binwrite
IO.readlines
IO.foreach
|
| |
|
|
|
|
|
|
|
|
|
|
| |
I used this regex:
(?<=\[)#(?:class|module)-([A-Za-z]+)-label-([A-Za-z0-9\-\+]+)
And performed a global find & replace for this:
rdoc-ref:$1@$2
|
|
|
|
|
|
|
|
|
|
| |
I used this regex:
([A-Za-z]+)\.html#(?:class|module)-[A-Za-z]+-label-([A-Za-z0-9\-\+]+)
And performed a global find & replace for this:
rdoc-ref:$1@$2
|
|
|
|
|
|
|
|
|
|
|
|
| |
[Feature #17881]
Works similarly to `method_added` but for constants.
```ruby
Foo::BAR = 42 # call Foo.const_added(:FOO)
class Foo::Baz; end # call Foo.const_added(:Baz)
Foo.autoload(:Something, "path") # call Foo.const_added(:Something)
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is to allow Module subclasses that include modules before
calling super in the subclass's initialize.
Remove rb_module_check_initializable from Module#initialize.
Module#initialize only calls module_exec if a block is passed,
it doesn't have other issues that would cause problems if
called multiple times or with an already initialized module.
Move initialization of super to Module#allocate, though I'm not
sure it is required there. However, it's needed to be removed
from Module#initialize for this to work.
Fixes [Bug #18292]
|