Ignore:
Timestamp:
May 22, 2018, 11:04:31 AM (7 years ago)
Author:
[email protected]
Message:

We should have a CoW storage for NewArrayBuffer arrays.
https://bugs.webkit.org/show_bug.cgi?id=185003

Reviewed by Filip Pizlo.

JSTests:

  • stress/cow-convert-contiguous-to-array-storage.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/cow-convert-double-to-array-storage.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/cow-convert-double-to-contiguous.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/cow-convert-int32-to-array-storage.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/cow-convert-int32-to-contiguous.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/cow-convert-int32-to-double.js: Added.

(createBuffer):
(shouldBe):
(test):

  • stress/put-on-cow-prototype.js: Added.

(putByVal):
(putById):

Source/JavaScriptCore:

This patch adds copy on write storage for new array buffers. In
order to do this there needed to be significant changes to the
layout of IndexingType. The new indexing type has the following
shape:

struct IndexingTypeAndMisc {

struct IndexingModeIncludingHistory {

struct IndexingMode {

struct IndexingType {

uint8_t isArray:1; bit 0
uint8_t shape:3;
bit 1 - 3

};
uint8_t copyOnWrite:1; bit 4

};
uint8_t mayHaveIndexedAccessors:1; bit 5

};
uint8_t cellLockBits:2; bit 6 - 7

};

For simplicity ArrayStorage shapes cannot be CoW. So the only
valid CoW indexing shapes are ArrayWithInt32, ArrayWithDouble, and
ArrayWithContiguous.

The backing store for a CoW array is a new class
JSImmutableButterfly, which looks exactly the same as a normal
butterfly except that it has a JSCell header. Like other
butterflies, JSImmutableButterfies are allocated out of the
Auxiliary Gigacage and are pointed to by JSCells in the same
way. However, when marking JSImmutableButterflies they are marked
as if they were a property.

With CoW arrays, the new_array_buffer bytecode will reallocate the
shared JSImmutableButterfly if it sees from the allocation profile
that the last array it allocated has transitioned to a different
indexing type. From then on, all arrays created by that
new_array_buffer bytecode will have the promoted indexing
type. This is more or less the same as what we used to do. The
only difference is that we don't promote all the way to array
storage even if we have seen it before.

Transitioning from a CoW indexing mode occurs whenever someone
tries to store to an element, grow the array, or add properties.
Storing or growing the array will call into code that does the
stupid thing of copying the butterfly then continue into the old
code. This doesn't end up costing us as future allocations will
use any upgraded indexing shape. We get adding properties for
free by just changing the indexing mode on transition (our C++
code always updates the indexing mode).

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/ArrayAllocationProfile.cpp:

(JSC::ArrayAllocationProfile::updateProfile):

  • bytecode/ArrayAllocationProfile.h:

(JSC::ArrayAllocationProfile::initializeIndexingMode):

  • bytecode/ArrayProfile.cpp:

(JSC::dumpArrayModes):
(JSC::ArrayProfile::briefDescriptionWithoutUpdating):

  • bytecode/ArrayProfile.h:

(JSC::asArrayModes):
(JSC::arrayModeFromStructure):
(JSC::arrayModesInclude):
(JSC::hasSeenCopyOnWriteArray):

  • bytecode/BytecodeList.json:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecode/InlineAccess.cpp:

(JSC::InlineAccess::generateArrayLength):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::addArrayAllocationProfile):
(JSC::UnlinkedCodeBlock::decompressArrayAllocationProfile):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::newArrayAllocationProfile):
(JSC::BytecodeGenerator::emitNewArrayBuffer):
(JSC::BytecodeGenerator::emitNewArray):
(JSC::BytecodeGenerator::emitNewArrayWithSize):
(JSC::BytecodeGenerator::emitExpectedFunctionSnippet):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ArrayNode::emitBytecode):
(JSC::ArrayPatternNode::bindValue const):
(JSC::ArrayPatternNode::emitDirectBinding):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGArgumentsEliminationPhase.cpp:
  • dfg/DFGArgumentsUtilities.cpp:

(JSC::DFG::emitCodeToGetArgumentsArrayLength):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::fromObserved):
(JSC::DFG::ArrayMode::refine const):
(JSC::DFG::ArrayMode::alreadyChecked const):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::ArrayMode):
(JSC::DFG::ArrayMode::action const):
(JSC::DFG::ArrayMode::withSpeculation const):
(JSC::DFG::ArrayMode::withArrayClass const):
(JSC::DFG::ArrayMode::withType const):
(JSC::DFG::ArrayMode::withConversion const):
(JSC::DFG::ArrayMode::withTypeAndConversion const):
(JSC::DFG::ArrayMode::arrayModesThatPassFiltering const):
(JSC::DFG::ArrayMode::arrayModesWithIndexingShape const):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
(JSC::DFG::ByteCodeParser::handleIntrinsicGetter):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::attemptToForceStringArrayModeByToStringConversion):
(JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNode.h:

(JSC::DFG::Node::indexingType):
(JSC::DFG::Node::indexingMode):

  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::compileExit):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
(JSC::DFG::SpeculativeJIT::arrayify):
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
(JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileCreateRest):
(JSC::DFG::SpeculativeJIT::compileArraySlice):
(JSC::DFG::SpeculativeJIT::compileNewArrayBuffer):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGValidate.cpp:
  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compilePutStructure):
(JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargsSpread):
(JSC::FTL::DFG::LowerDFGToB3::compileForwardVarargsWithSpread):
(JSC::FTL::DFG::LowerDFGToB3::storeStructure):
(JSC::FTL::DFG::LowerDFGToB3::isArrayTypeForArrayify):

  • ftl/FTLOperations.cpp:

(JSC::FTL::operationMaterializeObjectInOSR):

  • generate-bytecode-files:
  • interpreter/Interpreter.cpp:

(JSC::sizeOfVarargs):
(JSC::loadVarargs):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):

  • jit/JITOperations.cpp:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):

  • jit/Repatch.cpp:

(JSC::tryCachePutByID):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/Butterfly.h:

(JSC::ContiguousData::Data::Data):
(JSC::ContiguousData::Data::operator bool const):
(JSC::ContiguousData::Data::operator=):
(JSC::ContiguousData::Data::operator const T& const):
(JSC::ContiguousData::Data::set):
(JSC::ContiguousData::Data::setWithoutWriteBarrier):
(JSC::ContiguousData::Data::clear):
(JSC::ContiguousData::Data::get const):
(JSC::ContiguousData::atUnsafe):
(JSC::ContiguousData::at const): Deleted.
(JSC::ContiguousData::at): Deleted.

  • runtime/ButterflyInlines.h:

(JSC::ContiguousData<T>::at const):
(JSC::ContiguousData<T>::at):

  • runtime/ClonedArguments.cpp:

(JSC::ClonedArguments::createEmpty):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::allocateNewArrayBuffer):

  • runtime/IndexingType.cpp:

(JSC::leastUpperBoundOfIndexingTypeAndType):
(JSC::leastUpperBoundOfIndexingTypeAndValue):
(JSC::dumpIndexingType):

  • runtime/IndexingType.h:

(JSC::hasIndexedProperties):
(JSC::hasUndecided):
(JSC::hasInt32):
(JSC::hasDouble):
(JSC::hasContiguous):
(JSC::hasArrayStorage):
(JSC::hasAnyArrayStorage):
(JSC::hasSlowPutArrayStorage):
(JSC::shouldUseSlowPut):
(JSC::isCopyOnWrite):
(JSC::arrayIndexFromIndexingType):

  • runtime/JSArray.cpp:

(JSC::JSArray::tryCreateUninitializedRestricted):
(JSC::JSArray::put):
(JSC::JSArray::appendMemcpy):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::fastSlice):
(JSC::JSArray::shiftCountWithAnyIndexingType):
(JSC::JSArray::unshiftCountWithAnyIndexingType):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):

  • runtime/JSArrayInlines.h:

(JSC::JSArray::pushInline):

  • runtime/JSCell.h:
  • runtime/JSCellInlines.h:

(JSC::JSCell::JSCell):
(JSC::JSCell::finishCreation):
(JSC::JSCell::indexingType const):
(JSC::JSCell::indexingMode const):
(JSC::JSCell::setStructure):

  • runtime/JSFixedArray.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::haveABadTime):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::originalArrayStructureForIndexingType const):
(JSC::JSGlobalObject::arrayStructureForIndexingTypeDuringAllocation const):
(JSC::JSGlobalObject::isOriginalArrayStructure):

  • runtime/JSImmutableButterfly.cpp: Added.

(JSC::JSImmutableButterfly::visitChildren):
(JSC::JSImmutableButterfly::copyToArguments):

  • runtime/JSImmutableButterfly.h: Added.

(JSC::JSImmutableButterfly::createStructure):
(JSC::JSImmutableButterfly::tryCreate):
(JSC::JSImmutableButterfly::create):
(JSC::JSImmutableButterfly::publicLength const):
(JSC::JSImmutableButterfly::vectorLength const):
(JSC::JSImmutableButterfly::length const):
(JSC::JSImmutableButterfly::toButterfly const):
(JSC::JSImmutableButterfly::fromButterfly):
(JSC::JSImmutableButterfly::get const):
(JSC::JSImmutableButterfly::subspaceFor):
(JSC::JSImmutableButterfly::setIndex):
(JSC::JSImmutableButterfly::allocationSize):
(JSC::JSImmutableButterfly::JSImmutableButterfly):

  • runtime/JSObject.cpp:

(JSC::JSObject::markAuxiliaryAndVisitOutOfLineProperties):
(JSC::JSObject::visitButterflyImpl):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::putByIndex):
(JSC::JSObject::createInitialInt32):
(JSC::JSObject::createInitialDouble):
(JSC::JSObject::createInitialContiguous):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToArrayStorage):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::convertDoubleToArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::createInitialForValueAndSet):
(JSC::JSObject::convertInt32ForValue):
(JSC::JSObject::convertFromCopyOnWrite):
(JSC::JSObject::ensureWritableInt32Slow):
(JSC::JSObject::ensureWritableDoubleSlow):
(JSC::JSObject::ensureWritableContiguousSlow):
(JSC::JSObject::ensureArrayStorageSlow):
(JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode):
(JSC::JSObject::switchToSlowPutArrayStorage):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::canDoFastPutDirectIndex):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putByIndexBeyondVectorLength):
(JSC::JSObject::countElements):
(JSC::JSObject::ensureLengthSlow):
(JSC::JSObject::getEnumerableLength):
(JSC::JSObject::ensureInt32Slow): Deleted.
(JSC::JSObject::ensureDoubleSlow): Deleted.
(JSC::JSObject::ensureContiguousSlow): Deleted.

  • runtime/JSObject.h:

(JSC::JSObject::putDirectIndex):
(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::tryGetIndexQuickly const):
(JSC::JSObject::canSetIndexQuickly):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::initializeIndexWithoutBarrier):
(JSC::JSObject::ensureWritableInt32):
(JSC::JSObject::ensureWritableDouble):
(JSC::JSObject::ensureWritableContiguous):
(JSC::JSObject::ensureLength):
(JSC::JSObject::ensureInt32): Deleted.
(JSC::JSObject::ensureDouble): Deleted.
(JSC::JSObject::ensureContiguous): Deleted.

  • runtime/JSObjectInlines.h:

(JSC::JSObject::putDirectInternal):

  • runtime/JSType.h:
  • runtime/RegExpMatchesArray.h:

(JSC::tryCreateUninitializedRegExpMatchesArray):

  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::addNewPropertyTransition):
(JSC::Structure::nonPropertyTransition):

  • runtime/Structure.h:
  • runtime/StructureIDBlob.h:

(JSC::StructureIDBlob::StructureIDBlob):
(JSC::StructureIDBlob::indexingModeIncludingHistory const):
(JSC::StructureIDBlob::setIndexingModeIncludingHistory):
(JSC::StructureIDBlob::indexingModeIncludingHistoryOffset):
(JSC::StructureIDBlob::indexingTypeIncludingHistory const): Deleted.
(JSC::StructureIDBlob::setIndexingTypeIncludingHistory): Deleted.
(JSC::StructureIDBlob::indexingTypeIncludingHistoryOffset): Deleted.

  • runtime/StructureTransitionTable.h:

(JSC::newIndexingType):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WebCore:

  • bindings/js/JSDOMConvertSequences.h:

(WebCore::Detail::NumericSequenceConverter::convertArray):
(WebCore::Detail::SequenceConverter::convertArray):

LayoutTests:

Test should have a real error that gives you the stack.

  • js/slow-stress/script-tests/variadic-closure-call.js:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r230078 r232070  
    4343    else
    4444        nonArray = Array::NonArray;
    45    
     45
     46    auto handleContiguousModes = [&] (Array::Type type, ArrayModes observed) {
     47        Array::Class isArray;
     48        Array::Conversion converts;
     49
     50        RELEASE_ASSERT((observed & (asArrayModes(toIndexingShape(type)) | asArrayModes(toIndexingShape(type) | ArrayClass) | asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite))) == observed);
     51
     52        if (observed & asArrayModes(toIndexingShape(type))) {
     53            if ((observed & asArrayModes(toIndexingShape(type))) == observed)
     54                isArray = nonArray;
     55            else
     56                isArray = Array::PossiblyArray;
     57        } else
     58            isArray = Array::Array;
     59
     60        if (action == Array::Write && (observed & asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite)))
     61            converts = Array::Convert;
     62        else
     63            converts = Array::AsIs;
     64
     65        return ArrayMode(type, isArray, converts, action).withProfile(locker, profile, makeSafe);
     66    };
     67
    4668    ArrayModes observed = profile->observedArrayModes(locker);
    4769    switch (observed) {
     
    5072    case asArrayModes(NonArray):
    5173        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
    52             return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert);
    53         return ArrayMode(Array::SelectUsingPredictions, nonArray).withSpeculationFromProfile(locker, profile, makeSafe);
     74            return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert, action);
     75        return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(locker, profile, makeSafe);
    5476
    5577    case asArrayModes(ArrayWithUndecided):
    5678        if (action == Array::Write)
    57             return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert);
    58         return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs).withProfile(locker, profile, makeSafe);
     79            return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert, action);
     80        return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    5981       
    6082    case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided):
    6183        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
    62             return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert);
    63         return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
     84            return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert, action);
     85        return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(locker, profile, makeSafe);
    6486
    6587    case asArrayModes(NonArrayWithInt32):
    66         return ArrayMode(Array::Int32, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
    6788    case asArrayModes(ArrayWithInt32):
    68         return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
    6989    case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32):
    70         return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     90    case asArrayModes(NonArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
     91    case asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
     92    case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
     93        return handleContiguousModes(Array::Int32, observed);
    7194
    7295    case asArrayModes(NonArrayWithDouble):
    73         return ArrayMode(Array::Double, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
    7496    case asArrayModes(ArrayWithDouble):
    75         return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
    7697    case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble):
    77         return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     98    case asArrayModes(NonArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
     99    case asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
     100    case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
     101        return handleContiguousModes(Array::Double, observed);
    78102
    79103    case asArrayModes(NonArrayWithContiguous):
    80         return ArrayMode(Array::Contiguous, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
    81104    case asArrayModes(ArrayWithContiguous):
    82         return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
    83105    case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
    84         return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     106    case asArrayModes(NonArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
     107    case asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
     108    case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
     109        return handleContiguousModes(Array::Contiguous, observed);
    85110
    86111    case asArrayModes(NonArrayWithArrayStorage):
    87         return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     112        return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    88113    case asArrayModes(NonArrayWithSlowPutArrayStorage):
    89114    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
    90         return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     115        return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    91116    case asArrayModes(ArrayWithArrayStorage):
    92         return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
     117        return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    93118    case asArrayModes(ArrayWithSlowPutArrayStorage):
    94119    case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
    95         return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
     120        return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    96121    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage):
    97         return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     122        return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    98123    case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
    99124    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
    100         return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     125        return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    101126    case Int8ArrayMode:
    102         return ArrayMode(Array::Int8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     127        return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    103128    case Int16ArrayMode:
    104         return ArrayMode(Array::Int16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     129        return ArrayMode(Array::Int16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    105130    case Int32ArrayMode:
    106         return ArrayMode(Array::Int32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     131        return ArrayMode(Array::Int32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    107132    case Uint8ArrayMode:
    108         return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     133        return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    109134    case Uint8ClampedArrayMode:
    110         return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     135        return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    111136    case Uint16ArrayMode:
    112         return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     137        return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    113138    case Uint32ArrayMode:
    114         return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     139        return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    115140    case Float32ArrayMode:
    116         return ArrayMode(Array::Float32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     141        return ArrayMode(Array::Float32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    117142    case Float64ArrayMode:
    118         return ArrayMode(Array::Float64Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     143        return ArrayMode(Array::Float64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    119144
    120145    default:
    121146        // If we have seen multiple TypedArray types, or a TypedArray and non-typed array, it doesn't make sense to try to convert the object since you can't convert typed arrays.
    122147        if (observed & ALL_TYPED_ARRAY_MODES)
    123             return ArrayMode(Array::Generic, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
     148            return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    124149
    125150        if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
     
    151176            arrayClass = Array::PossiblyArray;
    152177       
    153         return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe);
     178        return ArrayMode(type, arrayClass, Array::Convert, action).withProfile(locker, profile, makeSafe);
    154179    }
    155180}
     
    172197        // realized that the callsite could not have possibly executed. It may be worthwhile
    173198        // to fix that, but for now I'm leaving it as-is.
    174         return ArrayMode(Array::ForceExit);
     199        return ArrayMode(Array::ForceExit, action());
    175200    }
    176201   
    177202    if (!isInt32Speculation(index))
    178         return ArrayMode(Array::Generic);
     203        return ArrayMode(Array::Generic, action());
    179204   
    180205    // If we had exited because of an exotic object behavior, then don't try to specialize.
    181206    if (graph.hasExitSite(node->origin.semantic, ExoticObjectMode))
    182         return ArrayMode(Array::Generic);
     207        return ArrayMode(Array::Generic, action());
    183208   
    184209    // Note: our profiling currently doesn't give us good information in case we have
     
    197222            // which we can't model as a simple store to the typed array since typed array indexed properties
    198223            // are non-configurable.
    199             return ArrayMode(Array::Generic);
     224            return ArrayMode(Array::Generic, action());
    200225        }
    201226        return result;
     
    228253                return withSpeculation(Array::SaneChain);
    229254        }
    230         return ArrayMode(Array::Generic);
     255        return ArrayMode(Array::Generic, action());
    231256    }
    232257    case Array::Int32:
     
    273298                // https://bugs.webkit.org/show_bug.cgi?id=179596
    274299                if (type == Array::DirectArguments)
    275                     return ArrayMode(type, Array::NonArray, Array::OutOfBounds, Array::AsIs);
    276                 return ArrayMode(Array::Generic);
     300                    return ArrayMode(type, Array::NonArray, Array::OutOfBounds, Array::AsIs, action());
     301                return ArrayMode(Array::Generic, action());
    277302            }
    278303            if (isX86() && is32Bit() && isScopedArgumentsSpeculation(base))
    279                 return ArrayMode(Array::Generic);
     304                return ArrayMode(Array::Generic, action());
    280305            return withType(type);
    281306        }
     
    323348
    324349        if (type() == Array::Unprofiled)
    325             return ArrayMode(Array::ForceExit);
    326         return ArrayMode(Array::Generic);
     350            return ArrayMode(Array::ForceExit, action());
     351        return ArrayMode(Array::Generic, action());
    327352    }
    328353
     
    383408            if ((structure->indexingType() & IndexingShapeMask) != shape)
    384409                return false;
     410            if (isCopyOnWrite(structure->indexingMode()) && action() == Array::Write)
     411                return false;
    385412            if (!(structure->indexingType() & IsArray))
    386413                return false;
     
    398425        for (unsigned i = value.m_structure.size(); i--;) {
    399426            RegisteredStructure structure = value.m_structure[i];
    400             if ((structure->indexingType() & IndexingShapeMask) != shape)
     427            if ((structure->indexingMode() & IndexingShapeMask) != shape)
     428                return false;
     429            if (isCopyOnWrite(structure->indexingMode()) && action() == Array::Write)
    401430                return false;
    402431            if (!(structure->indexingType() & IsArray))
     
    413442        for (unsigned i = value.m_structure.size(); i--;) {
    414443            RegisteredStructure structure = value.m_structure[i];
    415             if ((structure->indexingType() & IndexingShapeMask) != shape)
     444            if ((structure->indexingMode() & IndexingShapeMask) != shape)
     445                return false;
     446            if (isCopyOnWrite(structure->indexingMode()) && action() == Array::Write)
    416447                return false;
    417448        }
Note: See TracChangeset for help on using the changeset viewer.