Changeset 161377 in webkit


Ignore:
Timestamp:
Jan 6, 2014 3:04:25 PM (10 years ago)
Author:
mhahnenberg@apple.com
Message:

Add write barriers to the LLInt
https://bugs.webkit.org/show_bug.cgi?id=126527

Reviewed by Filip Pizlo.

This patch takes a similar approach to how write barriers work in the baseline JIT.
We execute the write barrier at the beginning of the opcode so we don't have to
worry about saving and restoring live registers across write barrier slow path calls
to C code.

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

(JSC::LLInt::llint_write_barrier_slow):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • offlineasm/arm64.rb:
  • offlineasm/instructions.rb:
  • offlineasm/x86.rb:
Location:
trunk/Source/JavaScriptCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r161365 r161377  
     12014-01-06  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Add write barriers to the LLInt
     4        https://bugs.webkit.org/show_bug.cgi?id=126527
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch takes a similar approach to how write barriers work in the baseline JIT.
     9        We execute the write barrier at the beginning of the opcode so we don't have to
     10        worry about saving and restoring live registers across write barrier slow path calls
     11        to C code.
     12
     13        * llint/LLIntOfflineAsmConfig.h:
     14        * llint/LLIntSlowPaths.cpp:
     15        (JSC::LLInt::llint_write_barrier_slow):
     16        * llint/LLIntSlowPaths.h:
     17        * llint/LowLevelInterpreter.asm:
     18        * llint/LowLevelInterpreter32_64.asm:
     19        * llint/LowLevelInterpreter64.asm:
     20        * offlineasm/arm64.rb:
     21        * offlineasm/instructions.rb:
     22        * offlineasm/x86.rb:
     23
    1242014-01-05  Sam Weinig  <sam@webkit.org>
    225
  • trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h

    r161364 r161377  
    149149#endif
    150150
     151#if ENABLE(GGC)
     152#define OFFLINE_ASM_GGC 1
     153#else
     154#define OFFLINE_ASM_GGC 0
     155#endif
     156
    151157#endif // LLIntOfflineAsmConfig_h
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r161364 r161377  
    13891389}
    13901390
     1391extern "C" void llint_write_barrier_slow(ExecState*, JSCell* cell)
     1392{
     1393    Heap::writeBarrier(cell);
     1394}
     1395
    13911396} } // namespace JSC::LLInt
    13921397
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r160244 r161377  
    4242extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
    4343extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
     44extern "C" void llint_write_barrier_slow(ExecState*, JSCell*);
    4445
    4546#define LLINT_SLOW_PATH_DECL(name) \
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r161364 r161377  
    171171const ResolveModeMask = 0xffff
    172172
    173 const MarkedBlockMask = ~0xffff
     173const MarkedBlockSize = 64 * 1024
     174const MarkedBlockMask = ~(MarkedBlockSize - 1)
     175# Constants for checking mark bits.
     176const AtomNumberShift = 3
     177const BitMapWordShift = 4
    174178
    175179# Allocation constants
     
    262266    storep structure, ArrayProfile::m_lastSeenStructure[profile]
    263267    loadb Structure::m_indexingType[structure], indexingType
     268end
     269
     270macro checkMarkByte(cell, scratch1, scratch2, continuation)
     271    move cell, scratch1
     272    move cell, scratch2
     273
     274    andp MarkedBlockMask, scratch1
     275    andp ~MarkedBlockMask, scratch2
     276
     277    rshiftp AtomNumberShift + BitMapWordShift, scratch2
     278    loadb MarkedBlock::m_marks[scratch1, scratch2, 1], scratch1
     279    continuation(scratch1)
    264280end
    265281
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r161364 r161377  
    492492end
    493493
    494 macro writeBarrier(tag, payload)
    495     # Nothing to do, since we don't have a generational or incremental collector.
     494macro writeBarrierOnOperand(cellOperand)
     495    if GGC
     496        loadisFromInstruction(cellOperand, t1)
     497        loadConstantOrVariablePayload(t1, CellTag, t0, .writeBarrierDone)
     498        checkMarkByte(t0, t1, t2,
     499            macro(marked)
     500                btbz marked, .writeBarrierDone
     501                push cfr, PC
     502                # We make two extra slots because cCall2 will poke.
     503                subp 8, sp
     504                cCall2(_llint_write_barrier_slow, cfr, t0)
     505                addp 8, sp
     506                pop PC, cfr
     507            end
     508        )
     509    .writeBarrierDone:
     510    end
     511end
     512
     513macro writeBarrierOnOperands(cellOperand, valueOperand)
     514    if GGC
     515        loadisFromInstruction(valueOperand, t1)
     516        loadConstantOrVariableTag(t1, t0)
     517        bineq t0, CellTag, .writeBarrierDone
     518   
     519        writeBarrierOnOperand(cellOperand)
     520    .writeBarrierDone:
     521    end
     522end
     523
     524macro writeBarrierOnGlobalObject(valueOperand)
     525    if GGC
     526        loadisFromInstruction(valueOperand, t1)
     527        bineq t0, CellTag, .writeBarrierDone
     528   
     529        loadp CodeBlock[cfr], t0
     530        loadp CodeBlock::m_globalObject[t0], t0
     531        checkMarkByte(t0, t1, t2,
     532            macro(marked)
     533                btbz marked, .writeBarrierDone
     534                push cfr, PC
     535                # We make two extra slots because cCall2 will poke.
     536                subp 8, sp
     537                cCall2(_llint_write_barrier_slow, cfr, t0)
     538                addp 8, sp
     539                pop PC, cfr
     540            end
     541        )
     542    .writeBarrierDone:
     543    end
    496544end
    497545
     
    576624    btinz t2, .opEnterLoop
    577625.opEnterDone:
     626    callSlowPath(_slow_path_enter)
    578627    dispatch(1)
    579628
     
    12561305_llint_op_init_global_const:
    12571306    traceExecution()
     1307    writeBarrierOnGlobalObject(2)
    12581308    loadi 8[PC], t1
    12591309    loadi 4[PC], t0
    12601310    loadConstantOrVariable(t1, t2, t3)
    1261     writeBarrier(t2, t3)
    12621311    storei t2, TagOffset[t0]
    12631312    storei t3, PayloadOffset[t0]
     
    13451394macro putById(getPropertyStorage)
    13461395    traceExecution()
     1396    writeBarrierOnOperands(1, 3)
    13471397    loadi 4[PC], t3
    13481398    loadi 16[PC], t1
     
    13561406            loadi 20[PC], t1
    13571407            loadConstantOrVariable2Reg(t2, scratch, t2)
    1358             writeBarrier(scratch, t2)
    13591408            storei scratch, TagOffset[propertyStorage, t1]
    13601409            storei t2, PayloadOffset[propertyStorage, t1]
     
    13771426macro putByIdTransition(additionalChecks, getPropertyStorage)
    13781427    traceExecution()
     1428    writeBarrierOnOperand(1)
    13791429    loadi 4[PC], t3
    13801430    loadi 16[PC], t1
     
    13901440            addp t1, propertyStorage, t3
    13911441            loadConstantOrVariable2Reg(t2, t1, t2)
    1392             writeBarrier(t1, t2)
    13931442            storei t1, TagOffset[t3]
    13941443            loadi 24[PC], t1
     
    15621611macro putByVal(holeCheck, slowPath)
    15631612    traceExecution()
     1613    writeBarrierOnOperands(1, 3)
    15641614    loadi 4[PC], t0
    15651615    loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
     
    16031653            const payload = operand
    16041654            loadConstantOrVariable2Reg(operand, tag, payload)
    1605             writeBarrier(tag, payload)
    16061655            storei tag, TagOffset[base, index, 8]
    16071656            storei payload, PayloadOffset[base, index, 8]
     
    16151664    loadi 12[PC], t2
    16161665    loadConstantOrVariable2Reg(t2, t1, t2)
    1617     writeBarrier(t1, t2)
    16181666    storei t1, ArrayStorage::m_vector + TagOffset[t0, t3, 8]
    16191667    storei t2, ArrayStorage::m_vector + PayloadOffset[t0, t3, 8]
     
    23402388#pGlobalProperty:
    23412389    bineq t0, GlobalProperty, .pGlobalVar
     2390    writeBarrierOnOperands(1, 3)
    23422391    loadWithStructureCheck(1, .pDynamic)
    23432392    putProperty()
     
    23462395.pGlobalVar:
    23472396    bineq t0, GlobalVar, .pClosureVar
     2397    writeBarrierOnGlobalObject(3)
    23482398    putGlobalVar()
    23492399    dispatch(7)
     
    23512401.pClosureVar:
    23522402    bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
     2403    writeBarrierOnOperands(1, 3)
    23532404    loadVariable(1, t2, t1, t0)
    23542405    putClosureVar()
     
    23572408.pGlobalPropertyWithVarInjectionChecks:
    23582409    bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
     2410    writeBarrierOnOperands(1, 3)
    23592411    loadWithStructureCheck(1, .pDynamic)
    23602412    putProperty()
     
    23632415.pGlobalVarWithVarInjectionChecks:
    23642416    bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
     2417    writeBarrierOnGlobalObject(3)
    23652418    varInjectionCheck(.pDynamic)
    23662419    putGlobalVar()
     
    23692422.pClosureVarWithVarInjectionChecks:
    23702423    bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
     2424    writeBarrierOnOperands(1, 3)
    23712425    varInjectionCheck(.pDynamic)
    23722426    loadVariable(1, t2, t1, t0)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r161364 r161377  
    332332end
    333333
    334 macro writeBarrier(value)
    335     # Nothing to do, since we don't have a generational or incremental collector.
     334macro writeBarrierOnOperand(cellOperand)
     335    if GGC
     336        loadisFromInstruction(cellOperand, t1)
     337        loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
     338        checkMarkByte(t0, t1, t2,
     339            macro(marked)
     340                btbz marked, .writeBarrierDone
     341                push PB, PC
     342                cCall2(_llint_write_barrier_slow, cfr, t0)
     343                push PC, PB
     344            end
     345        )
     346    .writeBarrierDone:
     347    end
     348end
     349
     350macro writeBarrierOnOperands(cellOperand, valueOperand)
     351    if GGC
     352        loadisFromInstruction(valueOperand, t1)
     353        loadConstantOrVariable(t1, t0)
     354        btpz t0, .writeBarrierDone
     355   
     356        writeBarrierOnOperand(cellOperand)
     357    .writeBarrierDone:
     358    end
     359end
     360
     361macro writeBarrierOnGlobalObject(valueOperand)
     362    if GGC
     363        loadisFromInstruction(valueOperand, t1)
     364        loadConstantOrVariable(t1, t0)
     365        btpz t0, .writeBarrierDone
     366   
     367        loadp CodeBlock[cfr], t0
     368        loadp CodeBlock::m_globalObject[t0], t0
     369        checkMarkByte(t0, t1, t2,
     370            macro(marked)
     371                btbz marked, .writeBarrierDone
     372                push PB, PC
     373                cCall2(_llint_write_barrier_slow, cfr, t0)
     374                pop PC, PB
     375            end
     376        )
     377    .writeBarrierDone:
     378    end
    336379end
    337380
     
    413456    btqnz t2, .opEnterLoop
    414457.opEnterDone:
     458    callSlowPath(_slow_path_enter)
    415459    dispatch(1)
    416460
     
    10651109_llint_op_init_global_const:
    10661110    traceExecution()
     1111    writeBarrierOnGlobalObject(2)
    10671112    loadisFromInstruction(2, t1)
    10681113    loadpFromInstruction(1, t0)
    10691114    loadConstantOrVariable(t1, t2)
    1070     writeBarrier(t2)
    10711115    storeq t2, [t0]
    10721116    dispatch(5)
     
    11501194macro putById(getPropertyStorage)
    11511195    traceExecution()
     1196    writeBarrierOnOperands(1, 3)
    11521197    loadisFromInstruction(1, t3)
    11531198    loadpFromInstruction(4, t1)
     
    11611206            loadisFromInstruction(5, t1)
    11621207            loadConstantOrVariable(t2, scratch)
    1163             writeBarrier(t0)
    11641208            storeq scratch, [propertyStorage, t1]
    11651209            dispatch(9)
     
    11811225macro putByIdTransition(additionalChecks, getPropertyStorage)
    11821226    traceExecution()
     1227    writeBarrierOnOperand(1)
    11831228    loadisFromInstruction(1, t3)
    11841229    loadpFromInstruction(4, t1)
     
    11941239            addp t1, propertyStorage, t3
    11951240            loadConstantOrVariable(t2, t1)
    1196             writeBarrier(t1)
    11971241            storeq t1, [t3]
    11981242            loadpFromInstruction(6, t1)
     
    13631407macro putByVal(holeCheck, slowPath)
    13641408    traceExecution()
     1409    writeBarrierOnOperands(1, 3)
    13651410    loadisFromInstruction(1, t0)
    13661411    loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
     
    14021447        macro (operand, scratch, address)
    14031448            loadConstantOrVariable(operand, scratch)
    1404             writeBarrier(scratch)
    14051449            storep scratch, address
    14061450        end)
     
    14131457    loadisFromInstruction(3, t2)
    14141458    loadConstantOrVariable(t2, t1)
    1415     writeBarrier(t1)
    14161459    storeq t1, ArrayStorage::m_vector[t0, t3, 8]
    14171460    dispatch(5)
     
    21082151#pGlobalProperty:
    21092152    bineq t0, GlobalProperty, .pGlobalVar
     2153    writeBarrierOnOperands(1, 3)
    21102154    loadWithStructureCheck(1, .pDynamic)
    21112155    putProperty()
     
    21142158.pGlobalVar:
    21152159    bineq t0, GlobalVar, .pClosureVar
     2160    writeBarrierOnGlobalObject(3)
    21162161    putGlobalVar()
    21172162    dispatch(7)
     
    21192164.pClosureVar:
    21202165    bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
     2166    writeBarrierOnOperands(1, 3)
    21212167    loadVariable(1, t0)
    21222168    putClosureVar()
     
    21252171.pGlobalPropertyWithVarInjectionChecks:
    21262172    bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
     2173    writeBarrierOnOperands(1, 3)
    21272174    loadWithStructureCheck(1, .pDynamic)
    21282175    putProperty()
     
    21312178.pGlobalVarWithVarInjectionChecks:
    21322179    bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
     2180    writeBarrierOnGlobalObject(3)
    21332181    varInjectionCheck(.pDynamic)
    21342182    putGlobalVar()
     
    21372185.pClosureVarWithVarInjectionChecks:
    21382186    bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
     2187    writeBarrierOnOperands(1, 3)
    21392188    varInjectionCheck(.pDynamic)
    21402189    loadVariable(1, t0)
  • trunk/Source/JavaScriptCore/offlineasm/arm.rb

    r159545 r161377  
    458458            raise "ARM does not support this opcode yet, #{codeOrigin}"
    459459        when "pop"
    460             $asm.puts "pop { #{operands[0].armOperand} }"
     460            operands.each {
     461                | op |
     462                $asm.puts "pop { #{op.armOperand} }"
     463            }
    461464        when "push"
    462             $asm.puts "push { #{operands[0].armOperand} }"
     465            operands.each {
     466                | op |
     467                $asm.puts "push { #{op.armOperand} }"
     468            }
    463469        when "popCalleeSaves"
    464470            if isARMv7
  • trunk/Source/JavaScriptCore/offlineasm/arm64.rb

    r159655 r161377  
    567567            raise "ARM64 does not support this opcode yet, #{codeOriginString}"
    568568        when "pop"
    569             # FIXME: Remove it or support it.
    570             raise "ARM64 does not support this opcode yet, #{codeOriginString}"
     569            operands.each_slice(2) {
     570                | ops |
     571                # Note that the operands are in the reverse order of the case for push.
     572                # This is due to the fact that order matters for pushing and popping, and
     573                # on platforms that only push/pop one slot at a time they pop their
     574                # arguments in the reverse order that they were pushed. In order to remain
     575                # compatible with those platforms we assume here that that's what has been done.
     576
     577                # So for example, if we did push(A, B, C, D), we would then pop(D, C, B, A).
     578                # But since the ordering of arguments doesn't change on arm64 between the stp and ldp
     579                # instructions we need to flip flop the argument positions that were passed to us.
     580                $asm.puts "ldp #{ops[1].arm64Operand(:ptr)}, #{ops[0].arm64Operand(:ptr)}, [sp], #16"
     581            }
    571582        when "push"
    572             # FIXME: Remove it or support it.
    573             raise "ARM64 does not support this opcode yet, #{codeOriginString}"
     583            operands.each_slice(2) {
     584                | ops |
     585                $asm.puts "stp #{ops[0].arm64Operand(:ptr)}, #{ops[1].arm64Operand(:ptr)}, [sp, #-16]!"
     586            }
    574587        when "popLRAndFP"
    575588            $asm.puts "ldp fp, lr, [sp], #16"
  • trunk/Source/JavaScriptCore/offlineasm/mips.rb

    r160387 r161377  
    840840            raise "MIPS does not support this opcode yet, #{codeOrigin}"
    841841        when "pop"
    842             $asm.puts "lw #{operands[0].mipsOperand}, 0($sp)"
    843             $asm.puts "addiu $sp, $sp, 4"
     842            operands.each {
     843                | op |
     844                $asm.puts "lw #{op.mipsOperand}, 0($sp)"
     845                $asm.puts "addiu $sp, $sp, 4"
     846            }
    844847        when "push"
    845             $asm.puts "addiu $sp, $sp, -4"
    846             $asm.puts "sw #{operands[0].mipsOperand}, 0($sp)"
     848            operands.each {
     849                | op |
     850                $asm.puts "addiu $sp, $sp, -4"
     851                $asm.puts "sw #{op.mipsOperand}, 0($sp)"
     852            }
    847853        when "popCalleeSaves"
    848854            $asm.puts "lw $16, 0($sp)"
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r159654 r161377  
    101101                isX64 ? "%rax" : raise
    102102            else
    103                 raise
     103                raise "Invalid kind #{kind} for name #{name}"
    104104            end
    105105        when "t1", "a1", "r1"
     
    979979            end
    980980        when "pop"
    981             $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
     981            operands.each {
     982                | op |
     983                $asm.puts "pop #{op.x86Operand(:ptr)}"
     984            }
    982985        when "push"
    983             $asm.puts "push #{operands[0].x86Operand(:ptr)}"
     986            operands.each {
     987                | op |
     988                $asm.puts "push #{op.x86Operand(:ptr)}"
     989            }
    984990        when "popCalleeSaves"
    985991            if isX64
Note: See TracChangeset for help on using the changeset viewer.