Changeset 123417 in webkit


Ignore:
Timestamp:
Jul 23, 2012 7:13:19 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

Property storage should grow in reverse address direction, to support butterflies
https://bugs.webkit.org/show_bug.cgi?id=91788

Reviewed by Geoffrey Garen.

Changes property storage to grow to the left, and changes the property storage pointer to point
one 8-byte word (i.e. JSValue) to the right of the first value in the storage.

Also improved debug support somewhat, by adding a describe() function to the jsc command-line,
and a slow mode of object access in LLInt.

  • assembler/ARMv7Assembler.h:

(JSC::ARMv7Assembler::repatchCompact):

  • assembler/MacroAssemblerARMv7.h:

(MacroAssemblerARMv7):
(JSC::MacroAssemblerARMv7::isCompactPtrAlignedAddressOffset):
(JSC::MacroAssemblerARMv7::load32WithCompactAddressOffsetPatch):

  • assembler/MacroAssemblerX86Common.h:

(JSC::MacroAssemblerX86Common::isCompactPtrAlignedAddressOffset):
(JSC::MacroAssemblerX86Common::repatchCompact):

  • assembler/X86Assembler.h:

(JSC::X86Assembler::repatchCompact):

  • bytecode/CodeBlock.cpp:

(JSC::dumpStructure):

  • bytecode/GetByIdStatus.h:

(JSC::GetByIdStatus::GetByIdStatus):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGRepatch.cpp:

(JSC::DFG::tryCacheGetByID):
(JSC::DFG::emitPutTransitionStub):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • heap/ConservativeRoots.cpp:

(JSC::ConservativeRoots::genericAddPointer):

  • heap/CopiedSpace.h:

(CopiedSpace):

  • heap/CopiedSpaceInlineMethods.h:

(JSC::CopiedSpace::pinIfNecessary):
(JSC):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::compileGetDirectOffset):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::compileGetDirectOffset):

  • jit/JITStubs.cpp:

(JSC::JITThunks::tryCacheGetByID):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionDescribe):

  • llint/LLIntCommon.h:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/JSObject.cpp:

(JSC::JSObject::visitChildren):
(JSC::JSFinalObject::visitChildren):
(JSC::JSObject::growOutOfLineStorage):

  • runtime/JSObject.h:

(JSC::JSObject::getDirectLocation):
(JSC::JSObject::offsetForLocation):

  • runtime/JSValue.h:

(JSValue):

  • runtime/PropertyOffset.h:

(JSC::offsetInOutOfLineStorage):

Location:
trunk/Source/JavaScriptCore
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r123394 r123417  
     12012-07-23  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Property storage should grow in reverse address direction, to support butterflies
     4        https://bugs.webkit.org/show_bug.cgi?id=91788
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Changes property storage to grow to the left, and changes the property storage pointer to point
     9        one 8-byte word (i.e. JSValue) to the right of the first value in the storage.
     10       
     11        Also improved debug support somewhat, by adding a describe() function to the jsc command-line,
     12        and a slow mode of object access in LLInt.
     13
     14        * assembler/ARMv7Assembler.h:
     15        (JSC::ARMv7Assembler::repatchCompact):
     16        * assembler/MacroAssemblerARMv7.h:
     17        (MacroAssemblerARMv7):
     18        (JSC::MacroAssemblerARMv7::isCompactPtrAlignedAddressOffset):
     19        (JSC::MacroAssemblerARMv7::load32WithCompactAddressOffsetPatch):
     20        * assembler/MacroAssemblerX86Common.h:
     21        (JSC::MacroAssemblerX86Common::isCompactPtrAlignedAddressOffset):
     22        (JSC::MacroAssemblerX86Common::repatchCompact):
     23        * assembler/X86Assembler.h:
     24        (JSC::X86Assembler::repatchCompact):
     25        * bytecode/CodeBlock.cpp:
     26        (JSC::dumpStructure):
     27        * bytecode/GetByIdStatus.h:
     28        (JSC::GetByIdStatus::GetByIdStatus):
     29        * dfg/DFGOperations.cpp:
     30        * dfg/DFGOperations.h:
     31        * dfg/DFGRepatch.cpp:
     32        (JSC::DFG::tryCacheGetByID):
     33        (JSC::DFG::emitPutTransitionStub):
     34        * dfg/DFGSpeculativeJIT.cpp:
     35        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
     36        (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
     37        * dfg/DFGSpeculativeJIT.h:
     38        (JSC::DFG::SpeculativeJIT::callOperation):
     39        * dfg/DFGSpeculativeJIT32_64.cpp:
     40        (JSC::DFG::SpeculativeJIT::compile):
     41        * dfg/DFGSpeculativeJIT64.cpp:
     42        (JSC::DFG::SpeculativeJIT::compile):
     43        * heap/ConservativeRoots.cpp:
     44        (JSC::ConservativeRoots::genericAddPointer):
     45        * heap/CopiedSpace.h:
     46        (CopiedSpace):
     47        * heap/CopiedSpaceInlineMethods.h:
     48        (JSC::CopiedSpace::pinIfNecessary):
     49        (JSC):
     50        * jit/JITPropertyAccess.cpp:
     51        (JSC::JIT::compileGetDirectOffset):
     52        * jit/JITPropertyAccess32_64.cpp:
     53        (JSC::JIT::compileGetDirectOffset):
     54        * jit/JITStubs.cpp:
     55        (JSC::JITThunks::tryCacheGetByID):
     56        * jsc.cpp:
     57        (GlobalObject::finishCreation):
     58        (functionDescribe):
     59        * llint/LLIntCommon.h:
     60        * llint/LLIntSlowPaths.cpp:
     61        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     62        * llint/LowLevelInterpreter32_64.asm:
     63        * llint/LowLevelInterpreter64.asm:
     64        * runtime/JSObject.cpp:
     65        (JSC::JSObject::visitChildren):
     66        (JSC::JSFinalObject::visitChildren):
     67        (JSC::JSObject::growOutOfLineStorage):
     68        * runtime/JSObject.h:
     69        (JSC::JSObject::getDirectLocation):
     70        (JSC::JSObject::offsetForLocation):
     71        * runtime/JSValue.h:
     72        (JSValue):
     73        * runtime/PropertyOffset.h:
     74        (JSC::offsetInOutOfLineStorage):
     75
    1762012-07-23  Filip Pizlo  <fpizlo@apple.com>
    277
  • trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h

    r122347 r123417  
    20962096    }
    20972097   
    2098     static void repatchCompact(void* where, int32_t value)
    2099     {
    2100         ASSERT(value >= 0);
    2101         ASSERT(ARMThumbImmediate::makeUInt12(value).isUInt7());
    2102         setUInt7ForLoad(where, ARMThumbImmediate::makeUInt12(value));
     2098    static void repatchCompact(void* where, int32_t offset)
     2099    {
     2100        ASSERT(offset >= -255 && offset <= 255);
     2101
     2102        bool add = true;
     2103        if (offset < 0) {
     2104            add = false;
     2105            offset = -offset;
     2106        }
     2107       
     2108        offset |= (add << 9);
     2109        offset |= (1 << 10);
     2110        offset |= (1 << 11);
     2111
     2112        uint16_t* location = reinterpret_cast<uint16_t*>(where);
     2113        location[1] &= ~((1 << 12) - 1);
     2114        location[1] |= offset;
     2115        cacheFlush(location, sizeof(uint16_t) * 2);
    21032116    }
    21042117
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r122677 r123417  
    5454    typedef ARMv7Assembler::JumpType JumpType;
    5555    typedef ARMv7Assembler::JumpLinkType JumpLinkType;
    56     // Magic number is the biggest useful offset we can get on ARMv7 with
    57     // a LDR_imm_T2 encoding
    58     static const int MaximumCompactPtrAlignedAddressOffset = 124;
    59    
     56
     57    static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
     58    {
     59        return value >= -255 && value <= 255;
     60    }
     61
    6062    Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
    6163    void* unlinkedCode() { return m_assembler.unlinkedCode(); }
     
    643645    }
    644646   
    645     // FIXME: we should be able to plant a compact load relative to/from any base/dest register.
    646647    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
    647648    {
    648649        RegisterID base = address.base;
    649650       
    650         if (base >= ARMRegisters::r8) {
    651             move(base, addressTempRegister);
    652             base = addressTempRegister;
    653         }
    654 
    655651        DataLabelCompact label(this);
    656         ASSERT(address.offset >= 0);
    657         ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
    658         ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7());
    659 
    660         if (dest >= ARMRegisters::r8) {
    661             m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset));
    662             move(addressTempRegister, dest);
    663         } else
    664             m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset));
     652        ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
     653
     654        m_assembler.ldr(dest, base, address.offset, true, false);
    665655        return label;
    666656    }
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r120244 r123417  
    4848    typedef X86Assembler::XMMRegisterID XMMRegisterID;
    4949   
    50     static const int MaximumCompactPtrAlignedAddressOffset = 127;
     50    static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
     51    {
     52        return value >= -128 && value <= 127;
     53    }
    5154
    5255    enum RelationalCondition {
     
    495498    static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
    496499    {
    497         ASSERT(value >= 0);
    498         ASSERT(value < MaximumCompactPtrAlignedAddressOffset);
     500        ASSERT(isCompactPtrAlignedAddressOffset(value));
    499501        AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
    500502    }
  • trunk/Source/JavaScriptCore/assembler/X86Assembler.h

    r123169 r123417  
    18301830    static void repatchCompact(void* where, int32_t value)
    18311831    {
    1832         ASSERT(value >= 0);
     1832        ASSERT(value >= std::numeric_limits<int8_t>::min());
    18331833        ASSERT(value <= std::numeric_limits<int8_t>::max());
    18341834        setInt8(where, value);
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r123042 r123417  
    256256    dataLog("%s = %p", name, structure);
    257257   
    258     size_t offset = structure->get(exec->globalData(), ident);
    259     if (offset != notFound)
    260         dataLog(" (offset = %lu)", static_cast<unsigned long>(offset));
     258    PropertyOffset offset = structure->get(exec->globalData(), ident);
     259    if (offset != invalidOffset)
     260        dataLog(" (offset = %d)", offset);
    261261}
    262262#endif
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h

    r121925 r123417  
    5454    GetByIdStatus(
    5555        State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(),
    56         size_t offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>())
     56        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>())
    5757        : m_state(state)
    5858        , m_structureSet(structureSet)
     
    6262        , m_wasSeenInJIT(wasSeenInJIT)
    6363    {
    64         ASSERT((state == Simple) == (offset != notFound));
     64        ASSERT((state == Simple) == (offset != invalidOffset));
    6565    }
    6666   
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r123052 r123417  
    12491249    if (!globalData.heap.tryAllocateStorage(initialOutOfLineCapacity * sizeof(JSValue), &result))
    12501250        CRASH();
    1251     return reinterpret_cast<char*>(result);
     1251    return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + initialOutOfLineCapacity + 1);
    12521252}
    12531253
     
    12581258    if (!globalData.heap.tryAllocateStorage(newSize, &result))
    12591259        CRASH();
    1260     return reinterpret_cast<char*>(result);
     1260    return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + 1) + newSize;
    12611261}
    12621262
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r123052 r123417  
    107107typedef char* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
    108108typedef char* DFG_OPERATION (*P_DFGOperation_ES)(ExecState*, size_t);
     109typedef char* DFG_OPERATION (*P_DFGOperation_EPS)(ExecState*, void*, size_t);
    109110
    110111// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp

    r123164 r123417  
    302302    // Optimize self access.
    303303    if (slot.slotBase() == baseValue) {
    304         if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)) {
     304        if ((slot.cachedPropertyType() != PropertySlot::Value)
     305            || !MacroAssembler::isCompactPtrAlignedAddressOffset(offsetRelativeToPatchedStorage(slot.cachedOffset()))) {
    305306            dfgRepatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdBuildList);
    306307            return true;
     
    825826            stubJit.negPtr(scratchGPR1);
    826827            stubJit.addPtr(MacroAssembler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR1);
    827             stubJit.subPtr(MacroAssembler::TrustedImm32(newSize), scratchGPR1);
     828            stubJit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSValue)), scratchGPR1);
    828829        } else {
    829830            size_t oldSize = oldStructure->outOfLineCapacity() * sizeof(JSValue);
     
    836837            stubJit.negPtr(scratchGPR1);
    837838            stubJit.addPtr(MacroAssembler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR1);
    838             stubJit.subPtr(MacroAssembler::TrustedImm32(newSize), scratchGPR1);
     839            stubJit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSValue)), scratchGPR1);
    839840            // We have scratchGPR1 = new storage, scratchGPR3 = old storage, scratchGPR2 = available
    840             for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) {
    841                 stubJit.loadPtr(MacroAssembler::Address(scratchGPR3, offset), scratchGPR2);
    842                 stubJit.storePtr(scratchGPR2, MacroAssembler::Address(scratchGPR1, offset));
     841            for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(oldSize); offset += sizeof(void*)) {
     842                stubJit.loadPtr(MacroAssembler::Address(scratchGPR3, -(offset + sizeof(JSValue) * 2)), scratchGPR2);
     843                stubJit.storePtr(scratchGPR2, MacroAssembler::Address(scratchGPR1, -(offset + sizeof(JSValue) * 2)));
    843844            }
    844845        }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r123393 r123417  
    31583158    m_jit.negPtr(scratchGPR);
    31593159    m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR);
    3160     m_jit.subPtr(JITCompiler::TrustedImm32(newSize), scratchGPR);
     3160    m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR);
    31613161       
    31623162    addSlowPathGenerator(
     
    31923192    m_jit.negPtr(scratchGPR2);
    31933193    m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR2);
    3194     m_jit.subPtr(JITCompiler::TrustedImm32(newSize), scratchGPR2);
     3194    m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR2);
    31953195       
    31963196    addSlowPathGenerator(
    31973197        slowPathCall(slowPath, this, operationAllocatePropertyStorage, scratchGPR2, newSize));
    31983198    // We have scratchGPR2 = new storage, scratchGPR1 = scratch
    3199     for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) {
    3200         m_jit.loadPtr(JITCompiler::Address(oldStorageGPR, offset), scratchGPR1);
    3201         m_jit.storePtr(scratchGPR1, JITCompiler::Address(scratchGPR2, offset));
     3199    for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(oldSize); offset += sizeof(void*)) {
     3200        m_jit.loadPtr(JITCompiler::Address(oldStorageGPR, -(offset + sizeof(JSValue) * 2)), scratchGPR1);
     3201        m_jit.storePtr(scratchGPR1, JITCompiler::Address(scratchGPR2, -(offset + sizeof(JSValue) * 2)));
    32023202    }
    32033203    m_jit.storePtr(scratchGPR2, JITCompiler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage()));
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r123052 r123417  
    11621162        return appendCallWithExceptionCheckSetResult(operation, result);
    11631163    }
     1164    JITCompiler::Call callOperation(P_DFGOperation_EPS operation, GPRReg result, GPRReg old, size_t size)
     1165    {
     1166        m_jit.setupArgumentsWithExecState(old, TrustedImmPtr(size));
     1167        return appendCallWithExceptionCheckSetResult(operation, result);
     1168    }
    11641169    JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg result)
    11651170    {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r123169 r123417  
    39143914        isOutOfLine.link(&m_jit);
    39153915#endif
    3916         m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) - inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR);
    3917         m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) - inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR);
     3916        m_jit.neg32(resolveInfoGPR);
     3917        m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR);
     3918        m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR);
     3919        m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR);
    39183920
    39193921        addSlowPathGenerator(
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r123169 r123417  
    39033903        isOutOfLine.link(&m_jit);
    39043904#endif
     3905        m_jit.neg32(resolveInfoGPR);
     3906        m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR);
    39053907        m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfOutOfLineStorage()), resultGPR);
    3906         m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, -inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR);
     3908        m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR);
    39073909       
    39083910        addSlowPathGenerator(
  • trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp

    r122166 r123417  
    6767{
    6868    markHook.mark(p);
    69    
    70     CopiedBlock* block;
    71     if (m_copiedSpace->contains(p, block))
    72         m_copiedSpace->pin(block);
     69
     70    m_copiedSpace->pinIfNecessary(p);
    7371   
    7472    MarkedBlock* candidate = MarkedBlock::blockFor(p);
  • trunk/Source/JavaScriptCore/heap/CopiedSpace.h

    r122677 r123417  
    6969    bool contains(CopiedBlock*);
    7070    bool contains(void*, CopiedBlock*&);
     71   
     72    void pinIfNecessary(void* pointer);
    7173
    7274    size_t size();
  • trunk/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h

    r122677 r123417  
    5656{
    5757    block->m_isPinned = true;
     58}
     59
     60inline void CopiedSpace::pinIfNecessary(void* opaquePointer)
     61{
     62    // Pointers into the copied space come in the following varieties:
     63    // 1)  Pointers to the start of a span of memory. This is the most
     64    //     natural though not necessarily the most common.
     65    // 2)  Pointers to one value-sized (8 byte) word past the end of
     66    //     a span of memory. This currently occurs with semi-butterflies
     67    //     and should be fixed soon, once the other half of the
     68    //     butterfly lands.
     69    // 3)  Pointers to the innards arising from loop induction variable
     70    //     optimizations (either manual ones or automatic, by the
     71    //     compiler).
     72    // 4)  Pointers to the end of a span of memory in arising from
     73    //     induction variable optimizations combined with the
     74    //     GC-to-compiler contract laid out in the C spec: a pointer to
     75    //     the end of a span of memory must be considered to be a
     76    //     pointer to that memory.
     77   
     78    EncodedJSValue* pointer = reinterpret_cast<EncodedJSValue*>(opaquePointer);
     79    CopiedBlock* block;
     80
     81    // Handle (1) and (3).
     82    if (contains(pointer, block))
     83        pin(block);
     84   
     85    // Handle (4). We don't have to explicitly check and pin the block under this
     86    // pointer because it cannot possibly point to something that cases (1) and
     87    // (3) above or case (2) below wouldn't already catch.
     88    pointer--;
     89   
     90    // Handle (2)
     91    pointer--;
     92    if (contains(pointer, block))
     93        pin(block);
    5894}
    5995
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r122166 r123417  
    160160        Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity));
    161161        loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), scratch);
     162        neg32(offset);
    162163        Jump done = jump();
    163164        isInline.link(this);
    164         addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() + inlineStorageCapacity * sizeof(EncodedJSValue)), base, scratch);
     165        addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base, scratch);
    165166        done.link(this);
    166167    } else {
     
    171172#endif
    172173        loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), scratch);
    173     }
    174     loadPtr(BaseIndex(scratch, offset, ScalePtr, -inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), result);
     174        neg32(offset);
     175    }
     176    signExtend32ToPtr(offset, offset);
     177    loadPtr(BaseIndex(scratch, offset, ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), result);
    175178}
    176179
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r122166 r123417  
    10191019        Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity));
    10201020        loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), base);
     1021        neg32(offset);
    10211022        Jump done = jump();
    10221023        isInline.link(this);
    1023         addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() + inlineStorageCapacity * sizeof(EncodedJSValue)), base);
     1024        addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base);
    10241025        done.link(this);
    10251026    } else {
     
    10301031#endif
    10311032        loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), base);
    1032     }
    1033     load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - inlineStorageCapacity * sizeof(EncodedJSValue)), resultPayload);
    1034     load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - inlineStorageCapacity * sizeof(EncodedJSValue)), resultTag);
     1033        neg32(offset);
     1034    }
     1035    load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), resultPayload);
     1036    load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), resultTag);
    10351037}
    10361038
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r122594 r123417  
    933933        // set this up, so derefStructures can do it's job.
    934934        stubInfo->initGetByIdSelf(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
    935         if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
     935        if ((slot.cachedPropertyType() != PropertySlot::Value)
     936            || !MacroAssembler::isCompactPtrAlignedAddressOffset(offsetRelativeToPatchedStorage(slot.cachedOffset())))
    936937            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
    937938        else
  • trunk/Source/JavaScriptCore/jsc.cpp

    r123042 r123417  
    8585static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
    8686static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
     87static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
    8788static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
    8889static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
     
    192193       
    193194        addFunction(globalData, "debug", functionDebug, 1);
     195        addFunction(globalData, "describe", functionDescribe, 1);
    194196        addFunction(globalData, "print", functionPrint, 1);
    195197        addFunction(globalData, "quit", functionQuit, 0);
     
    296298{
    297299    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
     300    return JSValue::encode(jsUndefined());
     301}
     302
     303EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
     304{
     305    fprintf(stderr, "--> %s\n", exec->argument(0).description());
    298306    return JSValue::encode(jsUndefined());
    299307}
  • trunk/Source/JavaScriptCore/llint/LLIntCommon.h

    r108444 r123417  
    3737#define LLINT_ALWAYS_ALLOCATE_SLOW 0
    3838
     39// Disable inline caching of get_by_id and put_by_id.
     40#define LLINT_ALWAYS_ACCESS_SLOW 0
     41
    3942// Enable OSR into the JIT. Disabling this while the LLInt is enabled effectively
    4043// turns off all JIT'ing, since in LLInt's parlance, OSR subsumes any form of JIT
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r121925 r123417  
    884884    LLINT_OP(1) = result;
    885885
    886     if (baseValue.isCell()
     886    if (!LLINT_ALWAYS_ACCESS_SLOW
     887        && baseValue.isCell()
    887888        && slot.isCacheable()
    888889        && slot.slotBase() == baseValue
     
    936937    LLINT_CHECK_EXCEPTION();
    937938   
    938     if (baseValue.isCell()
     939    if (!LLINT_ALWAYS_ACCESS_SLOW
     940        && baseValue.isCell()
    939941        && slot.isCacheable()) {
    940942       
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r122650 r123417  
    922922macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffset, objectAndStorage, tag, payload)
    923923    assert(macro (ok) bigteq propertyOffset, InlineStorageCapacity, ok end)
     924    negi propertyOffset
    924925    loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage
    925     loadi TagOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], tag
    926     loadi PayloadOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], payload
     926    loadi TagOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], tag
     927    loadi PayloadOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], payload
    927928end
    928929
     
    930931    bilt propertyOffset, InlineStorageCapacity, .isInline
    931932    loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage
     933    negi propertyOffset
    932934    jmp .ready
    933935.isInline:
    934     addp JSFinalObject::m_inlineStorage + InlineStorageCapacity * 8, objectAndStorage
     936    addp JSFinalObject::m_inlineStorage - (InlineStorageCapacity - 2) * 8, objectAndStorage
    935937.ready:
    936     loadi TagOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], tag
    937     loadi PayloadOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], payload
     938    loadi TagOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], tag
     939    loadi PayloadOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], payload
    938940end
    939941
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r122650 r123417  
    779779
    780780
    781 macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffset, objectAndStorage, value)
    782     assert(macro (ok) bigteq propertyOffset, InlineStorageCapacity, ok end)
     781macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffsetAsPointer, objectAndStorage, value)
     782    assert(macro (ok) bigteq propertyOffsetAsPointer, InlineStorageCapacity, ok end)
     783    negp propertyOffsetAsPointer
    783784    loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage
    784     loadp -8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], value
    785 end
    786 
    787 macro loadPropertyAtVariableOffset(propertyOffset, objectAndStorage, value)
    788     bilt propertyOffset, InlineStorageCapacity, .isInline
     785    loadp (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffsetAsPointer, 8], value
     786end
     787
     788macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
     789    bilt propertyOffsetAsInt, InlineStorageCapacity, .isInline
    789790    loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage
     791    negi propertyOffsetAsInt
     792    sxi2p propertyOffsetAsInt, propertyOffsetAsInt
    790793    jmp .ready
    791794.isInline:
    792     addp JSFinalObject::m_inlineStorage + InlineStorageCapacity * 8, objectAndStorage
     795    addp JSFinalObject::m_inlineStorage - (InlineStorageCapacity - 2) * 8, objectAndStorage
    793796.ready:
    794     loadp -8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], value
     797    loadp (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
    795798end
    796799
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r123164 r123417  
    100100    if (storage) {
    101101        size_t storageSize = thisObject->structure()->outOfLineSizeForKnownNonFinalObject();
     102        size_t capacity = thisObject->structure()->outOfLineCapacity();
    102103        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
    103         void* temp = storage;
    104         visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize);
    105         storage = static_cast<PropertyStorage>(temp);
     104        void* temp = storage - capacity - 1;
     105        visitor.copyAndAppend(&temp, capacity * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize);
     106        storage = static_cast<PropertyStorage>(temp) + capacity + 1;
    106107        thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked);
    107108    }
     
    129130    if (storage) {
    130131        size_t storageSize = thisObject->structure()->outOfLineSizeForKnownFinalObject();
     132        size_t capacity = thisObject->structure()->outOfLineCapacity();
    131133        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
    132         void* temp = storage;
    133         visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize);
    134         storage = static_cast<PropertyStorage>(temp);
     134        void* temp = storage - capacity - 1;
     135        visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize);
     136        storage = static_cast<PropertyStorage>(temp) + capacity + 1;
    135137        thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked);
    136138    }
     
    596598    // It's important that this function not rely on structure(), since
    597599    // we might be in the middle of a transition.
    598 
     600   
    599601    PropertyStorage oldPropertyStorage = m_outOfLineStorage.get();
    600602    PropertyStorage newPropertyStorage = 0;
     
    604606    if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp))
    605607        CRASH();
    606     newPropertyStorage = static_cast<PropertyStorage>(temp);
     608    newPropertyStorage = static_cast<PropertyStorage>(temp) + newSize + 1;
    607609   
    608     memcpy(newPropertyStorage, oldPropertyStorage, sizeof(WriteBarrierBase<Unknown>) * oldSize);
     610    memcpy(newPropertyStorage - oldSize - 1, oldPropertyStorage - oldSize - 1, sizeof(WriteBarrierBase<Unknown>) * oldSize);
    609611
    610612    ASSERT(newPropertyStorage);
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r122090 r123417  
    174174            PropertyOffset offset = structure()->get(globalData, propertyName);
    175175            checkOffset(offset, structure()->typeInfo().type());
    176             return offset != invalidOffset ? locationForOffset(offset) : 0;
     176            return isValidOffset(offset) ? locationForOffset(offset) : 0;
    177177        }
    178178
     
    181181            JSCell* specificFunction;
    182182            PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction);
    183             return offset != invalidOffset ? locationForOffset(offset) : 0;
     183            return isValidOffset(offset) ? locationForOffset(offset) : 0;
    184184        }
    185185
     
    228228                result = offsetInInlineStorage;
    229229            else
    230                 result = location - outOfLineStorage() + firstOutOfLineOffset;
     230                result = outOfLineStorage() - location + (inlineStorageCapacity - 2);
    231231            validateOffset(result, structure()->typeInfo().type());
    232232            return result;
  • trunk/Source/JavaScriptCore/runtime/JSValue.h

    r122392 r123417  
    255255        JSValue structureOrUndefined() const;
    256256
    257         char* description() const;
     257        JS_EXPORT_PRIVATE char* description() const;
    258258
    259259        JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
  • trunk/Source/JavaScriptCore/runtime/PropertyOffset.h

    r121925 r123417  
    119119    validateOffset(offset);
    120120    ASSERT(isOutOfLineOffset(offset));
    121     return offset - firstOutOfLineOffset;
     121    return -static_cast<ptrdiff_t>(offset - firstOutOfLineOffset) - 2;
    122122}
    123123
Note: See TracChangeset for help on using the changeset viewer.