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
Notes:
sideshowbarker
2024-07-16 23:59:28 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/51ac0d8821 Pull-request: https://github.com/SerenityOS/serenity/pull/22058
2 changed files with 29 additions and 1 deletions
|
@ -15,6 +15,8 @@
|
|||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
#include <LibJS/Runtime/ObjectEnvironment.h>
|
||||
#include <LibJS/Runtime/RegExpObject.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibJS/Runtime/ValueInlines.h>
|
||||
|
||||
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)
|
||||
{
|
||||
// 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* storage = object.indexed_properties().storage();
|
||||
auto index = static_cast<u32>(property_key_value.as_i32());
|
||||
|
||||
// For "non-typed arrays":
|
||||
if (storage
|
||||
&& storage->is_simple_storage()
|
||||
&& !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 {};
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {};
|
||||
|
|
|
@ -32,6 +32,13 @@ public:
|
|||
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::*)();
|
||||
|
||||
u32 array_length() const { return m_array_length; }
|
||||
|
@ -48,6 +55,7 @@ public:
|
|||
|
||||
virtual size_t element_size() 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
|
||||
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 NonnullGCPtr<ClassName> create(Realm&, u32 length, ArrayBuffer& buffer); \
|
||||
virtual DeprecatedFlyString const& element_name() const override; \
|
||||
virtual Kind kind() const override { return Kind::ClassName; } \
|
||||
\
|
||||
protected: \
|
||||
ClassName(Object& prototype, u32 length, ArrayBuffer& array_buffer); \
|
||||
|
|
Loading…
Add table
Reference in a new issue