Changeset 47186 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Aug 12, 2009, 10:58:36 PM (16 years ago)
Author:
[email protected]
Message:

Add optimize call and property access support for ARM JIT.
https://bugs.webkit.org/show_bug.cgi?id=24986

Patch by Gabor Loki <[email protected]> on 2009-08-12
Reviewed by Gavin Barraclough.

For tightly coupled sequences the BEGIN_UNINTERRUPTED_SEQUENCE and
END_UNINTERRUPTED_SEQUENCE macros have been introduced which ensure
space for instructions and constants of the named sequence. This
method is vital for those architecture which are using constant pool.

The 'latePatch' method - which was linked to JmpSrc - is replaced with
a port specific solution (each calls are marked to place their address
on the constant pool).

  • assembler/ARMAssembler.cpp:

(JSC::ARMAssembler::linkBranch):
(JSC::ARMAssembler::executableCopy): Add extra align for constant pool.

  • assembler/ARMAssembler.h:

(JSC::ARMAssembler::JmpSrc::JmpSrc):
(JSC::ARMAssembler::sizeOfConstantPool):
(JSC::ARMAssembler::jmp):
(JSC::ARMAssembler::linkCall):

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

(JSC::AssemblerBufferWithConstantPool::flushIfNoSpaceFor): Fix the
computation of the remaining space.

  • assembler/MacroAssemblerARM.h:

(JSC::MacroAssemblerARM::branch32):
(JSC::MacroAssemblerARM::nearCall):
(JSC::MacroAssemblerARM::call):
(JSC::MacroAssemblerARM::branchPtrWithPatch):
(JSC::MacroAssemblerARM::ensureSpace):
(JSC::MacroAssemblerARM::sizeOfConstantPool):
(JSC::MacroAssemblerARM::prepareCall):

  • assembler/X86Assembler.h:
  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):

  • jit/JITInlineMethods.h:

(JSC::JIT::beginUninterruptedSequence):
(JSC::JIT::endUninterruptedSequence):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::compileGetByIdSlowCase):
(JSC::JIT::emit_op_put_by_id):

