Changeset 92498 in webkit


Ignore:
Timestamp:
Aug 5, 2011 1:03:19 PM (13 years ago)
Author:
oliver@apple.com
Message:

Inline allocation of function objects
https://bugs.webkit.org/show_bug.cgi?id=65779

Reviewed by Gavin Barraclough.

Inline allocation and initilisation of function objects
in generated code. This ended up being a 60-70% improvement
in function allocation performance. This improvement shows
up as a ~2% improvement in 32bit sunspider and V8, but is a
wash on 64-bit.

We currently don't inline the allocation of named function
expressions, as that requires being able to gc allocate a
variable object.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:

(JSC::JIT::emitStoreCell):

  • jit/JITInlineMethods.h:

(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSFunction):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_new_func):
(JSC::JIT::emitSlow_op_new_func):
(JSC::JIT::emit_op_new_func_exp):
(JSC::JIT::emitSlow_op_new_func_exp):

  • jit/JITOpcodes32_64.cpp:

Removed duplicate implementation of op_new_func and op_new_func_exp

  • runtime/JSFunction.h:

(JSC::JSFunction::offsetOfScopeChain):
(JSC::JSFunction::offsetOfExecutable):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r92437 r92498  
     12011-08-05  Oliver Hunt  <oliver@apple.com>
     2
     3        Inline allocation of function objects
     4        https://bugs.webkit.org/show_bug.cgi?id=65779
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Inline allocation and initilisation of function objects
     9        in generated code.  This ended up being a 60-70% improvement
     10        in function allocation performance.  This improvement shows
     11        up as a ~2% improvement in 32bit sunspider and V8, but is a
     12        wash on 64-bit.
     13
     14        We currently don't inline the allocation of named function
     15        expressions, as that requires being able to gc allocate a
     16        variable object.
     17
     18        * jit/JIT.cpp:
     19        (JSC::JIT::privateCompileSlowCases):
     20        * jit/JIT.h:
     21        (JSC::JIT::emitStoreCell):
     22        * jit/JITInlineMethods.h:
     23        (JSC::JIT::emitAllocateBasicJSObject):
     24        (JSC::JIT::emitAllocateJSFinalObject):
     25        (JSC::JIT::emitAllocateJSFunction):
     26        * jit/JITOpcodes.cpp:
     27        (JSC::JIT::emit_op_new_func):
     28        (JSC::JIT::emitSlow_op_new_func):
     29        (JSC::JIT::emit_op_new_func_exp):
     30        (JSC::JIT::emitSlow_op_new_func_exp):
     31        * jit/JITOpcodes32_64.cpp:
     32            Removed duplicate implementation of op_new_func and op_new_func_exp
     33        * runtime/JSFunction.h:
     34        (JSC::JSFunction::offsetOfScopeChain):
     35        (JSC::JSFunction::offsetOfExecutable):
     36
    1372011-08-04  David Levin  <levin@chromium.org>
    238
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r91952 r92498  
    432432        DEFINE_SLOWCASE_OP(op_neq)
    433433        DEFINE_SLOWCASE_OP(op_new_object)
     434        DEFINE_SLOWCASE_OP(op_new_func)
     435        DEFINE_SLOWCASE_OP(op_new_func_exp)
    434436        DEFINE_SLOWCASE_OP(op_not)
    435437        DEFINE_SLOWCASE_OP(op_nstricteq)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r91199 r92498  
    5050
    5151    class CodeBlock;
     52    class FunctionExecutable;
    5253    class JIT;
    5354    class JSPropertyNameIterator;
     
    300301
    301302        void emitWriteBarrier(RegisterID owner, RegisterID scratch);
    302        
    303         template<typename T>
    304         void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch);
     303
     304        template<typename ClassType, typename StructureType> void emitAllocateBasicJSObject(StructureType, void* vtable, RegisterID result, RegisterID storagePtr);
     305        template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
     306        void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
    305307
    306308#if USE(JSVALUE32_64)
     
    529531        void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
    530532        void emitPutVirtualRegister(unsigned dst, RegisterID from = regT0);
     533        void emitStoreCell(unsigned dst, RegisterID payload, bool /* only used in JSValue32_64 */ = false)
     534        {
     535            emitPutVirtualRegister(dst, payload);
     536        }
    531537
    532538        int32_t getConstantOperandImmediateInt(unsigned src);
     
    907913        void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
    908914        void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
     915        void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&);
     916        void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&);
    909917
    910918       
  • trunk/Source/JavaScriptCore/jit/JITInlineMethods.h

    r91199 r92498  
    375375}
    376376
    377 template<typename T>
    378 inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
    379 {
    380     NewSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassFor(sizeof(JSFinalObject));
     377template <typename ClassType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, void* vtable, RegisterID result, RegisterID storagePtr)
     378{
     379    NewSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassFor(sizeof(ClassType));
    381380    loadPtr(&sizeClass->firstFreeCell, result);
    382381    addSlowCase(branchTestPtr(Zero, result));
    383    
     382
    384383    // remove the object from the free list
    385     loadPtr(Address(result), scratch);
    386     storePtr(scratch, &sizeClass->firstFreeCell);
    387    
     384    loadPtr(Address(result), storagePtr);
     385    storePtr(storagePtr, &sizeClass->firstFreeCell);
     386
    388387    // initialize the object's vtable
    389     storePtr(ImmPtr(m_globalData->jsFinalObjectVPtr), Address(result));
    390    
     388    storePtr(TrustedImmPtr(vtable), Address(result));
     389
    391390    // initialize the object's structure
    392391    storePtr(structure, Address(result, JSCell::structureOffset()));
     392
     393    // initialize the inheritor ID
     394    storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
     395
     396    // initialize the object's property storage pointer
     397    addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
     398    storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
     399}
     400
     401template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
     402{
     403    emitAllocateBasicJSObject<JSFinalObject>(structure, m_globalData->jsFinalObjectVPtr, result, scratch);
     404}
     405
     406inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
     407{
     408    emitAllocateBasicJSObject<JSFunction>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), m_globalData->jsFunctionVPtr, result, storagePtr);
     409
     410    // store the function's scope chain
     411    storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
     412
     413    // store the function's executable member
     414    storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
     415
    393416   
    394     // initialize the inheritor ID
    395     storePtr(ImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
    396    
    397     // initialize the object's property storage pointer
    398     addPtr(Imm32(sizeof(JSObject)), result, scratch);
    399     storePtr(scratch, Address(result, JSObject::offsetOfPropertyStorage()));
     417    // store the function's global object
     418    int globalObjectOffset = sizeof(JSValue) * JSFunction::GlobalObjectSlot;
     419    storePtr(TrustedImmPtr(m_codeBlock->globalObject()), Address(regT1, globalObjectOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     420#if USE(JSVALUE32_64)
     421    store32(TrustedImm32(JSValue::CellTag), Address(regT1, globalObjectOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     422#endif
     423
     424    // store the function's name
     425    ASSERT(executable->nameValue());
     426    int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
     427    storePtr(TrustedImmPtr(executable->nameValue()), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     428#if USE(JSVALUE32_64)
     429    store32(TrustedImm32(JSValue::CellTag), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     430#endif
    400431}
    401432
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r91199 r92498  
    726726}
    727727
    728 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
    729 {
    730     JITStubCall stubCall(this, cti_op_new_func_exp);
    731     stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
    732     stubCall.call(currentInstruction[1].u.operand);
    733 }
    734 
    735728void JIT::emit_op_jtrue(Instruction* currentInstruction)
    736729{
     
    16221615#endif
    16231616    }
     1617
     1618    FunctionExecutable* executable = m_codeBlock->functionDecl(currentInstruction[2].u.operand);
     1619    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
     1620    emitAllocateJSFunction(executable, regT2, regT0, regT1);
     1621
     1622    emitStoreCell(dst, regT0);
     1623
     1624    if (currentInstruction[3].u.operand) {
     1625#if USE(JSVALUE32_64)       
     1626        unmap();
     1627#else
     1628        killLastResultRegister();
     1629#endif
     1630        lazyJump.link(this);
     1631    }
     1632}
     1633
     1634void JIT::emitSlow_op_new_func(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1635{
     1636    linkSlowCase(iter);
    16241637    JITStubCall stubCall(this, cti_op_new_func);
    16251638    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
    16261639    stubCall.call(currentInstruction[1].u.operand);
    1627     if (currentInstruction[3].u.operand)
    1628         lazyJump.link(this);
     1640}
     1641
     1642void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
     1643{
     1644    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
     1645
     1646    // We only inline the allocation of a anonymous function expressions
     1647    // If we want to be able to allocate a named function expression, we would
     1648    // need to be able to do inline allocation of a JSStaticScopeObject.
     1649    if (executable->name().isNull()) {
     1650        emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
     1651        emitAllocateJSFunction(executable, regT2, regT0, regT1);
     1652        emitStoreCell(currentInstruction[1].u.operand, regT0);
     1653        return;
     1654    }
     1655
     1656    JITStubCall stubCall(this, cti_op_new_func_exp);
     1657    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     1658    stubCall.call(currentInstruction[1].u.operand);
     1659}
     1660
     1661void JIT::emitSlow_op_new_func_exp(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1662{
     1663    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
     1664    if (!executable->name().isNull())
     1665        return;
     1666    linkSlowCase(iter);
     1667    JITStubCall stubCall(this, cti_op_new_func_exp);
     1668    stubCall.addArgument(TrustedImmPtr(executable));
     1669    stubCall.call(currentInstruction[1].u.operand);
    16291670}
    16301671
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r91199 r92498  
    11191119}
    11201120
    1121 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
    1122 {
    1123     JITStubCall stubCall(this, cti_op_new_func_exp);
    1124     stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
    1125     stubCall.call(currentInstruction[1].u.operand);
    1126 }
    1127 
    11281121void JIT::emit_op_throw(Instruction* currentInstruction)
    11291122{
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r91194 r92498  
    111111        virtual CallType getCallData(CallData&);
    112112
     113        static inline size_t offsetOfScopeChain()
     114        {
     115            return OBJECT_OFFSETOF(JSFunction, m_scopeChain);
     116        }
     117
     118        static inline size_t offsetOfExecutable()
     119        {
     120            return OBJECT_OFFSETOF(JSFunction, m_executable);
     121        }
     122
    113123    protected:
    114124        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
Note: See TracChangeset for help on using the changeset viewer.