Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (90186 => 90187)
--- trunk/Source/_javascript_Core/ChangeLog 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-07-01 00:10:23 UTC (rev 90187)
@@ -1,3 +1,59 @@
+2011-06-30 Geoffrey Garen <[email protected]>
+
+ Reviewed by Gavin Barraclough.
+
+ Added empty write barrier stubs in all the right places in the DFG JIT
+ https://bugs.webkit.org/show_bug.cgi?id=63764
+
+ SunSpider thinks this might be a 0.5% speedup. Meh.
+
+ * dfg/DFGJITCodeGenerator.cpp:
+ (JSC::DFG::JITCodeGenerator::writeBarrier): Le stub.
+
+ (JSC::DFG::JITCodeGenerator::cachedPutById): Don't do anything special
+ for the case where base == scratch, since we now require base and scratch
+ to be not equal, for the sake of the write barrier.
+
+ * dfg/DFGJITCodeGenerator.h: Le stub.
+
+ * dfg/DFGNonSpeculativeJIT.cpp:
+ (JSC::DFG::NonSpeculativeJIT::compile): Don't reuse the base register
+ as the scratch register, since that's incompatible with the write barrier,
+ which needs a distinct base and scratch.
+
+ Do put the global object into a register before loading its var storage,
+ since it needs to be in a register for the write barrier to operate on it.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emitWriteBarrier): Second verse, same as the first.
+
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC::JIT::emit_op_put_scoped_var):
+ (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
+ places.
+
+ (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
+ is a little more than meaningless.
+
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC::JIT::emit_op_put_scoped_var):
+ (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
+ places.
+
+ (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
+ is a little more than meaningless.
+
+ * runtime/JSVariableObject.h:
+ (JSC::JSVariableObject::offsetOfRegisters): Now used by the JIT, since
+ we put the global object in a register and only then load its var storage
+ by offset.
+
+ (JSC::JIT::emitWriteBarrier):
+
2011-06-30 Oliver Hunt <[email protected]>
Fix ARMv6 build
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (90186 => 90187)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp 2011-07-01 00:10:23 UTC (rev 90187)
@@ -368,16 +368,20 @@
unlock(scratchGPR);
}
+void JITCodeGenerator::writeBarrier(GPRReg owner, GPRReg scratch)
+{
+ UNUSED_PARAM(owner);
+ UNUSED_PARAM(scratch);
+ ASSERT(owner != scratch);
+}
+
void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
{
- GPRReg slowPathScratch = scratchGPR;
-
- if (scratchGPR == baseGPR)
- slowPathScratch = tryAllocate();
-
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+ writeBarrier(baseGPR, scratchGPR);
+
m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
@@ -418,10 +422,7 @@
int8_t callToSlowCase = static_cast<int8_t>(m_jit.differenceBetween(functionCall, slowCase));
int8_t callToDone = static_cast<int8_t>(m_jit.differenceBetween(functionCall, doneLabel));
- m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(slowPathScratch));
-
- if (scratchGPR == baseGPR && slowPathScratch != InvalidGPRReg)
- unlock(slowPathScratch);
+ m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(scratchGPR));
}
#ifndef NDEBUG
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (90186 => 90187)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-07-01 00:10:23 UTC (rev 90187)
@@ -517,6 +517,8 @@
ASSERT_NOT_REACHED();
}
}
+
+ void writeBarrier(GPRReg ownerGPR, GPRReg scratchGPR);
void cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
void cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (90186 => 90187)
--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp 2011-07-01 00:10:23 UTC (rev 90187)
@@ -770,7 +770,7 @@
case PutById: {
JSValueOperand base(this, node.child1);
JSValueOperand value(this, node.child2);
- GPRTemporary scratch(this, base);
+ GPRTemporary scratch(this);
GPRReg valueGPR = value.gpr();
GPRReg baseGPR = base.gpr();
@@ -785,7 +785,7 @@
case PutByIdDirect: {
JSValueOperand base(this, node.child1);
JSValueOperand value(this, node.child2);
- GPRTemporary scratch(this, base);
+ GPRTemporary scratch(this);
GPRReg valueGPR = value.gpr();
GPRReg baseGPR = base.gpr();
@@ -810,12 +810,19 @@
case PutGlobalVar: {
JSValueOperand value(this, node.child1);
- GPRTemporary temp(this);
+ GPRTemporary globalObject(this);
+ GPRTemporary scratch(this);
+
+ GPRReg globalObjectReg = globalObject.gpr();
+ GPRReg scratchReg = scratch.gpr();
- JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
- m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
- m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+ m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
+ writeBarrier(globalObjectReg, scratchReg);
+
+ m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+ m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
noResult(m_compileIndex);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (90186 => 90187)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-07-01 00:10:23 UTC (rev 90187)
@@ -891,14 +891,16 @@
SpeculateCellOperand base(this, node.child1);
SpeculateStrictInt32Operand property(this, node.child2);
JSValueOperand value(this, node.child3);
- GPRTemporary storage(this);
+ GPRTemporary scratch(this);
- // Map base, property & value into registers, allocate a register for storage.
+ // Map base, property & value into registers, allocate a scratch register.
GPRReg baseReg = base.gpr();
GPRReg propertyReg = property.gpr();
GPRReg valueReg = value.gpr();
- GPRReg storageReg = storage.gpr();
+ GPRReg scratchReg = scratch.gpr();
+ writeBarrier(baseReg, scratchReg);
+
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
Node& baseNode = m_jit.graph()[node.child1];
@@ -907,16 +909,17 @@
MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
// Code to handle put beyond array bounds.
- silentSpillAllRegisters(storageReg, baseReg, propertyReg, valueReg);
+ silentSpillAllRegisters(scratchReg, baseReg, propertyReg, valueReg);
setupStubArguments(baseReg, propertyReg, valueReg);
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
- silentFillAllRegisters(storageReg);
+ silentFillAllRegisters(scratchReg);
JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
withinArrayBounds.link(&m_jit);
// Get the array storage.
+ GPRReg storageReg = scratchReg;
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
// Check if we're writing to a hole; if so increment m_numValuesInVector.
@@ -945,17 +948,20 @@
SpeculateCellOperand base(this, node.child1);
SpeculateStrictInt32Operand property(this, node.child2);
JSValueOperand value(this, node.child3);
- GPRTemporary storage(this, base); // storage may overwrite base.
+ GPRTemporary scratch(this);
+
+ GPRReg baseReg = base.gpr();
+ GPRReg scratchReg = scratch.gpr();
+ writeBarrier(baseReg, scratchReg);
+
// Get the array storage.
- GPRReg storageReg = storage.gpr();
- m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSArray::storageOffset()), storageReg);
+ GPRReg storageReg = scratchReg;
+ m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
- // Map property & value into registers.
+ // Store the value to the array.
GPRReg propertyReg = property.gpr();
GPRReg valueReg = value.gpr();
-
- // Store the value to the array.
m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
noResult(m_compileIndex);
@@ -1048,7 +1054,7 @@
case PutById: {
SpeculateCellOperand base(this, node.child1);
JSValueOperand value(this, node.child2);
- GPRTemporary scratch(this, base);
+ GPRTemporary scratch(this);
cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect);
@@ -1059,7 +1065,7 @@
case PutByIdDirect: {
SpeculateCellOperand base(this, node.child1);
JSValueOperand value(this, node.child2);
- GPRTemporary scratch(this, base);
+ GPRTemporary scratch(this);
cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct);
@@ -1080,12 +1086,19 @@
case PutGlobalVar: {
JSValueOperand value(this, node.child1);
- GPRTemporary temp(this);
+ GPRTemporary globalObject(this);
+ GPRTemporary scratch(this);
+
+ GPRReg globalObjectReg = globalObject.gpr();
+ GPRReg scratchReg = scratch.gpr();
- JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
- m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
- m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+ m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
+ writeBarrier(globalObjectReg, scratchReg);
+
+ m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+ m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
noResult(m_compileIndex);
break;
}
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (90186 => 90187)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2011-07-01 00:10:23 UTC (rev 90187)
@@ -965,7 +965,7 @@
loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
- loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT0);
+ loadPtr(Address(regT0, JSVariableObject::offsetOfRegisters()), regT0);
loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
@@ -992,7 +992,7 @@
emitWriteBarrier(regT1, regT2);
- loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
+ loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
}
@@ -1013,7 +1013,7 @@
emitWriteBarrier(regT1, regT2);
- loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
+ loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
}
@@ -1021,6 +1021,7 @@
{
UNUSED_PARAM(owner);
UNUSED_PARAM(scratch);
+ ASSERT(owner != scratch);
}
#endif // USE(JSVALUE64)
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (90186 => 90187)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2011-07-01 00:10:23 UTC (rev 90187)
@@ -1004,7 +1004,7 @@
loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
- loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+ loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
emitLoad(index, regT1, regT0, regT2);
emitStore(dst, regT1, regT0);
@@ -1035,7 +1035,7 @@
emitWriteBarrier(regT2, regT3);
- loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+ loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
emitStore(index, regT1, regT0, regT2);
map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
}
@@ -1066,7 +1066,7 @@
emitWriteBarrier(regT2, regT3);
- loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+ loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
emitStore(index, regT1, regT0, regT2);
map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
}
@@ -1075,6 +1075,7 @@
{
UNUSED_PARAM(owner);
UNUSED_PARAM(scratch);
+ ASSERT(owner != scratch);
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSVariableObject.h (90186 => 90187)
--- trunk/Source/_javascript_Core/runtime/JSVariableObject.h 2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/runtime/JSVariableObject.h 2011-07-01 00:10:23 UTC (rev 90187)
@@ -57,6 +57,7 @@
WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+ static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{