Location:
trunk/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r47184 r47186  
     12009-08-12  Gabor Loki  <[email protected]>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Add optimize call and property access support for ARM JIT.
     6        https://bugs.webkit.org/show_bug.cgi?id=24986
     7
     8        For tightly coupled sequences the BEGIN_UNINTERRUPTED_SEQUENCE and
     9        END_UNINTERRUPTED_SEQUENCE macros have been introduced which ensure
     10        space for instructions and constants of the named sequence. This
     11        method is vital for those architecture which are using constant pool.
     12
     13        The 'latePatch' method - which was linked to JmpSrc - is replaced with
     14        a port specific solution (each calls are marked to place their address
     15        on the constant pool).
     16
     17        * assembler/ARMAssembler.cpp:
     18        (JSC::ARMAssembler::linkBranch):
     19        (JSC::ARMAssembler::executableCopy): Add extra align for constant pool.
     20        * assembler/ARMAssembler.h:
     21        (JSC::ARMAssembler::JmpSrc::JmpSrc):
     22        (JSC::ARMAssembler::sizeOfConstantPool):
     23        (JSC::ARMAssembler::jmp):
     24        (JSC::ARMAssembler::linkCall):
     25        * assembler/ARMv7Assembler.h:
     26        * assembler/AbstractMacroAssembler.h:
     27        * assembler/AssemblerBufferWithConstantPool.h:
     28        (JSC::AssemblerBufferWithConstantPool::flushIfNoSpaceFor): Fix the
     29        computation of the remaining space.
     30        * assembler/MacroAssemblerARM.h:
     31        (JSC::MacroAssemblerARM::branch32):
     32        (JSC::MacroAssemblerARM::nearCall):
     33        (JSC::MacroAssemblerARM::call):
     34        (JSC::MacroAssemblerARM::branchPtrWithPatch):
     35        (JSC::MacroAssemblerARM::ensureSpace):
     36        (JSC::MacroAssemblerARM::sizeOfConstantPool):
     37        (JSC::MacroAssemblerARM::prepareCall):
     38        * assembler/X86Assembler.h:
     39        * jit/JIT.h:
     40        * jit/JITCall.cpp:
     41        (JSC::JIT::compileOpCall):
     42        * jit/JITInlineMethods.h:
     43        (JSC::JIT::beginUninterruptedSequence):
     44        (JSC::JIT::endUninterruptedSequence):
     45        * jit/JITPropertyAccess.cpp:
     46        (JSC::JIT::emit_op_method_check):
     47        (JSC::JIT::compileGetByIdHotPath):
     48        (JSC::JIT::compileGetByIdSlowCase):
     49        (JSC::JIT::emit_op_put_by_id):
     50
    1512009-08-12  Gavin Barraclough  <[email protected]>
    252
  • trunk/JavaScriptCore/assembler/ARMAssembler.cpp

    r46832 r47186  
    5050}
    5151
    52 void ARMAssembler::linkBranch(void* code, JmpSrc from, void* to)
     52void ARMAssembler::linkBranch(void* code, JmpSrc from, void* to, int useConstantPool)
    5353{
    5454    ARMWord* insn = reinterpret_cast<ARMWord*>(code) + (from.m_offset / sizeof(ARMWord));
    5555
    56     if (!from.m_latePatch) {
     56    if (!useConstantPool) {
    5757        int diff = reinterpret_cast<ARMWord*>(to) - reinterpret_cast<ARMWord*>(insn + 2);
    5858
     
    368368void* ARMAssembler::executableCopy(ExecutablePool* allocator)
    369369{
     370    // 64-bit alignment is required for next constant pool and JIT code as well
     371    m_buffer.flushWithoutBarrier(true);
     372    if (m_buffer.uncheckedSize() & 0x7)
     373        bkpt(0);
     374
    370375    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(allocator));
    371376
    372377    for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
    373         ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + *iter);
    374         ARMWord* offset = getLdrImmAddress(ldrAddr);
    375         if (*offset != 0xffffffff)
    376             linkBranch(data, JmpSrc(*iter), data + *offset);
     378        // The last bit is set if the constant must be placed on constant pool.
     379        int pos = (*iter) & (~0x1);
     380        ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
     381        ARMWord offset = *getLdrImmAddress(ldrAddr);
     382        if (offset != 0xffffffff) {
     383            JmpSrc jmpSrc(pos);
     384            linkBranch(data, jmpSrc, data + offset, ((*iter) & 1));
     385        }
    377386    }
    378387
  • trunk/JavaScriptCore/assembler/ARMAssembler.h

    r46832 r47186  
    181181            JmpSrc()
    182182                : m_offset(-1)
    183                 , m_latePatch(false)
    184183            {
    185184            }
    186185
    187             void enableLatePatch() { m_latePatch = true; }
    188186        private:
    189187            JmpSrc(int offset)
    190188                : m_offset(offset)
    191                 , m_latePatch(false)
    192189            {
    193190            }
    194191
    195             int m_offset : 31;
    196             int m_latePatch : 1;
     192            int m_offset;
    197193        };
    198194
     
    568564        }
    569565
     566        int sizeOfConstantPool()
     567        {
     568            return m_buffer.sizeOfConstantPool();
     569        }
     570
    570571        JmpDst label()
    571572        {
     
    581582        }
    582583
    583         JmpSrc jmp(Condition cc = AL)
    584         {
    585             int s = size();
     584        JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
     585        {
     586            ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
     587            int s = m_buffer.uncheckedSize();
    586588            ldr_un_imm(ARM::pc, 0xffffffff, cc);
    587             m_jumps.append(s);
     589            m_jumps.append(s | (useConstantPool & 0x1));
    588590            return JmpSrc(s);
    589591        }
     
    594596
    595597        static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
    596         static void linkBranch(void* code, JmpSrc from, void* to);
     598        static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0);
    597599
    598600        static void patchPointerInternal(intptr_t from, void* to)
     
    661663        static void linkCall(void* code, JmpSrc from, void* to)
    662664        {
    663             linkBranch(code, from, to);
     665            linkBranch(code, from, to, true);
    664666        }
    665667
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.h

    r46247 r47186  
    443443        }
    444444
    445         void enableLatePatch() { }
    446445    private:
    447446        JmpSrc(int offset)
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r46831 r47186  
    321321        }
    322322
    323         void enableLatePatch()
    324         {
    325             m_jmp.enableLatePatch();
    326         }
    327 
    328323        JmpSrc m_jmp;
    329324    private:
     
    362357        }
    363358
    364         void enableLatePatch()
    365         {
    366             m_jmp.enableLatePatch();
    367         }
    368 
    369359    private:
    370360        JmpSrc m_jmp;
  • trunk/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h

    r46057 r47186  
    3535#include <wtf/SegmentedVector.h>
    3636
     37#define ASSEMBLER_HAS_CONSTANT_POOL 1
     38
    3739namespace JSC {
    3840
     
    178180    }
    179181
     182    int uncheckedSize()
     183    {
     184        return AssemblerBuffer::size();
     185    }
     186
    180187    void* executableCopy(ExecutablePool* allocator)
    181188    {
     
    208215
    209216    // This flushing mechanism can be called after any unconditional jumps.
    210     void flushWithoutBarrier()
     217    void flushWithoutBarrier(bool isForced = false)
    211218    {
    212219        // Flush if constant pool is more than 60% full to avoid overuse of this function.
    213         if (5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
     220        if (isForced || 5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
    214221            flushConstantPool(false);
    215222    }
     
    218225    {
    219226        return m_pool;
     227    }
     228
     229    int sizeOfConstantPool()
     230    {
     231        return m_numConsts;
    220232    }
    221233
     
    277289        if (m_numConsts == 0)
    278290            return;
    279         if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
     291        int lastConstDelta = m_lastConstDelta > nextInsnSize ? m_lastConstDelta - nextInsnSize : 0;
     292        if ((m_maxDistance < nextInsnSize + lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
    280293            flushConstantPool();
    281294    }
     
    285298        if (m_numConsts == 0)
    286299            return;
    287         if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)) ||
    288             (m_numConsts + nextConstSize / sizeof(uint32_t) >= maxPoolSize))
     300        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + nextConstSize + barrierSize + (int)sizeof(uint32_t)) ||
     301            (m_numConsts * sizeof(uint32_t) + nextConstSize >= maxPoolSize))
    289302            flushConstantPool();
    290303    }
  • trunk/JavaScriptCore/assembler/MacroAssemblerARM.h

    r46832 r47186  
    325325    }
    326326
    327     Jump branch32(Condition cond, RegisterID left, RegisterID right)
     327    Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
    328328    {
    329329        m_assembler.cmp_r(left, right);
    330         return Jump(m_assembler.jmp(ARMCondition(cond)));
    331     }
    332 
    333     Jump branch32(Condition cond, RegisterID left, Imm32 right)
     330        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
     331    }
     332
     333    Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
    334334    {
    335335        if (right.m_isPointer) {
     
    338338        } else
    339339            m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARM::S0));
    340         return Jump(m_assembler.jmp(ARMCondition(cond)));
     340        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
    341341    }
    342342
     
    498498    {
    499499        prepareCall();
    500         return Call(m_assembler.jmp(), Call::LinkableNear);
     500        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear);
    501501    }
    502502
     
    588588    {
    589589        prepareCall();
    590         return Call(m_assembler.jmp(), Call::Linkable);
     590        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable);
    591591    }
    592592
     
    611611    {
    612612        dataLabel = moveWithPatch(initialRightValue, ARM::S1);
    613         Jump jump = branch32(cond, left, ARM::S1);
    614         jump.enableLatePatch();
     613        Jump jump = branch32(cond, left, ARM::S1, true);
    615614        return jump;
    616615    }
     
    620619        load32(left, ARM::S1);
    621620        dataLabel = moveWithPatch(initialRightValue, ARM::S0);
    622         Jump jump = branch32(cond, ARM::S0, ARM::S1);
    623         jump.enableLatePatch();
     621        Jump jump = branch32(cond, ARM::S0, ARM::S1, true);
    624622        return jump;
    625623    }
     
    723721    }
    724722
     723    void ensureSpace(int insnSpace, int constSpace)
     724    {
     725        m_assembler.ensureSpace(insnSpace, constSpace);
     726    }
     727
     728    int sizeOfConstantPool()
     729    {
     730        return m_assembler.sizeOfConstantPool();
     731    }
     732
    725733    void prepareCall()
    726734    {
    727         m_assembler.ensureSpace(3 * sizeof(ARMWord), sizeof(ARMWord));
     735        ensureSpace(3 * sizeof(ARMWord), sizeof(ARMWord));
    728736
    729737        // S0 might be used for parameter passing
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r46598 r47186  
    232232        }
    233233
    234         void enableLatePatch() { }
    235234    private:
    236235        JmpSrc(int offset)
  • trunk/JavaScriptCore/jit/JIT.h

    r46879 r47186  
    596596        static const int patchOffsetMethodCheckProtoStruct = 28;
    597597        static const int patchOffsetMethodCheckPutFunction = 46;
     598#elif PLATFORM(ARM)
     599        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
     600        static const int patchOffsetPutByIdStructure = 4;
     601        static const int patchOffsetPutByIdExternalLoad = 16;
     602        static const int patchLengthPutByIdExternalLoad = 4;
     603        static const int patchOffsetPutByIdPropertyMapOffset = 20;
     604        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
     605        static const int patchOffsetGetByIdStructure = 4;
     606        static const int patchOffsetGetByIdBranchToSlowCase = 16;
     607        static const int patchOffsetGetByIdExternalLoad = 16;
     608        static const int patchLengthGetByIdExternalLoad = 4;
     609        static const int patchOffsetGetByIdPropertyMapOffset = 20;
     610        static const int patchOffsetGetByIdPutResult = 28;
     611#if ENABLE(OPCODE_SAMPLING)
     612        #error "OPCODE_SAMPLING is not yet supported"
     613#else
     614        static const int patchOffsetGetByIdSlowCaseCall = 36;
     615#endif
     616        static const int patchOffsetOpCallCompareToJump = 12;
     617
     618        static const int patchOffsetMethodCheckProtoObj = 12;
     619        static const int patchOffsetMethodCheckProtoStruct = 20;
     620        static const int patchOffsetMethodCheckPutFunction = 32;
    598621#endif
    599622#endif // USE(JSVALUE32_64)
     623
     624#if PLATFORM(ARM) && !PLATFORM_ARM_ARCH(7)
     625        // sequenceOpCall
     626        static const int sequenceOpCallInstructionSpace = 12;
     627        static const int sequenceOpCallConstantSpace = 2;
     628        // sequenceMethodCheck
     629        static const int sequenceMethodCheckInstructionSpace = 40;
     630        static const int sequenceMethodCheckConstantSpace = 6;
     631        // sequenceGetByIdHotPath
     632        static const int sequenceGetByIdHotPathInstructionSpace = 28;
     633        static const int sequenceGetByIdHotPathConstantSpace = 3;
     634        // sequenceGetByIdSlowCase
     635        static const int sequenceGetByIdSlowCaseInstructionSpace = 40;
     636        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
     637        // sequencePutById
     638        static const int sequencePutByIdInstructionSpace = 28;
     639        static const int sequencePutByIdConstantSpace = 3;
     640#endif
     641
     642#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     643#define BEGIN_UNINTERRUPTED_SEQUENCE(name) beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
     644#define END_UNINTERRUPTED_SEQUENCE(name) endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
     645
     646        void beginUninterruptedSequence(int, int);
     647        void endUninterruptedSequence(int, int);
     648
     649#else
     650#define BEGIN_UNINTERRUPTED_SEQUENCE(name)
     651#define END_UNINTERRUPTED_SEQUENCE(name)
     652#endif
    600653
    601654        void emit_op_add(Instruction*);
     
    836889        unsigned m_jumpTargetsPosition;
    837890#endif
     891
     892#ifndef NDEBUG
     893#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     894        Label m_uninterruptedInstructionSequenceBegin;
     895        int m_uninterruptedConstantSequenceBegin;
     896#endif
     897#endif
    838898    } JIT_CLASS_ALIGNMENT;
    839899} // namespace JSC
  • trunk/JavaScriptCore/jit/JITCall.cpp

    r46879 r47186  
    618618    emitGetVirtualRegister(callee, regT2);
    619619    DataLabelPtr addressOfLinkedFunctionCheck;
     620
     621    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
     622
    620623    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT2, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue())));
     624
     625    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
     626
    621627    addSlowCase(jumpToSlow);
    622628    ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
  • trunk/JavaScriptCore/jit/JITInlineMethods.h

    r46831 r47186  
    103103}
    104104
     105#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     106
     107ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace)
     108{
     109#if PLATFORM(ARM) && !PLATFORM_ARM_ARCH(7)
     110#ifndef NDEBUG
     111    // Ensure the label after the sequence can also fit
     112    insnSpace += sizeof(ARMWord);
     113    constSpace += sizeof(uint64_t);
     114#endif
     115
     116    ensureSpace(insnSpace, constSpace);
     117
     118#endif
     119
     120#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     121#ifndef NDEBUG
     122    m_uninterruptedInstructionSequenceBegin = label();
     123    m_uninterruptedConstantSequenceBegin = sizeOfConstantPool();
     124#endif
     125#endif
     126}
     127
     128ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
     129{
     130#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     131    ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) == insnSpace);
     132    ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin == constSpace);
     133#endif
     134}
     135
     136#endif
     137
    105138#if PLATFORM(X86) || PLATFORM(X86_64) || (PLATFORM(ARM) && !PLATFORM_ARM_ARCH(7))
    106139
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r46879 r47186  
    11231123    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
    11241124    MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
     1125
    11251126    Jump notCell = emitJumpIfNotJSCell(regT0);
     1127
     1128    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     1129
    11261130    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
    11271131    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1);
     
    11301134    // This will be relinked to load the function without doing a load.
    11311135    DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
     1136
     1137    END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     1138
    11321139    Jump match = jump();
    11331140
     
    11921199
    11931200    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
     1201
     1202    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
    11941203
    11951204    Label hotPathBegin(this);
     
    12111220
    12121221    Label putResult(this);
     1222
     1223    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
     1224
    12131225    ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
    12141226}
     
    12331245    linkSlowCaseIfNotJSCell(iter, baseVReg);
    12341246    linkSlowCase(iter);
     1247
     1248    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
    12351249
    12361250#ifndef NDEBUG
     
    12421256    Call call = stubCall.call(resultVReg);
    12431257
     1258    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
     1259
    12441260    ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
    12451261
     
    12641280    // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
    12651281    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
     1282
     1283    BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
    12661284
    12671285    Label hotPathBegin(this);
     
    12801298
    12811299    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
     1300
     1301    END_UNINTERRUPTED_SEQUENCE(sequencePutById);
     1302
    12821303    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
    12831304}
Note: See TracChangeset for help on using the changeset viewer.