mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 02:07:34 +00:00
LibJS: Add common fast path for PutByValue into TypedArray
When putting to a numeric indexed property, we can skip a lot of the ceremony and go directly to IntegerIndexedElementSet. :^)
This commit is contained in:
parent
743a9e9ebf
commit
51ac0d8821
2 changed files with 29 additions and 1 deletions
|
@ -15,6 +15,8 @@
|
||||||
#include <LibJS/Runtime/NativeFunction.h>
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
#include <LibJS/Runtime/ObjectEnvironment.h>
|
#include <LibJS/Runtime/ObjectEnvironment.h>
|
||||||
#include <LibJS/Runtime/RegExpObject.h>
|
#include <LibJS/Runtime/RegExpObject.h>
|
||||||
|
#include <LibJS/Runtime/TypedArray.h>
|
||||||
|
#include <LibJS/Runtime/ValueInlines.h>
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
|
@ -306,10 +308,13 @@ Value new_function(VM& vm, FunctionExpression const& function_node, Optional<Ide
|
||||||
ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Value property_key_value, Value value, Op::PropertyKind kind)
|
ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Value property_key_value, Value value, Op::PropertyKind kind)
|
||||||
{
|
{
|
||||||
// OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects.
|
// OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects.
|
||||||
if (base.is_object() && property_key_value.is_int32() && property_key_value.as_i32() >= 0) {
|
if ((kind == Op::PropertyKind::KeyValue || kind == Op::PropertyKind::DirectKeyValue)
|
||||||
|
&& base.is_object() && property_key_value.is_int32() && property_key_value.as_i32() >= 0) {
|
||||||
auto& object = base.as_object();
|
auto& object = base.as_object();
|
||||||
auto* storage = object.indexed_properties().storage();
|
auto* storage = object.indexed_properties().storage();
|
||||||
auto index = static_cast<u32>(property_key_value.as_i32());
|
auto index = static_cast<u32>(property_key_value.as_i32());
|
||||||
|
|
||||||
|
// For "non-typed arrays":
|
||||||
if (storage
|
if (storage
|
||||||
&& storage->is_simple_storage()
|
&& storage->is_simple_storage()
|
||||||
&& !object.may_interfere_with_indexed_property_access()
|
&& !object.may_interfere_with_indexed_property_access()
|
||||||
|
@ -320,6 +325,20 @@ ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Value property_key_valu
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For typed arrays:
|
||||||
|
if (object.is_typed_array()) {
|
||||||
|
auto& typed_array = static_cast<TypedArrayBase&>(object);
|
||||||
|
auto canonical_index = CanonicalIndex { CanonicalIndex::Type::Index, index };
|
||||||
|
switch (typed_array.kind()) {
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
|
||||||
|
case TypedArrayBase::Kind::ClassName: \
|
||||||
|
return integer_indexed_element_set<Type>(typed_array, canonical_index, value);
|
||||||
|
JS_ENUMERATE_TYPED_ARRAYS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto property_key = kind != Op::PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey {};
|
auto property_key = kind != Op::PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey {};
|
||||||
|
|
|
@ -32,6 +32,13 @@ public:
|
||||||
Number,
|
Number,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Kind {
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
|
||||||
|
ClassName,
|
||||||
|
JS_ENUMERATE_TYPED_ARRAYS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
};
|
||||||
|
|
||||||
using IntrinsicConstructor = NonnullGCPtr<TypedArrayConstructor> (Intrinsics::*)();
|
using IntrinsicConstructor = NonnullGCPtr<TypedArrayConstructor> (Intrinsics::*)();
|
||||||
|
|
||||||
u32 array_length() const { return m_array_length; }
|
u32 array_length() const { return m_array_length; }
|
||||||
|
@ -48,6 +55,7 @@ public:
|
||||||
|
|
||||||
virtual size_t element_size() const = 0;
|
virtual size_t element_size() const = 0;
|
||||||
virtual DeprecatedFlyString const& element_name() const = 0;
|
virtual DeprecatedFlyString const& element_name() const = 0;
|
||||||
|
virtual Kind kind() const = 0;
|
||||||
|
|
||||||
// 25.1.2.6 IsUnclampedIntegerElementType ( type ), https://tc39.es/ecma262/#sec-isunclampedintegerelementtype
|
// 25.1.2.6 IsUnclampedIntegerElementType ( type ), https://tc39.es/ecma262/#sec-isunclampedintegerelementtype
|
||||||
virtual bool is_unclamped_integer_element_type() const = 0;
|
virtual bool is_unclamped_integer_element_type() const = 0;
|
||||||
|
@ -472,6 +480,7 @@ ThrowCompletionOr<double> compare_typed_array_elements(VM&, Value x, Value y, Fu
|
||||||
static ThrowCompletionOr<NonnullGCPtr<ClassName>> create(Realm&, u32 length); \
|
static ThrowCompletionOr<NonnullGCPtr<ClassName>> create(Realm&, u32 length); \
|
||||||
static NonnullGCPtr<ClassName> create(Realm&, u32 length, ArrayBuffer& buffer); \
|
static NonnullGCPtr<ClassName> create(Realm&, u32 length, ArrayBuffer& buffer); \
|
||||||
virtual DeprecatedFlyString const& element_name() const override; \
|
virtual DeprecatedFlyString const& element_name() const override; \
|
||||||
|
virtual Kind kind() const override { return Kind::ClassName; } \
|
||||||
\
|
\
|
||||||
protected: \
|
protected: \
|
||||||
ClassName(Object& prototype, u32 length, ArrayBuffer& array_buffer); \
|
ClassName(Object& prototype, u32 length, ArrayBuffer& array_buffer); \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue