Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (161239 => 161240)
--- trunk/Source/_javascript_Core/ChangeLog 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-01-03 00:24:14 UTC (rev 161240)
@@ -1,5 +1,28 @@
2014-01-02 Mark Hahnenberg <mhahnenb...@apple.com>
+ Add support for StoreBarrier and friends to the FTL
+ https://bugs.webkit.org/show_bug.cgi?id=126040
+
+ Reviewed by Filip Pizlo.
+
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLIntrinsicRepository.h:
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileStoreBarrier):
+ (JSC::FTL::LowerDFGToLLVM::compileConditionalStoreBarrier):
+ (JSC::FTL::LowerDFGToLLVM::compileStoreBarrierWithNullCheck):
+ (JSC::FTL::LowerDFGToLLVM::loadMarkByte):
+ (JSC::FTL::LowerDFGToLLVM::emitStoreBarrier):
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ * heap/Heap.h:
+ (JSC::Heap::writeBarrierBuffer):
+
+2014-01-02 Mark Hahnenberg <mhahnenb...@apple.com>
+
Storing new CopiedSpace memory into a JSObject should fire a write barrier
https://bugs.webkit.org/show_bug.cgi?id=126025
Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (161239 => 161240)
--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2014-01-03 00:24:14 UTC (rev 161240)
@@ -37,7 +37,8 @@
#define FOR_EACH_ABSTRACT_HEAP(macro) \
macro(length) \
- macro(typedArrayProperties)
+ macro(typedArrayProperties) \
+ macro(WriteBarrierBuffer_bufferContents)
#define FOR_EACH_ABSTRACT_FIELD(macro) \
macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
@@ -53,6 +54,7 @@
macro(JSString_value, JSString::offsetOfValue()) \
macro(JSVariableObject_registers, JSVariableObject::offsetOfRegisters()) \
macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \
+ macro(MarkedBlock_markBits, MarkedBlock::offsetOfMarks()) \
macro(StringImpl_data, StringImpl::dataOffset()) \
macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \
macro(Structure_classInfo, Structure::classInfoOffset()) \
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (161239 => 161240)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2014-01-03 00:24:14 UTC (rev 161240)
@@ -105,6 +105,9 @@
case TypedArrayWatchpoint:
case VariableWatchpoint:
case NotifyWrite:
+ case StoreBarrier:
+ case ConditionalStoreBarrier:
+ case StoreBarrierWithNullCheck:
case ValueToInt32:
case Branch:
case LogicalNot:
Modified: trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (161239 => 161240)
--- trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h 2014-01-03 00:24:14 UTC (rev 161240)
@@ -71,6 +71,7 @@
macro(V_JITOperation_EJJJ, functionType(voidType, intPtr, int64, int64, int64)) \
macro(V_JITOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \
macro(V_JITOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \
+ macro(V_JITOperation_EC, functionType(voidType, intPtr, intPtr)) \
macro(V_JITOperation_EVws, functionType(voidType, intPtr, intPtr)) \
macro(Z_JITOperation_D, functionType(int32, doubleType))
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (161239 => 161240)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2014-01-03 00:24:14 UTC (rev 161240)
@@ -466,6 +466,15 @@
case Int52ToValue:
compileInt52ToValue();
break;
+ case StoreBarrier:
+ compileStoreBarrier();
+ break;
+ case ConditionalStoreBarrier:
+ compileConditionalStoreBarrier();
+ break;
+ case StoreBarrierWithNullCheck:
+ compileStoreBarrierWithNullCheck();
+ break;
case Flush:
case PhantomLocal:
case SetArgument:
@@ -584,6 +593,34 @@
setJSValue(lowJSValue(m_node->child1()));
}
+ void compileStoreBarrier()
+ {
+ emitStoreBarrier(lowCell(m_node->child1()));
+ }
+
+ void compileConditionalStoreBarrier()
+ {
+ LValue base = lowCell(m_node->child1());
+ LValue value = lowJSValue(m_node->child2());
+ emitStoreBarrier(base, value, m_node->child2());
+ }
+
+ void compileStoreBarrierWithNullCheck()
+ {
+#if ENABLE(GGC)
+ LBasicBlock isNotNull = FTL_NEW_BLOCK(m_out, ("Store barrier with null check value not null"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
+
+ LValue base = lowJSValue(m_node->child1());
+ m_out.branch(m_out.isZero64(base), continuation, isNotNull);
+ LBasicBlock lastNext = m_out.appendTo(isNotNull, continuation);
+ emitStoreBarrier(base);
+ m_out.appendTo(continuation, lastNext);
+#else
+ speculate(m_node->child1());
+#endif
+ }
+
void compileUpsilon()
{
LValue destination = m_phis.get(m_node->phi());
@@ -3947,6 +3984,72 @@
return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
}
+ LValue loadMarkByte(LValue base)
+ {
+ LValue markedBlock = m_out.bitAnd(base, m_out.constInt64(MarkedBlock::blockMask));
+ LValue baseOffset = m_out.bitAnd(base, m_out.constInt64(~MarkedBlock::blockMask));
+ LValue markByteIndex = m_out.lShr(baseOffset, m_out.constInt64(MarkedBlock::atomShiftAmount + MarkedBlock::markByteShiftAmount));
+ return m_out.load8(m_out.baseIndex(m_heaps.MarkedBlock_markBits, markedBlock, markByteIndex, ScaleOne, MarkedBlock::offsetOfMarks()));
+ }
+
+ void emitStoreBarrier(LValue base, LValue value, Edge& valueEdge)
+ {
+#if ENABLE(GGC)
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
+ LBasicBlock isCell = FTL_NEW_BLOCK(m_out, ("Store barrier is cell block"));
+
+ if (m_state.forNode(valueEdge.node()).couldBeType(SpecCell))
+ m_out.branch(isNotCell(value), continuation, isCell);
+ else
+ m_out.jump(isCell);
+
+ LBasicBlock lastNext = m_out.appendTo(isCell, continuation);
+ emitStoreBarrier(base);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+#else
+ UNUSED_PARAM(base);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(valueEdge);
+#endif
+ }
+
+ void emitStoreBarrier(LValue base)
+ {
+#if ENABLE(GGC)
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
+ LBasicBlock isMarked = FTL_NEW_BLOCK(m_out, ("Store barrier is marked block"));
+ LBasicBlock bufferHasSpace = FTL_NEW_BLOCK(m_out, ("Store barrier buffer is full"));
+ LBasicBlock bufferIsFull = FTL_NEW_BLOCK(m_out, ("Store barrier buffer is full"));
+
+ // Check the mark byte.
+ m_out.branch(m_out.isZero8(loadMarkByte(base)), continuation, isMarked);
+
+ // Append to the write barrier buffer.
+ LBasicBlock lastNext = m_out.appendTo(isMarked, bufferHasSpace);
+ LValue currentBufferIndex = m_out.load32(m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex));
+ LValue bufferCapacity = m_out.load32(m_out.absolute(&vm().heap.writeBarrierBuffer().m_capacity));
+ m_out.branch(m_out.lessThan(currentBufferIndex, bufferCapacity), bufferHasSpace, bufferIsFull);
+
+ // Buffer has space, store to it.
+ m_out.appendTo(bufferHasSpace, bufferIsFull);
+ LValue writeBarrierBufferBase = m_out.loadPtr(m_out.absolute(&vm().heap.writeBarrierBuffer().m_buffer));
+ m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExt(currentBufferIndex, m_out.intPtr), ScalePtr));
+ m_out.store32(m_out.add(currentBufferIndex, m_out.constInt32(1)), m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex));
+ m_out.jump(continuation);
+
+ // Buffer is out of space, flush it.
+ m_out.appendTo(bufferIsFull, continuation);
+ vmCall(m_out.operation(operationFlushWriteBarrierBuffer), m_callFrame, base);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+#else
+ UNUSED_PARAM(base);
+#endif
+ }
+
enum ExceptionCheckMode { NoExceptions, CheckExceptions };
LValue vmCall(LValue function, ExceptionCheckMode mode = CheckExceptions)
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (161239 => 161240)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2014-01-03 00:24:14 UTC (rev 161240)
@@ -269,9 +269,7 @@
, m_copyVisitor(m_sharedData)
, m_handleSet(vm)
, m_isSafeToCollect(false)
-#if ENABLE(GGC)
, m_writeBarrierBuffer(128)
-#endif
, m_vm(vm)
, m_lastGCLength(0)
, m_lastCodeDiscardTime(WTF::monotonicallyIncreasingTime())
Modified: trunk/Source/_javascript_Core/heap/Heap.h (161239 => 161240)
--- trunk/Source/_javascript_Core/heap/Heap.h 2014-01-03 00:10:48 UTC (rev 161239)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2014-01-03 00:24:14 UTC (rev 161240)
@@ -100,9 +100,7 @@
static void writeBarrier(const JSCell*, JSCell*);
static uint8_t* addressOfCardFor(JSCell*);
-#if ENABLE(GGC)
WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; }
-#endif
void flushWriteBarrierBuffer(JSCell*);
Heap(VM*, HeapType);
@@ -292,9 +290,7 @@
bool m_isSafeToCollect;
-#if ENABLE(GGC)
WriteBarrierBuffer m_writeBarrierBuffer;
-#endif
VM* m_vm;
double m_lastGCLength;