Ignore:
Timestamp:
May 9, 2009, 1:35:57 AM (16 years ago)
Author:
[email protected]
Message:

2009-05-09 Maciej Stachowiak <[email protected]>

Reviewed by Gavin Barraclough.


Original patch by John McCall. Updated by Cameron Zwarich. Further refined by me.


  • Assorted speedups to property access


~.3%-1% speedup on SunSpider


1) When we know from the structure ID that an object is using inline storage, plant direct
loads and stores against it; no need to indirect through storage pointer.


2) Also because of the above, union the property storage pointer with the first inline property
slot and add an extra inline property slot.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::CodeLocationInstruction::CodeLocationInstruction): (JSC::AbstractMacroAssembler::CodeLocationInstruction::patchLoadToLEA): (JSC::::CodeLocationCommon::instructionAtOffset):
  • assembler/MacroAssembler.h: (JSC::MacroAssembler::storePtr):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::store32):
  • assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::storePtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::movq_EAXm): (JSC::X86Assembler::movl_rm): (JSC::X86Assembler::patchLoadToLEA):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JIT.h:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compilePutByIdHotPath): (JSC::JIT::compilePutDirectOffset): (JSC::JIT::compileGetDirectOffset): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchPutByIdReplace): (JSC::JIT::privateCompileGetByIdSelf): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain): (JSC::JIT::privateCompilePutByIdReplace):
  • runtime/JSObject.cpp: (JSC::JSObject::mark): (JSC::JSObject::removeDirect):
  • runtime/JSObject.h: (JSC::JSObject::propertyStorage): (JSC::JSObject::getDirect): (JSC::JSObject::getOffset): (JSC::JSObject::offsetForLocation): (JSC::JSObject::locationForOffset): (JSC::JSObject::getDirectOffset): (JSC::JSObject::putDirectOffset): (JSC::JSObject::isUsingInlineStorage): (JSC::JSObject::): (JSC::JSObject::JSObject): (JSC::JSObject::~JSObject): (JSC::Structure::isUsingInlineStorage): (JSC::JSObject::putDirect): (JSC::JSObject::putDirectWithoutTransition): (JSC::JSObject::allocatePropertyStorageInline):
  • runtime/Structure.h:
File:
1 edited

Legend:

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

    r43409 r43432  
    109109    ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
    110110
    111     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
     111    Label externalLoad(this);
     112    loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_externalStorage)), regT0);
     113    Label externalLoadComplete(this);
     114    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
     115    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
     116
    112117    DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
    113118    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);
     
    164169
    165170    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
    166     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
     171    Label externalLoad(this);
     172    loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_externalStorage)), regT0);
     173    Label externalLoadComplete(this);
     174    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
     175    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
     176
    167177    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
    168178    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
     
    182192    // Track the location of the call; this will be used to recover patch information.
    183193    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
     194}
     195
     196// Compile a store into an object's property storage.  May overwrite the
     197// value in objectReg.
     198void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset)
     199{
     200    int offset = cachedOffset * sizeof(JSValue);
     201    if (structure->isUsingInlineStorage())
     202        offset += FIELD_OFFSET(JSObject, m_inlineStorage);
     203    else
     204        loadPtr(Address(base, FIELD_OFFSET(JSObject, m_externalStorage)), base);
     205    storePtr(value, Address(base, offset));
     206}
     207
     208// Compile a load from an object's property storage.  May overwrite base.
     209void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset)
     210{
     211    int offset = cachedOffset * sizeof(JSValue);
     212    if (structure->isUsingInlineStorage())
     213        offset += FIELD_OFFSET(JSObject, m_inlineStorage);
     214    else
     215        loadPtr(Address(base, FIELD_OFFSET(JSObject, m_externalStorage)), base);
     216    loadPtr(Address(base, offset), result);
     217}
     218
     219void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
     220{
     221    if (base->isUsingInlineStorage())
     222        loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
     223    else {
     224        PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
     225        loadPtr(static_cast<void*>(protoPropertyStorage), temp);
     226        loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
     227    }
    184228}
    185229
     
    254298
    255299    // write the value
    256     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
    257     storePtr(regT1, Address(regT0, cachedOffset * sizeof(JSValue)));
     300    compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset);
    258301
    259302    ret();
     
    283326    returnAddress.relinkCallerToFunction(JITStubs::cti_op_get_by_id_self_fail);
    284327
     328    int offset = sizeof(JSValue) * cachedOffset;
     329
     330    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
     331    // and makes the subsequent load's offset automatically correct
     332    if (structure->isUsingInlineStorage())
     333        stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad).patchLoadToLEA();
     334
    285335    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
    286336    stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure).repatch(structure);
    287     stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset).repatch(cachedOffset * sizeof(JSValue));
     337    stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset).repatch(offset);
    288338}
    289339
     
    294344    returnAddress.relinkCallerToFunction(JITStubs::cti_op_put_by_id_generic);
    295345
     346    int offset = sizeof(JSValue) * cachedOffset;
     347
     348    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
     349    // and makes the subsequent load's offset automatically correct
     350    if (structure->isUsingInlineStorage())
     351        stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad).patchLoadToLEA();
     352
    296353    // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
    297354    stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure).repatch(structure);
    298     stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset).repatch(cachedOffset * sizeof(JSValue));
     355    stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset).repatch(offset);
    299356}
    300357
     
    345402
    346403    // Checks out okay! - getDirectOffset
    347     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
    348     loadPtr(Address(regT0, cachedOffset * sizeof(JSValue)), regT0);
     404    compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
    349405    ret();
    350406
     
    386442
    387443    // Checks out okay! - getDirectOffset
    388     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    389     loadPtr(static_cast<void*>(protoPropertyStorage), regT1);
    390     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     444    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    391445
    392446    Jump success = jump();
     
    424478
    425479    // Checks out okay! - getDirectOffset
    426     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    427     loadPtr(protoPropertyStorage, regT1);
    428     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     480    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    429481
    430482    ret();
     
    447499{
    448500    Jump failureCase = checkStructure(regT0, structure);
    449     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
    450     loadPtr(Address(regT0, cachedOffset * sizeof(JSValue)), regT0);
     501    compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
    451502    Jump success = jump();
    452503
     
    494545
    495546    // Checks out okay! - getDirectOffset
    496     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    497     loadPtr(protoPropertyStorage, regT1);
    498     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     547    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    499548
    500549    Jump success = jump();
     
    550599    ASSERT(protoObject);
    551600
    552     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    553     loadPtr(protoPropertyStorage, regT1);
    554     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     601    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    555602    Jump success = jump();
    556603
     
    610657    ASSERT(protoObject);
    611658
    612     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    613     loadPtr(protoPropertyStorage, regT1);
    614     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     659    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    615660    Jump success = jump();
    616661
     
    658703    ASSERT(protoObject);
    659704
    660     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    661     loadPtr(protoPropertyStorage, regT1);
    662     loadPtr(Address(regT1, cachedOffset * sizeof(JSValue)), regT0);
     705    compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     706    compilePutDirectOffset(regT0, regT1, structure, cachedOffset);
    663707    ret();
    664708
     
    680724
    681725    // checks out okay! - putDirectOffset
    682     loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);
    683     storePtr(regT1, Address(regT0, cachedOffset * sizeof(JSValue)));
     726    compilePutDirectOffset(regT0, regT1, structure, cachedOffset);
    684727    ret();
    685728
Note: See TracChangeset for help on using the changeset viewer.