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):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@92498 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h
index 724de3a..7445994 100644
--- a/Source/JavaScriptCore/jit/JITInlineMethods.h
+++ b/Source/JavaScriptCore/jit/JITInlineMethods.h
@@ -374,29 +374,60 @@
     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1;
 }
 
-template<typename T>
-inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
+template <typename ClassType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, void* vtable, RegisterID result, RegisterID storagePtr)
 {
-    NewSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassFor(sizeof(JSFinalObject));
+    NewSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassFor(sizeof(ClassType));
     loadPtr(&sizeClass->firstFreeCell, result);
     addSlowCase(branchTestPtr(Zero, result));
-    
+
     // remove the object from the free list
-    loadPtr(Address(result), scratch);
-    storePtr(scratch, &sizeClass->firstFreeCell);
-    
+    loadPtr(Address(result), storagePtr);
+    storePtr(storagePtr, &sizeClass->firstFreeCell);
+
     // initialize the object's vtable
-    storePtr(ImmPtr(m_globalData->jsFinalObjectVPtr), Address(result));
-    
+    storePtr(TrustedImmPtr(vtable), Address(result));
+
     // initialize the object's structure
     storePtr(structure, Address(result, JSCell::structureOffset()));
-    
+
     // initialize the inheritor ID
-    storePtr(ImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
-    
+    storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
+
     // initialize the object's property storage pointer
-    addPtr(Imm32(sizeof(JSObject)), result, scratch);
-    storePtr(scratch, Address(result, JSObject::offsetOfPropertyStorage()));
+    addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
+    storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
+}
+
+template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
+{
+    emitAllocateBasicJSObject<JSFinalObject>(structure, m_globalData->jsFinalObjectVPtr, result, scratch);
+}
+
+inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
+{
+    emitAllocateBasicJSObject<JSFunction>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), m_globalData->jsFunctionVPtr, result, storagePtr);
+
+    // store the function's scope chain
+    storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
+
+    // store the function's executable member
+    storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
+
+    
+    // store the function's global object
+    int globalObjectOffset = sizeof(JSValue) * JSFunction::GlobalObjectSlot;
+    storePtr(TrustedImmPtr(m_codeBlock->globalObject()), Address(regT1, globalObjectOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#if USE(JSVALUE32_64)
+    store32(TrustedImm32(JSValue::CellTag), Address(regT1, globalObjectOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
+
+    // store the function's name
+    ASSERT(executable->nameValue());
+    int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
+    storePtr(TrustedImmPtr(executable->nameValue()), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#if USE(JSVALUE32_64)
+    store32(TrustedImm32(JSValue::CellTag), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
 }
 
 #if USE(JSVALUE32_64)