From dc8a30cccaceeffcb67307fc1937cd2124c409ce Mon Sep 17 00:00:00 2001 From: "mjs@apple.com" Date: Fri, 17 Oct 2008 11:55:09 +0000 Subject: [PATCH] 2008-10-17 Maciej Stachowiak Reviewed by Cameron Zwarich. - speed up transitions that resize the property storage a fair bit ~3% speedup on v8 RayTrace benchmark, ~1% on DeltaBlue * VM/CTI.cpp: (JSC::resizePropertyStorage): renamed from transitionObject, and reduced to just resize the object's property storage with one inline call. (JSC::CTI::privateCompilePutByIdTransition): Use a separate function for property storage resize, but still do all the rest of the work in assembly in that case, and pass the known compile-time constants of old and new size rather than structureIDs, saving a bunch of redundant memory access. * kjs/JSObject.cpp: (JSC::JSObject::allocatePropertyStorage): Just call the inline version. * kjs/JSObject.h: (JSC::JSObject::allocatePropertyStorageInline): Inline version of allocatePropertyStorage * masm/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::pushl_i32): Add code to assmeble push of a constant; code originally by Cameron Zwarich. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37653 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- JavaScriptCore/ChangeLog | 23 ++++++++++++++ JavaScriptCore/VM/CTI.cpp | 50 ++++++++++++++---------------- JavaScriptCore/kjs/JSObject.cpp | 11 +------ JavaScriptCore/kjs/JSObject.h | 15 +++++++++ JavaScriptCore/masm/X86Assembler.h | 7 +++++ 5 files changed, 70 insertions(+), 36 deletions(-) diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 5a505e6db603..4ac3cba9e7a1 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,26 @@ +2008-10-17 Maciej Stachowiak + + Reviewed by Cameron Zwarich. + + - speed up transitions that resize the property storage a fair bit + + ~3% speedup on v8 RayTrace benchmark, ~1% on DeltaBlue + + * VM/CTI.cpp: + (JSC::resizePropertyStorage): renamed from transitionObject, and reduced to just resize + the object's property storage with one inline call. + (JSC::CTI::privateCompilePutByIdTransition): Use a separate function for property storage + resize, but still do all the rest of the work in assembly in that case, and pass the known + compile-time constants of old and new size rather than structureIDs, saving a bunch of + redundant memory access. + * kjs/JSObject.cpp: + (JSC::JSObject::allocatePropertyStorage): Just call the inline version. + * kjs/JSObject.h: + (JSC::JSObject::allocatePropertyStorageInline): Inline version of allocatePropertyStorage + * masm/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::pushl_i32): Add code to assmeble push of a constant; code originally by Cameron Zwarich. + 2008-10-17 Cameron Zwarich Reviewed by Maciej Stachowiak. diff --git a/JavaScriptCore/VM/CTI.cpp b/JavaScriptCore/VM/CTI.cpp index 93b8af366cd4..3c4c3bbf9df0 100644 --- a/JavaScriptCore/VM/CTI.cpp +++ b/JavaScriptCore/VM/CTI.cpp @@ -2875,12 +2875,11 @@ void CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOf extern "C" { -static JSValue* transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value) -{ - baseObject->transitionTo(newStructureID); - baseObject->putDirectOffset(cachedOffset, value); - return baseObject; -} + static JSValue* resizePropertyStorage(JSObject* baseObject, size_t oldSize, size_t newSize) + { + baseObject->allocatePropertyStorageInline(oldSize, newSize); + return baseObject; + } } @@ -2927,29 +2926,28 @@ void CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, Structure m_jit.link(successCases[i], m_jit.label()); X86Assembler::JmpSrc callTarget; - // Fast case, don't need to do any heavy lifting, so don't bother making a call. - if (!transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) { - // Assumes m_refCount can be decremented easily, refcount decrement is safe as - // codeblock should ensure oldStructureID->m_refCount > 0 - m_jit.subl_i8m(1, reinterpret_cast(oldStructureID)); - m_jit.addl_i8m(1, reinterpret_cast(newStructureID)); - m_jit.movl_i32m(reinterpret_cast(newStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); - - // write the value - m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); - m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax); - } else { - // Slow case transition -- we're going to need to quite a bit of work, - // so just make a call + + // emit a call only if storage realloc is needed + if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) { m_jit.pushl_r(X86::edx); - m_jit.pushl_r(X86::eax); - m_jit.movl_i32r(cachedOffset, X86::eax); - m_jit.pushl_r(X86::eax); - m_jit.movl_i32r(reinterpret_cast(newStructureID), X86::eax); + m_jit.pushl_i32(newStructureID->propertyStorageCapacity()); + m_jit.pushl_i32(oldStructureID->propertyStorageCapacity()); m_jit.pushl_r(X86::eax); callTarget = m_jit.emitCall(); - m_jit.addl_i32r(4 * sizeof(void*), X86::esp); + m_jit.addl_i32r(3 * sizeof(void*), X86::esp); + m_jit.popl_r(X86::edx); } + + // Assumes m_refCount can be decremented easily, refcount decrement is safe as + // codeblock should ensure oldStructureID->m_refCount > 0 + m_jit.subl_i8m(1, reinterpret_cast(oldStructureID)); + m_jit.addl_i8m(1, reinterpret_cast(newStructureID)); + m_jit.movl_i32m(reinterpret_cast(newStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); + + // write the value + m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax); + m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax); + m_jit.ret(); X86Assembler::JmpSrc failureJump; @@ -2967,7 +2965,7 @@ void CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, Structure X86Assembler::link(code, failureJump, reinterpret_cast(Machine::cti_op_put_by_id_fail)); if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) - X86Assembler::link(code, callTarget, reinterpret_cast(transitionObject)); + X86Assembler::link(code, callTarget, reinterpret_cast(resizePropertyStorage)); m_codeBlock->getStubInfo(returnAddress).stubRoutine = code; diff --git a/JavaScriptCore/kjs/JSObject.cpp b/JavaScriptCore/kjs/JSObject.cpp index a7548150f9ae..010429eff22c 100644 --- a/JavaScriptCore/kjs/JSObject.cpp +++ b/JavaScriptCore/kjs/JSObject.cpp @@ -511,16 +511,7 @@ StructureID* JSObject::createInheritorID() void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize) { - ASSERT(newSize > oldSize); - - JSValue** oldPropertStorage = m_propertyStorage; - m_propertyStorage = new JSValue*[newSize]; - - for (unsigned i = 0; i < oldSize; ++i) - m_propertyStorage[i] = oldPropertStorage[i]; - - if (oldPropertStorage != m_inlineStorage) - delete [] oldPropertStorage; + allocatePropertyStorageInline(oldSize, newSize); } JSObject* constructEmptyObject(ExecState* exec) diff --git a/JavaScriptCore/kjs/JSObject.h b/JavaScriptCore/kjs/JSObject.h index 241cee830f56..f690fc118784 100644 --- a/JavaScriptCore/kjs/JSObject.h +++ b/JavaScriptCore/kjs/JSObject.h @@ -177,6 +177,7 @@ namespace JSC { virtual bool isNotAnObjectErrorStub() const { return false; } void allocatePropertyStorage(size_t oldSize, size_t newSize); + void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; } static const size_t inlineStorageCapacity = 2; @@ -506,6 +507,20 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue* value) asCell()->put(exec, propertyName, value); } +ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize) +{ + ASSERT(newSize > oldSize); + + JSValue** oldPropertStorage = m_propertyStorage; + m_propertyStorage = new JSValue*[newSize]; + + for (unsigned i = 0; i < oldSize; ++i) + m_propertyStorage[i] = oldPropertStorage[i]; + + if (oldPropertStorage != m_inlineStorage) + delete [] oldPropertStorage; +} + } // namespace JSC #endif // JSObject_h diff --git a/JavaScriptCore/masm/X86Assembler.h b/JavaScriptCore/masm/X86Assembler.h index 6112df88d632..dd08d38ef093 100644 --- a/JavaScriptCore/masm/X86Assembler.h +++ b/JavaScriptCore/masm/X86Assembler.h @@ -196,6 +196,7 @@ public: OP_POP_EAX = 0x58, PRE_OPERAND_SIZE = 0x66, PRE_SSE_66 = 0x66, + OP_PUSH_Iz = 0x68, OP_IMUL_GvEvIz = 0x69, OP_GROUP1_EvIz = 0x81, OP_GROUP1_EvIb = 0x83, @@ -292,6 +293,12 @@ public: m_buffer->putByte(OP_GROUP5_Ev); emitModRm_opm(GROUP5_OP_PUSH, base, offset); } + + void pushl_i32(int imm) + { + m_buffer->putByte(OP_PUSH_Iz); + m_buffer->putInt(imm); + } void popl_r(RegisterID reg) { -- 2.36.0