Commit 72454da3 authored by mhahnenberg@apple.com's avatar mhahnenberg@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):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@161240 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 60344bcb
2014-01-02 Mark Hahnenberg <mhahnenberg@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 <mhahnenberg@apple.com>
Storing new CopiedSpace memory into a JSObject should fire a write barrier
......
......@@ -37,7 +37,8 @@ namespace JSC { namespace FTL {
#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 @@ namespace JSC { namespace FTL {
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()) \
......
......@@ -105,6 +105,9 @@ inline CapabilityLevel canCompile(Node* node)
case TypedArrayWatchpoint:
case VariableWatchpoint:
case NotifyWrite:
case StoreBarrier:
case ConditionalStoreBarrier:
case StoreBarrierWithNullCheck:
case ValueToInt32:
case Branch:
case LogicalNot:
......
......@@ -71,6 +71,7 @@ namespace JSC { namespace FTL {
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))
......
......@@ -466,6 +466,15 @@ private:
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 @@ private:
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 @@ private:
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)
......
......@@ -269,9 +269,7 @@ Heap::Heap(VM* vm, HeapType heapType)
, 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())
......
......@@ -100,9 +100,7 @@ namespace JSC {
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 @@ namespace JSC {
bool m_isSafeToCollect;
#if ENABLE(GGC)
WriteBarrierBuffer m_writeBarrierBuffer;
#endif
VM* m_vm;
double m_lastGCLength;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment