Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (167590 => 167591)
--- trunk/Source/_javascript_Core/ChangeLog 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-04-21 15:11:33 UTC (rev 167591)
@@ -1,3 +1,30 @@
+2014-04-21 Mark Hahnenberg <[email protected]>
+
+ Inline allocate Arguments objects in the DFG
+ https://bugs.webkit.org/show_bug.cgi?id=131897
+
+ Reviewed by Geoffrey Garen.
+
+ Many libraries/frameworks depend on the arguments object for overloaded API entry points.
+ This is the first step to making Arguments fast(er). We'll duplicate the logic in Arguments::create
+ for now and take the slow path for complicated cases like slow arguments, tearing off for strict mode, etc.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::emitAllocateArguments):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateDestructibleObject):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * runtime/Arguments.h:
+ (JSC::Arguments::offsetOfActivation):
+ (JSC::Arguments::offsetOfOverrodeLength):
+ (JSC::Arguments::offsetOfIsStrictMode):
+ (JSC::Arguments::offsetOfRegisterArray):
+ (JSC::Arguments::offsetOfCallee):
+ (JSC::Arguments::allocationSize):
+
2014-04-20 Andreas Kling <[email protected]>
Speed up jsStringWithCache() through WeakGCMap inlining.
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (167590 => 167591)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2014-04-21 15:11:33 UTC (rev 167591)
@@ -106,6 +106,29 @@
structure, numElements)));
}
+void SpeculativeJIT::emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
+{
+ Structure* structure = m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)->argumentsStructure();
+ emitAllocateDestructibleObject<Arguments>(resultGPR, structure, scratchGPR1, scratchGPR2, slowPath);
+
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfActivation()));
+
+ m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1);
+ m_jit.sub32(TrustedImm32(1), scratchGPR1);
+ m_jit.store32(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfNumArguments()));
+
+ m_jit.store32(TrustedImm32(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfOverrodeLength()));
+ m_jit.store8(TrustedImm32(m_jit.isStrictModeFor(m_currentNode->origin.semantic)),
+ MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode()));
+
+ m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters()));
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisterArray()));
+ m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfSlowArgumentData()));
+
+ m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), scratchGPR1);
+ m_jit.storePtr(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfCallee()));
+}
+
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
{
if (!m_compileOkay)
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (167590 => 167591)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2014-04-21 15:11:33 UTC (rev 167591)
@@ -2178,7 +2178,7 @@
m_jit.storePtr(storage, MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()));
}
- // Convenience allocator for a buit-in object.
+ // Convenience allocator for a built-in object.
template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
void emitAllocateJSObject(GPRReg resultGPR, StructureType structure, StorageType storage,
GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
@@ -2195,7 +2195,16 @@
emitAllocateJSObject(resultGPR, scratchGPR1, structure, storage, scratchGPR2, slowPath);
}
+ template <typename T>
+ void emitAllocateDestructibleObject(GPRReg resultGPR, Structure* structure,
+ GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
+ {
+ emitAllocateJSObject<T>(resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR1, scratchGPR2, slowPath);
+ m_jit.storePtr(TrustedImmPtr(structure->classInfo()), MacroAssembler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
+ }
+
void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements);
+ void emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath);
// Add a speculation check.
void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (167590 => 167591)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2014-04-21 15:11:33 UTC (rev 167591)
@@ -4167,26 +4167,47 @@
case CreateArguments: {
JSValueOperand value(this, node->child1());
+ GPRTemporary scratch1(this);
+ GPRTemporary scratch2(this);
GPRTemporary result(this, Reuse, value, PayloadWord);
GPRReg valueTagGPR = value.tagGPR();
GPRReg valuePayloadGPR = value.payloadGPR();
+ GPRReg scratch1GPR = scratch1.gpr();
+ GPRReg scratch2GPR = scratch2.gpr();
GPRReg resultGPR = result.gpr();
m_jit.move(valuePayloadGPR, resultGPR);
- JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
-
if (node->origin.semantic.inlineCallFrame) {
+ JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
addSlowPathGenerator(
slowPathCall(
notCreated, this, operationCreateInlinedArguments, resultGPR,
node->origin.semantic.inlineCallFrame));
- } else {
+ cellResult(resultGPR, node);
+ break;
+ }
+
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic));
+ if (m_jit.codeBlock()->hasSlowArguments()
+ || executable->isStrictMode()
+ || !executable->parameterCount()) {
+ JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
addSlowPathGenerator(
slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
+ cellResult(resultGPR, node);
+ break;
}
-
+
+ JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+
+ MacroAssembler::JumpList slowPaths;
+ emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths);
+ addSlowPathGenerator(
+ slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
+
+ alreadyCreated.link(&m_jit);
cellResult(resultGPR, node);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (167590 => 167591)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2014-04-21 15:11:33 UTC (rev 167591)
@@ -4224,25 +4224,46 @@
case CreateArguments: {
JSValueOperand value(this, node->child1());
+ GPRTemporary scratch1(this);
+ GPRTemporary scratch2(this);
GPRTemporary result(this, Reuse, value);
GPRReg valueGPR = value.gpr();
+ GPRReg scratchGPR1 = scratch1.gpr();
+ GPRReg scratchGPR2 = scratch2.gpr();
GPRReg resultGPR = result.gpr();
m_jit.move(valueGPR, resultGPR);
- JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
-
if (node->origin.semantic.inlineCallFrame) {
+ JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
addSlowPathGenerator(
slowPathCall(
notCreated, this, operationCreateInlinedArguments, resultGPR,
node->origin.semantic.inlineCallFrame));
- } else {
+ cellResult(resultGPR, node);
+ break;
+ }
+
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic));
+ if (m_jit.codeBlock()->hasSlowArguments()
+ || executable->isStrictMode()
+ || !executable->parameterCount()) {
+ JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
addSlowPathGenerator(
slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
+ cellResult(resultGPR, node);
+ break;
}
-
+
+ JITCompiler::Jump alreadyCreated = m_jit.branchTest64(JITCompiler::NonZero, resultGPR);
+
+ MacroAssembler::JumpList slowPaths;
+ emitAllocateArguments(resultGPR, scratchGPR1, scratchGPR2, slowPaths);
+ addSlowPathGenerator(
+ slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
+
+ alreadyCreated.link(&m_jit);
cellResult(resultGPR, node);
break;
}
Modified: trunk/Source/_javascript_Core/runtime/Arguments.h (167590 => 167591)
--- trunk/Source/_javascript_Core/runtime/Arguments.h 2014-04-21 10:39:51 UTC (rev 167590)
+++ trunk/Source/_javascript_Core/runtime/Arguments.h 2014-04-21 15:11:33 UTC (rev 167591)
@@ -89,10 +89,20 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(ArgumentsType, StructureFlags), info());
}
+ static ptrdiff_t offsetOfActivation() { return OBJECT_OFFSETOF(Arguments, m_activation); }
static ptrdiff_t offsetOfNumArguments() { return OBJECT_OFFSETOF(Arguments, m_numArguments); }
+ static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); }
+ static ptrdiff_t offsetOfIsStrictMode() { return OBJECT_OFFSETOF(Arguments, m_isStrictMode); }
static ptrdiff_t offsetOfRegisters() { return OBJECT_OFFSETOF(Arguments, m_registers); }
+ static ptrdiff_t offsetOfRegisterArray() { return OBJECT_OFFSETOF(Arguments, m_registerArray); }
static ptrdiff_t offsetOfSlowArgumentData() { return OBJECT_OFFSETOF(Arguments, m_slowArgumentData); }
- static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); }
+ static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(Arguments, m_callee); }
+
+ static size_t allocationSize(size_t inlineCapacity)
+ {
+ ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
+ return sizeof(Arguments);
+ }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;