[JSC] Reduce size of memory used for ShadowChicken
https://bugs.webkit.org/show_bug.cgi?id=193546
Reviewed by Mark Lam.
This patch lazily instantiate ShadowChicken. We do not need this until we start logging ShadowChicken packets.
The removal of ShadowChicken saves 55KB memory.
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::create):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::ensureShadowChickenPacket):
* heap/Heap.cpp:
(JSC::Heap::stopThePeriphery):
(JSC::Heap::addCoreConstraints):
* jit/CCallHelpers.cpp:
(JSC::CCallHelpers::ensureShadowChickenPacket):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_log_shadow_chicken_prologue):
(JSC::JIT::emit_op_log_shadow_chicken_tail):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_log_shadow_chicken_prologue):
(JSC::JIT::emit_op_log_shadow_chicken_tail):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::setDebugger):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::setDebugger): Deleted.
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::ensureShadowChicken):
* runtime/VM.h:
(JSC::VM::shadowChicken):
* tools/JSDollarVM.cpp:
(JSC::functionShadowChickenFunctionsOnStack):
(JSC::changeDebuggerModeWhenIdle):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@240637 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 0857da5..b446191 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,46 @@
+2019-01-28 Yusuke Suzuki <ysuzuki@apple.com>
+
+ [JSC] Reduce size of memory used for ShadowChicken
+ https://bugs.webkit.org/show_bug.cgi?id=193546
+
+ Reviewed by Mark Lam.
+
+ This patch lazily instantiate ShadowChicken. We do not need this until we start logging ShadowChicken packets.
+ The removal of ShadowChicken saves 55KB memory.
+
+ * debugger/DebuggerCallFrame.cpp:
+ (JSC::DebuggerCallFrame::create):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::ensureShadowChickenPacket):
+ * heap/Heap.cpp:
+ (JSC::Heap::stopThePeriphery):
+ (JSC::Heap::addCoreConstraints):
+ * jit/CCallHelpers.cpp:
+ (JSC::CCallHelpers::ensureShadowChickenPacket):
+ * jit/JITExceptions.cpp:
+ (JSC::genericUnwind):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_log_shadow_chicken_prologue):
+ (JSC::JIT::emit_op_log_shadow_chicken_tail):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_log_shadow_chicken_prologue):
+ (JSC::JIT::emit_op_log_shadow_chicken_tail):
+ * jit/JITOperations.cpp:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::setDebugger):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::setDebugger): Deleted.
+ * runtime/VM.cpp:
+ (JSC::VM::VM):
+ (JSC::VM::ensureShadowChicken):
+ * runtime/VM.h:
+ (JSC::VM::shadowChicken):
+ * tools/JSDollarVM.cpp:
+ (JSC::functionShadowChickenFunctionsOnStack):
+ (JSC::changeDebuggerModeWhenIdle):
+
2019-01-28 Andy Estes <aestes@apple.com>
[watchOS] Enable Parental Controls content filtering
diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
index 630f8f0..b30a862 100644
--- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
+++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
@@ -70,7 +70,8 @@
}
Vector<ShadowChicken::Frame> frames;
- vm.shadowChicken().iterate(vm, callFrame, [&] (const ShadowChicken::Frame& frame) -> bool {
+ vm.ensureShadowChicken();
+ vm.shadowChicken()->iterate(vm, callFrame, [&] (const ShadowChicken::Frame& frame) -> bool {
frames.append(frame);
return true;
});
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
index d7618dd..078e12a 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
@@ -13469,16 +13469,18 @@
LValue ensureShadowChickenPacket()
{
+ ShadowChicken* shadowChicken = vm().shadowChicken();
+ RELEASE_ASSERT(shadowChicken);
LBasicBlock slowCase = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
- TypedPointer addressOfLogCursor = m_out.absolute(vm().shadowChicken().addressOfLogCursor());
+ TypedPointer addressOfLogCursor = m_out.absolute(shadowChicken->addressOfLogCursor());
LValue logCursor = m_out.loadPtr(addressOfLogCursor);
ValueFromBlock fastResult = m_out.anchor(logCursor);
m_out.branch(
- m_out.below(logCursor, m_out.constIntPtr(vm().shadowChicken().logEnd())),
+ m_out.below(logCursor, m_out.constIntPtr(shadowChicken->logEnd())),
usually(continuation), rarely(slowCase));
LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index 8da70dd..06ea3b6 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -1588,7 +1588,8 @@
#endif // ENABLE(JIT)
UNUSED_PARAM(conn);
- vm()->shadowChicken().update(*vm(), vm()->topCallFrame);
+ if (auto* shadowChicken = vm()->shadowChicken())
+ shadowChicken->update(*vm(), vm()->topCallFrame);
m_structureIDTable.flushOldTables();
m_objectSpace.stopAllocating();
@@ -2699,7 +2700,8 @@
if (m_vm->typeProfiler())
m_vm->typeProfilerLog()->visit(slotVisitor);
- m_vm->shadowChicken().visitChildren(slotVisitor);
+ if (auto* shadowChicken = m_vm->shadowChicken())
+ shadowChicken->visitChildren(slotVisitor);
},
ConstraintVolatility::GreyedByExecution);
diff --git a/Source/JavaScriptCore/jit/CCallHelpers.cpp b/Source/JavaScriptCore/jit/CCallHelpers.cpp
index 74d740f..de063b9 100644
--- a/Source/JavaScriptCore/jit/CCallHelpers.cpp
+++ b/Source/JavaScriptCore/jit/CCallHelpers.cpp
@@ -54,14 +54,16 @@
void CCallHelpers::ensureShadowChickenPacket(VM& vm, GPRReg shadowPacket, GPRReg scratch1NonArgGPR, GPRReg scratch2)
{
+ ShadowChicken* shadowChicken = vm.shadowChicken();
+ RELEASE_ASSERT(shadowChicken);
ASSERT(!RegisterSet::argumentGPRS().get(scratch1NonArgGPR));
- move(TrustedImmPtr(vm.shadowChicken().addressOfLogCursor()), scratch1NonArgGPR);
+ move(TrustedImmPtr(shadowChicken->addressOfLogCursor()), scratch1NonArgGPR);
loadPtr(Address(scratch1NonArgGPR), shadowPacket);
- Jump ok = branchPtr(Below, shadowPacket, TrustedImmPtr(vm.shadowChicken().logEnd()));
+ Jump ok = branchPtr(Below, shadowPacket, TrustedImmPtr(shadowChicken->logEnd()));
setupArguments<decltype(operationProcessShadowChickenLog)>();
move(TrustedImmPtr(tagCFunctionPtr<OperationPtrTag>(operationProcessShadowChickenLog)), scratch1NonArgGPR);
call(scratch1NonArgGPR, OperationPtrTag);
- move(TrustedImmPtr(vm.shadowChicken().addressOfLogCursor()), scratch1NonArgGPR);
+ move(TrustedImmPtr(shadowChicken->addressOfLogCursor()), scratch1NonArgGPR);
loadPtr(Address(scratch1NonArgGPR), shadowPacket);
ok.link(this);
addPtr(TrustedImm32(sizeof(ShadowChicken::Packet)), shadowPacket, scratch2);
diff --git a/Source/JavaScriptCore/jit/JITExceptions.cpp b/Source/JavaScriptCore/jit/JITExceptions.cpp
index 3aaa87f..7fb225b 100644
--- a/Source/JavaScriptCore/jit/JITExceptions.cpp
+++ b/Source/JavaScriptCore/jit/JITExceptions.cpp
@@ -53,7 +53,8 @@
CRASH();
}
- vm->shadowChicken().log(*vm, topJSCallFrame, ShadowChicken::Packet::throwPacket());
+ if (auto* shadowChicken = vm->shadowChicken())
+ shadowChicken->log(*vm, topJSCallFrame, ShadowChicken::Packet::throwPacket());
Exception* exception = scope.exception();
RELEASE_ASSERT(exception);
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index c4dced9..378dc50 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1460,6 +1460,7 @@
void JIT::emit_op_log_shadow_chicken_prologue(const Instruction* currentInstruction)
{
+ RELEASE_ASSERT(vm()->shadowChicken());
updateTopCallFrame();
static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
auto bytecode = currentInstruction->as<OpLogShadowChickenPrologue>();
@@ -1473,6 +1474,7 @@
void JIT::emit_op_log_shadow_chicken_tail(const Instruction* currentInstruction)
{
+ RELEASE_ASSERT(vm()->shadowChicken());
updateTopCallFrame();
static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
auto bytecode = currentInstruction->as<OpLogShadowChickenTail>();
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 6462f6d..f36cd43 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1335,6 +1335,7 @@
void JIT::emit_op_log_shadow_chicken_prologue(const Instruction* currentInstruction)
{
+ RELEASE_ASSERT(vm()->shadowChicken());
updateTopCallFrame();
static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
auto bytecode = currentInstruction->as<OpLogShadowChickenPrologue>();
@@ -1350,6 +1351,7 @@
void JIT::emit_op_log_shadow_chicken_tail(const Instruction* currentInstruction)
{
+ RELEASE_ASSERT(vm()->shadowChicken());
updateTopCallFrame();
static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
auto bytecode = currentInstruction->as<OpLogShadowChickenTail>();
diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp
index 95bfb81..6292db2 100644
--- a/Source/JavaScriptCore/jit/JITOperations.cpp
+++ b/Source/JavaScriptCore/jit/JITOperations.cpp
@@ -2882,7 +2882,8 @@
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- vm.shadowChicken().update(vm, exec);
+ RELEASE_ASSERT(vm.shadowChicken());
+ vm.shadowChicken()->update(vm, exec);
}
int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(ExecState* exec)
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index 0facee6..0028b13 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -1891,7 +1891,9 @@
auto bytecode = pc->as<OpLogShadowChickenPrologue>();
JSScope* scope = exec->uncheckedR(bytecode.m_scope).Register::scope();
- vm.shadowChicken().log(vm, exec, ShadowChicken::Packet::prologue(exec->jsCallee(), exec, exec->callerFrame(), scope));
+ ShadowChicken* shadowChicken = vm.shadowChicken();
+ RELEASE_ASSERT(shadowChicken);
+ shadowChicken->log(vm, exec, ShadowChicken::Packet::prologue(exec->jsCallee(), exec, exec->callerFrame(), scope));
LLINT_END();
}
@@ -1909,7 +1911,9 @@
#else
CallSiteIndex callSiteIndex(pc);
#endif
- vm.shadowChicken().log(vm, exec, ShadowChicken::Packet::tail(exec, thisValue, scope, exec->codeBlock(), callSiteIndex));
+ ShadowChicken* shadowChicken = vm.shadowChicken();
+ RELEASE_ASSERT(shadowChicken);
+ shadowChicken->log(vm, exec, ShadowChicken::Packet::tail(exec, thisValue, scope, exec->codeBlock(), callSiteIndex));
LLINT_END();
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 676ec0e..019bf9b 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -1897,6 +1897,13 @@
vm().queueMicrotask(*this, WTFMove(task));
}
+void JSGlobalObject::setDebugger(Debugger* debugger)
+{
+ m_debugger = debugger;
+ if (debugger)
+ vm().ensureShadowChicken();
+}
+
bool JSGlobalObject::hasDebugger() const
{
return m_debugger;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 60c2426..c3ab151 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -914,7 +914,7 @@
}
Debugger* debugger() const { return m_debugger; }
- void setDebugger(Debugger* debugger) { m_debugger = debugger; }
+ void setDebugger(Debugger*);
const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp
index 0a640b2..5f4aa78 100644
--- a/Source/JavaScriptCore/runtime/VM.cpp
+++ b/Source/JavaScriptCore/runtime/VM.cpp
@@ -360,7 +360,6 @@
, m_typeProfilerEnabledCount(0)
, m_primitiveGigacageEnabled(IsWatched)
, m_controlFlowProfilerEnabledCount(0)
- , m_shadowChicken(std::make_unique<ShadowChicken>())
{
interpreter = new Interpreter(*this);
StackBounds stack = Thread::current().stack();
@@ -509,6 +508,9 @@
if (!canUseJIT())
noJITValueProfileSingleton = std::make_unique<ValueProfile>(0);
+ if (Options::forceDebuggerBytecodeGeneration() || Options::alwaysUseShadowChicken())
+ ensureShadowChicken();
+
VMInspector::instance().add(this);
}
@@ -1239,6 +1241,13 @@
scratchBuffer->setActiveLength(0);
}
+void VM::ensureShadowChicken()
+{
+ if (m_shadowChicken)
+ return;
+ m_shadowChicken = std::make_unique<ShadowChicken>();
+}
+
JSGlobalObject* VM::vmEntryGlobalObject(const CallFrame* callFrame) const
{
if (callFrame && callFrame->isGlobalExec()) {
diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h
index df5886d..5839e20 100644
--- a/Source/JavaScriptCore/runtime/VM.h
+++ b/Source/JavaScriptCore/runtime/VM.h
@@ -857,7 +857,8 @@
BytecodeIntrinsicRegistry& bytecodeIntrinsicRegistry() { return *m_bytecodeIntrinsicRegistry; }
- ShadowChicken& shadowChicken() { return *m_shadowChicken; }
+ ShadowChicken* shadowChicken() { return m_shadowChicken.get(); }
+ void ensureShadowChicken();
template<typename Func>
void logEvent(CodeBlock*, const char* summary, const Func& func);
diff --git a/Source/JavaScriptCore/tools/JSDollarVM.cpp b/Source/JavaScriptCore/tools/JSDollarVM.cpp
index 53c5c46..ac4e00f 100644
--- a/Source/JavaScriptCore/tools/JSDollarVM.cpp
+++ b/Source/JavaScriptCore/tools/JSDollarVM.cpp
@@ -1932,7 +1932,22 @@
static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
{
VM& vm = exec->vm();
- return JSValue::encode(vm.shadowChicken().functionsOnStack(exec));
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (auto* shadowChicken = vm.shadowChicken())
+ return JSValue::encode(shadowChicken->functionsOnStack(exec));
+
+ JSArray* result = constructEmptyArray(exec, 0);
+ RETURN_IF_EXCEPTION(scope, { });
+ StackVisitor::visit(exec, &vm, [&] (StackVisitor& visitor) -> StackVisitor::Status {
+ if (visitor->isInlinedFrame())
+ return StackVisitor::Continue;
+ if (visitor->isWasmFrame())
+ return StackVisitor::Continue;
+ result->push(exec, jsCast<JSObject*>(visitor->callee().asCell()));
+ scope.releaseAssertNoException(); // This function is only called from tests.
+ return StackVisitor::Continue;
+ });
+ return JSValue::encode(result);
}
static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
@@ -2047,6 +2062,8 @@
vm->whenIdle([=] () {
Options::forceDebuggerBytecodeGeneration() = newDebuggerMode;
vm->deleteAllCode(PreventCollectionAndDeleteAllCode);
+ if (mode == DebuggerMode::DebuggerOn)
+ vm->ensureShadowChicken();
});
return JSValue::encode(jsUndefined());
}