Ignore:
Timestamp:
Sep 12, 2012, 9:18:52 PM (13 years ago)
Author:
[email protected]
Message:

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.
File:
1 edited

Legend:

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

    r128096 r128400  
    2828
    2929#include "Arguments.h"
     30#include "ButterflyInlineMethods.h"
    3031#include "CodeBlock.h"
    3132#include "CopiedSpaceInlineMethods.h"
     
    227228    NativeCallFrameTracer tracer(&globalData, exec);
    228229   
    229     if (isJSArray(baseValue)) {
    230         JSArray* array = asArray(baseValue);
    231         if (array->canSetIndex(index)) {
    232             array->setIndex(globalData, index, value);
     230    if (baseValue.isObject()) {
     231        JSObject* object = asObject(baseValue);
     232        if (object->canSetIndexQuickly(index)) {
     233            object->setIndexQuickly(globalData, index, value);
    233234            return;
    234235        }
    235236
    236         JSArray::putByIndex(array, exec, index, value, strict);
     237        object->methodTable()->putByIndex(object, exec, index, value, strict);
    237238        return;
    238239    }
     
    342343    NativeCallFrameTracer tracer(&globalData, exec);
    343344   
    344     // FIXME: the JIT used to handle these in compiled code!
    345     if (isJSArray(base) && asArray(base)->canGetIndex(index))
    346         return JSValue::encode(asArray(base)->getIndex(index));
    347 
    348     // FIXME: the JITstub used to relink this to an optimized form!
     345    if (base->isObject()) {
     346        JSObject* object = asObject(base);
     347        if (object->canGetIndexQuickly(index))
     348            return JSValue::encode(object->getIndexQuickly(index));
     349    }
     350
    349351    if (isJSString(base) && asString(base)->canGetIndex(index))
    350352        return JSValue::encode(asString(base)->getIndex(exec, index));
     
    549551}
    550552
    551 void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
     553void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
    552554{
    553555    JSGlobalData* globalData = &exec->globalData();
     
    556558    if (index >= 0) {
    557559        // We should only get here if index is outside the existing vector.
    558         ASSERT(!array->canSetIndex(index));
    559         JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), true);
     560        ASSERT(!array->canSetIndexQuickly(index));
     561        array->methodTable()->putByIndex(array, exec, index, JSValue::decode(encodedValue), true);
    560562        return;
    561563    }
     
    566568}
    567569
    568 void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
     570void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
    569571{
    570572    JSGlobalData* globalData = &exec->globalData();
     
    573575    if (index >= 0) {
    574576        // We should only get here if index is outside the existing vector.
    575         ASSERT(!array->canSetIndex(index));
    576         JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), false);
     577        ASSERT(!array->canSetIndexQuickly(index));
     578        array->methodTable()->putByIndex(array, exec, index, JSValue::decode(encodedValue), false);
    577579        return;
    578580    }
     
    12641266char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
    12651267{
    1266     JSGlobalData& globalData = exec->globalData();
    1267     void* result;
    1268     if (!globalData.heap.tryAllocateStorage(initialOutOfLineCapacity * sizeof(JSValue), &result))
    1269         CRASH();
    1270     return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + initialOutOfLineCapacity + 1);
     1268    return reinterpret_cast<char*>(
     1269        Butterfly::createUninitialized(exec->globalData(), 0, initialOutOfLineCapacity, false, 0));
    12711270}
    12721271
    12731272char* DFG_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
    12741273{
    1275     JSGlobalData& globalData = exec->globalData();
    1276     void* result;
    1277     if (!globalData.heap.tryAllocateStorage(newSize, &result))
    1278         CRASH();
    1279     return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + 1) + newSize;
     1274    return reinterpret_cast<char*>(
     1275        Butterfly::createUninitialized(exec->globalData(), 0, newSize, false, 0));
     1276}
     1277
     1278char* DFG_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
     1279{
     1280    ASSERT(!object->structure()->outOfLineCapacity());
     1281    Butterfly* result = object->growOutOfLineStorage(exec->globalData(), 0, initialOutOfLineCapacity);
     1282    object->setButterflyWithoutChangingStructure(result);
     1283    return reinterpret_cast<char*>(result);
     1284}
     1285
     1286char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
     1287{
     1288    Butterfly* result = object->growOutOfLineStorage(exec->globalData(), object->structure()->outOfLineCapacity(), newSize);
     1289    object->setButterflyWithoutChangingStructure(result);
     1290    return reinterpret_cast<char*>(result);
    12801291}
    12811292
Note: See TracChangeset for help on using the changeset viewer.