Commit d8dd0535 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSC should have property butterflies

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

Reviewed by Geoffrey Garen.

Source/JavaScriptCore: 

This changes the JSC object model. Previously, all objects had fast lookup for
named properties. Integer indexed properties were only fast if you used a
JSArray. With this change, all objects have fast indexed properties. This is
accomplished without any space overhead by using a bidirectional object layout,
aka butterflies. Each JSObject has a m_butterfly pointer where previously it
had a m_outOfLineStorage pointer. To the left of the location pointed to by
m_butterfly, we place all named out-of-line properties. To the right, we place
all indexed properties along with indexing meta-data. Though, some indexing
meta-data is placed in the 8-byte word immediately left of the pointed-to
location; this is in anticipation of the indexing meta-data being small enough
in the common case that m_butterfly always points to the first indexed
property.
        
This is performance neutral, except on tests that use indexed properties on
plain objects, where the speed-up is in excess of an order of magnitude.
        
One notable aspect of what this change brings is that it allows indexing
storage to morph over time. Currently this is only used to allow all non-array
objects to start out without any indexed storage. But it could be used for
some kinds of array type inference in the future.

* API/JSCallbackObject.h:
(JSCallbackObject):
* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertySlotByIndex):
(JSC):
(JSC::::getOwnNonIndexPropertyNames):
* API/JSObjectRef.cpp:
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/ArrayProfile.h:
(JSC):
(JSC::arrayModeFromStructure):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitDirectPutById):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGAdjacencyList.h:
(JSC::DFG::AdjacencyList::AdjacencyList):
(AdjacencyList):
* 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::modeSupportsLength):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleGetByOffset):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::addNode):
(FixupPhase):
(JSC::DFG::FixupPhase::checkArray):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::byValIsPure):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(Node):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOperations.cpp:
(JSC::DFG::putByVal):
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGRepatch.cpp:
(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):
(JSC::DFG::tryBuildPutByIdList):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureCheckHoistingPhase.cpp:
(JSC::DFG::StructureCheckHoistingPhase::run):
* heap/CopiedSpace.h:
(CopiedSpace):
* jit/JIT.h:
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateBasicStorage):
(JSC::JIT::emitAllocateJSArray):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_array):
(JSC::JIT::emitSlow_op_new_array):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::privateCompilePatchGetArrayLength):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::privateCompilePatchGetArrayLength):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/Arguments.cpp:
(JSC::Arguments::deletePropertyByIndex):
(JSC::Arguments::defineOwnProperty):
* runtime/ArrayConstructor.cpp:
* runtime/ArrayConventions.h: Added.
(JSC):
(JSC::isDenseEnoughForVector):
(JSC::indexingHeaderForArray):
(JSC::baseIndexingHeaderForArray):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::create):
(JSC):
(JSC::ArrayPrototype::ArrayPrototype):
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncSort):
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncMap):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncForEach):
(JSC::arrayProtoFuncSome):
(JSC::arrayProtoFuncReduce):
(JSC::arrayProtoFuncReduceRight):
* runtime/ArrayPrototype.h:
(ArrayPrototype):
(JSC::ArrayPrototype::createStructure):
* runtime/ArrayStorage.h: Added.
(JSC):
(ArrayStorage):
(JSC::ArrayStorage::ArrayStorage):
(JSC::ArrayStorage::from):
(JSC::ArrayStorage::butterfly):
(JSC::ArrayStorage::indexingHeader):
(JSC::ArrayStorage::length):
(JSC::ArrayStorage::setLength):
(JSC::ArrayStorage::vectorLength):
(JSC::ArrayStorage::setVectorLength):
(JSC::ArrayStorage::copyHeaderFromDuringGC):
(JSC::ArrayStorage::inSparseMode):
(JSC::ArrayStorage::lengthOffset):
(JSC::ArrayStorage::vectorLengthOffset):
(JSC::ArrayStorage::numValuesInVectorOffset):
(JSC::ArrayStorage::vectorOffset):
(JSC::ArrayStorage::indexBiasOffset):
(JSC::ArrayStorage::sparseMapOffset):
(JSC::ArrayStorage::sizeFor):
* runtime/Butterfly.h: Added.
(JSC):
(Butterfly):
(JSC::Butterfly::Butterfly):
(JSC::Butterfly::totalSize):
(JSC::Butterfly::fromBase):
(JSC::Butterfly::offsetOfIndexingHeader):
(JSC::Butterfly::offsetOfPublicLength):
(JSC::Butterfly::offsetOfVectorLength):
(JSC::Butterfly::indexingHeader):
(JSC::Butterfly::propertyStorage):
(JSC::Butterfly::indexingPayload):
(JSC::Butterfly::arrayStorage):
(JSC::Butterfly::offsetOfPropertyStorage):
(JSC::Butterfly::indexOfPropertyStorage):
(JSC::Butterfly::base):
* runtime/ButterflyInlineMethods.h: Added.
(JSC):
(JSC::Butterfly::createUninitialized):
(JSC::Butterfly::create):
(JSC::Butterfly::createUninitializedDuringCollection):
(JSC::Butterfly::base):
(JSC::Butterfly::growPropertyStorage):
(JSC::Butterfly::growArrayRight):
(JSC::Butterfly::resizeArray):
(JSC::Butterfly::unshift):
(JSC::Butterfly::shift):
* runtime/ClassInfo.h:
(MethodTable):
(JSC):
* runtime/IndexingHeader.h: Added.
(JSC):
(IndexingHeader):
(JSC::IndexingHeader::offsetOfIndexingHeader):
(JSC::IndexingHeader::offsetOfPublicLength):
(JSC::IndexingHeader::offsetOfVectorLength):
(JSC::IndexingHeader::IndexingHeader):
(JSC::IndexingHeader::vectorLength):
(JSC::IndexingHeader::setVectorLength):
(JSC::IndexingHeader::publicLength):
(JSC::IndexingHeader::setPublicLength):
(JSC::IndexingHeader::from):
(JSC::IndexingHeader::fromEndOf):
(JSC::IndexingHeader::propertyStorage):
(JSC::IndexingHeader::arrayStorage):
(JSC::IndexingHeader::butterfly):
* runtime/IndexingHeaderInlineMethods.h: Added.
(JSC):
(JSC::IndexingHeader::preCapacity):
(JSC::IndexingHeader::indexingPayloadSizeInBytes):
* runtime/IndexingType.h: Added.
(JSC):
(JSC::hasIndexingHeader):
* runtime/JSActivation.cpp:
(JSC::JSActivation::JSActivation):
(JSC::JSActivation::visitChildren):
(JSC::JSActivation::getOwnNonIndexPropertyNames):
* runtime/JSActivation.h:
(JSActivation):
(JSC::JSActivation::tearOff):
* runtime/JSArray.cpp:
(JSC):
(JSC::createArrayButterflyInDictionaryIndexingMode):
(JSC::JSArray::setLengthWritable):
(JSC::JSArray::defineOwnProperty):
(JSC::JSArray::getOwnPropertySlot):
(JSC::JSArray::getOwnPropertyDescriptor):
(JSC::JSArray::put):
(JSC::JSArray::deleteProperty):
(JSC::JSArray::getOwnNonIndexPropertyNames):
(JSC::JSArray::unshiftCountSlowCase):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::shiftCount):
(JSC::JSArray::unshiftCount):
(JSC::JSArray::sortNumeric):
(JSC::JSArray::sort):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):
(JSC::JSArray::compactForSorting):
* runtime/JSArray.h:
(JSC):
(JSArray):
(JSC::JSArray::JSArray):
(JSC::JSArray::length):
(JSC::JSArray::createStructure):
(JSC::JSArray::isLengthWritable):
(JSC::createArrayButterfly):
(JSC::JSArray::create):
(JSC::JSArray::tryCreateUninitialized):
* runtime/JSBoundFunction.cpp:
(JSC::boundFunctionCall):
(JSC::boundFunctionConstruct):
(JSC::JSBoundFunction::finishCreation):
* runtime/JSCell.cpp:
(JSC::JSCell::getOwnNonIndexPropertyNames):
(JSC):
* runtime/JSCell.h:
(JSCell):
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::getOwnPropertyDescriptor):
(JSC::JSFunction::getOwnNonIndexPropertyNames):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSFunction.h:
(JSFunction):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
* runtime/JSObject.cpp:
(JSC):
(JSC::JSObject::visitButterfly):
(JSC::JSObject::visitChildren):
(JSC::JSFinalObject::visitChildren):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::put):
(JSC::JSObject::putByIndex):
(JSC::JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists):
(JSC::JSObject::enterDictionaryIndexingMode):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::createInitialArrayStorage):
(JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode):
(JSC::JSObject::putDirectAccessor):
(JSC::JSObject::deleteProperty):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::getOwnNonIndexPropertyNames):
(JSC::JSObject::preventExtensions):
(JSC::JSObject::fillGetterPropertySlot):
(JSC::JSObject::putIndexedDescriptor):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::allocateSparseIndexMap):
(JSC::JSObject::deallocateSparseIndexMap):
(JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putByIndexBeyondVectorLength):
(JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putDirectIndexBeyondVectorLength):
(JSC::JSObject::getNewVectorLength):
(JSC::JSObject::increaseVectorLength):
(JSC::JSObject::checkIndexingConsistency):
(JSC::JSObject::growOutOfLineStorage):
(JSC::JSObject::getOwnPropertyDescriptor):
(JSC::putDescriptor):
(JSC::JSObject::putDirectMayBeIndex):
(JSC::JSObject::defineOwnNonIndexProperty):
(JSC::JSObject::defineOwnProperty):
(JSC::JSObject::getOwnPropertySlotSlow):
* runtime/JSObject.h:
(JSC::JSObject::getArrayLength):
(JSObject):
(JSC::JSObject::getVectorLength):
(JSC::JSObject::putDirectIndex):
(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::canSetIndexQuickly):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::completeInitialization):
(JSC::JSObject::inSparseIndexingMode):
(JSC::JSObject::butterfly):
(JSC::JSObject::outOfLineStorage):
(JSC::JSObject::offsetForLocation):
(JSC::JSObject::indexingShouldBeSparse):
(JSC::JSObject::butterflyOffset):
(JSC::JSObject::butterflyAddress):
(JSC::JSObject::arrayStorage):
(JSC::JSObject::arrayStorageOrZero):
(JSC::JSObject::ensureArrayStorage):
(JSC::JSObject::checkIndexingConsistency):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC):
(JSC::JSObject::setButterfly):
(JSC::JSObject::setButterflyWithoutChangingStructure):
(JSC::JSObject::JSObject):
(JSC::JSObject::inlineGetOwnPropertySlot):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::setStructureAndReallocateStorageIfNecessary):
(JSC::JSObject::putDirectWithoutTransition):
(JSC::offsetInButterfly):
(JSC::offsetRelativeToPatchedStorage):
(JSC::indexRelativeToBase):
(JSC::offsetRelativeToBase):
* runtime/JSPropertyNameIterator.cpp:
(JSC::JSPropertyNameIterator::create):
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* runtime/JSSymbolTableObject.h:
(JSSymbolTableObject):
* runtime/JSTypeInfo.h:
(JSC):
(JSC::TypeInfo::interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero):
(JSC::TypeInfo::overridesGetPropertyNames):
* runtime/LiteralParser.cpp:
(JSC::::parse):
* runtime/ObjectConstructor.cpp:
* runtime/ObjectPrototype.cpp:
(JSC::ObjectPrototype::ObjectPrototype):
(JSC):
* runtime/ObjectPrototype.h:
(ObjectPrototype):
* runtime/PropertyOffset.h:
(JSC::offsetInOutOfLineStorage):
* runtime/PropertyStorage.h: Added.
(JSC):
* runtime/PutDirectIndexMode.h: Added.
(JSC):
* runtime/RegExpMatchesArray.cpp:
(JSC::RegExpMatchesArray::RegExpMatchesArray):
(JSC):
(JSC::RegExpMatchesArray::create):
(JSC::RegExpMatchesArray::finishCreation):
* runtime/RegExpMatchesArray.h:
(RegExpMatchesArray):
(JSC::RegExpMatchesArray::createStructure):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnNonIndexPropertyNames):
* runtime/RegExpObject.h:
(RegExpObject):
* runtime/Reject.h: Added.
(JSC):
(JSC::reject):
* runtime/SparseArrayValueMap.cpp: Added.
(JSC):
* runtime/SparseArrayValueMap.h: Added.
(JSC):
(SparseArrayEntry):
(JSC::SparseArrayEntry::SparseArrayEntry):
(SparseArrayValueMap):
(JSC::SparseArrayValueMap::sparseMode):
(JSC::SparseArrayValueMap::setSparseMode):
(JSC::SparseArrayValueMap::lengthIsReadOnly):
(JSC::SparseArrayValueMap::setLengthIsReadOnly):
(JSC::SparseArrayValueMap::find):
(JSC::SparseArrayValueMap::remove):
(JSC::SparseArrayValueMap::notFound):
(JSC::SparseArrayValueMap::isEmpty):
(JSC::SparseArrayValueMap::contains):
(JSC::SparseArrayValueMap::size):
(JSC::SparseArrayValueMap::begin):
(JSC::SparseArrayValueMap::end):
* runtime/SparseArrayValueMapInlineMethods.h: Added.
(JSC):
(JSC::SparseArrayValueMap::SparseArrayValueMap):
(JSC::SparseArrayValueMap::~SparseArrayValueMap):
(JSC::SparseArrayValueMap::finishCreation):
(JSC::SparseArrayValueMap::create):
(JSC::SparseArrayValueMap::destroy):
(JSC::SparseArrayValueMap::createStructure):
(JSC::SparseArrayValueMap::add):
(JSC::SparseArrayValueMap::putEntry):
(JSC::SparseArrayValueMap::putDirect):
(JSC::SparseArrayEntry::get):
(JSC::SparseArrayEntry::getNonSparseMode):
(JSC::SparseArrayValueMap::visitChildren):
* runtime/StorageBarrier.h: Removed.
* runtime/StringObject.cpp:
(JSC::StringObject::putByIndex):
(JSC):
(JSC::StringObject::deletePropertyByIndex):
* runtime/StringObject.h:
(StringObject):
* runtime/StringPrototype.cpp:
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::nonPropertyTransition):
(JSC):
* runtime/Structure.h:
(Structure):
(JSC::Structure::indexingType):
(JSC::Structure::indexingTypeIncludingHistory):
(JSC::Structure::indexingTypeOffset):
(JSC::Structure::create):
* runtime/StructureTransitionTable.h:
(JSC):
(JSC::toAttributes):
(JSC::newIndexingType):
(JSC::StructureTransitionTable::Hash::hash):
* tests/mozilla/js1_6/Array/regress-304828.js:

Source/WebCore: 

Teach the DOM that to intercept get/put on indexed properties, you now have
to override getOwnPropertySlotByIndex and putByIndex.

No new tests because no new behavior. One test was rebased because indexed
property iteration order now matches other engines (indexed properties always
come first).

* bindings/js/ArrayValue.cpp:
(WebCore::ArrayValue::get):
* bindings/js/JSBlobCustom.cpp:
(WebCore::JSBlobConstructor::constructJSBlob):
* bindings/js/JSCanvasRenderingContext2DCustom.cpp:
(WebCore::JSCanvasRenderingContext2D::setWebkitLineDash):
* bindings/js/JSDOMStringListCustom.cpp:
(WebCore::toDOMStringList):
* bindings/js/JSDOMStringMapCustom.cpp:
(WebCore::JSDOMStringMap::deletePropertyByIndex):
(WebCore):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
(WebCore):
(WebCore::JSDOMWindow::putByIndex):
(WebCore::JSDOMWindow::deletePropertyByIndex):
* bindings/js/JSDOMWindowShell.cpp:
(WebCore::JSDOMWindowShell::getOwnPropertySlotByIndex):
(WebCore):
(WebCore::JSDOMWindowShell::putByIndex):
(WebCore::JSDOMWindowShell::deletePropertyByIndex):
* bindings/js/JSDOMWindowShell.h:
(JSDOMWindowShell):
* bindings/js/JSHistoryCustom.cpp:
(WebCore::JSHistory::deletePropertyByIndex):
(WebCore):
* bindings/js/JSInspectorFrontendHostCustom.cpp:
(WebCore::populateContextMenuItems):
* bindings/js/JSLocationCustom.cpp:
(WebCore::JSLocation::deletePropertyByIndex):
(WebCore):
* bindings/js/JSStorageCustom.cpp:
(WebCore::JSStorage::deletePropertyByIndex):
(WebCore):
* bindings/js/JSWebSocketCustom.cpp:
(WebCore::JSWebSocketConstructor::constructJSWebSocket):
* bindings/js/ScriptValue.cpp:
(WebCore::jsToInspectorValue):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
(GenerateImplementation):
* bridge/runtime_array.cpp:
(JSC::RuntimeArray::RuntimeArray):
* bridge/runtime_array.h:
(JSC::RuntimeArray::createStructure):
(RuntimeArray):

LayoutTests: 

Modify the JSON test to indicate that iterating over properties now returns
indexed properties first. This is a behavior change that makes us more
compliant with other implementations.
        
Also check in new expected file for the edge cases of indexed property access
with prototype accessors. This changeset introduces a known regression in that
department, which is tracked here: https://bugs.webkit.org/show_bug.cgi?id=96596

* fast/js/resources/JSON-stringify.js:
* platform/mac/fast/js/primitive-property-access-edge-cases-expected.txt: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@128400 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6b2f531e
2012-09-12 Filip Pizlo <fpizlo@apple.com>
JSC should have property butterflies
https://bugs.webkit.org/show_bug.cgi?id=91933
Reviewed by Geoffrey Garen.
Modify the JSON test to indicate that iterating over properties now returns
indexed properties first. This is a behavior change that makes us more
compliant with other implementations.
Also check in new expected file for the edge cases of indexed property access
with prototype accessors. This changeset introduces a known regression in that
department, which is tracked here: https://bugs.webkit.org/show_bug.cgi?id=96596
* fast/js/resources/JSON-stringify.js:
* platform/mac/fast/js/primitive-property-access-edge-cases-expected.txt: Added.
2012-09-12 Kent Tamura <tkent@chromium.org>
[Chromium] Test expectation update
......@@ -334,7 +334,7 @@ function createTests() {
jsonObject.stringify({a:"a", b:"b", c:"c", 3: "d", 2: "e", 1: "f"}, replaceFunc);
return replaceTracker;
});
result[result.length - 1].expected = '(string){"a":"a","b":"b","c":"c","3":"d","2":"e","1":"f"};a(string)"a";b(string)"b";c(string)"c";3(string)"d";2(string)"e";1(string)"f";';
result[result.length - 1].expected = '(string){"1":"f","2":"e","3":"d","a":"a","b":"b","c":"c"};1(string)"f";2(string)"e";3(string)"d";a(string)"a";b(string)"b";c(string)"c";';
result.push(function(jsonObject){
var count = 0;
var array = [{toString:function(){count++; array[0]='a'; array[1]='c'; array[2]='b'; return 'a'}}];
......
This page tests for assertion failures in edge cases of property lookup on primitive values.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS checkGet(1, Number) is true
PASS checkGet('hello', String) is true
PASS checkGet(true, Boolean) is true
PASS checkSet(1, Number) is true
PASS checkSet('hello', String) is true
PASS checkSet(true, Boolean) is true
PASS checkGetStrict(1, Number) is true
PASS checkGetStrict('hello', String) is true
PASS checkGetStrict(true, Boolean) is true
PASS checkSetStrict(1, Number) is true
PASS checkSetStrict('hello', String) is true
PASS checkSetStrict(true, Boolean) is true
PASS checkRead(1, Number) is true
PASS checkRead('hello', String) is true
PASS checkRead(true, Boolean) is true
PASS checkWrite(1, Number) is true
PASS checkWrite('hello', String) is true
PASS checkWrite(true, Boolean) is true
PASS checkReadStrict(1, Number) is true
PASS checkReadStrict('hello', String) is true
PASS checkReadStrict(true, Boolean) is true
PASS checkWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property..
PASS checkWriteStrict('hello', String) threw exception TypeError: Attempted to assign to readonly property..
PASS checkWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
PASS checkNumericGet(1, Number) is true
PASS checkNumericGet('hello', String) is true
PASS checkNumericGet(true, Boolean) is true
FAIL checkNumericSet(1, Number) should be true. Was false.
FAIL checkNumericSet('hello', String) should be true. Was false.
FAIL checkNumericSet(true, Boolean) should be true. Was false.
PASS checkNumericGetStrict(1, Number) is true
PASS checkNumericGetStrict('hello', String) is true
PASS checkNumericGetStrict(true, Boolean) is true
FAIL checkNumericSetStrict(1, Number) should be true. Was false.
FAIL checkNumericSetStrict('hello', String) should be true. Was false.
FAIL checkNumericSetStrict(true, Boolean) should be true. Was false.
PASS checkNumericRead(1, Number) is true
PASS checkNumericRead('hello', String) is true
PASS checkNumericRead(true, Boolean) is true
PASS checkNumericWrite(1, Number) is true
PASS checkNumericWrite('hello', String) is true
PASS checkNumericWrite(true, Boolean) is true
PASS checkNumericReadStrict(1, Number) is true
PASS checkNumericReadStrict('hello', String) is true
PASS checkNumericReadStrict(true, Boolean) is true
PASS checkNumericWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property..
PASS checkNumericWriteStrict('hello', String) threw exception TypeError: Attempted to assign to readonly property..
PASS checkNumericWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
PASS didNotCrash is true
PASS successfullyParsed is true
TEST COMPLETE
......@@ -168,7 +168,7 @@ public:
using Parent::methodTable;
protected:
static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Parent::StructureFlags;
static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Parent::StructureFlags;
private:
static String className(const JSObject*);
......@@ -178,6 +178,7 @@ private:
static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
......@@ -187,7 +188,7 @@ private:
static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static ConstructType getConstructData(JSCell*, ConstructData&);
static CallType getCallData(JSCell*, CallData&);
......
......@@ -182,6 +182,12 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSCell* cell, ExecState* exec,
return Parent::getOwnPropertySlot(thisObject, exec, propertyName, slot);
}
template <class Parent>
bool JSCallbackObject<Parent>::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
return cell->methodTable()->getOwnPropertySlot(cell, exec, Identifier::from(exec, propertyName), slot);
}
template <class Parent>
JSValue JSCallbackObject<Parent>::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
{
......@@ -449,7 +455,7 @@ EncodedJSValue JSCallbackObject<Parent>::call(ExecState* exec)
}
template <class Parent>
void JSCallbackObject<Parent>::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
void JSCallbackObject<Parent>::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);
JSContextRef execRef = toRef(exec);
......@@ -484,7 +490,7 @@ void JSCallbackObject<Parent>::getOwnPropertyNames(JSObject* object, ExecState*
}
}
Parent::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
Parent::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
}
template <class Parent>
......
......@@ -29,7 +29,9 @@
#include "JSObjectRefPrivate.h"
#include "APICast.h"
#include "ButterflyInlineMethods.h"
#include "CodeBlock.h"
#include "CopiedSpaceInlineMethods.h"
#include "DateConstructor.h"
#include "ErrorConstructor.h"
#include "FunctionConstructor.h"
......
......@@ -246,6 +246,7 @@ SET(JavaScriptCore_SOURCES
runtime/RegExpObject.cpp
runtime/RegExpPrototype.cpp
runtime/SmallStrings.cpp
runtime/SparseArrayValueMap.cpp
runtime/StrictEvalActivation.cpp
runtime/StringConstructor.cpp
runtime/StringObject.cpp
......
This diff is collapsed.
......@@ -457,8 +457,10 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/Arguments.h \
Source/JavaScriptCore/runtime/ArrayConstructor.cpp \
Source/JavaScriptCore/runtime/ArrayConstructor.h \
Source/JavaScriptCore/runtime/ArrayConventions.h \
Source/JavaScriptCore/runtime/ArrayPrototype.cpp \
Source/JavaScriptCore/runtime/ArrayPrototype.h \
Source/JavaScriptCore/runtime/ArrayStorage.h \
Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
Source/JavaScriptCore/runtime/BigInteger.h \
Source/JavaScriptCore/runtime/BooleanConstructor.cpp \
......@@ -467,6 +469,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/BooleanObject.h \
Source/JavaScriptCore/runtime/BooleanPrototype.cpp \
Source/JavaScriptCore/runtime/BooleanPrototype.h \
Source/JavaScriptCore/runtime/ButterflyInlineMethods.h \
Source/JavaScriptCore/runtime/Butterfly.h \
Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h \
Source/JavaScriptCore/runtime/CallData.cpp \
Source/JavaScriptCore/runtime/CallData.h \
......@@ -511,6 +515,9 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/GetterSetter.h \
Source/JavaScriptCore/runtime/Identifier.cpp \
Source/JavaScriptCore/runtime/Identifier.h \
Source/JavaScriptCore/runtime/IndexingHeaderInlineMethods.h \
Source/JavaScriptCore/runtime/IndexingHeader.h \
Source/JavaScriptCore/runtime/IndexingType.h \
Source/JavaScriptCore/runtime/InitializeThreading.cpp \
Source/JavaScriptCore/runtime/InitializeThreading.h \
Source/JavaScriptCore/runtime/InternalFunction.cpp \
......@@ -616,7 +623,9 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/PropertyOffset.h \
Source/JavaScriptCore/runtime/PropertySlot.cpp \
Source/JavaScriptCore/runtime/PropertySlot.h \
Source/JavaScriptCore/runtime/PropertyStorage.h \
Source/JavaScriptCore/runtime/Protect.h \
Source/JavaScriptCore/runtime/PutDirectIndexMode.h \
Source/JavaScriptCore/runtime/PutPropertySlot.h \
Source/JavaScriptCore/runtime/RegExpCache.cpp \
Source/JavaScriptCore/runtime/RegExpCache.h \
......@@ -633,11 +642,14 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/RegExpObject.h \
Source/JavaScriptCore/runtime/RegExpPrototype.cpp \
Source/JavaScriptCore/runtime/RegExpPrototype.h \
Source/JavaScriptCore/runtime/Reject.h \
Source/JavaScriptCore/runtime/SamplingCounter.cpp \
Source/JavaScriptCore/runtime/SamplingCounter.h \
Source/JavaScriptCore/runtime/SmallStrings.cpp \
Source/JavaScriptCore/runtime/SmallStrings.h \
Source/JavaScriptCore/runtime/StorageBarrier.h \
Source/JavaScriptCore/runtime/SparseArrayValueMapInlineMethods.h \
Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp \
Source/JavaScriptCore/runtime/SparseArrayValueMap.h \
Source/JavaScriptCore/runtime/StrictEvalActivation.cpp \
Source/JavaScriptCore/runtime/StrictEvalActivation.h \
Source/JavaScriptCore/runtime/StringConstructor.cpp \
......
......@@ -22,7 +22,7 @@ EXPORTS
??0RegExpObject@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@PAVRegExp@1@@Z
??0SHA1@WTF@@QAE@XZ
??0StringObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@@Z
??0Structure@JSC@@AAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@VJSValue@1@ABVTypeInfo@1@PBUClassInfo@1@@Z
??0Structure@JSC@@AAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@VJSValue@1@ABVTypeInfo@1@PBUClassInfo@1@E@Z
??0ThreadCondition@WTF@@QAE@XZ
??0WTFThreadData@WTF@@QAE@XZ
??0YarrPattern@Yarr@JSC@@QAE@ABVString@WTF@@_N1PAPBD@Z
......@@ -185,13 +185,12 @@ EXPORTS
?fastRealloc@WTF@@YAPAXPAXI@Z
?fastStrDup@WTF@@YAPADPBD@Z
?fastZeroedMalloc@WTF@@YAPAXI@Z
?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@PAV?$WriteBarrierBase@W4Unknown@JSC@@@2@@Z
?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@H@Z
?finalize@WeakHandleOwner@JSC@@UAEXV?$Handle@W4Unknown@JSC@@@2@PAX@Z
?findAllocator@WeakSet@JSC@@AAEPAUFreeCell@WeakBlock@2@XZ
?finishCreation@BooleanObject@JSC@@IAEXAAVJSGlobalData@2@@Z
?finishCreation@DateInstance@JSC@@IAEXAAVJSGlobalData@2@N@Z
?finishCreation@InternalFunction@JSC@@IAEXAAVJSGlobalData@2@ABVString@WTF@@@Z
?finishCreation@JSArray@JSC@@IAEXAAVJSGlobalData@2@I@Z
?finishCreation@RegExpObject@JSC@@IAEXPAVJSGlobalObject@2@@Z
?finishCreation@StringObject@JSC@@IAEXAAVJSGlobalData@2@PAVJSString@2@@Z
?focus@Profile@JSC@@QAEXPBVProfileNode@2@@Z
......@@ -204,13 +203,14 @@ EXPORTS
?getCallableObjectSlow@JSC@@YAPAVJSCell@1@PAV21@@Z
?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z
?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ
?getOwnNonIndexPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnNonIndexPropertyNames@JSSymbolTableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertyDescriptor@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyDescriptor@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z
?getOwnPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertyNames@JSSymbolTableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getOwnPropertySlot@JSGlobalObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@VPropertyName@2@AAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
?getOwnPropertySlotByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z
?getOwnPropertySlotSlow@JSObject@JSC@@AAE_NPAVExecState@2@VPropertyName@2@AAVPropertySlot@2@@Z
?getPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z
?getSlice@ArgList@JSC@@QBEXHAAV12@@Z
?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@AAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z
......@@ -220,8 +220,8 @@ EXPORTS
?getter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
?globalExec@JSGlobalObject@JSC@@QAEPAVExecState@2@XZ
?globalObjectCount@Heap@JSC@@QAEIXZ
?growOutOfLineStorage@JSObject@JSC@@QAEPAV?$WriteBarrierBase@W4Unknown@JSC@@@2@AAVJSGlobalData@2@II@Z
?grow@HandleSet@JSC@@AAEXXZ
?growOutOfLineStorage@JSObject@JSC@@QAEPAVButterfly@2@AAVJSGlobalData@2@II@Z
?hasInstance@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VJSValue@2@2@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@VPropertyName@2@@Z
......@@ -276,7 +276,7 @@ EXPORTS
?put@JSGlobalObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@VPropertyName@2@VJSValue@2@AAVPutPropertySlot@2@@Z
?put@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@VPropertyName@2@VJSValue@2@AAVPutPropertySlot@2@@Z
?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@_N@Z
?putDirectIndexBeyondVectorLength@JSArray@JSC@@AAE_NPAVExecState@2@IVJSValue@2@W4PutDirectIndexMode@2@@Z
?putDirectIndexBeyondVectorLength@JSObject@JSC@@AAE_NPAVExecState@2@IVJSValue@2@IW4PutDirectIndexMode@2@@Z
?putDirectVirtual@JSGlobalObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@VPropertyName@2@VJSValue@2@I@Z
?putDirectVirtual@JSObject@JSC@@SAXPAV12@PAVExecState@2@VPropertyName@2@VJSValue@2@I@Z
?randomNumber@WTF@@YANXZ
......@@ -355,10 +355,10 @@ EXPORTS
?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z
?toWTFStringSlowCase@JSValue@JSC@@ABE?AVString@WTF@@PAVExecState@2@@Z
?transfer@ArrayBuffer@WTF@@QAE_NAAVArrayBufferContents@2@AAV?$Vector@V?$RefPtr@VArrayBufferView@WTF@@@WTF@@$0A@@2@@Z
?tryAllocateSlowCase@CopiedSpace@JSC@@AAE?AVCheckedBoolean@@IPAPAX@Z
?tryFastCalloc@WTF@@YA?AUTryMallocReturnValue@1@II@Z
?tryFastMalloc@WTF@@YA?AUTryMallocReturnValue@1@I@Z
?tryFastRealloc@WTF@@YA?AUTryMallocReturnValue@1@PAXI@Z
?tryFinishCreationUninitialized@JSArray@JSC@@IAEPAV12@AAVJSGlobalData@2@I@Z
?tryLock@Mutex@WTF@@QAE_NXZ
?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ
?unlock@JSLock@JSC@@QAEXXZ
......
......@@ -513,6 +513,58 @@
<Filter
Name="runtime"
>
<File
RelativePath="..\..\runtime\Reject.h"
>
</File>
<File
RelativePath="..\..\runtime\SparseArrayValueMapInlineMethods.h"
>
</File>
<File
RelativePath="..\..\runtime\ArrayStorage.h"
>
</File>
<File
RelativePath="..\..\runtime\IndexingType.h"
>
</File>
<File
RelativePath="..\..\runtime\PropertyStorage.h"
>
</File>
<File
RelativePath="..\..\runtime\PutDirectIndexMode.h"
>
</File>
<File
RelativePath="..\..\runtime\ButterflyInlineMethods.h"
>
</File>
<File
RelativePath="..\..\runtime\Butterfly.h"
>
</File>
<File
RelativePath="..\..\runtime\IndexingHeaderInlineMethods.h"
>
</File>
<File
RelativePath="..\..\runtime\SparseArrayValueMap.h"
>
</File>
<File
RelativePath="..\..\runtime\ArrayConventions.h"
>
</File>
<File
RelativePath="..\..\runtime\IndexingHeader.h"
>
</File>
<File
RelativePath="..\..\runtime\SparseArrayValueMap.cpp"
>
</File>
<File
RelativePath="..\..\runtime\ArgList.cpp"
>
......
......@@ -246,6 +246,7 @@ SOURCES += \
runtime/RegExpCache.cpp \
runtime/SamplingCounter.cpp \
runtime/SmallStrings.cpp \
runtime/SparseArrayValueMap.cpp \
runtime/StrictEvalActivation.cpp \
runtime/StringConstructor.cpp \
runtime/StringObject.cpp \
......
......@@ -35,16 +35,16 @@ namespace JSC {
class LLIntOffsetsExtractor;
// This is a bitfield where each bit represents an IndexingType that we have seen.
// There are 17 indexing types (0 to 16, inclusive), so 32 bits is more than enough.
typedef unsigned ArrayModes;
static const unsigned IsNotArray = 1;
static const unsigned IsJSArray = 2;
#define asArrayModes(type) \
(1 << static_cast<unsigned>(type))
inline ArrayModes arrayModeFromStructure(Structure* structure)
{
if (structure->classInfo() == &JSArray::s_info)
return IsJSArray;
return IsNotArray;
return asArrayModes(structure->indexingTypeIncludingHistory());
}
class ArrayProfile {
......
......@@ -1758,7 +1758,9 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif
instructions().append(0);
instructions().append(0);
instructions().append(0);
instructions().append(property != m_globalData->propertyNames->underscoreProto);
instructions().append(
property != m_globalData->propertyNames->underscoreProto
&& PropertyName(property).asIndex() == PropertyName::NotAnIndex);
return value;
}
......
......@@ -852,11 +852,11 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
case Array::JSArray:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
case Array::JSArrayOutOfBounds:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
forNode(node.child2()).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
......@@ -916,10 +916,10 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::Generic:
clobberWorld(node.codeOrigin, indexInBlock);
break;
case Array::JSArray:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(child2).filter(SpecInt32);
break;
case Array::JSArrayOutOfBounds:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
forNode(child2).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
break;
......@@ -1341,7 +1341,7 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child1()).set(node.structureTransitionData().newStructure);
m_haveStructures = true;
break;
case GetPropertyStorage:
case GetButterfly:
case AllocatePropertyStorage:
case ReallocatePropertyStorage:
node.setCanExit(false);
......@@ -1359,8 +1359,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::String:
forNode(node.child1()).filter(SpecString);
break;
case Array::JSArray:
case Array::JSArrayOutOfBounds:
case ALL_ARRAY_STORAGE_MODES:
// 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);
......
......@@ -44,6 +44,8 @@ public:
enum { Size = 3 };
AdjacencyList() { }
AdjacencyList(Kind kind)
#if !ASSERT_DISABLED
: m_kind(kind)
......
......@@ -40,8 +40,12 @@ Array::Mode fromObserved(ArrayModes modes, bool makeSafe)
switch (modes) {
case 0:
return Array::Undecided;
case IsJSArray:
return makeSafe ? Array::JSArrayOutOfBounds : Array::JSArray;
case asArrayModes(NonArrayWithArrayStorage):
return makeSafe ? Array::ArrayStorageOutOfBounds : Array::ArrayStorage;
case asArrayModes(ArrayWithArrayStorage):
return makeSafe ? Array::ArrayWithArrayStorageOutOfBounds : Array::ArrayWithArrayStorage;
case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage):
return makeSafe ? Array::PossiblyArrayWithArrayStorageOutOfBounds : Array::PossiblyArrayWithArrayStorage;
default:
// We know that this is possibly a kind of array for which, though there is no
// useful data in the array profile, we may be able to extract useful data from
......@@ -120,10 +124,14 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
case Array::String:
return isStringSpeculation(value.m_type);
case Array::JSArray:
case Array::JSArrayOutOfBounds:
case NON_ARRAY_ARRAY_STORAGE_MODES:
return value.m_currentKnownStructure.hasSingleton()
&& value.m_currentKnownStructure.singleton()->classInfo() == &JSArray::s_info;
&& (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage);
case ARRAY_WITH_ARRAY_STORAGE_MODES:
return value.m_currentKnownStructure.hasSingleton()
&& (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage)
&& (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
case Array::Arguments:
return isArgumentsSpeculation(value.m_type);
......@@ -174,10 +182,18 @@ const char* modeToString(Array::Mode mode)
return "ForceExit";
case Array::String:
return "String";
case Array::JSArray:
return "JSArray";
case Array::JSArrayOutOfBounds:
return "JSArrayOutOfBounds";
case Array::ArrayStorage:
return "ArrayStorage";
case Array::ArrayStorageOutOfBounds:
return "ArrayStorageOutOfBounds";
case Array::ArrayWithArrayStorage:
return "ArrayWithArrayStorage";
case Array::ArrayWithArrayStorageOutOfBounds:
return "ArrayWithArrayStorageOutOfBounds";
case Array::PossiblyArrayWithArrayStorage:
return "PossiblyArrayWithArrayStorage";
case Array::PossiblyArrayWithArrayStorageOutOfBounds:
return "PossiblyArrayWithArrayStorageOutOfBounds";
case Array::Arguments:
return "Arguments";
case Array::Int8Array:
......
......@@ -46,8 +46,12 @@ enum Mode {
ForceExit, // Implies that we have no idea how to execute this operation, so we should just give up.
Generic,
String,
JSArray,
JSArrayOutOfBounds,
ArrayStorage,
ArrayStorageOutOfBounds,
ArrayWithArrayStorage,
ArrayWithArrayStorageOutOfBounds,
PossiblyArrayWithArrayStorage,
PossiblyArrayWithArrayStorageOutOfBounds,
Arguments,
Int8Array,
Int16Array,
......@@ -61,6 +65,29 @@ enum Mode {
};
} // namespace Array
// Helpers for 'case' statements. For example, saying "case AllArrayStorageModes:"
// is the same as having multiple case statements listing off all of the modes that
// have the word "ArrayStorage" in them.
#define NON_ARRAY_ARRAY_STORAGE_MODES \
Array::ArrayStorage: \
case Array::ArrayStorageOutOfBounds: \
case Array::PossiblyArrayWithArrayStorage: \
case Array::PossiblyArrayWithArrayStorageOutOfBounds
#define ARRAY_WITH_ARRAY_STORAGE_MODES \
Array::ArrayWithArrayStorage: \
case Array::ArrayWithArrayStorageOutOfBounds
#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 OUT_OF_BOUNDS_ARRAY_STORAGE_MODES \
Array::ArrayStorageOutOfBounds: \
case Array::ArrayWithArrayStorageOutOfBounds: \
case Array::PossiblyArrayWithArrayStorageOutOfBounds
Array::Mode fromObserved(ArrayModes modes, bool makeSafe);
Array::Mode fromStructure(Structure*, bool makeSafe);
......@@ -71,11 +98,30 @@ bool modeAlreadyChecked(AbstractValue&, Array::Mode);
const char* modeToString(Array::Mode);
inline bool modeUsesButterfly(Array::Mode arrayMode)
{
switch (arrayMode) {
case ALL_ARRAY_STORAGE_MODES:
return true;
default:
return false;
}
}
inline bool modeIsJSArray(Array::Mode arrayMode)
{
switch (arrayMode) {
case Array::JSArray: