[JSC] Use Function / ScopedLambda / RecursableLambda instead of std::function
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Jul 2018 13:10:43 +0000 (13:10 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Jul 2018 13:10:43 +0000 (13:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187472

Reviewed by Mark Lam.

Source/JavaScriptCore:

std::function allocates memory from standard malloc instead of bmalloc. Instead of
using that, we should use WTF::{Function,ScopedLambda,RecursableLambda}.

This patch attempts to replace std::function with the above WTF function types.
If the function's lifetime can be the same to the stack, we can use ScopedLambda, which
is really efficient. Otherwise, we should use WTF::Function.
For recurring use cases, we can use RecursableLambda.

* assembler/MacroAssembler.cpp:
(JSC::stdFunctionCallback):
(JSC::MacroAssembler::probe):
* assembler/MacroAssembler.h:
* b3/air/AirDisassembler.cpp:
(JSC::B3::Air::Disassembler::dump):
* b3/air/AirDisassembler.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::emitEnumeration):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ArrayNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::ForOfNode::emitBytecode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::addSlowPathGeneratorLambda):
(JSC::DFG::SpeculativeJIT::compileMathIC):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValidate.cpp:
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* heap/HeapSnapshotBuilder.cpp:
(JSC::HeapSnapshotBuilder::json):
* heap/HeapSnapshotBuilder.h:
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::dump const):
* interpreter/StackVisitor.h:
* runtime/PromiseDeferredTimer.h:
* runtime/VM.cpp:
(JSC::VM::whenIdle):
(JSC::enableProfilerWithRespectToCount):
(JSC::disableProfilerWithRespectToCount):
* runtime/VM.h:
* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::addDidPopListener):
* runtime/VMEntryScope.h:
* tools/HeapVerifier.cpp:
(JSC::HeapVerifier::verifyCellList):
(JSC::HeapVerifier::validateCell):
(JSC::HeapVerifier::validateJSCell):
* tools/HeapVerifier.h:

Source/WTF:

* wtf/ScopedLambda.h:
(WTF::ScopedLambda<ResultType):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234082 268f45cc-cd09-0410-ab3c-d52691b4dbfc

26 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/MacroAssembler.cpp
Source/JavaScriptCore/assembler/MacroAssembler.h
Source/JavaScriptCore/b3/air/AirDisassembler.cpp
Source/JavaScriptCore/b3/air/AirDisassembler.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLCompile.cpp
Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp
Source/JavaScriptCore/heap/HeapSnapshotBuilder.h
Source/JavaScriptCore/interpreter/StackVisitor.cpp
Source/JavaScriptCore/interpreter/StackVisitor.h
Source/JavaScriptCore/runtime/PromiseDeferredTimer.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/VMEntryScope.cpp
Source/JavaScriptCore/runtime/VMEntryScope.h
Source/JavaScriptCore/tools/HeapVerifier.cpp
Source/JavaScriptCore/tools/HeapVerifier.h
Source/WTF/ChangeLog
Source/WTF/wtf/ScopedLambda.h

index 3727091..e348113 100644 (file)
@@ -1,3 +1,64 @@
+2018-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Use Function / ScopedLambda / RecursableLambda instead of std::function
+        https://bugs.webkit.org/show_bug.cgi?id=187472
+
+        Reviewed by Mark Lam.
+
+        std::function allocates memory from standard malloc instead of bmalloc. Instead of
+        using that, we should use WTF::{Function,ScopedLambda,RecursableLambda}.
+
+        This patch attempts to replace std::function with the above WTF function types.
+        If the function's lifetime can be the same to the stack, we can use ScopedLambda, which
+        is really efficient. Otherwise, we should use WTF::Function.
+        For recurring use cases, we can use RecursableLambda.
+
+        * assembler/MacroAssembler.cpp:
+        (JSC::stdFunctionCallback):
+        (JSC::MacroAssembler::probe):
+        * assembler/MacroAssembler.h:
+        * b3/air/AirDisassembler.cpp:
+        (JSC::B3::Air::Disassembler::dump):
+        * b3/air/AirDisassembler.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::emitEnumeration):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ArrayNode::emitBytecode):
+        (JSC::ApplyFunctionCallDotNode::emitBytecode):
+        (JSC::ForOfNode::emitBytecode):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::addSlowPathGeneratorLambda):
+        (JSC::DFG::SpeculativeJIT::compileMathIC):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGValidate.cpp:
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * heap/HeapSnapshotBuilder.cpp:
+        (JSC::HeapSnapshotBuilder::json):
+        * heap/HeapSnapshotBuilder.h:
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::Frame::dump const):
+        * interpreter/StackVisitor.h:
+        * runtime/PromiseDeferredTimer.h:
+        * runtime/VM.cpp:
+        (JSC::VM::whenIdle):
+        (JSC::enableProfilerWithRespectToCount):
+        (JSC::disableProfilerWithRespectToCount):
+        * runtime/VM.h:
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::addDidPopListener):
+        * runtime/VMEntryScope.h:
+        * tools/HeapVerifier.cpp:
+        (JSC::HeapVerifier::verifyCellList):
+        (JSC::HeapVerifier::validateCell):
+        (JSC::HeapVerifier::validateJSCell):
+        * tools/HeapVerifier.h:
+
 2018-07-20  Michael Saboff  <msaboff@apple.com>
 
         DFG AbstractInterpreter: CheckArray filters array modes for DirectArguments/ScopedArguments using only NonArray
index 208a65d..ecab4d1 100644 (file)
@@ -53,13 +53,13 @@ void MacroAssembler::jitAssert(const ScopedLambda<Jump(void)>& functor)
 #if ENABLE(MASM_PROBE)
 static void stdFunctionCallback(Probe::Context& context)
 {
-    auto func = context.arg<const std::function<void(Probe::Context&)>*>();
+    auto func = context.arg<const Function<void(Probe::Context&)>*>();
     (*func)(context);
 }
     
-void MacroAssembler::probe(std::function<void(Probe::Context&)> func)
+void MacroAssembler::probe(Function<void(Probe::Context&)> func)
 {
-    probe(stdFunctionCallback, new std::function<void(Probe::Context&)>(func));
+    probe(stdFunctionCallback, new Function<void(Probe::Context&)>(WTFMove(func)));
 }
 #endif // ENABLE(MASM_PROBE)
 
index f958156..6a15a86 100644 (file)
@@ -1954,7 +1954,7 @@ public:
     // MacroAssembler.
     void probe(Probe::Function, void* arg);
 
-    JS_EXPORT_PRIVATE void probe(std::function<void(Probe::Context&)>);
+    JS_EXPORT_PRIVATE void probe(Function<void(Probe::Context&)>);
 
     // Let's you print from your JIT generated code.
     // See comments in MacroAssemblerPrinter.h for examples of how to use this.
index e5fe0b5..b641d7a 100644 (file)
@@ -69,7 +69,7 @@ void Disassembler::addInst(Inst* inst, CCallHelpers::Label start, CCallHelpers::
     RELEASE_ASSERT(addResult.isNewEntry);
 }
 
-void Disassembler::dump(Code& code, PrintStream& out, LinkBuffer& linkBuffer, const char* airPrefix, const char* asmPrefix, std::function<void(Inst&)> doToEachInst)
+void Disassembler::dump(Code& code, PrintStream& out, LinkBuffer& linkBuffer, const char* airPrefix, const char* asmPrefix, const ScopedLambda<void(Inst&)>& doToEachInst)
 {
     auto dumpAsmRange = [&] (CCallHelpers::Label startLabel, CCallHelpers::Label endLabel) {
         RELEASE_ASSERT(startLabel.isSet());
index c2690e5..f8a2b68 100644 (file)
@@ -50,7 +50,7 @@ public:
     void startBlock(BasicBlock*, CCallHelpers&);
     void addInst(Inst*, CCallHelpers::Label, CCallHelpers::Label);
 
-    void dump(Code&, PrintStream&, LinkBuffer&, const char* airPrefix, const char* asmPrefix, std::function<void(Inst&)> doToEachInst);
+    void dump(Code&, PrintStream&, LinkBuffer&, const char* airPrefix, const char* asmPrefix, const ScopedLambda<void(Inst&)>& doToEachInst);
 
 private:
     HashMap<Inst*, std::pair<CCallHelpers::Label, CCallHelpers::Label>> m_instToRange;
index af0607b..00afc9f 100644 (file)
@@ -340,7 +340,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
     if (shouldCaptureAllOfTheThings)
         functionNode->varDeclarations().markAllVariablesAsCaptured();
     
-    auto captures = [&] (UniquedStringImpl* uid) -> bool {
+    auto captures = scopedLambda<bool (UniquedStringImpl*)>([&] (UniquedStringImpl* uid) -> bool {
         if (!shouldCaptureSomeOfTheThings)
             return false;
         if (needsArguments && uid == propertyNames().arguments.impl()) {
@@ -351,7 +351,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
             return true;
         }
         return functionNode->captures(uid);
-    };
+    });
     auto varKind = [&] (UniquedStringImpl* uid) -> VarKind {
         return captures(uid) ? VarKind::Scope : VarKind::Stack;
     };
@@ -975,7 +975,7 @@ BytecodeGenerator::~BytecodeGenerator()
 
 void BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack(
     FunctionParameters& parameters, bool isSimpleParameterList, FunctionNode* functionNode, SymbolTable* functionSymbolTable, 
-    int symbolTableConstantIndex, const std::function<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope)
+    int symbolTableConstantIndex, const ScopedLambda<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope)
 {
     Vector<std::pair<Identifier, RefPtr<RegisterID>>> valuesToMoveIntoVars;
     ASSERT(!(isSimpleParameterList && shouldCreateArgumentsVariableInParameterScope));
@@ -4289,7 +4289,7 @@ bool BytecodeGenerator::emitReadOnlyExceptionIfNeeded(const Variable& variable)
     return false;
 }
 
-void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
+void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const ScopedLambda<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
 {
     bool isForAwait = forLoopNode ? forLoopNode->isForAwait() : false;
     ASSERT(!isForAwait || (isForAwait && isAsyncFunctionParseMode(parseMode())));
index 35957d8..8ac6bc1 100644 (file)
@@ -748,7 +748,7 @@ namespace JSC {
         void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
             RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
 
-        void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
+        void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const ScopedLambda<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
 
         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
         RegisterID* emitGetGlobalPrivate(RegisterID* dst, const Identifier& property);
@@ -1109,7 +1109,7 @@ namespace JSC {
 
         void initializeParameters(FunctionParameters&);
         void initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables);
-        void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, bool isSimpleParameterList, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope);
+        void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, bool isSimpleParameterList, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const ScopedLambda<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope);
         void initializeArrowFunctionContextScopeIfNeeded(SymbolTable* functionSymbolTable = nullptr, bool canReuseLexicalEnvironment = false);
         bool needsDerivedConstructorInArrowFunctionLexicalEnvironment();
 
index 88670a6..366964f 100644 (file)
@@ -457,11 +457,11 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
     
 handleSpread:
     RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
-    auto spreader = [array, index](BytecodeGenerator& generator, RegisterID* value)
+    auto spreader = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([array, index](BytecodeGenerator& generator, RegisterID* value)
     {
         generator.emitDirectPutByVal(array.get(), index.get(), value);
         generator.emitInc(index.get());
-    };
+    });
     for (; n; n = n->next()) {
         if (n->elision())
             generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
@@ -1455,7 +1455,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
                 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
                 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
                 
-                auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
+                auto extractor = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
                 {
                     Ref<Label> haveThis = generator.newLabel();
                     Ref<Label> end = generator.newLabel();
@@ -1471,7 +1471,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
                     generator.move(argumentsRegister.get(), value);
                     generator.emitLoad(index.get(), jsNumber(2));
                     generator.emitLabel(end.get());
-                };
+                });
                 generator.emitEnumeration(this, spread->expression(), extractor);
                 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
             } else if (m_args->m_listNode->m_next) {
@@ -3216,7 +3216,7 @@ void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
     RegisterID* forLoopSymbolTable = nullptr;
     generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
-    auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
+    auto extractor = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([this, dst](BytecodeGenerator& generator, RegisterID* value)
     {
         if (m_lexpr->isResolveNode()) {
             const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
@@ -3267,7 +3267,7 @@ void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
         }
         generator.emitProfileControlFlow(m_statement->startOffset());
         generator.emitNode(dst, m_statement);
-    };
+    });
     generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
     generator.popLexicalScope(this);
     generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
index 89af173..b845f40 100644 (file)
@@ -388,9 +388,9 @@ void SpeculativeJIT::addSlowPathGenerator(std::unique_ptr<SlowPathGenerator> slo
     m_slowPathGenerators.append(WTFMove(slowPathGenerator));
 }
 
-void SpeculativeJIT::addSlowPathGenerator(std::function<void()> lambda)
+void SpeculativeJIT::addSlowPathGeneratorLambda(Function<void()>&& lambda)
 {
-    m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast<unsigned>(m_stream->size()) });
+    m_slowPathLambdas.append(SlowPathLambda{ WTFMove(lambda), m_currentNode, static_cast<unsigned>(m_stream->size()) });
 }
 
 void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder& pcToCodeOriginMapBuilder)
@@ -3900,7 +3900,7 @@ void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathI
 
         auto done = m_jit.label();
 
-        addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () {
+        addSlowPathGeneratorLambda([=, savePlans = WTFMove(savePlans)] () {
             addICGenerationState->slowPathJumps.link(&m_jit);
             addICGenerationState->slowPathStart = m_jit.label();
 #if ENABLE(MATH_IC_STATS)
@@ -4608,7 +4608,7 @@ void SpeculativeJIT::compileMathIC(Node* node, JITUnaryMathIC<Generator>* mathIC
 
         auto done = m_jit.label();
 
-        addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () {
+        addSlowPathGeneratorLambda([=, savePlans = WTFMove(savePlans)] () {
             icGenerationState->slowPathJumps.link(&m_jit);
             icGenerationState->slowPathStart = m_jit.label();
 #if ENABLE(MATH_IC_STATS)
index ae7fe8b..65be2d1 100644 (file)
@@ -356,7 +356,7 @@ public:
     GeneratedOperandType checkGeneratedTypeForToInt32(Node*);
 
     void addSlowPathGenerator(std::unique_ptr<SlowPathGenerator>);
-    void addSlowPathGenerator(std::function<void()>);
+    void addSlowPathGeneratorLambda(Function<void()>&&);
     void runSlowPathGenerators(PCToCodeOriginMapBuilder&);
     
     void compile(Node*);
@@ -1720,7 +1720,7 @@ public:
     
     Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
     struct SlowPathLambda {
-        std::function<void()> generator;
+        Function<void()> generator;
         Node* currentNode;
         unsigned streamIndex;
     };
index b82370f..5792594 100644 (file)
@@ -4565,7 +4565,7 @@ void SpeculativeJIT::compile(Node* node)
         silentSpillAllRegistersImpl(false, savePlans, InvalidGPRReg);
         unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex;
 
-        addSlowPathGenerator([=]() {
+        addSlowPathGeneratorLambda([=]() {
             callTierUp.link(&m_jit);
 
             silentSpill(savePlans);
@@ -4617,7 +4617,7 @@ void SpeculativeJIT::compile(Node* node)
         unsigned streamIndex = m_stream->size();
         m_jit.jitCode()->bytecodeIndexToStreamIndex.add(bytecodeIndex, streamIndex);
 
-        addSlowPathGenerator([=]() {
+        addSlowPathGeneratorLambda([=]() {
             forceOSREntry.link(&m_jit);
             overflowedCounter.link(&m_jit);
 
index 7aa871a..20cf75c 100644 (file)
@@ -377,8 +377,8 @@ public:
 
         // Validate clobbered states.
         struct DefLambdaAdaptor {
-            std::function<void(PureValue)> pureValue;
-            std::function<void(HeapLocation, LazyNode)> locationAndNode;
+            Function<void(PureValue)> pureValue;
+            Function<void(HeapLocation, LazyNode)> locationAndNode;
 
             void operator()(PureValue value) const
             {
index a55e5b6..ca87da3 100644 (file)
@@ -48,7 +48,7 @@
 #include "LinkBuffer.h"
 #include "PCToCodeOriginMap.h"
 #include "ScratchRegisterAllocator.h"
-#include <wtf/Function.h>
+#include <wtf/RecursableLambda.h>
 
 namespace JSC { namespace FTL {
 
@@ -215,25 +215,25 @@ void compile(State& state, Safepoint::Result& safepointResult)
             printDFGNode(bitwise_cast<Node*>(value->origin().data()));
 
             HashSet<B3::Value*> localPrintedValues;
-            WTF::Function<void(B3::Value*)> printValueRecursive = [&] (B3::Value* value) {
+            auto printValueRecursive = recursableLambda([&] (auto self, B3::Value* value) -> void {
                 if (printedValues.contains(value) || localPrintedValues.contains(value))
                     return;
 
                 localPrintedValues.add(value);
                 for (unsigned i = 0; i < value->numChildren(); i++)
-                    printValueRecursive(value->child(i));
+                    self(value->child(i));
                 out.print(b3Prefix);
                 value->deepDump(state.proc.get(), out);
                 out.print("\n");
-            };
+            });
 
             printValueRecursive(currentB3Value);
             printedValues.add(value);
         };
 
-        auto forEachInst = [&] (B3::Air::Inst& inst) {
+        auto forEachInst = scopedLambda<void(B3::Air::Inst&)>([&] (B3::Air::Inst& inst) {
             printB3Value(inst.origin);
-        };
+        });
 
         disassembler->dump(state.proc->code(), out, linkBuffer, airPrefix, asmPrefix, forEachInst);
         linkBuffer.didAlreadyDisassemble();
index 4d46eaf..624935a 100644 (file)
@@ -199,7 +199,7 @@ String HeapSnapshotBuilder::json()
     return json([] (const HeapSnapshotNode&) { return true; });
 }
 
-String HeapSnapshotBuilder::json(std::function<bool (const HeapSnapshotNode&)> allowNodeCallback)
+String HeapSnapshotBuilder::json(Function<bool (const HeapSnapshotNode&)> allowNodeCallback)
 {
     VM& vm = m_profiler.vm();
     DeferGCForAWhile deferGC(vm.heap);
index 0ed85d1..ae7f0bd 100644 (file)
@@ -121,7 +121,7 @@ public:
     void appendIndexEdge(JSCell* from, JSCell* to, uint32_t index);
 
     String json();
-    String json(std::function<bool (const HeapSnapshotNode&)> allowNodeCallback);
+    String json(Function<bool (const HeapSnapshotNode&)> allowNodeCallback);
 
 private:
     // Finalized snapshots are not modified during building. So searching them
index 134f42f..cae3d9a 100644 (file)
@@ -426,7 +426,7 @@ void StackVisitor::Frame::dump(PrintStream& out, Indenter indent) const
     dump(out, indent, [] (PrintStream&) { });
 }
 
-void StackVisitor::Frame::dump(PrintStream& out, Indenter indent, std::function<void(PrintStream&)> prefix) const
+void StackVisitor::Frame::dump(PrintStream& out, Indenter indent, WTF::Function<void(PrintStream&)> prefix) const
 {
     if (!this->callFrame()) {
         out.print(indent, "frame 0x0\n");
index 4755a93..6bf8331 100644 (file)
@@ -28,7 +28,7 @@
 #include "CalleeBits.h"
 #include "VMEntryRecord.h"
 #include "WasmIndexOrName.h"
-#include <functional>
+#include <wtf/Function.h>
 #include <wtf/Indenter.h>
 #include <wtf/text/WTFString.h>
 
@@ -100,7 +100,7 @@ public:
         CallFrame* callFrame() const { return m_callFrame; }
         
         void dump(PrintStream&, Indenter = Indenter()) const;
-        void dump(PrintStream&, Indenter, std::function<void(PrintStream&)> prefix) const;
+        void dump(PrintStream&, Indenter, WTF::Function<void(PrintStream&)> prefix) const;
 
     private:
         Frame() { }
index 6c0542c..615b087 100644 (file)
@@ -52,7 +52,7 @@ public:
     // JSPromiseDeferred should handle canceling when the promise is resolved or rejected.
     bool cancelPendingPromise(JSPromiseDeferred*);
 
-    typedef std::function<void()> Task;
+    using Task = Function<void()>;
     void scheduleWorkSoon(JSPromiseDeferred*, Task&&);
 
     void stopRunningTasks() { m_runTasks = false; }
index 24b9f60..3371282 100644 (file)
@@ -753,14 +753,14 @@ void VM::resetDateCache()
     dateInstanceCache.reset();
 }
 
-void VM::whenIdle(std::function<void()> callback)
+void VM::whenIdle(Function<void()>&& callback)
 {
     if (!entryScope) {
         callback();
         return;
     }
 
-    entryScope->addDidPopListener(callback);
+    entryScope->addDidPopListener(WTFMove(callback));
 }
 
 void VM::deleteAllLinkedCode(DeleteAllCodeEffort effort)
@@ -1023,7 +1023,8 @@ void VM::addImpureProperty(const String& propertyName)
         watchpointSet->fireAll(*this, "Impure property added");
 }
 
-static bool enableProfilerWithRespectToCount(unsigned& counter, std::function<void()> doEnableWork)
+template<typename Func>
+static bool enableProfilerWithRespectToCount(unsigned& counter, const Func& doEnableWork)
 {
     bool needsToRecompile = false;
     if (!counter) {
@@ -1035,7 +1036,8 @@ static bool enableProfilerWithRespectToCount(unsigned& counter, std::function<vo
     return needsToRecompile;
 }
 
-static bool disableProfilerWithRespectToCount(unsigned& counter, std::function<void()> doDisableWork)
+template<typename Func>
+static bool disableProfilerWithRespectToCount(unsigned& counter, const Func& doDisableWork)
 {
     RELEASE_ASSERT(counter > 0);
     bool needsToRecompile = false;
index eb1ae65..187c0fc 100644 (file)
@@ -796,7 +796,7 @@ public:
     JSLock& apiLock() { return *m_apiLock; }
     CodeCache* codeCache() { return m_codeCache.get(); }
 
-    JS_EXPORT_PRIVATE void whenIdle(std::function<void()>);
+    JS_EXPORT_PRIVATE void whenIdle(Function<void()>&&);
 
     JS_EXPORT_PRIVATE void deleteAllCode(DeleteAllCodeEffort);
     JS_EXPORT_PRIVATE void deleteAllLinkedCode(DeleteAllCodeEffort);
index 58da684..fbc2de3 100644 (file)
@@ -64,9 +64,9 @@ VMEntryScope::VMEntryScope(VM& vm, JSGlobalObject* globalObject)
     vm.clearLastException();
 }
 
-void VMEntryScope::addDidPopListener(std::function<void ()> listener)
+void VMEntryScope::addDidPopListener(Function<void ()>&& listener)
 {
-    m_didPopListeners.append(listener);
+    m_didPopListeners.append(WTFMove(listener));
 }
 
 VMEntryScope::~VMEntryScope()
index c2971f6..aeef21b 100644 (file)
@@ -41,12 +41,12 @@ public:
     VM& vm() const { return m_vm; }
     JSGlobalObject* globalObject() const { return m_globalObject; }
 
-    void addDidPopListener(std::function<void ()>);
+    void addDidPopListener(Function<void ()>&&);
 
 private:
     VM& m_vm;
     JSGlobalObject* m_globalObject;
-    Vector<std::function<void ()>> m_didPopListeners;
+    Vector<Function<void ()>> m_didPopListeners;
 };
 
 } // namespace JSC
index 2990ff7..b59531f 100644 (file)
@@ -153,7 +153,7 @@ bool HeapVerifier::verifyCellList(Phase phase, CellList& list)
     auto& liveCells = list.cells();
 
     bool listNamePrinted = false;
-    auto printHeaderIfNeeded = [&] () {
+    auto printHeaderIfNeeded = scopedLambda<void()>([&] () {
         if (listNamePrinted)
             return;
         
@@ -161,7 +161,7 @@ bool HeapVerifier::verifyCellList(Phase phase, CellList& list)
         dataLog(" @ phase ", phaseName(phase), ": FAILED in cell list '", list.name(), "' (size ", liveCells.size(), ")\n");
         listNamePrinted = true;
         m_didPrintLogs = true;
-    };
+    });
     
     bool success = true;
     for (size_t i = 0; i < liveCells.size(); i++) {
@@ -181,7 +181,7 @@ bool HeapVerifier::verifyCellList(Phase phase, CellList& list)
 
 bool HeapVerifier::validateCell(HeapCell* cell, VM* expectedVM)
 {
-    auto printNothing = [] () { };
+    auto printNothing = scopedLambda<void()>([] () { });
 
     if (cell->isZapped()) {
         dataLog("    cell ", RawPointer(cell), " is ZAPPED\n");
@@ -195,9 +195,9 @@ bool HeapVerifier::validateCell(HeapCell* cell, VM* expectedVM)
     return validateJSCell(expectedVM, jsCell, nullptr, nullptr, printNothing);
 }
 
-bool HeapVerifier::validateJSCell(VM* expectedVM, JSCell* cell, CellProfile* profile, CellList* list, std::function<void()> printHeaderIfNeeded, const char* prefix)
+bool HeapVerifier::validateJSCell(VM* expectedVM, JSCell* cell, CellProfile* profile, CellList* list, const ScopedLambda<void()>& printHeaderIfNeeded, const char* prefix)
 {
-    auto printHeaderAndCell = [cell, profile, printHeaderIfNeeded, prefix] () {
+    auto printHeaderAndCell = [cell, profile, &printHeaderIfNeeded, prefix] () {
         printHeaderIfNeeded();
         dataLog(prefix, "cell ", RawPointer(cell));
         if (profile)
index cc201c4..456678e 100644 (file)
@@ -28,6 +28,7 @@
 #include "CellList.h"
 #include "Heap.h"
 #include <wtf/MonotonicTime.h>
+#include <wtf/ScopedLambda.h>
 #include <wtf/UniqueArray.h>
 
 namespace JSC {
@@ -99,7 +100,7 @@ private:
 
     CellList* cellListForGathering(Phase);
     bool verifyCellList(Phase, CellList&);
-    static bool validateJSCell(VM* expectedVM, JSCell*, CellProfile*, CellList*, std::function<void()> printHeaderIfNeeded, const char* prefix = "");
+    static bool validateJSCell(VM* expectedVM, JSCell*, CellProfile*, CellList*, const ScopedLambda<void()>& printHeaderIfNeeded, const char* prefix = "");
 
     void printVerificationHeader();
 
index 553f74e..6084c84 100644 (file)
@@ -1,3 +1,13 @@
+2018-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Use Function / ScopedLambda / RecursableLambda instead of std::function
+        https://bugs.webkit.org/show_bug.cgi?id=187472
+
+        Reviewed by Mark Lam.
+
+        * wtf/ScopedLambda.h:
+        (WTF::ScopedLambda<ResultType):
+
 2018-07-18  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Switch CMake ports back to C++ 14
index 69fce40..3cb2df4 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef ScopedLambda_h
 #define ScopedLambda_h
 
+#include <wtf/ForbidHeapAllocation.h>
+
 namespace WTF {
 
 // You can use ScopedLambda to efficiently pass lambdas without allocating memory or requiring
@@ -43,6 +45,7 @@ namespace WTF {
 template<typename FunctionType> class ScopedLambda;
 template<typename ResultType, typename... ArgumentTypes>
 class ScopedLambda<ResultType (ArgumentTypes...)> {
+    WTF_FORBID_HEAP_ALLOCATION;
 public:
     ScopedLambda(ResultType (*impl)(void* arg, ArgumentTypes...) = nullptr, void* arg = nullptr)
         : m_impl(impl)