Ignore:
Timestamp:
Jan 5, 2016, 2:49:44 PM (10 years ago)
Author:
[email protected]
Message:

[ES6] Arrays should be subclassable.
https://bugs.webkit.org/show_bug.cgi?id=152706

Reviewed by Benjamin Poulain.

This patch enables full subclassing of Arrays. We do this by fetching the new.target's prototype property
in the Array constructor and transitioning the old structure to have the new prototype. This method has
two downsides. The first is that we clobber the transition watchpoint on the base structure. The second,
which is currently very significant but should be fixed in a future patch, is that we allocate a new
structure for each new derived class we allocate.

  • runtime/ArrayConstructor.cpp:

(JSC::constructArrayWithSizeQuirk):
(JSC::constructWithArrayConstructor):
(JSC::callArrayConstructor):

  • runtime/ArrayConstructor.h:
  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::arrayStructureForIndexingTypeDuringAllocation):
(JSC::JSGlobalObject::arrayStructureForProfileDuringAllocation):
(JSC::constructEmptyArray):
(JSC::constructArray):
(JSC::constructArrayNegativeIndexed):

  • runtime/PrototypeMap.h:
  • runtime/Structure.h:
  • runtime/StructureInlines.h:

(JSC::Structure::createSubclassStructure):

  • tests/es6.yaml:
  • tests/stress/class-subclassing-array.js: Added.

(A):
(B.prototype.get 1):
(B):
(C):
(test):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r194248 r194612  
    248248    WriteBarrier<Structure> m_originalArrayStructureForIndexingShape[NumberOfIndexingShapes];
    249249    // Lists the structures we should use during allocation for these particular indexing shapes.
     250    // These structures will differ from the originals list above when we are having a bad time.
    250251    WriteBarrier<Structure> m_arrayStructureForIndexingShapeDuringAllocation[NumberOfIndexingShapes];
    251252
     
    482483        return m_arrayStructureForIndexingShapeDuringAllocation[(indexingType & IndexingShapeMask) >> IndexingShapeShift].get();
    483484    }
    484     Structure* arrayStructureForProfileDuringAllocation(ArrayAllocationProfile* profile) const
    485     {
    486         return arrayStructureForIndexingTypeDuringAllocation(ArrayAllocationProfile::selectIndexingTypeFor(profile));
     485    Structure* arrayStructureForIndexingTypeDuringAllocation(VM& vm, IndexingType indexingType, JSValue prototype) const
     486    {
     487        return Structure::createSubclassStructure(vm, arrayStructureForIndexingTypeDuringAllocation(indexingType), prototype);
     488    }
     489    Structure* arrayStructureForProfileDuringAllocation(VM& vm, ArrayAllocationProfile* profile, JSValue prototype) const
     490    {
     491        return arrayStructureForIndexingTypeDuringAllocation(vm, ArrayAllocationProfile::selectIndexingTypeFor(profile), prototype);
    487492    }
    488493       
     
    722727}
    723728
    724 inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, unsigned initialLength = 0)
    725 {
    726     return ArrayAllocationProfile::updateLastAllocationFor(profile, JSArray::create(exec->vm(), initialLength >= MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : globalObject->arrayStructureForProfileDuringAllocation(profile), initialLength));
    727 }
    728 
    729 inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, unsigned initialLength = 0)
    730 {
    731     return constructEmptyArray(exec, profile, exec->lexicalGlobalObject(), initialLength);
     729inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, unsigned initialLength = 0, JSValue prototype = JSValue())
     730{
     731    VM& vm = exec->vm();
     732    Structure* structure;
     733    if (initialLength >= MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)
     734        structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(vm, ArrayWithArrayStorage, prototype);
     735    else
     736        structure = globalObject->arrayStructureForProfileDuringAllocation(vm, profile, prototype);
     737
     738    return ArrayAllocationProfile::updateLastAllocationFor(profile, JSArray::create(vm, structure, initialLength));
     739}
     740
     741inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, unsigned initialLength = 0, JSValue prototype = JSValue())
     742{
     743    return constructEmptyArray(exec, profile, exec->lexicalGlobalObject(), initialLength, prototype);
    732744}
    733745 
    734 inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values)
    735 {
    736     return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values));
    737 }
    738 
    739 inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values)
    740 {
    741     return constructArray(exec, profile, exec->lexicalGlobalObject(), values);
    742 }
    743 
    744 inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
    745 {
    746     return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values, length));
    747 }
    748 
    749 inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length)
    750 {
    751     return constructArray(exec, profile, exec->lexicalGlobalObject(), values, length);
    752 }
    753 
    754 inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
    755 {
    756     return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArrayNegativeIndexed(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values, length));
    757 }
    758 
    759 inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length)
    760 {
    761     return constructArrayNegativeIndexed(exec, profile, exec->lexicalGlobalObject(), values, length);
     746inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values, JSValue prototype = JSValue())
     747{
     748    return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(exec->vm(), profile, prototype), values));
     749}
     750
     751inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values, JSValue prototype = JSValue())
     752{
     753    return constructArray(exec, profile, exec->lexicalGlobalObject(), values, prototype);
     754}
     755
     756inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length, JSValue prototype = JSValue())
     757{
     758    return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(exec->vm(), profile, prototype), values, length));
     759}
     760
     761inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length, JSValue prototype = JSValue())
     762{
     763    return constructArray(exec, profile, exec->lexicalGlobalObject(), values, length, prototype);
     764}
     765
     766inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length, JSValue prototype = JSValue())
     767{
     768    return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArrayNegativeIndexed(exec, globalObject->arrayStructureForProfileDuringAllocation(exec->vm(), profile, prototype), values, length));
     769}
     770
     771inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length, JSValue prototype = JSValue())
     772{
     773    return constructArrayNegativeIndexed(exec, profile, exec->lexicalGlobalObject(), values, length, prototype);
    762774}
    763775
Note: See TracChangeset for help on using the changeset viewer.