Changeset 160878 in webkit


Ignore:
Timestamp:
Dec 19, 2013 4:49:58 PM (10 years ago)
Author:
mhahnenberg@apple.com
Message:

Put write barriers in the right places in the baseline JIT
https://bugs.webkit.org/show_bug.cgi?id=125975

Reviewed by Filip Pizlo.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITInlines.h:

(JSC::JIT::callOperation):
(JSC::JIT::emitArrayProfilingSite):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_enter):
(JSC::JIT::emitSlow_op_enter):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_enter):
(JSC::JIT::emitSlow_op_enter):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitGenericContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitPutGlobalProperty):
(JSC::JIT::emitPutGlobalVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_init_global_const):
(JSC::JIT::checkMarkWord):
(JSC::JIT::emitWriteBarrier):
(JSC::JIT::privateCompilePutByVal):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitGenericContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
(JSC::JIT::emitPutGlobalProperty):
(JSC::JIT::emitPutGlobalVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_init_global_const):

  • jit/Repatch.cpp:

(JSC::emitPutReplaceStub):
(JSC::emitPutTransitionStub):
(JSC::repatchPutByID):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r160876 r160878  
     12013-12-19  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Put write barriers in the right places in the baseline JIT
     4        https://bugs.webkit.org/show_bug.cgi?id=125975
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * jit/JIT.cpp:
     9        (JSC::JIT::privateCompileSlowCases):
     10        * jit/JIT.h:
     11        * jit/JITInlines.h:
     12        (JSC::JIT::callOperation):
     13        (JSC::JIT::emitArrayProfilingSite):
     14        * jit/JITOpcodes.cpp:
     15        (JSC::JIT::emit_op_enter):
     16        (JSC::JIT::emitSlow_op_enter):
     17        * jit/JITOpcodes32_64.cpp:
     18        (JSC::JIT::emit_op_enter):
     19        (JSC::JIT::emitSlow_op_enter):
     20        * jit/JITPropertyAccess.cpp:
     21        (JSC::JIT::emit_op_put_by_val):
     22        (JSC::JIT::emitGenericContiguousPutByVal):
     23        (JSC::JIT::emitArrayStoragePutByVal):
     24        (JSC::JIT::emit_op_put_by_id):
     25        (JSC::JIT::emitPutGlobalProperty):
     26        (JSC::JIT::emitPutGlobalVar):
     27        (JSC::JIT::emitPutClosureVar):
     28        (JSC::JIT::emit_op_init_global_const):
     29        (JSC::JIT::checkMarkWord):
     30        (JSC::JIT::emitWriteBarrier):
     31        (JSC::JIT::privateCompilePutByVal):
     32        * jit/JITPropertyAccess32_64.cpp:
     33        (JSC::JIT::emitGenericContiguousPutByVal):
     34        (JSC::JIT::emitArrayStoragePutByVal):
     35        (JSC::JIT::emit_op_put_by_id):
     36        (JSC::JIT::emitSlow_op_put_by_id):
     37        (JSC::JIT::emitPutGlobalProperty):
     38        (JSC::JIT::emitPutGlobalVar):
     39        (JSC::JIT::emitPutClosureVar):
     40        (JSC::JIT::emit_op_init_global_const):
     41        * jit/Repatch.cpp:
     42        (JSC::emitPutReplaceStub):
     43        (JSC::emitPutTransitionStub):
     44        (JSC::repatchPutByID):
     45        * runtime/CommonSlowPaths.cpp:
     46        (JSC::SLOW_PATH_DECL):
     47        * runtime/CommonSlowPaths.h:
     48
    1492013-12-19  Brent Fulgham  <bfulgham@apple.com>
    250
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r160587 r160878  
    317317        void testPrototype(JSValue, JumpList& failureCases, StructureStubInfo*);
    318318
    319         enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterImmediates };
     319        enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterValue, ShouldFilterBaseAndValue };
    320320        // value register in write barrier is used before any scratch registers
    321321        // so may safely be the same as either of the scratch registers.
    322         void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind);
    323         void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
     322        Jump checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2);
     323        Jump checkMarkWord(JSCell* owner);
     324        void emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode);
     325        void emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode);
     326/*
     327        void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch1, RegisterID scratch2, WriteBarrierMode);
     328        void emitWriteBarrier(JSCell* owner, RegisterID value, WriteBarrierMode);
     329*/
    324330
    325331        template<typename StructureType> // StructureType can be RegisterID or ImmPtr.
     
    679685        MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, const JSValue*, int32_t);
    680686        MacroAssembler::Call callOperation(J_JITOperation_EC, int, JSCell*);
     687        MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*);
    681688        MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg);
    682689#if USE(JSVALUE64)
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r160244 r160878  
    200200}
    201201
     202ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, JSCell* cell)
     203{
     204    setupArgumentsWithExecState(TrustedImmPtr(cell));
     205    return appendCallWithExceptionCheck(operation);
     206}
     207
    202208ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EP operation, int dst, void* pointer)
    203209{
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r160213 r160878  
    792792}
    793793
    794 void JIT::emit_op_enter(Instruction*)
     794void JIT::emit_op_enter(Instruction* currentInstruction)
    795795{
    796796    emitEnterOptimizationCheck();
     
    802802    for (size_t j = 0; j < count; ++j)
    803803        emitInitRegister(virtualRegisterForLocal(j).offset());
     804
     805    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter);
     806    slowPathCall.call();
    804807}
    805808
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r160213 r160878  
    10131013
    10141014
    1015 void JIT::emit_op_enter(Instruction*)
     1015void JIT::emit_op_enter(Instruction* currentInstruction)
    10161016{
    10171017    emitEnterOptimizationCheck();
     
    10221022    for (int i = 0; i < m_codeBlock->m_numVars; ++i)
    10231023        emitStore(virtualRegisterForLocal(i).offset(), jsUndefined());
     1024
     1025    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter);
     1026    slowPathCall.call();
    10241027}
    10251028
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r160092 r160878  
    350350    m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
    351351
    352     emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
    353352}
    354353
     
    386385    case ContiguousShape:
    387386        store64(regT3, BaseIndex(regT2, regT1, TimesEight));
     387        emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue);
    388388        break;
    389389    default:
     
    424424    emitGetVirtualRegister(value, regT3);
    425425    store64(regT3, BaseIndex(regT2, regT1, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     426    emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue);
    426427    Jump end = jump();
    427428   
     
    553554    unsigned direct = currentInstruction[8].u.operand;
    554555
     556    emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBaseAndValue);
     557
    555558    // In order to be able to patch both the Structure, and the object offset, we store one pointer,
    556559    // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
     
    561564    // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
    562565    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
    563    
    564     emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
    565566
    566567    JITPutByIdGenerator gen(
     
    760761void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value)
    761762{
     763    emitGetVirtualRegister(value, regT2);
     764
    762765    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
    763766    loadPtr(operandSlot, regT1);
    764767    negPtr(regT1);
    765     emitGetVirtualRegister(value, regT2);
    766768    storePtr(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)));
    767769}
     
    823825    case GlobalProperty:
    824826    case GlobalPropertyWithVarInjectionChecks:
     827        emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
    825828        emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
    826829        emitPutGlobalProperty(operandSlot, value);
     
    828831    case GlobalVar:
    829832    case GlobalVarWithVarInjectionChecks:
     833        emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
    830834        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    831835        emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
     
    833837    case ClosureVar:
    834838    case ClosureVarWithVarInjectionChecks:
     839        emitWriteBarrier(scope, value, ShouldFilterValue);
    835840        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    836841        emitPutClosureVar(scope, *operandSlot, value);
     
    861866{
    862867    JSGlobalObject* globalObject = m_codeBlock->globalObject();
    863 
     868    emitWriteBarrier(globalObject, currentInstruction[2].u.operand, ShouldFilterValue);
    864869    emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
    865 
    866870    store64(regT0, currentInstruction[1].u.registerPointer);
    867     if (Heap::isWriteBarrierEnabled())
    868         emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
    869871}
    870872
    871873#endif // USE(JSVALUE64)
    872874
    873 void JIT::emitWriteBarrier(RegisterID owner, RegisterID value, RegisterID scratch, RegisterID scratch2, WriteBarrierMode mode, WriteBarrierUseKind useKind)
    874 {
     875JIT::Jump JIT::checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2)
     876{
     877    move(owner, scratch1);
     878    move(owner, scratch2);
     879
     880    andPtr(TrustedImmPtr(MarkedBlock::blockMask), scratch1);
     881    andPtr(TrustedImmPtr(~MarkedBlock::blockMask), scratch2);
     882
     883    rshift32(TrustedImm32(3 + 4), scratch2);
     884
     885    return branchTest8(Zero, BaseIndex(scratch1, scratch2, TimesOne, MarkedBlock::offsetOfMarks()));
     886}
     887
     888JIT::Jump JIT::checkMarkWord(JSCell* owner)
     889{
     890    MarkedBlock* block = MarkedBlock::blockFor(owner);
     891    size_t index = (reinterpret_cast<size_t>(owner) & ~MarkedBlock::blockMask) >> (3 + 4);
     892    void* address = (reinterpret_cast<char*>(block) + MarkedBlock::offsetOfMarks()) + index;
     893
     894    return branchTest8(Zero, AbsoluteAddress(address));
     895}
     896
     897#if USE(JSVALUE64)
     898void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode)
     899{
     900#if ENABLE(GGC)
     901    emitGetVirtualRegister(value, regT0);
     902    Jump valueNotCell;
     903    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
     904        valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
     905   
     906    emitGetVirtualRegister(owner, regT0);
     907    Jump ownerNotCell;
     908    if (mode == ShouldFilterBaseAndValue)
     909        ownerNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
     910
     911    Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
     912    callOperation(operationUnconditionalWriteBarrier, regT0);
     913    ownerNotMarked.link(this);
     914
     915    if (mode == ShouldFilterBaseAndValue)
     916        ownerNotCell.link(this);
     917    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
     918        valueNotCell.link(this);
     919#else
    875920    UNUSED_PARAM(owner);
    876     UNUSED_PARAM(scratch);
    877     UNUSED_PARAM(scratch2);
    878     UNUSED_PARAM(useKind);
    879921    UNUSED_PARAM(value);
    880922    UNUSED_PARAM(mode);
    881     ASSERT(owner != scratch);
    882     ASSERT(owner != scratch2);
    883    
    884 #if ENABLE(WRITE_BARRIER_PROFILING)
    885     emitCount(WriteBarrierCounters::jitCounterFor(useKind));
    886 #endif
    887 }
    888 
    889 void JIT::emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode mode, WriteBarrierUseKind useKind)
    890 {
     923#endif
     924}
     925
     926void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode)
     927{
     928#if ENABLE(GGC)
     929    emitGetVirtualRegister(value, regT0);
     930    Jump valueNotCell;
     931    if (mode == ShouldFilterValue)
     932        valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
     933
     934    if (!MarkedBlock::blockFor(owner)->isMarked(owner)) {
     935        Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
     936        callOperation(operationUnconditionalWriteBarrier, owner);
     937        ownerNotMarked.link(this);
     938    } else
     939        callOperation(operationUnconditionalWriteBarrier, owner);
     940
     941    if (mode == ShouldFilterValue)
     942        valueNotCell.link(this);
     943#else
    891944    UNUSED_PARAM(owner);
    892     UNUSED_PARAM(scratch);
    893     UNUSED_PARAM(useKind);
    894945    UNUSED_PARAM(value);
    895946    UNUSED_PARAM(mode);
    896    
    897 #if ENABLE(WRITE_BARRIER_PROFILING)
    898     emitCount(WriteBarrierCounters::jitCounterFor(useKind));
    899 #endif
    900 }
     947#endif
     948}
     949
     950#else // USE(JSVALUE64)
     951
     952void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode)
     953{
     954#if ENABLE(GGC)
     955    emitLoadTag(value, regT0);
     956    Jump valueNotCell;
     957    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
     958        valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
     959   
     960    emitLoad(owner, regT0, regT1);
     961    Jump ownerNotCell;
     962    if (mode == ShouldFilterBaseAndValue)
     963        ownerNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
     964
     965    Jump ownerNotMarked = checkMarkWord(regT1, regT0, regT2);
     966    callOperation(operationUnconditionalWriteBarrier, regT1);
     967    ownerNotMarked.link(this);
     968
     969    if (mode == ShouldFilterBaseAndValue)
     970        ownerNotCell.link(this);
     971    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
     972        valueNotCell.link(this);
     973#else
     974    UNUSED_PARAM(owner);
     975    UNUSED_PARAM(value);
     976    UNUSED_PARAM(mode);
     977#endif
     978}
     979
     980void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode)
     981{
     982#if ENABLE(GGC)
     983    emitLoadTag(value, regT0);
     984    Jump valueNotCell;
     985    if (mode == ShouldFilterValue)
     986        valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
     987
     988    if (!MarkedBlock::blockFor(owner)->isMarked(owner)) {
     989        Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
     990        callOperation(operationUnconditionalWriteBarrier, owner);
     991        ownerNotMarked.link(this);
     992    } else
     993        callOperation(operationUnconditionalWriteBarrier, owner);
     994
     995    if (mode == ShouldFilterValue)
     996        valueNotCell.link(this);
     997#else
     998    UNUSED_PARAM(owner);
     999    UNUSED_PARAM(value);
     1000    UNUSED_PARAM(mode);
     1001#endif
     1002}
     1003
     1004#endif // USE(JSVALUE64)
    9011005
    9021006JIT::Jump JIT::addStructureTransitionCheck(JSCell* object, Structure* structure, StructureStubInfo* stubInfo, RegisterID scratch)
     
    9891093    PatchableJump badType;
    9901094    JumpList slowCases;
    991    
     1095
     1096#if ENABLE(GGC)
     1097    bool needsLinkForWriteBarrier = false;
     1098#endif
     1099
    9921100    switch (arrayMode) {
    9931101    case JITInt32:
     
    9991107    case JITContiguous:
    10001108        slowCases = emitContiguousPutByVal(currentInstruction, badType);
     1109#if ENABLE(GGC)
     1110        needsLinkForWriteBarrier = true;
     1111#endif
    10011112        break;
    10021113    case JITArrayStorage:
    10031114        slowCases = emitArrayStoragePutByVal(currentInstruction, badType);
     1115#if ENABLE(GGC)
     1116        needsLinkForWriteBarrier = true;
     1117#endif
    10041118        break;
    10051119    default:
     
    10151129
    10161130    LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
    1017    
    10181131    patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
    10191132    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
    1020    
    10211133    patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
     1134#if ENABLE(GGC)
     1135    if (needsLinkForWriteBarrier) {
     1136        ASSERT(m_calls.last().to == operationUnconditionalWriteBarrier);
     1137        patchBuffer.link(m_calls.last().from, operationUnconditionalWriteBarrier);
     1138    }
     1139#endif
    10221140   
    10231141    bool isDirect = m_interpreter->getOpcodeID(currentInstruction->u.opcode) == op_put_by_val_direct;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r160092 r160878  
    313313JIT::JumpList JIT::emitGenericContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType, IndexingType indexingShape)
    314314{
     315    int base = currentInstruction[1].u.operand;
    315316    int value = currentInstruction[3].u.operand;
    316317    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     
    328329    case Int32Shape:
    329330        slowCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
    330         // Fall through.
     331        store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     332        store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     333        break;
    331334    case ContiguousShape:
    332335        store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
    333336        store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     337        emitLoad(base, regT2, regT3);
     338        emitWriteBarrier(base, value, ShouldFilterValue);
    334339        break;
    335340    case DoubleShape: {
     
    362367    done.link(this);
    363368   
    364     emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
    365    
    366369    return slowCases;
    367370}
     
    369372JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump& badType)
    370373{
     374    int base = currentInstruction[1].u.operand;
    371375    int value = currentInstruction[3].u.operand;
    372376    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     
    398402    end.link(this);
    399403   
    400     emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
     404    emitWriteBarrier(base, value, ShouldFilterValue);
    401405   
    402406    return slowCases;
     
    516520    int direct = currentInstruction[8].u.operand;
    517521   
     522    emitWriteBarrier(base, value, ShouldFilterBaseAndValue);
     523
    518524    emitLoad2(base, regT1, regT0, value, regT3, regT2);
    519525   
    520526    emitJumpSlowCaseIfNotJSCell(base, regT1);
    521527   
    522     emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
    523    
     528    emitLoad(base, regT1, regT0);
     529    emitLoad(value, regT3, regT2);
     530
    524531    JITPutByIdGenerator gen(
    525532        m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
     
    795802void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value)
    796803{
     804    emitLoad(value, regT3, regT2);
     805   
    797806    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
    798807    loadPtr(operandSlot, regT1);
    799808    negPtr(regT1);
    800     emitLoad(value, regT3, regT2);
    801809    store32(regT3, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
    802810    store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
     
    867875    case GlobalProperty:
    868876    case GlobalPropertyWithVarInjectionChecks:
     877        emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
    869878        emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
    870879        emitPutGlobalProperty(operandSlot, value);
     
    872881    case GlobalVar:
    873882    case GlobalVarWithVarInjectionChecks:
     883        emitWriteBarrier(m_codeBlock->globalObject(), value, ShouldFilterValue);
    874884        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    875885        emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
     
    877887    case ClosureVar:
    878888    case ClosureVarWithVarInjectionChecks:
     889        emitWriteBarrier(scope, value, ShouldFilterValue);
    879890        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    880891        emitPutClosureVar(scope, *operandSlot, value);
     
    909920    JSGlobalObject* globalObject = m_codeBlock->globalObject();
    910921
     922    emitWriteBarrier(globalObject, value, ShouldFilterValue);
     923
    911924    emitLoad(value, regT1, regT0);
    912925   
    913     if (Heap::isWriteBarrierEnabled()) {
    914         move(TrustedImmPtr(globalObject), regT2);
    915        
    916         emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
    917     }
    918 
    919926    store32(regT1, registerPointer->tagPointer());
    920927    store32(regT0, registerPointer->payloadPointer());
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r160688 r160878  
    3131#include "CCallHelpers.h"
    3232#include "CallFrameInlines.h"
     33#include "DFGOperations.h"
     34#include "DFGSpeculativeJIT.h"
    3335#include "FTLThunks.h"
    3436#include "GCAwareJITStubRoutine.h"
     
    789791#endif
    790792    GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.valueGPR);
    791     GPRReg scratchGPR = TempRegisterSet(stubInfo.patch.usedRegisters).getFreeGPR();
    792     bool needToRestoreScratch = false;
    793 #if ENABLE(WRITE_BARRIER_PROFILING)
    794     GPRReg scratchGPR2;
    795     const bool writeBarrierNeeded = true;
    796 #else
    797     const bool writeBarrierNeeded = false;
    798 #endif
    799    
    800     MacroAssembler stubJit;
    801    
    802     if (scratchGPR == InvalidGPRReg && (writeBarrierNeeded || isOutOfLineOffset(slot.cachedOffset()))) {
    803 #if USE(JSVALUE64)
    804         scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR);
    805 #else
    806         scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR);
    807 #endif
    808         needToRestoreScratch = true;
    809         stubJit.pushToSave(scratchGPR);
    810     }
     793
     794    ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
     795    allocator.lock(baseGPR);
     796#if USE(JSVALUE32_64)
     797    allocator.lock(valueTagGPR);
     798#endif
     799    allocator.lock(valueGPR);
     800   
     801    GPRReg scratchGPR1 = allocator.allocateScratchGPR();
     802#if ENABLE(GGC)
     803    GPRReg scratchGPR2 = allocator.allocateScratchGPR();
     804#endif
     805
     806    CCallHelpers stubJit(vm, exec->codeBlock());
     807
     808    allocator.preserveReusedRegistersByPushing(stubJit);
    811809
    812810    MacroAssembler::Jump badStructure = stubJit.branchPtr(
     
    814812        MacroAssembler::Address(baseGPR, JSCell::structureOffset()),
    815813        MacroAssembler::TrustedImmPtr(structure));
    816    
    817 #if ENABLE(WRITE_BARRIER_PROFILING)
    818 #if USE(JSVALUE64)
    819     scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, scratchGPR);
    820 #else
    821     scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR, scratchGPR);
    822 #endif
    823     stubJit.pushToSave(scratchGPR2);
    824     AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR, scratchGPR2, WriteBarrierForPropertyAccess);
    825     stubJit.popToRestore(scratchGPR2);
    826 #endif
    827    
     814
    828815#if USE(JSVALUE64)
    829816    if (isInlineOffset(slot.cachedOffset()))
    830817        stubJit.store64(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue)));
    831818    else {
    832         stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
    833         stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue)));
     819        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1);
     820        stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue)));
    834821    }
    835822#elif USE(JSVALUE32_64)
     
    838825        stubJit.store32(valueTagGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
    839826    } else {
    840         stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
    841         stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
    842         stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
    843     }
     827        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1);
     828        stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
     829        stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
     830    }
     831#endif
     832   
     833#if ENABLE(GGC)
     834    MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2);
    844835#endif
    845836   
     
    847838    MacroAssembler::Jump failure;
    848839   
    849     if (needToRestoreScratch) {
    850         stubJit.popToRestore(scratchGPR);
     840    if (allocator.didReuseRegisters()) {
     841        allocator.restoreReusedRegistersByPopping(stubJit);
    851842        success = stubJit.jump();
    852843       
    853844        badStructure.link(&stubJit);
    854         stubJit.popToRestore(scratchGPR);
     845        allocator.restoreReusedRegistersByPopping(stubJit);
    855846        failure = stubJit.jump();
    856847    } else {
     
    860851   
    861852    LinkBuffer patchBuffer(*vm, &stubJit, exec->codeBlock());
     853#if ENABLE(GGC)
     854    patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer);
     855#endif
    862856    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
    863857    patchBuffer.link(failure, failureLabel);
     
    901895    CCallHelpers stubJit(vm);
    902896   
     897    bool needThirdScratch = false;
     898    if (structure->outOfLineCapacity() != oldStructure->outOfLineCapacity()
     899        && oldStructure->outOfLineCapacity()) {
     900        needThirdScratch = true;
     901    }
     902
    903903    GPRReg scratchGPR1 = allocator.allocateScratchGPR();
    904904    ASSERT(scratchGPR1 != baseGPR);
    905905    ASSERT(scratchGPR1 != valueGPR);
    906906   
    907     bool needSecondScratch = false;
    908     bool needThirdScratch = false;
    909 #if ENABLE(WRITE_BARRIER_PROFILING)
    910     needSecondScratch = true;
    911 #endif
    912     if (structure->outOfLineCapacity() != oldStructure->outOfLineCapacity()
    913         && oldStructure->outOfLineCapacity()) {
    914         needSecondScratch = true;
    915         needThirdScratch = true;
    916     }
    917 
    918     GPRReg scratchGPR2;
    919     if (needSecondScratch) {
    920         scratchGPR2 = allocator.allocateScratchGPR();
    921         ASSERT(scratchGPR2 != baseGPR);
    922         ASSERT(scratchGPR2 != valueGPR);
    923         ASSERT(scratchGPR2 != scratchGPR1);
    924     } else
    925         scratchGPR2 = InvalidGPRReg;
     907    GPRReg scratchGPR2 = allocator.allocateScratchGPR();
     908    ASSERT(scratchGPR2 != baseGPR);
     909    ASSERT(scratchGPR2 != valueGPR);
     910    ASSERT(scratchGPR2 != scratchGPR1);
     911
    926912    GPRReg scratchGPR3;
    927913    if (needThirdScratch) {
     
    933919    } else
    934920        scratchGPR3 = InvalidGPRReg;
    935            
     921   
    936922    allocator.preserveReusedRegistersByPushing(stubJit);
    937923
     
    954940    }
    955941
    956 #if ENABLE(WRITE_BARRIER_PROFILING)
    957     ASSERT(needSecondScratch);
    958     ASSERT(scratchGPR2 != InvalidGPRReg);
    959     // Must always emit this write barrier as the structure transition itself requires it
    960     AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2, WriteBarrierForPropertyAccess);
    961 #endif
    962    
    963942    MacroAssembler::JumpList slowPath;
    964943   
     
    1019998#endif
    1020999   
     1000#if ENABLE(GGC)
     1001    MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2);
     1002#endif
     1003   
    10211004    MacroAssembler::Jump success;
    10221005    MacroAssembler::Jump failure;
     
    10521035   
    10531036    LinkBuffer patchBuffer(*vm, &stubJit, exec->codeBlock());
     1037#if ENABLE(GGC)
     1038    patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer);
     1039#endif
    10541040    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
    10551041    if (allocator.didReuseRegisters())
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r160587 r160878  
    516516}
    517517
     518SLOW_PATH_DECL(slow_path_enter)
     519{
     520    BEGIN();
     521    ScriptExecutable* ownerExecutable = exec->codeBlock()->ownerExecutable();
     522    Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable);
     523    END();
     524}
     525
    518526} // namespace JSC
    519527
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r160665 r160878  
    164164SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
    165165SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
     166SLOW_PATH_HIDDEN_DECL(slow_path_enter);
    166167SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
    167168SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
Note: See TracChangeset for help on using the changeset viewer.