Changeset 203076 in webkit


Ignore:
Timestamp:
Jul 11, 2016 12:13:05 PM (8 years ago)
Author:
keith_miller@apple.com
Message:

STP TypedArray.subarray 5x slowdown compared to 9.1
https://bugs.webkit.org/show_bug.cgi?id=156404
Source/JavaScriptCore:

<rdar://problem/26493032>

Reviewed by Geoffrey Garen.

This patch moves the species constructor work for
%TypedArray%.prototype.subarray to a js wrapper. By moving the
species constructor work to JS we are able to completely optimize
it out in DFG. The actual work of creating a TypedArray is still
done in C++ since we are able to avoid calling into the
constructor, which is expensive. This patch also changes the error
message when a %TypedArray%.prototype function is passed a non-typed
array this value. Finally, we used to check that the this value
had not been detached, however, this behavior was incorrect.

  • builtins/BuiltinNames.h:
  • builtins/TypedArrayPrototype.js:

(globalPrivate.typedArraySpeciesConstructor):
(subarray):

  • runtime/ConstructData.cpp:

(JSC::construct):

  • runtime/ConstructData.h:
  • runtime/JSGenericTypedArrayViewPrototypeFunctions.h:

(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
(JSC::genericTypedArrayViewProtoFuncSubarray): Deleted.

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSTypedArrayViewPrototype.cpp:

(JSC::typedArrayViewPrivateFuncLength):
(JSC::typedArrayViewPrivateFuncSubarrayCreate):
(JSC::JSTypedArrayViewPrototype::finishCreation):
(JSC::typedArrayViewProtoFuncSubarray): Deleted.

  • runtime/JSTypedArrayViewPrototype.h:

LayoutTests:

Reviewed by Geoffrey Garen.

Add new micro-benchmark for testing subarray performance with small subarray sizes.

  • js/regress/script-tests/typed-array-subarray.js: Added.

(createManySubs):
(go):

  • js/regress/typed-array-subarray-expected.txt: Added.
  • js/regress/typed-array-subarray.html: Added.
Location:
trunk
Files:
3 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r203075 r203076  
     12016-07-11  Keith Miller  <keith_miller@apple.com>
     2
     3        STP TypedArray.subarray 5x slowdown compared to 9.1
     4        https://bugs.webkit.org/show_bug.cgi?id=156404
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add new micro-benchmark for testing subarray performance with small subarray sizes.
     9
     10        * js/regress/script-tests/typed-array-subarray.js: Added.
     11        (createManySubs):
     12        (go):
     13        * js/regress/typed-array-subarray-expected.txt: Added.
     14        * js/regress/typed-array-subarray.html: Added.
     15
    1162016-07-11  Nan Wang  <n_wang@apple.com>
    217
  • trunk/Source/JavaScriptCore/ChangeLog

    r203053 r203076  
     12016-07-11  Keith Miller  <keith_miller@apple.com>
     2
     3        STP TypedArray.subarray 5x slowdown compared to 9.1
     4        https://bugs.webkit.org/show_bug.cgi?id=156404
     5        <rdar://problem/26493032>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        This patch moves the species constructor work for
     10        %TypedArray%.prototype.subarray to a js wrapper. By moving the
     11        species constructor work to JS we are able to completely optimize
     12        it out in DFG. The actual work of creating a TypedArray is still
     13        done in C++ since we are able to avoid calling into the
     14        constructor, which is expensive. This patch also changes the error
     15        message when a %TypedArray%.prototype function is passed a non-typed
     16        array this value. Finally, we used to check that the this value
     17        had not been detached, however, this behavior was incorrect.
     18
     19        * builtins/BuiltinNames.h:
     20        * builtins/TypedArrayPrototype.js:
     21        (globalPrivate.typedArraySpeciesConstructor):
     22        (subarray):
     23        * runtime/ConstructData.cpp:
     24        (JSC::construct):
     25        * runtime/ConstructData.h:
     26        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
     27        (JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
     28        (JSC::genericTypedArrayViewProtoFuncSubarray): Deleted.
     29        * runtime/JSGlobalObject.cpp:
     30        (JSC::JSGlobalObject::init):
     31        * runtime/JSTypedArrayViewPrototype.cpp:
     32        (JSC::typedArrayViewPrivateFuncLength):
     33        (JSC::typedArrayViewPrivateFuncSubarrayCreate):
     34        (JSC::JSTypedArrayViewPrototype::finishCreation):
     35        (JSC::typedArrayViewProtoFuncSubarray): Deleted.
     36        * runtime/JSTypedArrayViewPrototype.h:
     37
    1382016-07-11  Yusuke Suzuki  <utatane.tea@gmail.com>
    239
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r202680 r203076  
    7777    macro(typedArraySort) \
    7878    macro(typedArrayGetOriginalConstructor) \
     79    macro(typedArraySubarrayCreate) \
    7980    macro(BuiltinLog) \
    8081    macro(homeObject) \
  • trunk/Source/JavaScriptCore/builtins/TypedArrayPrototype.js

    r201825 r203076  
    2727// and throws if it is not.
    2828
     29
     30// Typed Arrays have their own species constructor function since they need
     31// to look up their default constructor, which is expensive. If we used the
     32// normal speciesConstructor helper we would need to look up the default
     33// constructor every time.
     34@globalPrivate
     35function typedArraySpeciesConstructor(value)
     36{
     37    "use strict";
     38    let constructor = value.constructor;
     39    if (constructor === @undefined)
     40        return @typedArrayGetOriginalConstructor(value);
     41
     42    if (!@isObject(constructor))
     43        throw new @TypeError("|this|.constructor is not an Object or undefined");
     44
     45    constructor = constructor.@speciesSymbol;
     46    if (constructor == null)
     47        return @typedArrayGetOriginalConstructor(value);
     48    // The lack of an @isConstructor(constructor) check here is not observable because
     49    // the first thing we will do with the value is attempt to construct the result with it.
     50    // If any user of this function does not immediately construct the result they need to
     51    // verify that the result is a constructor.
     52    return constructor;
     53}
     54
    2955function values()
    3056{
     
    192218   
    193219    return this;
     220}
     221
     222function subarray(begin, end)
     223{
     224    "use strict";
     225
     226    if (!@isTypedArrayView(this))
     227        throw new @TypeError("|this| should be a typed array view");
     228
     229    let start = @toInteger(begin);
     230    let finish;
     231    if (end !== @undefined)
     232        finish = @toInteger(end);
     233
     234    let constructor = @typedArraySpeciesConstructor(this);
     235
     236    return @typedArraySubarrayCreate.@call(this, start, finish, constructor);
    194237}
    195238
  • trunk/Source/JavaScriptCore/runtime/ConstructData.cpp

    r197614 r203076  
    3636namespace JSC {
    3737
    38 JSObject* construct(ExecState* exec, JSValue constructorObject, const ArgList& args, const String& errorMessage)
     38JSObject* construct(ExecState* exec, JSValue constructorObject, const ArgList& args, const char* errorMessage)
    3939{
    4040    ConstructData constructData;
  • trunk/Source/JavaScriptCore/runtime/ConstructData.h

    r197614 r203076  
    6060
    6161// Convenience wrapper so you don't need to deal with CallData and CallType unless you are going to use them.
    62 JSObject* construct(ExecState*, JSValue functionObject, const ArgList&, const String& errorMessage);
     62JSObject* construct(ExecState*, JSValue functionObject, const ArgList&, const char* errorMessage);
    6363JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&, JSValue newTarget);
    6464
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h

    r203046 r203076  
    463463
    464464template<typename ViewClass>
    465 EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncSubarray(ExecState* exec)
     465EncodedJSValue JSC_HOST_CALL genericTypedArrayViewPrivateFuncSubarrayCreate(ExecState* exec)
    466466{
    467467    // 22.2.3.23
     
    476476    unsigned thisLength = thisObject->length();
    477477
     478    ASSERT(exec->argument(0).isAnyInt());
     479    ASSERT(exec->argument(1).isUndefined() || exec->argument(1).isAnyInt());
    478480    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
    479     if (vm.exception())
    480         return encodedJSValue();
     481    ASSERT(!vm.exception());
    481482    unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
    482     if (vm.exception())
    483         return encodedJSValue();
    484 
    485     if (thisObject->isNeutered())
    486         return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
     483    ASSERT(!vm.exception());
     484
     485    RELEASE_ASSERT(!thisObject->isNeutered());
    487486
    488487    // Clamp end to begin.
     
    498497    unsigned newByteOffset = thisObject->byteOffset() + offset * ViewClass::elementSize;
    499498
     499    JSObject* defaultConstructor = callee->globalObject()->typedArrayConstructor(ViewClass::TypedArrayStorageType);
     500    JSValue species = exec->uncheckedArgument(2);
     501    if (species == defaultConstructor) {
     502        Structure* structure = callee->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType);
     503
     504        return JSValue::encode(ViewClass::create(
     505            exec, structure, arrayBuffer,
     506            thisObject->byteOffset() + offset * ViewClass::elementSize,
     507            length));
     508    }
     509
    500510    MarkedArgumentBuffer args;
    501     args.append(exec->vm().m_typedArrayController->toJS(exec, thisObject->globalObject(), thisObject->buffer()));
     511    args.append(vm.m_typedArrayController->toJS(exec, thisObject->globalObject(), thisObject->buffer()));
    502512    args.append(jsNumber(newByteOffset));
    503513    args.append(jsNumber(length));
    504514
    505     JSArrayBufferView* result = speciesConstruct(exec, thisObject, args, [&]() {
    506         Structure* structure = callee->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType);
    507 
    508         return ViewClass::create(
    509             exec, structure, arrayBuffer,
    510             thisObject->byteOffset() + offset * ViewClass::elementSize,
    511             length);
    512     });
     515    JSObject* result = construct(exec, species, args, "species is not a constructor");
    513516    if (exec->hadException())
    514517        return JSValue::encode(JSValue());
    515518
    516     return JSValue::encode(result);
     519    if (jsDynamicCast<JSArrayBufferView*>(result))
     520        return JSValue::encode(result);
     521
     522    throwTypeError(exec, "species constructor did not return a TypedArray View");
     523    return JSValue::encode(JSValue());
    517524}
    518525
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r203006 r203076  
    658658    JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
    659659    JSFunction* privateFuncIsTypedArrayView = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncIsTypedArrayView, IsTypedArrayViewIntrinsic);
     660    JSFunction* privateFuncTypedArraySubarrayCreate = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSubarrayCreate);
    660661    JSFunction* privateFuncIsBoundFunction = JSFunction::create(vm, this, 0, String(), isBoundFunction);
    661662    JSFunction* privateFuncHasInstanceBoundFunction = JSFunction::create(vm, this, 0, String(), hasInstanceBoundFunction);
     
    707708        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArraySortPrivateName(), privateFuncTypedArraySort, DontEnum | DontDelete | ReadOnly),
    708709        GlobalPropertyInfo(vm.propertyNames->builtinNames().isTypedArrayViewPrivateName(), privateFuncIsTypedArrayView, DontEnum | DontDelete | ReadOnly),
     710        GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArraySubarrayCreatePrivateName(), privateFuncTypedArraySubarrayCreate, DontEnum | DontDelete | ReadOnly),
    709711        GlobalPropertyInfo(vm.propertyNames->builtinNames().isBoundFunctionPrivateName(), privateFuncIsBoundFunction, DontEnum | DontDelete | ReadOnly),
    710712        GlobalPropertyInfo(vm.propertyNames->builtinNames().hasInstanceBoundFunctionPrivateName(), privateFuncHasInstanceBoundFunction, DontEnum | DontDelete | ReadOnly),
  • trunk/Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp

    r203046 r203076  
    7575    JSValue argument = exec->argument(0);
    7676    if (!argument.isCell() || !isTypedView(argument.asCell()->classInfo()->typedArrayStorageType))
    77         return throwVMTypeError(exec, "Receiver should be a typed array view");
     77        return throwVMTypeError(exec, ASCIILiteral("Receiver should be a typed array view"));
    7878
    7979    JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(argument);
    80     if (!thisObject || thisObject->mode() == DataViewMode)
    81         return throwVMTypeError(exec, ASCIILiteral("Receiver should be a typed array view"));
     80
    8281    if (thisObject->isNeutered())
    83         return throwVMTypeError(exec, "Underlying ArrayBuffer has been detached from the view");
     82        return throwVMTypeError(exec, ASCIILiteral("Underlying ArrayBuffer has been detached from the view"));
    8483
    8584    return JSValue::encode(jsNumber(thisObject->length()));
     
    188187}
    189188
    190 static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncSubarray(ExecState* exec)
    191 {
    192     JSValue thisValue = exec->thisValue();
    193     if (!thisValue.isObject())
    194         return throwVMTypeError(exec, ASCIILiteral("Receiver should be a typed array view but was not an object"));
    195     CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewProtoFuncSubarray);
     189EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSubarrayCreate(ExecState* exec)
     190{
     191    JSValue thisValue = exec->thisValue();
     192    if (!thisValue.isObject())
     193        return throwVMTypeError(exec, ASCIILiteral("Receiver should be a typed array view but was not an object"));
     194    CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewPrivateFuncSubarrayCreate);
    196195}
    197196
     
    277276    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, typedArrayViewProtoFuncSlice, DontEnum, 2);
    278277    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("some", typedArrayPrototypeSomeCodeGenerator, DontEnum);
    279     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->subarray, typedArrayViewProtoFuncSubarray, DontEnum, 2);
     278    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->subarray, typedArrayPrototypeSubarrayCodeGenerator, DontEnum);
    280279    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, typedArrayPrototypeToLocaleStringCodeGenerator, DontEnum);
    281280
  • trunk/Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.h

    r202363 r203076  
    5151EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncLength(ExecState*);
    5252EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncGetOriginalConstructor(ExecState*);
     53EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSubarrayCreate(ExecState*);
    5354
    5455   
Note: See TracChangeset for help on using the changeset viewer.