+2008-10-07 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Switch CTI runtime calls to the fastcall calling convention
+
+ Basically this means that we get to store the argument for CTI
+ calls in the ECX register, which saves a register->memory write
+ and subsequent memory->register read.
+
+ This is a 1.7% progression in SunSpider and 2.4% on commandline
+ v8 tests on Windows
+
+ * VM/CTI.cpp:
+ (JSC::):
+ (JSC::CTI::privateCompilePutByIdTransition):
+ (JSC::CTI::privateCompilePatchGetArrayLength):
+ * VM/CTI.h:
+ * VM/Machine.h:
+ * masm/X86Assembler.h:
+ (JSC::X86Assembler::emitRestoreArgumentReference):
+ (JSC::X86Assembler::emitRestoreArgumentReferenceForTrampoline):
+ We need this to correctly reload ecx from inside certain property access
+ trampolines.
+ * wtf/Platform.h:
+
2008-10-07 Maciej Stachowiak <mjs@apple.com>
Reviewed by Mark Rowe.
push edi;
sub esp, 0x24;
mov esi, 512;
- mov [esp], esp;
+ mov ecx, esp;
mov edi, [esp + 0x38];
call [esp + 0x30];
add esp, 0x24;
__declspec(naked) void ctiVMThrowTrampoline()
{
__asm {
- mov [esp], esp;
+ mov ecx, esp;
call JSC::Machine::cti_vm_throw;
add esp, 0x24;
pop edi;
extern "C" {
-static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value)
+static JSValue* transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value)
{
baseObject->transitionTo(newStructureID);
baseObject->putDirectOffset(cachedOffset, value);
m_jit.addl_i32r(4 * sizeof(void*), X86::esp);
}
m_jit.ret();
+
+ X86Assembler::JmpSrc failureJump;
+ if (failureCases.size()) {
+ for (unsigned i = 0; i < failureCases.size(); ++i)
+ m_jit.link(failureCases[i], m_jit.label());
+ m_jit.emitRestoreArgumentReferenceForTrampoline();
+ failureJump = m_jit.emitUnlinkedJmp();
+ }
+
void* code = m_jit.copy();
ASSERT(code);
-
- for (unsigned i = 0; i < failureCases.size(); ++i)
- X86Assembler::link(code, failureCases[i], reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
+
+ if (failureCases.size())
+ 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));
m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::ecx, X86::ecx);
m_jit.addl_rr(X86::ecx, X86::ecx);
- X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
+ X86Assembler::JmpSrc failureClobberedECX = m_jit.emitUnlinkedJo();
m_jit.addl_i8r(1, X86::ecx);
X86Assembler::JmpSrc success = m_jit.emitUnlinkedJmp();
+ m_jit.link(failureClobberedECX, m_jit.label());
+ m_jit.emitRestoreArgumentReference();
+ X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJmp();
+
void* code = m_jit.copy();
ASSERT(code);
struct VoidPtrPair { void* first; void* second; };
- typedef JSValue* (*CTIHelper_j)(CTI_ARGS);
- typedef JSPropertyNameIterator* (*CTIHelper_p)(CTI_ARGS);
- typedef void (*CTIHelper_v)(CTI_ARGS);
- typedef void* (*CTIHelper_s)(CTI_ARGS);
- typedef int (*CTIHelper_b)(CTI_ARGS);
- typedef VoidPtrPair (*CTIHelper_2)(CTI_ARGS);
+#if COMPILER(MSVC)
+
+#if USE(FAST_CALL_CTI_ARGUMENT)
+#define SFX_CALL __fastcall
+#else
+#define SFX_CALL __cdecl
+#endif
+
+#else
+#define SFX_CALL
+#endif
+
+ typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS);
+ typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS);
+ typedef void (SFX_CALL *CTIHelper_v)(CTI_ARGS);
+ typedef void* (SFX_CALL *CTIHelper_s)(CTI_ARGS);
+ typedef int (SFX_CALL *CTIHelper_b)(CTI_ARGS);
+ typedef VoidPtrPair (SFX_CALL *CTIHelper_2)(CTI_ARGS);
struct CallRecord {
X86Assembler::JmpSrc from;
// will compress the displacement, and we may not be able to fit a repatched offset.
static const int repatchGetByIdDefaultOffset = 256;
-#if USE(CTI_ARGUMENT)
+#if USE(FAST_CALL_CTI_ARGUMENT)
+ static const int ctiArgumentInitSize = 2;
+#elif USE(CTI_ARGUMENT)
static const int ctiArgumentInitSize = 4;
#else
static const int ctiArgumentInitSize = 0;
SamplingTool* m_sampler;
#if ENABLE(CTI)
-#if COMPILER(MSVC)
-#define SFX_CALL __cdecl
-#else
-#define SFX_CALL
-#endif
static void SFX_CALL cti_timeout_check(CTI_ARGS);
void emitRestoreArgumentReference()
{
+#if USE(FAST_CALL_CTI_ARGUMENT)
+ movl_rr(X86::esp, X86::ecx);
+#else
movl_rm(X86::esp, 0, X86::esp);
+#endif
+ }
+
+ void emitRestoreArgumentReferenceForTrampoline()
+ {
+#if USE(FAST_CALL_CTI_ARGUMENT)
+ movl_rr(X86::esp, X86::ecx);
+ addl_i32r(4, X86::ecx);
+#else
+#endif
}
#else
void emitConvertToFastCall() {};
void emitRestoreArgumentReference() {};
+ void emitRestoreArgumentReferenceForTrampoline() {};
#endif
private:
#define WTF_USE_CTI_ARGUMENT 1
#endif
+#if COMPILER(MSVC)
+#define WTF_USE_FAST_CALL_CTI_ARGUMENT 1
+#endif
+
#endif /* WTF_Platform_h */