Commit 0e9910a8 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSC should infer when indexed storage is contiguous, and optimize for it

https://bugs.webkit.org/show_bug.cgi?id=97288

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore: 

This introduces a new kind of indexed property storage called Contiguous,
which has the following properties:
        
- No header bits beyond IndexedHeader. This results in a 16 byte reduction
  in memory usage per array versus an ArrayStorage array. It also means
  that the total memory usage for an empty array is now just 3 * 8 on both
  32-bit and 64-bit. Of that, only 8 bytes are array-specific; the rest is
  our standard object header overhead.
        
- No need for hole checks on store. This results in a ~4% speed-up on
  Kraken and a ~1% speed-up on V8v7.
        
- publicLength <= vectorLength. This means that doing new Array(blah)
  immediately allocates room for blah elements.
        
- No sparse map or index bias.
        
If you ever do things to an array that would require publicLength >
vectorLength, a sparse map, or index bias, then we switch to ArrayStorage
mode. This seems to never happen in any benchmark we track, and is unlikely
to happen very frequently on any website.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::JumpList::append):
* assembler/MacroAssembler.h:
(MacroAssembler):
(JSC::MacroAssembler::patchableBranchTest32):
* bytecode/ByValInfo.h: Added.
(JSC):
(JSC::isOptimizableIndexingType):
(JSC::jitArrayModeForIndexingType):
(JSC::ByValInfo::ByValInfo):
(ByValInfo):
(JSC::getByValInfoBytecodeIndex):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::getByValInfo):
(JSC::CodeBlock::setNumberOfByValInfos):
(JSC::CodeBlock::numberOfByValInfos):
(JSC::CodeBlock::byValInfo):
* bytecode/SamplingTool.h:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::fromObserved):
(JSC::DFG::modeAlreadyChecked):
(JSC::DFG::modeToString):
* dfg/DFGArrayMode.h:
(DFG):
(JSC::DFG::modeUsesButterfly):
(JSC::DFG::modeIsJSArray):
(JSC::DFG::isInBoundsAccess):
(JSC::DFG::mayStoreToTail):
(JSC::DFG::mayStoreToHole):
(JSC::DFG::modeIsPolymorphic):
(JSC::DFG::polymorphicIncludesContiguous):
(JSC::DFG::polymorphicIncludesArrayStorage):
(JSC::DFG::canCSEStorage):
(JSC::DFG::modeSupportsLength):
(JSC::DFG::benefitsFromStructureCheck):
(JSC::DFG::isEffectful):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsic):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getArrayLengthElimination):
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::checkArray):
(JSC::DFG::FixupPhase::blessArrayOperation):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::byValIsPure):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGRepatch.cpp:
(JSC::DFG::tryCacheGetByID):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::arrayify):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::temporaryRegisterForPutByVal):
(DFG):
* dfg/DFGSpeculativeJIT.h:
(DFG):
(JSC::DFG::SpeculativeJIT::callOperation):
(SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::putByValWillNeedExtraRegister):
(JSC::DFG::SpeculativeJIT::temporaryRegisterForPutByVal):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compileContiguousGetByVal):
(DFG):
(JSC::DFG::SpeculativeJIT::compileArrayStorageGetByVal):
(JSC::DFG::SpeculativeJIT::compileContiguousPutByVal):
(JSC::DFG::SpeculativeJIT::compileArrayStoragePutByVal):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compileContiguousGetByVal):
(DFG):
(JSC::DFG::SpeculativeJIT::compileArrayStorageGetByVal):
(JSC::DFG::SpeculativeJIT::compileContiguousPutByVal):
(JSC::DFG::SpeculativeJIT::compileArrayStoragePutByVal):
(JSC::DFG::SpeculativeJIT::compile):
* interpreter/Interpreter.cpp:
(SamplingScope):
(JSC::SamplingScope::SamplingScope):
(JSC::SamplingScope::~SamplingScope):
(JSC):
(JSC::Interpreter::execute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JSC::ByValCompilationInfo::ByValCompilationInfo):
(ByValCompilationInfo):
(JSC):
(JIT):
(JSC::JIT::compileGetByVal):
(JSC::JIT::compilePutByVal):
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateJSArray):
(JSC::JIT::emitArrayProfileStoreToHoleSpecialCase):
(JSC):
(JSC::arrayProfileSaw):
(JSC::JIT::chooseArrayMode):
* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_get_argument_by_val):
(JSC::JIT::emit_op_new_array):
(JSC::JIT::emitSlow_op_new_array):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emitSlow_op_get_argument_by_val):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC):
(JSC::JIT::emitContiguousGetByVal):
(JSC::JIT::emitArrayStorageGetByVal):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):
(JSC::JIT::privateCompileGetByVal):
(JSC::JIT::privateCompilePutByVal):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC):
(JSC::JIT::emitContiguousGetByVal):
(JSC::JIT::emitArrayStorageGetByVal):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emitSlow_op_put_by_val):
* jit/JITStubs.cpp:
(JSC::getByVal):
(JSC):
(JSC::DEFINE_STUB_FUNCTION):
(JSC::putByVal):
* jit/JITStubs.h:
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/ArrayConventions.h:
(JSC::isDenseEnoughForVector):
* runtime/ArrayPrototype.cpp:
(JSC):
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
* runtime/Butterfly.h:
(Butterfly):
(JSC::Butterfly::fromPointer):
(JSC::Butterfly::pointer):
(JSC::Butterfly::publicLength):
(JSC::Butterfly::vectorLength):
(JSC::Butterfly::setPublicLength):
(JSC::Butterfly::setVectorLength):
(JSC::Butterfly::contiguous):
(JSC::Butterfly::fromContiguous):
* runtime/ButterflyInlineMethods.h:
(JSC::Butterfly::unshift):
(JSC::Butterfly::shift):
* runtime/IndexingHeaderInlineMethods.h:
(JSC::IndexingHeader::indexingPayloadSizeInBytes):
* runtime/IndexingType.cpp: Added.
(JSC):
(JSC::indexingTypeToString):
* runtime/IndexingType.h:
(JSC):
(JSC::hasContiguous):
* runtime/JSArray.cpp:
(JSC::JSArray::setLengthWithArrayStorage):
(JSC::JSArray::setLength):
(JSC):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::shiftCountWithArrayStorage):
(JSC::JSArray::shiftCountWithAnyIndexingType):
(JSC::JSArray::unshiftCountWithArrayStorage):
(JSC::JSArray::unshiftCountWithAnyIndexingType):
(JSC::JSArray::sortNumericVector):
(JSC::JSArray::sortNumeric):
(JSC::JSArray::sortCompactedVector):
(JSC::JSArray::sort):
(JSC::JSArray::sortVector):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):
(JSC::JSArray::compactForSorting):
* runtime/JSArray.h:
(JSC::JSArray::shiftCountForShift):
(JSC::JSArray::shiftCountForSplice):
(JSArray):
(JSC::JSArray::shiftCount):
(JSC::JSArray::unshiftCountForShift):
(JSC::JSArray::unshiftCountForSplice):
(JSC::JSArray::unshiftCount):
(JSC::JSArray::isLengthWritable):
(JSC::createContiguousArrayButterfly):
(JSC):
(JSC::JSArray::create):
(JSC::JSArray::tryCreateUninitialized):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC):
(JSC::JSGlobalObject::haveABadTime):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::arrayStructureWithArrayStorage):
(JSC::JSGlobalObject::addressOfArrayStructureWithArrayStorage):
(JSC::constructEmptyArray):
* runtime/JSObject.cpp:
(JSC::JSObject::visitButterfly):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::putByIndex):
(JSC::JSObject::enterDictionaryIndexingMode):
(JSC::JSObject::createInitialContiguous):
(JSC):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::ensureContiguousSlow):
(JSC::JSObject::ensureArrayStorageSlow):
(JSC::JSObject::ensureIndexedStorageSlow):
(JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode):
(JSC::JSObject::switchToSlowPutArrayStorage):
(JSC::JSObject::setPrototype):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthContiguousWithoutAttributes):
(JSC::JSObject::putByIndexBeyondVectorLength):
(JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putDirectIndexBeyondVectorLength):
(JSC::JSObject::getNewVectorLength):
(JSC::JSObject::countElementsInContiguous):
(JSC::JSObject::increaseVectorLength):
(JSC::JSObject::ensureContiguousLengthSlow):
(JSC::JSObject::getOwnPropertyDescriptor):
* runtime/JSObject.h:
(JSC::JSObject::getArrayLength):
(JSC::JSObject::getVectorLength):
(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::tryGetIndexQuickly):
(JSC::JSObject::canSetIndexQuickly):
(JSC::JSObject::canSetIndexQuicklyForPutDirect):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::hasSparseMap):
(JSC::JSObject::inSparseIndexingMode):
(JSObject):
(JSC::JSObject::ensureContiguous):
(JSC::JSObject::ensureIndexedStorage):
(JSC::JSObject::ensureContiguousLength):
(JSC::JSObject::indexingData):
(JSC::JSObject::relevantLength):
* runtime/JSValue.cpp:
(JSC::JSValue::description):
* runtime/Options.cpp:
(JSC::Options::initialize):
* runtime/Structure.cpp:
(JSC::Structure::needsSlowPutIndexing):
(JSC):
(JSC::Structure::suggestedArrayStorageTransition):
* runtime/Structure.h:
(Structure):
* runtime/StructureTransitionTable.h:
(JSC::newIndexingType):

Source/WTF: 

Moved out this helpful math utility to MathExtras, since we now use it in
multiple places.

* wtf/MathExtras.h:
(timesThreePlusOneDividedByTwo):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@130826 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9f69b20a
......@@ -191,6 +191,7 @@ SET(JavaScriptCore_SOURCES
runtime/GCActivityCallback.cpp
runtime/GetterSetter.cpp
runtime/Identifier.cpp
runtime/IndexingType.cpp
runtime/InitializeThreading.cpp
runtime/InternalFunction.cpp
runtime/JSActivation.cpp
......
This diff is collapsed.
......@@ -84,6 +84,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/assembler/X86Assembler.h \
Source/JavaScriptCore/bytecode/ArrayProfile.cpp \
Source/JavaScriptCore/bytecode/ArrayProfile.h \
Source/JavaScriptCore/bytecode/ByValInfo.h \
Source/JavaScriptCore/bytecode/BytecodeConventions.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
......@@ -521,6 +522,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/Identifier.h \
Source/JavaScriptCore/runtime/IndexingHeaderInlineMethods.h \
Source/JavaScriptCore/runtime/IndexingHeader.h \
Source/JavaScriptCore/runtime/IndexingType.cpp \
Source/JavaScriptCore/runtime/IndexingType.h \
Source/JavaScriptCore/runtime/InitializeThreading.cpp \
Source/JavaScriptCore/runtime/InitializeThreading.h \
......
......@@ -521,6 +521,10 @@
RelativePath="..\..\runtime\ArrayStorage.h"
>
</File>
<File
RelativePath="..\..\runtime\IndexingType.cpp"
>
</File>
<File
RelativePath="..\..\runtime\IndexingType.h"
>
......@@ -1573,6 +1577,10 @@
RelativePath="..\..\bytecode\ArrayProfile.h"
>
</File>
<File
RelativePath="..\..\bytecode\ByValInfo.h"
>
</File>
<File
RelativePath="..\..\bytecode\CallLinkInfo.cpp"
>
......
......@@ -76,6 +76,7 @@
0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */; };
0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */; };
0F16015E156198C900C2587C /* DFGArgumentsSimplificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -165,6 +166,7 @@
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */; };
0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */; };
......@@ -850,6 +852,7 @@
0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutDirectIndexMode.h; sourceTree = "<group>"; };
0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SparseArrayValueMap.cpp; sourceTree = "<group>"; };
0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; };
0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsSimplificationPhase.cpp; path = dfg/DFGArgumentsSimplificationPhase.cpp; sourceTree = "<group>"; };
0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentsSimplificationPhase.h; path = dfg/DFGArgumentsSimplificationPhase.h; sourceTree = "<group>"; };
......@@ -940,6 +943,7 @@
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = "<group>"; };
0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSymbolTableObject.cpp; sourceTree = "<group>"; };
0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSymbolTableObject.h; sourceTree = "<group>"; };
0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObject.cpp; sourceTree = "<group>"; };
......@@ -2114,7 +2118,6 @@
F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
F692A85D0255597D01FF60F7 /* FunctionPrototype.h */,
C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */,
BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
BC337BDE0E1AF0B80076918A /* GetterSetter.h */,
......@@ -2122,6 +2125,7 @@
933A349A038AE7C6008635CE /* Identifier.h */,
0FB7F38D15ED8E3800F167B2 /* IndexingHeader.h */,
0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlineMethods.h */,
0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
......@@ -2280,6 +2284,7 @@
14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
A7DCB77912E3D90500911940 /* WriteBarrier.h */,
C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
);
path = runtime;
sourceTree = "<group>";
......@@ -2486,6 +2491,7 @@
0F63945115D07051006A597C /* ArrayProfile.cpp */,
0F63945215D07051006A597C /* ArrayProfile.h */,
0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */,
0F8023E91613832300A0BA45 /* ByValInfo.h */,
0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */,
0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */,
0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
......@@ -2966,6 +2972,7 @@
0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */,
0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */,
0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */,
862553D216136E1A009F17D0 /* JSProxy.h in Headers */,
0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
);
......@@ -3572,6 +3579,7 @@
FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */,
C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */,
862553D116136DA9009F17D0 /* JSProxy.cpp in Sources */,
0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */,
0F5541B11613C1FB00CE3E25 /* SpecialPointer.cpp in Sources */,
C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */,
);
......
......@@ -200,6 +200,7 @@ SOURCES += \
runtime/GetterSetter.cpp \
runtime/Options.cpp \
runtime/Identifier.cpp \
runtime/IndexingType.cpp \
runtime/InitializeThreading.cpp \
runtime/InternalFunction.cpp \
runtime/JSActivation.cpp \
......
......@@ -564,7 +564,7 @@ public:
m_jumps.append(jump);
}
void append(JumpList& other)
void append(const JumpList& other)
{
m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
}
......
......@@ -239,6 +239,11 @@ public:
{
return PatchableJump(jump());
}
PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
{
return PatchableJump(branchTest32(cond, reg, mask));
}
#endif
void jump(Label target)
......
......@@ -1672,6 +1672,14 @@ public:
dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
return branch32(cond, addressTempRegister, dataTempRegister);
}
PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
{
m_makeJumpPatchable = true;
Jump result = branchTest32(cond, reg, mask);
m_makeJumpPatchable = false;
return PatchableJump(result);
}
PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
{
......
......@@ -31,6 +31,7 @@
#define CodeBlock_h
#include "ArrayProfile.h"
#include "ByValInfo.h"
#include "BytecodeConventions.h"
#include "CallLinkInfo.h"
#include "CallReturnOffsetToBytecodeOffset.h"
......@@ -209,6 +210,11 @@ namespace JSC {
}
void resetStub(StructureStubInfo&);
ByValInfo& getByValInfo(unsigned bytecodeIndex)
{
return *(binarySearch<ByValInfo, unsigned, getByValInfoBytecodeIndex>(m_byValInfos.begin(), m_byValInfos.size(), bytecodeIndex));
}
CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
{
......@@ -610,6 +616,10 @@ namespace JSC {
void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
void setNumberOfByValInfos(size_t size) { m_byValInfos.grow(size); }
size_t numberOfByValInfos() const { return m_byValInfos.size(); }
ByValInfo& byValInfo(size_t index) { return m_byValInfos[index]; }
void addGlobalResolveInfo(unsigned globalResolveInstruction)
{
......@@ -1289,6 +1299,7 @@ namespace JSC {
#endif
#if ENABLE(JIT)
Vector<StructureStubInfo> m_structureStubInfos;
Vector<ByValInfo> m_byValInfos;
Vector<GlobalResolveInfo> m_globalResolveInfos;
Vector<CallLinkInfo> m_callLinkInfos;
Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
......
......@@ -37,6 +37,7 @@
#include <wtf/Atomics.h>
#include <wtf/HashMap.h>
#include <wtf/MainThread.h>
#include <wtf/Spectrum.h>
#include <wtf/Threading.h>
namespace JSC {
......
......@@ -859,12 +859,17 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
case IN_BOUNDS_CONTIGUOUS_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_MODES:
case POLYMORPHIC_MODES:
forNode(node.child1()).filter(SpecCell);
forNode(node.child2()).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
......@@ -908,6 +913,9 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecDouble);
break;
default:
ASSERT_NOT_REACHED();
break;
}
break;
}
......@@ -915,6 +923,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case PutByVal:
case PutByValAlias: {
node.setCanExit(true);
Edge child1 = m_graph.varArgChild(node, 0);
Edge child2 = m_graph.varArgChild(node, 1);
Edge child3 = m_graph.varArgChild(node, 2);
switch (modeForPut(node.arrayMode())) {
......@@ -924,11 +933,18 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::Generic:
clobberWorld(node.codeOrigin, indexInBlock);
break;
case IN_BOUNDS_CONTIGUOUS_MODES:
case CONTIGUOUS_TO_TAIL_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(child2).filter(SpecInt32);
break;
case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
case ARRAY_STORAGE_TO_HOLE_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_MODES:
case POLYMORPHIC_MODES:
forNode(child1).filter(SpecCell);
forNode(child2).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
break;
......@@ -1367,7 +1383,9 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::String:
forNode(node.child1()).filter(SpecString);
break;
case ALL_CONTIGUOUS_MODES:
case ALL_ARRAY_STORAGE_MODES:
case POLYMORPHIC_MODES: // These only get a CheckArray for GetArrayLength
// This doesn't filter anything meaningful right now. We may want to add
// CFA tracking of array mode speculations, but we don't have that, yet.
forNode(node.child1()).filter(SpecCell);
......@@ -1410,9 +1428,10 @@ bool AbstractState::execute(unsigned indexInBlock)
}
case Arrayify: {
switch (node.arrayMode()) {
case EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_MODES:
node.setCanExit(true);
forNode(node.child1()).filter(SpecCell);
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).clear();
clobberStructures(indexInBlock);
break;
......
......@@ -39,8 +39,14 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
return Array::Unprofiled;
case asArrayModes(NonArray):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
return Array::BlankToArrayStorage; // FIXME: we don't know whether to go to slow put mode, or not. This is a decent guess.
return Array::BlankToContiguousOrArrayStorage; // FIXME: we don't know whether to go to slow put mode or not. We're guessing that we don't need slow put.
return Array::Undecided;
case asArrayModes(NonArrayWithContiguous):
return makeSafe ? Array::ContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ContiguousToTail : Array::Contiguous);
case asArrayModes(ArrayWithContiguous):
return makeSafe ? Array::ArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayWithContiguousToTail : Array::ArrayWithContiguous);
case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
return makeSafe ? Array::PossiblyArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::PossiblyArrayWithContiguousToTail : Array::PossiblyArrayWithContiguous);
case asArrayModes(NonArrayWithArrayStorage):
return makeSafe ? Array::ArrayStorageOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayStorageToHole : Array::ArrayStorage);
case asArrayModes(NonArrayWithSlowPutArrayStorage):
......@@ -56,6 +62,20 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
return Array::PossiblyArrayWithSlowPutArrayStorage;
case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
return Array::ContiguousOrArrayStorage;
case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
return Array::ArrayWithContiguousOrArrayStorage;
case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
return Array::PossiblyArrayWithContiguousOrArrayStorage;
case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
return Array::BlankToContiguous;
return Array::Undecided;
case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
return Array::BlankToContiguousOrArrayStorage;
return Array::Undecided;
case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
return Array::BlankToArrayStorage;
......@@ -144,6 +164,22 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
case Array::String:
return isStringSpeculation(value.m_type);
case Array::Contiguous:
case Array::ContiguousToTail:
case Array::ContiguousOutOfBounds:
case Array::PossiblyArrayWithContiguous:
case Array::PossiblyArrayWithContiguousToTail:
case Array::PossiblyArrayWithContiguousOutOfBounds:
return value.m_currentKnownStructure.hasSingleton()
&& (value.m_currentKnownStructure.singleton()->indexingType() & HasContiguous);
case Array::ArrayWithContiguous:
case Array::ArrayWithContiguousToTail:
case Array::ArrayWithContiguousOutOfBounds:
return value.m_currentKnownStructure.hasSingleton()
&& (value.m_currentKnownStructure.singleton()->indexingType() & HasContiguous)
&& (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
case Array::ArrayStorage:
case Array::ArrayStorageToHole:
case Array::ArrayStorageOutOfBounds:
......@@ -170,7 +206,8 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
&& (value.m_currentKnownStructure.singleton()->indexingType() & (HasArrayStorage | HasSlowPutArrayStorage))
&& (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_MODES:
case POLYMORPHIC_MODES:
return false;
case Array::Arguments:
......@@ -225,6 +262,24 @@ const char* modeToString(Array::Mode mode)
return "ForceExit";
case Array::String:
return "String";
case Array::Contiguous:
return "Contiguous";
case Array::ContiguousToTail:
return "ContiguousToTail";
case Array::ContiguousOutOfBounds:
return "ContiguousOutOfBounds";
case Array::ArrayWithContiguous:
return "ArrayWithContiguous";
case Array::ArrayWithContiguousToTail:
return "ArrayWithContiguousToTail";
case Array::ArrayWithContiguousOutOfBounds:
return "ArrayWithContiguousOutOfBounds";
case Array::PossiblyArrayWithContiguous:
return "PossiblyArrayWithContiguous";
case Array::PossiblyArrayWithContiguousToTail:
return "PossiblyArrayWithContiguousToTail";
case Array::PossiblyArrayWithContiguousOutOfBounds:
return "PossiblyArrayWithContiguousOutOfBounds";
case Array::ArrayStorage:
return "ArrayStorage";
case Array::ArrayStorageToHole:
......@@ -249,10 +304,20 @@ const char* modeToString(Array::Mode mode)
return "PossiblyArrayWithSlowPutArrayStorage";
case Array::PossiblyArrayWithArrayStorageOutOfBounds:
return "PossiblyArrayWithArrayStorageOutOfBounds";
case Array::BlankToContiguous:
return "BlankToContiguous";
case Array::BlankToArrayStorage:
return "BlankToArrayStorage";
case Array::BlankToSlowPutArrayStorage:
return "BlankToSlowPutArrayStorage";
case Array::BlankToContiguousOrArrayStorage:
return "BlankToContiguousOrArrayStorage";
case Array::ContiguousOrArrayStorage:
return "ContiguousOrArrayStorage";
case Array::ArrayWithContiguousOrArrayStorage:
return "ArrayWithContiguousOrArrayStorage";
case Array::PossiblyArrayWithContiguousOrArrayStorage:
return "PossiblyArrayWithContiguousOrArrayStorage";
case Array::Arguments:
return "Arguments";
case Array::Int8Array:
......
......@@ -54,6 +54,15 @@ enum Mode {
String,
// Modes of conventional indexed storage where the check is non side-effecting.
Contiguous,
ContiguousToTail,
ContiguousOutOfBounds,
ArrayWithContiguous,
ArrayWithContiguousToTail,
ArrayWithContiguousOutOfBounds,
PossiblyArrayWithContiguous,
PossiblyArrayWithContiguousToTail,
PossiblyArrayWithContiguousOutOfBounds,
ArrayStorage,
ArrayStorageToHole,
SlowPutArrayStorage,
......@@ -68,8 +77,16 @@ enum Mode {
PossiblyArrayWithArrayStorageOutOfBounds,
// Modes of conventional indexed storage where the check is side-effecting.
BlankToContiguous,
BlankToArrayStorage,
BlankToSlowPutArrayStorage,
BlankToContiguousOrArrayStorage,
// Modes that indicate polymorphic array storage. These don't benefit from
// any checking or storage CSE.
ContiguousOrArrayStorage,
ArrayWithContiguousOrArrayStorage,
PossiblyArrayWithContiguousOrArrayStorage,
Arguments,
Int8Array,
......@@ -89,6 +106,32 @@ enum Mode {
// have the word "ArrayStorage" in them.
// First: helpers for non-side-effecting checks.
#define NON_ARRAY_CONTIGUOUS_MODES \
Array::Contiguous: \
case Array::ContiguousToTail: \
case Array::ContiguousOutOfBounds: \
case Array::PossiblyArrayWithContiguous: \
case Array::PossiblyArrayWithContiguousToTail: \
case Array::PossiblyArrayWithContiguousOutOfBounds
#define ARRAY_WITH_CONTIGUOUS_MODES \
Array::ArrayWithContiguous: \
case Array::ArrayWithContiguousToTail: \
case Array::ArrayWithContiguousOutOfBounds
#define ALL_CONTIGUOUS_MODES \
NON_ARRAY_CONTIGUOUS_MODES: \
case ARRAY_WITH_CONTIGUOUS_MODES
#define IN_BOUNDS_CONTIGUOUS_MODES \
Array::Contiguous: \
case Array::ArrayWithContiguous: \
case Array::PossiblyArrayWithContiguous
#define CONTIGUOUS_TO_TAIL_MODES \
Array::ContiguousToTail: \
case Array::ArrayWithContiguousToTail: \
case Array::PossiblyArrayWithContiguousToTail
#define OUT_OF_BOUNDS_CONTIGUOUS_MODES \
Array::ContiguousOutOfBounds: \
case Array::ArrayWithContiguousOutOfBounds: \
case Array::PossiblyArrayWithContiguousOutOfBounds
#define NON_ARRAY_ARRAY_STORAGE_MODES \
Array::ArrayStorage: \
case Array::ArrayStorageToHole: \
......@@ -106,33 +149,48 @@ enum Mode {
#define ALL_ARRAY_STORAGE_MODES \
NON_ARRAY_ARRAY_STORAGE_MODES: \
case ARRAY_WITH_ARRAY_STORAGE_MODES
#define IN_BOUNDS_ARRAY_STORAGE_MODES \
Array::ArrayStorage: \
case Array::ArrayWithArrayStorage: \
case Array::PossiblyArrayWithArrayStorage
#define ARRAY_STORAGE_TO_HOLE_MODES \
Array::ArrayStorageToHole: \
case Array::ArrayWithArrayStorageToHole: \
case Array::PossiblyArrayWithArrayStorageToHole
#define IN_BOUNDS_ARRAY_STORAGE_MODES \
ARRAY_STORAGE_TO_HOLE_MODES: \
case Array::ArrayStorage: \
case Array::ArrayWithArrayStorage: \
case Array::PossiblyArrayWithArrayStorage
#define SLOW_PUT_ARRAY_STORAGE_MODES \
Array::SlowPutArrayStorage: \
case Array::ArrayWithSlowPutArrayStorage: \
case Array::PossiblyArrayWithSlowPutArrayStorage
#define OUT_OF_BOUNDS_ARRAY_STORAGE_MODES \
SLOW_PUT_ARRAY_STORAGE_MODES: \
case Array::ArrayStorageOutOfBounds: \
Array::ArrayStorageOutOfBounds: \
case Array::ArrayWithArrayStorageOutOfBounds: \
case Array::PossiblyArrayWithArrayStorageOutOfBounds
// Next: helpers for side-effecting checks.
#define EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES \
Array::BlankToArrayStorage: \
#define ALL_EFFECTFUL_CONTIGUOUS_MODES \
Array::BlankToContiguous
#define EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES \
Array::BlankToArrayStorage: \
case Array::BlankToSlowPutArrayStorage
#define ALL_EFFECTFUL_ARRAY_STORAGE_MODES \
#define ALL_EFFECTFUL_ARRAY_STORAGE_MODES \
EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES
#define SLOW_PUT_EFFECTFUL_ARRAY_STORAGE_MODES \
#define SLOW_PUT_EFFECTFUL_ARRAY_STORAGE_MODES \
Array::BlankToSlowPutArrayStorage
#define POLYMORPHIC_EFFECTFUL_MODES \
Array::BlankToContiguousOrArrayStorage
#define ALL_EFFECTFUL_MODES \
ALL_EFFECTFUL_CONTIGUOUS_MODES: \
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: \
case POLYMORPHIC_EFFECTFUL_MODES
// Finally: helpers for polymorphic array accesses.
#define POLYMORPHIC_MODES \
Array::ContiguousOrArrayStorage: \
case Array::ArrayWithContiguousOrArrayStorage: \
case Array::PossiblyArrayWithContiguousOrArrayStorage
#define ALL_POLYMORPHIC_MODES \
POLYMORPHIC_EFFECTFUL_MODES: \
case POLYMORPHIC_MODES
Array::Mode fromObserved(ArrayProfile*, Array::Action, bool makeSafe);
......@@ -145,8 +203,10 @@ const char* modeToString(Array::Mode);
inline bool modeUsesButterfly(Array::Mode arrayMode)
{
switch (arrayMode) {
case ALL_CONTIGUOUS_MODES:
case ALL_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_MODES:
case POLYMORPHIC_MODES:
return true;
default:
return false;
......@@ -156,7 +216,9 @@ inline bool modeUsesButterfly(Array::Mode arrayMode)
inline bool modeIsJSArray(Array::Mode arrayMode)
{
switch (arrayMode) {
case ARRAY_WITH_CONTIGUOUS_MODES:
case ARRAY_WITH_ARRAY_STORAGE_MODES:
case Array::ArrayWithContiguousOrArrayStorage:
return true;
default:
return false;
......@@ -166,6 +228,9 @@ inline bool modeIsJSArray(Array::Mode arrayMode)
inline bool isInBoundsAccess(Array::Mode arrayMode)
{
switch (arrayMode) {
case IN_BOUNDS_CONTIGUOUS_MODES:
case CONTIGUOUS_TO_TAIL_MODES:
case ARRAY_STORAGE_TO_HOLE_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
return true;
default:
......@@ -184,18 +249,55 @@ inline bool isSlowPutAccess(Array::Mode arrayMode)
}
}
inline bool mayStoreToTail(Array::Mode arrayMode)
{
switch (arrayMode) {
case CONTIGUOUS_TO_TAIL_MODES:
case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
case ALL_EFFECTFUL_CONTIGUOUS_MODES:
case ALL_POLYMORPHIC_MODES:
return true;
default:
return false;
}
}
inline bool mayStoreToHole(Array::Mode arrayMode)
{
switch (arrayMode) {
case ARRAY_STORAGE_TO_HOLE_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case ALL_POLYMORPHIC_MODES:
return true;
default:
return false;
}
}
inline bool modeIsPolymorphic(Array::Mode mode)
{
switch (mode) {
case ALL_POLYMORPHIC_MODES:
return true;
default:
return false;
}
}
inline bool polymorphicIncludesContiguous(Array::Mode arrayMode)
{
ASSERT_UNUSED(arrayMode, modeIsPolymorphic(arrayMode));
return true;
}
inline bool polymorphicIncludesArrayStorage(Array::Mode arrayMode)
{
ASSERT_UNUSED(arrayMode, modeIsPolymorphic(arrayMode));
return true;
}
inline bool canCSEStorage(Array::Mode arrayMode)
{
switch (arrayMode) {
......@@ -204,6 +306,7 @@ inline bool canCSEStorage(Array::Mode arrayMode)
case Array::ForceExit:
case Array::Generic:
case Array::Arguments:
case ALL_POLYMORPHIC_MODES: