Ignore:
Timestamp:
Feb 16, 2011, 1:35:19 PM (14 years ago)
Author:
[email protected]
Message:

Bug 54524 - Allow JSObject to fully utilize cell's capacity for inline storage.

Reviewed by Geoff Garen.

Currently JSObject is both directly instantiated for regular JS objects, and
derived to implement subtypes. A consequence of this is that we need to ensure
that sufficient space from the cell is left unused and available for any data
members that will be introduced by subclasses of JSObject. By restructuring
the internal storage array out of JSObject we can increase the size in the
internal storage for regular objects.

Add classes JSFinalObject and JSNonFinalObject. JSNonFinalObject retains as
much additional capacity as is currently available to allow for data members
in subclasses. JSFinalObject utilizes all available space for internal storage,
and only allows construction through JSFinalObject::create().

Source/JavaScriptCore:

The additional storage made available in the JSObject means that we need no
longer rely on a union of the internal storage with a pointer to storage that
is only valid for external storage. This means we can go back to always having
a valid pointer to property storage, regardless of whether this is internal or
external. This simplifies some cases of access to the array from C code, and
significantly simplifies JIT access, since repatching no longer needs to be
able to change between a load of the storage pointer / a LEA of the internal
storage.

  • API/JSObjectRef.cpp:

(JSObjectMake):

  • assembler/ARMAssembler.h:
  • assembler/ARMv7Assembler.h:
  • assembler/AbstractMacroAssembler.h:

(JSC::AbstractMacroAssembler::repatchPointer):

  • assembler/MIPSAssembler.h:
  • assembler/MacroAssemblerARM.h:
  • assembler/MacroAssemblerARMv7.h:
  • assembler/MacroAssemblerMIPS.h:
  • assembler/MacroAssemblerX86.h:
  • assembler/MacroAssemblerX86_64.h:
  • assembler/RepatchBuffer.h:
  • assembler/X86Assembler.h:
  • debugger/DebuggerActivation.cpp:

(JSC::DebuggerActivation::DebuggerActivation):

  • debugger/DebuggerActivation.h:
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_resolve_global):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_resolve_global):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::emit_op_get_by_pname):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::patchGetByIdSelf):
(JSC::JIT::patchPutByIdReplace):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::patchGetByIdSelf):
(JSC::JIT::patchPutByIdReplace):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
(JSC::JIT::emit_op_get_by_pname):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • runtime/Arguments.h:

(JSC::Arguments::Arguments):

  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::ErrorInstance):

  • runtime/ErrorInstance.h:
  • runtime/ExceptionHelpers.cpp:

(JSC::InterruptedExecutionError::InterruptedExecutionError):
(JSC::TerminatedExecutionError::TerminatedExecutionError):

  • runtime/JSArray.cpp:

(JSC::JSArray::JSArray):

  • runtime/JSArray.h:
  • runtime/JSByteArray.cpp:

(JSC::JSByteArray::JSByteArray):

  • runtime/JSByteArray.h:

(JSC::JSByteArray::JSByteArray):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::getOwnPropertySlot):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):

  • runtime/JSGlobalObject.h:

(JSC::constructEmptyObject):

  • runtime/JSNotAnObject.h:

(JSC::JSNotAnObject::JSNotAnObject):

  • runtime/JSObject.cpp:

(JSC::JSObject::createInheritorID):
(JSC::JSObject::allocatePropertyStorage):

  • runtime/JSObject.h:

(JSC::JSObject::propertyStorage):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC::JSNonFinalObject::createStructure):
(JSC::JSFinalObject::create):
(JSC::JSFinalObject::createStructure):
(JSC::JSFinalObject::JSFinalObject):
(JSC::JSObject::offsetOfInlineStorage):
(JSC::constructEmptyObject):
(JSC::createEmptyObjectStructure):
(JSC::JSObject::JSObject):
(JSC::JSObject::~JSObject):
(JSC::Structure::isUsingInlineStorage):

  • runtime/JSObjectWithGlobalObject.cpp:

(JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):

  • runtime/JSObjectWithGlobalObject.h:

(JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):

  • runtime/JSTypeInfo.h:

(JSC::TypeInfo::TypeInfo):
(JSC::TypeInfo::isVanilla):

  • runtime/JSVariableObject.h:

(JSC::JSVariableObject::JSVariableObject):

  • runtime/JSWrapperObject.h:

(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/ObjectConstructor.cpp:

(JSC::constructObject):

  • runtime/ObjectPrototype.cpp:

(JSC::ObjectPrototype::ObjectPrototype):

  • runtime/ObjectPrototype.h:
  • runtime/StrictEvalActivation.cpp:

(JSC::StrictEvalActivation::StrictEvalActivation):

  • runtime/StrictEvalActivation.h:
  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::growPropertyStorageCapacity):

Source/JavaScriptGlue:

  • UserObjectImp.cpp:
  • UserObjectImp.h:

Update JSObject -> JSNonFinalObject.

Source/WebCore:

  • bindings/js/JSDOMWindowShell.h:

Update JSObject -> JSNonFinalObject.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r70750 r78732  
    139139}
    140140
    141 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch)
    142 {
    143     ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
    144     ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
    145 
    146     Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
    147     loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result);
    148     Jump finishedLoad = jump();
    149     notUsingInlineStorage.link(this);
    150     loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch);
     141void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
     142{
     143    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), scratch);
    151144    loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
    152     finishedLoad.link(this);
    153145}
    154146
     
    173165    sub32(Imm32(1), regT3);
    174166    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
    175     compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1);
     167    compileGetDirectOffset(regT0, regT0, regT3, regT1);
    176168
    177169    emitPutVirtualRegister(dst, regT0);
     
    428420    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase)
    429421
    430     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
    431     Label externalLoadComplete(this);
    432     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetGetByIdExternalLoad);
    433     ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthGetByIdExternalLoad);
    434 
     422    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
    435423    DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
    436424    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
     
    508496    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
    509497
    510     // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
    511     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
    512     Label externalLoadComplete(this);
    513     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetPutByIdExternalLoad);
    514     ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthPutByIdExternalLoad);
    515 
     498    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
    516499    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
    517500
     
    548531    int offset = cachedOffset * sizeof(JSValue);
    549532    if (structure->isUsingInlineStorage())
    550         offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
     533        offset += JSObject::offsetOfInlineStorage();
    551534    else
    552         loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
     535        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
    553536    storePtr(value, Address(base, offset));
    554537}
     
    558541{
    559542    int offset = cachedOffset * sizeof(JSValue);
    560     if (structure->isUsingInlineStorage())
    561         offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
    562     else
    563         loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
    564     loadPtr(Address(base, offset), result);
    565 }
    566 
    567 void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
    568 {
    569     if (base->isUsingInlineStorage())
    570         loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
    571     else {
    572         PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
    573         loadPtr(static_cast<void*>(protoPropertyStorage), temp);
    574         loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
    575     }
     543    if (structure->isUsingInlineStorage()) {
     544        offset += JSObject::offsetOfInlineStorage();
     545        loadPtr(Address(base, offset), result);
     546    } else {
     547        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), result);
     548        loadPtr(Address(result, offset), result);
     549    }
     550}
     551
     552void JIT::compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset)
     553{
     554    loadPtr(static_cast<void*>(&base->m_propertyStorage[cachedOffset]), result);
    576555}
    577556
     
    669648    int offset = sizeof(JSValue) * cachedOffset;
    670649
    671     // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
    672     // and makes the subsequent load's offset automatically correct
    673     if (structure->isUsingInlineStorage())
    674         repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
    675 
    676650    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
    677651    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
     
    708682
    709683    int offset = sizeof(JSValue) * cachedOffset;
    710 
    711     // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
    712     // and makes the subsequent load's offset automatically correct
    713     if (structure->isUsingInlineStorage())
    714         repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
    715684
    716685    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     
    780749    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    781750        needsStubLink = true;
    782         compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     751        compileGetDirectOffset(protoObject, regT1, cachedOffset);
    783752        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    784753        stubCall.addArgument(regT1);
     
    795764        stubCall.call();
    796765    } else
    797         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     766        compileGetDirectOffset(protoObject, regT0, cachedOffset);
    798767    Jump success = jump();
    799768    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
     
    832801    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    833802        needsStubLink = true;
    834         if (!structure->isUsingInlineStorage()) {
    835             move(regT0, regT1);
    836             compileGetDirectOffset(regT1, regT1, structure, cachedOffset);
    837         } else
    838             compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
     803        compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
    839804        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    840805        stubCall.addArgument(regT1);
     
    906871    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    907872        needsStubLink = true;
    908         compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     873        compileGetDirectOffset(protoObject, regT1, cachedOffset);
    909874        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    910875        stubCall.addArgument(regT1);
     
    921886        stubCall.call();
    922887    } else
    923         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     888        compileGetDirectOffset(protoObject, regT0, cachedOffset);
    924889
    925890    Jump success = jump();
     
    976941    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    977942        needsStubLink = true;
    978         compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     943        compileGetDirectOffset(protoObject, regT1, cachedOffset);
    979944        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    980945        stubCall.addArgument(regT1);
     
    991956        stubCall.call();
    992957    } else
    993         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     958        compileGetDirectOffset(protoObject, regT0, cachedOffset);
    994959    Jump success = jump();
    995960
     
    10461011    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    10471012        needsStubLink = true;
    1048         compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     1013        compileGetDirectOffset(protoObject, regT1, cachedOffset);
    10491014        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    10501015        stubCall.addArgument(regT1);
     
    10611026        stubCall.call();
    10621027    } else
    1063         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     1028        compileGetDirectOffset(protoObject, regT0, cachedOffset);
    10641029    Jump success = jump();
    10651030
Note: See TracChangeset for help on using the changeset viewer.