Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (191839 => 191840)
--- trunk/Source/_javascript_Core/ChangeLog 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-10-31 09:15:35 UTC (rev 191840)
@@ -1,3 +1,36 @@
+2015-10-31 Saam barati <[email protected]>
+
+ JSC should have a forceGCSlowPaths option
+ https://bugs.webkit.org/show_bug.cgi?id=150744
+
+ Reviewed by Filip Pizlo.
+
+ This patch implements the forceGCSlowPaths option.
+ It defaults to false, but when it is set to true,
+ the JITs will always allocate objects along the slow
+ path. This will be helpful for writing a certain class
+ of tests. This may also come in handy for debugging
+ later.
+
+ This patch also adds the "forceGCSlowPaths" function
+ in jsc.cpp which sets the option to true. If you
+ use this function in a jsc stress test, it's best
+ to call it as the first thing in the program before
+ we JIT anything.
+
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::emitAllocateJSCell):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::allocateCell):
+ * jit/JITInlines.h:
+ (JSC::JIT::emitAllocateJSObject):
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionEdenGC):
+ (functionForceGCSlowPaths):
+ (functionHeapSize):
+ * runtime/Options.h:
+
2015-10-30 Joseph Pecoraro <[email protected]>
Web Inspector: Test Debugger.scriptParsed events received after opening inspector frontend
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (191839 => 191840)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-10-31 09:15:35 UTC (rev 191840)
@@ -2282,8 +2282,12 @@
void emitAllocateJSCell(GPRReg resultGPR, GPRReg allocatorGPR, StructureType structure,
GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
{
- m_jit.loadPtr(MacroAssembler::Address(allocatorGPR, MarkedAllocator::offsetOfFreeListHead()), resultGPR);
- slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
+ if (Options::forceGCSlowPaths())
+ slowPath.append(m_jit.jump());
+ else {
+ m_jit.loadPtr(MacroAssembler::Address(allocatorGPR, MarkedAllocator::offsetOfFreeListHead()), resultGPR);
+ slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
+ }
// The object is half-allocated: we have what we know is a fresh object, but
// it's still on the GC's free list.
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (191839 => 191840)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-10-31 09:15:35 UTC (rev 191840)
@@ -6411,18 +6411,25 @@
LValue allocateCell(LValue allocator, LBasicBlock slowPath)
{
LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success"));
+
+ LValue result;
+ LValue condition;
+ if (Options::forceGCSlowPaths()) {
+ result = getUndef(m_out.int64);
+ condition = m_out.booleanFalse;
+ } else {
+ result = m_out.loadPtr(
+ allocator, m_heaps.MarkedAllocator_freeListHead);
+ condition = m_out.notNull(result);
+ }
+ m_out.branch(condition, usually(success), rarely(slowPath));
- LValue result = m_out.loadPtr(
- allocator, m_heaps.MarkedAllocator_freeListHead);
-
- m_out.branch(m_out.notNull(result), usually(success), rarely(slowPath));
-
m_out.appendTo(success);
m_out.storePtr(
m_out.loadPtr(result, m_heaps.JSCell_freeListNext),
allocator, m_heaps.MarkedAllocator_freeListHead);
-
+
return result;
}
Modified: trunk/Source/_javascript_Core/jit/JITInlines.h (191839 => 191840)
--- trunk/Source/_javascript_Core/jit/JITInlines.h 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/jit/JITInlines.h 2015-10-31 09:15:35 UTC (rev 191840)
@@ -880,8 +880,12 @@
template<typename StructureType>
inline void JIT::emitAllocateJSObject(RegisterID allocator, StructureType structure, RegisterID result, RegisterID scratch)
{
- loadPtr(Address(allocator, MarkedAllocator::offsetOfFreeListHead()), result);
- addSlowCase(branchTestPtr(Zero, result));
+ if (Options::forceGCSlowPaths())
+ addSlowCase(jump());
+ else {
+ loadPtr(Address(allocator, MarkedAllocator::offsetOfFreeListHead()), result);
+ addSlowCase(branchTestPtr(Zero, result));
+ }
// remove the object from the free list
loadPtr(Address(result), scratch);
Modified: trunk/Source/_javascript_Core/jsc.cpp (191839 => 191840)
--- trunk/Source/_javascript_Core/jsc.cpp 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/jsc.cpp 2015-10-31 09:15:35 UTC (rev 191840)
@@ -508,6 +508,7 @@
static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
#ifndef NDEBUG
@@ -668,6 +669,7 @@
addFunction(vm, "gc", functionGCAndSweep, 0);
addFunction(vm, "fullGC", functionFullGC, 0);
addFunction(vm, "edenGC", functionEdenGC, 0);
+ addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
addFunction(vm, "gcHeapSize", functionHeapSize, 0);
addFunction(vm, "addressOf", functionAddressOf, 1);
#ifndef NDEBUG
@@ -1186,6 +1188,14 @@
return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
}
+EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
+{
+ // It's best for this to be the first thing called in the
+ // JS program so the option is set to true before we JIT.
+ Options::forceGCSlowPaths() = true;
+ return JSValue::encode(jsUndefined());
+}
+
EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
{
JSLockHolder lock(exec);
Modified: trunk/Source/_javascript_Core/runtime/Options.h (191839 => 191840)
--- trunk/Source/_javascript_Core/runtime/Options.h 2015-10-31 04:58:28 UTC (rev 191839)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2015-10-31 09:15:35 UTC (rev 191840)
@@ -313,6 +313,7 @@
\
v(gcLogLevel, logGC, GCLogging::None, "debugging option to log GC activity (0 = None, 1 = Basic, 2 = Verbose)") \
v(bool, useGC, true, nullptr) \
+ v(bool, forceGCSlowPaths, false, "If true, we will force all JIT fast allocations down their slow paths.")\
v(unsigned, gcMaxHeapSize, 0, nullptr) \
v(unsigned, forceRAMSize, 0, nullptr) \
v(bool, recordGCPauseTimes, false, nullptr) \