Commit dc8a30cc authored by mjs@apple.com's avatar mjs@apple.com

2008-10-17 Maciej Stachowiak <mjs@apple.com>

        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
parent 6e0fdcb6
2008-10-17 Maciej Stachowiak <mjs@apple.com>
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 <zwarich@apple.com>
Reviewed by Maciej Stachowiak.
......
......@@ -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<void*>(oldStructureID));
m_jit.addl_i8m(1, reinterpret_cast<void*>(newStructureID));
m_jit.movl_i32m(reinterpret_cast<uint32_t>(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<uint32_t>(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<void*>(oldStructureID));
m_jit.addl_i8m(1, reinterpret_cast<void*>(newStructureID));
m_jit.movl_i32m(reinterpret_cast<uint32_t>(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<void*>(Machine::cti_op_put_by_id_fail));
if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID))
X86Assembler::link(code, callTarget, reinterpret_cast<void*>(transitionObject));
X86Assembler::link(code, callTarget, reinterpret_cast<void*>(resizePropertyStorage));
m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
......
......@@ -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)
......
......@@ -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
......@@ -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)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment