mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:38:11 +00:00
LibJS: Support instrinsic Object properties with deferred evaluation
For performance, it is desirable to defer evaluation of intrinsics that are stored on the GlobalObject for every created Realm. To support this, Object now maintains a global storage map to store lambdas that will return the associated intrinsic when evaluated. Once accessed, the instrinsic is moved from this global map to normal Object storage. To prevent this flow from becoming observable, when a deferred intrinsic is stored, we still place an empty object in the normal Object storage. This is so we still create the metadata for the object, and in doing so, can preserve insertion order of the Object storage. Otherwise, this will be observable by way of Object.getOwnPropertyDescriptors.
This commit is contained in:
parent
4f08f2f581
commit
12f9f3d9ef
2 changed files with 53 additions and 1 deletions
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
static HashMap<Object const*, HashMap<FlyString, Object::IntrinsicAccessor>> s_intrinsics;
|
||||
|
||||
// 10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinaryobjectcreate
|
||||
Object* Object::create(Realm& realm, Object* prototype)
|
||||
{
|
||||
|
@ -67,6 +69,11 @@ Object::Object(Shape& shape)
|
|||
m_storage.resize(shape.property_count());
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
{
|
||||
s_intrinsics.remove(this);
|
||||
}
|
||||
|
||||
void Object::initialize(Realm&)
|
||||
{
|
||||
}
|
||||
|
@ -970,6 +977,23 @@ ThrowCompletionOr<bool> Object::set_immutable_prototype(Object* prototype)
|
|||
return false;
|
||||
}
|
||||
|
||||
static Optional<Object::IntrinsicAccessor> find_intrinsic_accessor(Object const* object, PropertyKey const& property_key)
|
||||
{
|
||||
if (!property_key.is_string())
|
||||
return {};
|
||||
|
||||
auto intrinsics = s_intrinsics.find(object);
|
||||
if (intrinsics == s_intrinsics.end())
|
||||
return {};
|
||||
|
||||
auto accessor = intrinsics->value.find(property_key.as_string());
|
||||
if (accessor == intrinsics->value.end())
|
||||
return {};
|
||||
|
||||
intrinsics->value.remove(accessor);
|
||||
return move(accessor->value);
|
||||
}
|
||||
|
||||
Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key) const
|
||||
{
|
||||
VERIFY(property_key.is_valid());
|
||||
|
@ -987,9 +1011,14 @@ Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key
|
|||
auto metadata = shape().lookup(property_key.to_string_or_symbol());
|
||||
if (!metadata.has_value())
|
||||
return {};
|
||||
|
||||
if (auto accessor = find_intrinsic_accessor(this, property_key); accessor.has_value())
|
||||
const_cast<Object&>(*this).m_storage[metadata->offset] = (*accessor)(shape().realm());
|
||||
|
||||
value = m_storage[metadata->offset];
|
||||
attributes = metadata->attributes;
|
||||
}
|
||||
|
||||
return ValueAndAttributes { .value = value, .attributes = attributes };
|
||||
}
|
||||
|
||||
|
@ -1013,6 +1042,11 @@ void Object::storage_set(PropertyKey const& property_key, ValueAndAttributes con
|
|||
return;
|
||||
}
|
||||
|
||||
if (property_key.is_string()) {
|
||||
if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
|
||||
intrinsics->value.remove(property_key.as_string());
|
||||
}
|
||||
|
||||
auto property_key_string_or_symbol = property_key.to_string_or_symbol();
|
||||
auto metadata = shape().lookup(property_key_string_or_symbol);
|
||||
|
||||
|
@ -1050,6 +1084,11 @@ void Object::storage_delete(PropertyKey const& property_key)
|
|||
if (property_key.is_number())
|
||||
return m_indexed_properties.remove(property_key.as_number());
|
||||
|
||||
if (property_key.is_string()) {
|
||||
if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
|
||||
intrinsics->value.remove(property_key.as_string());
|
||||
}
|
||||
|
||||
auto metadata = shape().lookup(property_key.to_string_or_symbol());
|
||||
VERIFY(metadata.has_value());
|
||||
|
||||
|
@ -1098,6 +1137,16 @@ void Object::define_direct_accessor(PropertyKey const& property_key, FunctionObj
|
|||
}
|
||||
}
|
||||
|
||||
void Object::define_intrinsic_accessor(PropertyKey const& property_key, PropertyAttributes attributes, IntrinsicAccessor accessor)
|
||||
{
|
||||
VERIFY(property_key.is_string());
|
||||
|
||||
storage_set(property_key, { {}, attributes });
|
||||
|
||||
auto& intrinsics = s_intrinsics.ensure(this);
|
||||
intrinsics.set(property_key.as_string(), move(accessor));
|
||||
}
|
||||
|
||||
void Object::ensure_shape_is_unique()
|
||||
{
|
||||
if (shape().is_unique())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue