Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (129425 => 129426)
--- trunk/Source/_javascript_Core/ChangeLog 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-09-24 23:12:00 UTC (rev 129426)
@@ -1,3 +1,31 @@
+2012-09-24 Geoffrey Garen <[email protected]>
+
+ Inlined activation tear-off in the DFG
+ https://bugs.webkit.org/show_bug.cgi?id=97487
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h: Activation tear-off is always inlined now, so I
+ removed its out-of-line implementation.
+
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile): Inlined the variable copy and update
+ of JSVariableObject::m_registers. This usually turns into < 10 instructions,
+ which is close to pure win as compared to the operation function call.
+
+ * runtime/JSActivation.h:
+ (JSActivation):
+ (JSC::JSActivation::registersOffset):
+ (JSC::JSActivation::tearOff):
+ (JSC::JSActivation::isTornOff):
+ (JSC):
+ (JSC::JSActivation::storageOffset):
+ (JSC::JSActivation::storage): Tiny bit of refactoring so the JIT can
+ share the pointer math helper functions we use internally.
+
2012-09-24 Balazs Kilvady <[email protected]>
MIPS: store8 functions added to MacroAssembler.
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (129425 => 129426)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-09-24 23:12:00 UTC (rev 129426)
@@ -1167,13 +1167,6 @@
return result;
}
-void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell)
-{
- JSGlobalData& globalData = exec->globalData();
- NativeCallFrameTracer tracer(&globalData, exec);
- jsCast<JSActivation*>(activationCell)->tearOff(exec->globalData());
-}
-
void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell)
{
ASSERT(exec->codeBlock()->usesArguments());
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (129425 => 129426)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2012-09-24 23:12:00 UTC (rev 129426)
@@ -177,7 +177,6 @@
JSCell* DFG_OPERATION operationCreateActivation(ExecState*) WTF_INTERNAL;
JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL;
JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL;
-void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL;
void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, JSCell*, InlineCallFrame*) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (129425 => 129426)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-09-24 23:12:00 UTC (rev 129426)
@@ -30,7 +30,7 @@
#if ENABLE(DFG_JIT)
#include "DFGSlowPathGenerator.h"
-#include "JSVariableObject.h"
+#include "JSActivation.h"
namespace JSC { namespace DFG {
@@ -4070,16 +4070,38 @@
case TearOffActivation: {
JSValueOperand activationValue(this, node.child1());
+ GPRTemporary scratch(this);
GPRReg activationValueTagGPR = activationValue.tagGPR();
GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
+ GPRReg scratchGPR = scratch.gpr();
- JITCompiler::Jump created = m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+ JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
- addSlowPathGenerator(
- slowPathCall(
- created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR));
+ SharedSymbolTable* symbolTable = m_jit.symbolTableFor(node.codeOrigin);
+ int registersOffset = JSActivation::registersOffset(symbolTable);
+
+ int captureEnd = symbolTable->captureEnd();
+ for (int i = symbolTable->captureStart(); i < captureEnd; ++i) {
+ m_jit.loadPtr(
+ JITCompiler::Address(
+ GPRInfo::callFrameRegister, i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
+ scratchGPR);
+ m_jit.storePtr(
+ scratchGPR, JITCompiler::Address(
+ activationValuePayloadGPR, registersOffset + i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+ m_jit.loadPtr(
+ JITCompiler::Address(
+ GPRInfo::callFrameRegister, i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
+ scratchGPR);
+ m_jit.storePtr(
+ scratchGPR, JITCompiler::Address(
+ activationValuePayloadGPR, registersOffset + i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+ }
+ m_jit.addPtr(TrustedImm32(registersOffset), activationValuePayloadGPR, scratchGPR);
+ m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValuePayloadGPR, JSActivation::offsetOfRegisters()));
+ notCreated.link(&m_jit);
noResult(m_compileIndex);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (129425 => 129426)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-09-24 23:12:00 UTC (rev 129426)
@@ -4041,14 +4041,28 @@
ASSERT(!node.codeOrigin.inlineCallFrame);
JSValueOperand activationValue(this, node.child1());
+ GPRTemporary scratch(this);
GPRReg activationValueGPR = activationValue.gpr();
+ GPRReg scratchGPR = scratch.gpr();
- JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR);
-
- addSlowPathGenerator(
- slowPathCall(
- created, this, operationTearOffActivation, NoResult, activationValueGPR));
-
+ JITCompiler::Jump notCreated = m_jit.branchTestPtr(JITCompiler::Zero, activationValueGPR);
+
+ SharedSymbolTable* symbolTable = m_jit.symbolTableFor(node.codeOrigin);
+ int registersOffset = JSActivation::registersOffset(symbolTable);
+
+ int captureEnd = symbolTable->captureEnd();
+ for (int i = symbolTable->captureStart(); i < captureEnd; ++i) {
+ m_jit.loadPtr(
+ JITCompiler::Address(
+ GPRInfo::callFrameRegister, i * sizeof(Register)), scratchGPR);
+ m_jit.storePtr(
+ scratchGPR, JITCompiler::Address(
+ activationValueGPR, registersOffset + i * sizeof(Register)));
+ }
+ m_jit.addPtr(TrustedImm32(registersOffset), activationValueGPR, scratchGPR);
+ m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValueGPR, JSActivation::offsetOfRegisters()));
+
+ notCreated.link(&m_jit);
noResult(m_compileIndex);
break;
}
Modified: trunk/Source/_javascript_Core/runtime/JSActivation.h (129425 => 129426)
--- trunk/Source/_javascript_Core/runtime/JSActivation.h 2012-09-24 22:23:38 UTC (rev 129425)
+++ trunk/Source/_javascript_Core/runtime/JSActivation.h 2012-09-24 23:12:00 UTC (rev 129426)
@@ -84,6 +84,8 @@
bool isValidIndex(int) const;
bool isValid(const SymbolTableEntry&) const;
bool isTornOff();
+ int registersOffset();
+ static int registersOffset(SharedSymbolTable*);
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
@@ -99,8 +101,8 @@
NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
static size_t allocationSize(SharedSymbolTable*);
+ static size_t storageOffset();
- int registerOffset();
WriteBarrier<Unknown>* storage(); // captureCount() number of registers.
};
@@ -141,17 +143,17 @@
return false;
}
- inline int JSActivation::registerOffset()
+ inline int JSActivation::registersOffset(SharedSymbolTable* symbolTable)
{
- return -symbolTable()->captureStart();
+ return storageOffset() - (symbolTable->captureStart() * sizeof(WriteBarrier<Unknown>));
}
inline void JSActivation::tearOff(JSGlobalData& globalData)
{
ASSERT(!isTornOff());
- int registerOffset = this->registerOffset();
- WriteBarrierBase<Unknown>* dst = storage() + registerOffset;
+ WriteBarrierBase<Unknown>* dst = reinterpret_cast<WriteBarrierBase<Unknown>*>(
+ reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
WriteBarrierBase<Unknown>* src = ""
int captureEnd = symbolTable()->captureEnd();
@@ -164,15 +166,19 @@
inline bool JSActivation::isTornOff()
{
- return m_registers == storage() + registerOffset();
+ return m_registers == reinterpret_cast<WriteBarrierBase<Unknown>*>(
+ reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
}
+ inline size_t JSActivation::storageOffset()
+ {
+ return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation));
+ }
+
inline WriteBarrier<Unknown>* JSActivation::storage()
{
return reinterpret_cast<WriteBarrier<Unknown>*>(
- reinterpret_cast<char*>(this) +
- WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation))
- );
+ reinterpret_cast<char*>(this) + storageOffset());
}
inline size_t JSActivation::allocationSize(SharedSymbolTable* symbolTable)