Skip to content

Commit d4e7e6d

Browse files
committed
[JSC] Move TypedArray.of from builtin JS to C++
https://bugs.webkit.org/show_bug.cgi?id=319332 rdar://182148177 Reviewed by Sosuke Suzuki. This patch moves TypedArray.of from builtin JS to C++. This is trivially convertible as it is not involving callbacks etc. We have a fast path for normal TypedArray constructors and we store arguments quickly by using type-specialized path. * Source/JavaScriptCore/builtins/TypedArrayConstructor.js: (of): Deleted. * Source/JavaScriptCore/runtime/JSGlobalObject.h: * Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h: (JSC::JSGlobalObject::typedArrayConstructorConcurrently const): * Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.cpp: (JSC::JSTypedArrayViewConstructor::finishCreation): (JSC::typedArrayOfSetElements): (JSC::typedArrayOfFast): (JSC::JSC_DEFINE_HOST_FUNCTION): Canonical link: https://commits.webkit.org/317162@main
1 parent 5958b2c commit d4e7e6d

4 files changed

Lines changed: 82 additions & 19 deletions

File tree

‎Source/JavaScriptCore/builtins/TypedArrayConstructor.js‎

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,6 @@
2424
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525
*/
2626

27-
function of(/* items... */)
28-
{
29-
"use strict";
30-
var len = @argumentCount();
31-
32-
if (!@isConstructor(this))
33-
@throwTypeError("TypedArray.of requires |this| to be a constructor");
34-
35-
var result = new this(len);
36-
if (@typedArrayLength(result) < len)
37-
@throwTypeError("TypedArray.of constructed typed array of insufficient length");
38-
39-
for (var i = 0; i < len; i++)
40-
result[i] = arguments[i];
41-
42-
return result;
43-
}
44-
4527
function from(items /* [ , mapfn [ , thisArg ] ] */)
4628
{
4729
"use strict";

‎Source/JavaScriptCore/runtime/JSGlobalObject.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,7 @@ class JSGlobalObject : public JSSegmentedVariableObject {
11511151
template<TypedArrayType type> Structure* resizableOrGrowableSharedTypedArrayStructureWithTypedArrayType() const { return typedArrayStructure(type, /* isResizableOrGrowableShared */ true); }
11521152

11531153
inline JSObject* typedArrayConstructor(TypedArrayType) const;
1154+
inline JSObject* typedArrayConstructorConcurrently(TypedArrayType) const;
11541155
inline JSObject* typedArrayPrototype(TypedArrayType) const;
11551156

11561157
inline JSCell* linkTimeConstant(LinkTimeConstant) const;

‎Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,11 @@ inline JSObject* JSGlobalObject::typedArrayConstructor(TypedArrayType type) cons
674674
return lazyTypedArrayStructure(type).constructor(this);
675675
}
676676

677+
inline JSObject* JSGlobalObject::typedArrayConstructorConcurrently(TypedArrayType type) const
678+
{
679+
return lazyTypedArrayStructure(type).constructorConcurrently();
680+
}
681+
677682
inline JSObject* JSGlobalObject::typedArrayPrototype(TypedArrayType type) const
678683
{
679684
return lazyTypedArrayStructure(type).prototype(this);

‎Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.cpp‎

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@
2929
#include "GetterSetter.h"
3030
#include "JSCBuiltins.h"
3131
#include "JSCInlines.h"
32+
#include "JSGenericTypedArrayViewInlines.h"
3233
#include "JSTypedArrayViewPrototype.h"
34+
#include "JSTypedArrays.h"
3335

3436
namespace JSC {
3537

3638
static JSC_DECLARE_HOST_FUNCTION(constructTypedArrayView);
39+
static JSC_DECLARE_HOST_FUNCTION(typedArrayConstructorOf);
3740

3841
JSTypedArrayViewConstructor::JSTypedArrayViewConstructor(VM& vm, Structure* structure)
3942
: Base(vm, structure, constructTypedArrayView, constructTypedArrayView)
@@ -48,7 +51,7 @@ void JSTypedArrayViewConstructor::finishCreation(VM& vm, JSGlobalObject* globalO
4851
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
4952
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, globalObject->typedArraySpeciesGetterSetter(), PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
5053

51-
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->of, typedArrayConstructorOfCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
54+
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->of, typedArrayConstructorOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ImplementationVisibility::Public);
5255
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->from, typedArrayConstructorFromCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
5356
globalObject->installTypedArrayConstructorSpeciesWatchpoint(this);
5457
}
@@ -66,4 +69,76 @@ JSC_DEFINE_HOST_FUNCTION(constructTypedArrayView, (JSGlobalObject* globalObject,
6669
return throwVMTypeError(globalObject, scope, "%TypedArray% should not be called directly"_s);
6770
}
6871

72+
template<typename ViewClass>
73+
static ALWAYS_INLINE void typedArrayOfSetElements(JSGlobalObject* globalObject, ViewClass* result, CallFrame* callFrame)
74+
{
75+
VM& vm = globalObject->vm();
76+
auto scope = DECLARE_THROW_SCOPE(vm);
77+
unsigned length = callFrame->argumentCount();
78+
for (unsigned index = 0; index < length; ++index) {
79+
result->setIndex(globalObject, index, callFrame->uncheckedArgument(index));
80+
RETURN_IF_EXCEPTION(scope, void());
81+
}
82+
}
83+
84+
template<typename ViewClass>
85+
static ALWAYS_INLINE ViewClass* typedArrayOfFast(JSGlobalObject* globalObject, CallFrame* callFrame)
86+
{
87+
VM& vm = globalObject->vm();
88+
auto scope = DECLARE_THROW_SCOPE(vm);
89+
unsigned length = callFrame->argumentCount();
90+
91+
Structure* structure = globalObject->typedArrayStructure(ViewClass::TypedArrayStorageType, /* isResizableOrGrowableShared */ false);
92+
ViewClass* result = ViewClass::createUninitialized(globalObject, structure, length);
93+
RETURN_IF_EXCEPTION(scope, { });
94+
95+
scope.release();
96+
typedArrayOfSetElements<ViewClass>(globalObject, result, callFrame);
97+
return result;
98+
}
99+
100+
// https://tc39.es/ecma262/#sec-%typedarray%.of
101+
JSC_DEFINE_HOST_FUNCTION(typedArrayConstructorOf, (JSGlobalObject* globalObject, CallFrame* callFrame))
102+
{
103+
VM& vm = globalObject->vm();
104+
auto scope = DECLARE_THROW_SCOPE(vm);
105+
106+
size_t length = callFrame->argumentCount();
107+
JSValue thisValue = callFrame->thisValue();
108+
109+
if (!thisValue.isConstructor()) [[unlikely]]
110+
return throwVMTypeError(globalObject, scope, "TypedArray.of requires |this| to be a constructor"_s);
111+
112+
#define JSC_TYPED_ARRAY_OF_FAST(name) \
113+
if (thisValue == globalObject->typedArrayConstructorConcurrently(Type##name)) \
114+
RELEASE_AND_RETURN(scope, JSValue::encode(typedArrayOfFast<JS##name##Array>(globalObject, callFrame)));
115+
FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(JSC_TYPED_ARRAY_OF_FAST)
116+
#undef JSC_TYPED_ARRAY_OF_FAST
117+
118+
MarkedArgumentBuffer args;
119+
args.append(jsNumber(length));
120+
ASSERT(!args.hasOverflowed());
121+
JSObject* constructed = construct(globalObject, thisValue, args, "TypedArray.of requires |this| to be a constructor"_s);
122+
RETURN_IF_EXCEPTION(scope, { });
123+
124+
JSArrayBufferView* view = validateTypedArray(globalObject, constructed);
125+
RETURN_IF_EXCEPTION(scope, { });
126+
if (view->length() < length) [[unlikely]]
127+
return throwVMTypeError(globalObject, scope, "TypedArray.of constructed typed array of insufficient length"_s);
128+
129+
switch (view->type()) {
130+
#define JSC_TYPED_ARRAY_OF_SET(name) \
131+
case name##ArrayType: { \
132+
scope.release(); \
133+
typedArrayOfSetElements(globalObject, uncheckedDowncast<JS##name##Array>(view), callFrame); \
134+
return JSValue::encode(view); \
135+
}
136+
FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(JSC_TYPED_ARRAY_OF_SET)
137+
#undef JSC_TYPED_ARRAY_OF_SET
138+
default:
139+
RELEASE_ASSERT_NOT_REACHED();
140+
return { };
141+
}
142+
}
143+
69144
} // namespace JSC

0 commit comments

Comments
 (0)