Title: [136261] trunk/Source/_javascript_Core
Revision
136261
Author
[email protected]
Date
2012-11-30 13:09:21 -0800 (Fri, 30 Nov 2012)

Log Message

Add direct string->function code cache
https://bugs.webkit.org/show_bug.cgi?id=103764

Reviewed by Michael Saboff.

A fairly logically simple patch.  We now track the start of the
unique portion of a functions body, and use that as our key for
unlinked function code.  This allows us to cache identical code
in different contexts, leading to a small but consistent improvement
on the benchmarks we track.

* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedFunctionExecutable::functionStartOffset):
(UnlinkedFunctionExecutable):
* parser/ASTBuilder.h:
(ASTBuilder):
(JSC::ASTBuilder::setFunctionStart):
* parser/Nodes.cpp:
* parser/Nodes.h:
(JSC::FunctionBodyNode::setFunctionStart):
(JSC::FunctionBodyNode::functionStart):
(FunctionBodyNode):
* parser/Parser.cpp:
(JSC::::parseFunctionInfo):
* parser/Parser.h:
(JSC::Parser::findCachedFunctionInfo):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::setFunctionStart):
* runtime/CodeCache.cpp:
(JSC::CodeCache::generateFunctionCodeBlock):
(JSC::CodeCache::getFunctionCodeBlock):
(JSC::CodeCache::usedFunctionCode):
* runtime/CodeCache.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (136260 => 136261)


--- trunk/Source/_javascript_Core/ChangeLog	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-11-30 21:09:21 UTC (rev 136261)
@@ -1,3 +1,41 @@
+2012-11-30  Oliver Hunt  <[email protected]>
+
+        Add direct string->function code cache
+        https://bugs.webkit.org/show_bug.cgi?id=103764
+
+        Reviewed by Michael Saboff.
+
+        A fairly logically simple patch.  We now track the start of the
+        unique portion of a functions body, and use that as our key for
+        unlinked function code.  This allows us to cache identical code
+        in different contexts, leading to a small but consistent improvement
+        on the benchmarks we track.
+
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedFunctionExecutable::functionStartOffset):
+        (UnlinkedFunctionExecutable):
+        * parser/ASTBuilder.h:
+        (ASTBuilder):
+        (JSC::ASTBuilder::setFunctionStart):
+        * parser/Nodes.cpp:
+        * parser/Nodes.h:
+        (JSC::FunctionBodyNode::setFunctionStart):
+        (JSC::FunctionBodyNode::functionStart):
+        (FunctionBodyNode):
+        * parser/Parser.cpp:
+        (JSC::::parseFunctionInfo):
+        * parser/Parser.h:
+        (JSC::Parser::findCachedFunctionInfo):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::setFunctionStart):
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::generateFunctionCodeBlock):
+        (JSC::CodeCache::getFunctionCodeBlock):
+        (JSC::CodeCache::usedFunctionCode):
+        * runtime/CodeCache.h:
+
 2012-11-30  Allan Sandfeld Jensen  <[email protected]>
 
         Crash in conversion of empty OpaqueJSString to Identifier 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (136260 => 136261)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2012-11-30 21:09:21 UTC (rev 136261)
@@ -66,6 +66,7 @@
     , m_parameters(node->parameters())
     , m_firstLineOffset(node->firstLine() - source.firstLine())
     , m_lineCount(node->lastLine() - node->firstLine())
+    , m_functionStartOffset(node->functionStart() - source.startOffset())
     , m_startOffset(node->source().startOffset() - source.startOffset())
     , m_sourceLength(node->source().length())
     , m_features(node->features())

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (136260 => 136261)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -98,6 +98,7 @@
 
     unsigned firstLineOffset() const { return m_firstLineOffset; }
     unsigned lineCount() const { return m_lineCount; }
+    unsigned functionStartOffset() const { return m_functionStartOffset; }
     unsigned startOffset() const { return m_startOffset; }
     unsigned sourceLength() { return m_sourceLength; }
 
@@ -153,6 +154,7 @@
     RefPtr<FunctionParameters> m_parameters;
     unsigned m_firstLineOffset;
     unsigned m_lineCount;
+    unsigned m_functionStartOffset;
     unsigned m_startOffset;
     unsigned m_sourceLength;
 

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -267,6 +267,11 @@
     {
         return FunctionBodyNode::create(m_globalData, location, inStrictContext);
     }
+
+    void setFunctionStart(FunctionBodyNode* body, int functionStart)
+    {
+        body->setFunctionStart(functionStart);
+    }
     
     template <bool> PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
     {

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2012-11-30 21:09:21 UTC (rev 136261)
@@ -41,6 +41,7 @@
 #include "PropertyNameArray.h"
 #include "RegExpObject.h"
 #include "SamplingTool.h"
+#include "SourceProviderCacheItem.h"
 #include <wtf/Assertions.h>
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/Threading.h>

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -46,6 +46,7 @@
     class RegisterID;
     class JSScope;
     class ScopeNode;
+    class SourceProviderCacheItem;
 
     typedef unsigned CodeFeatures;
 
@@ -1424,6 +1425,9 @@
         bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; }
         FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; }
 
+        void setFunctionStart(int functionStart) { m_functionStart = functionStart; }
+        int functionStart() const { return m_functionStart; }
+
         static const bool scopeIsFunction = true;
 
     private:
@@ -1434,6 +1438,7 @@
         Identifier m_inferredName;
         FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
         RefPtr<FunctionParameters> m_parameters;
+        int m_functionStart;
     };
 
     class FuncExprNode : public ExpressionNode {

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2012-11-30 21:09:21 UTC (rev 136261)
@@ -842,6 +842,7 @@
         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
         
         closeBracePos = cachedInfo->closeBracePos;
+        context.setFunctionStart(body, functionStart);
         m_token = cachedInfo->closeBraceToken();
         m_lexer->setOffset(m_token.m_location.endOffset);
         m_lexer->setLineNumber(m_token.m_location.line);
@@ -869,7 +870,8 @@
         newInfo = adoptPtr(new SourceProviderCacheItem(functionStart, m_token.m_location.line, closeBracePos));
         functionScope->saveFunctionInfo(newInfo.get());
     }
-    
+    context.setFunctionStart(body, functionStart);
+
     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
     matchOrFail(CLOSEBRACE);
     

Modified: trunk/Source/_javascript_Core/parser/Parser.h (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/Parser.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -509,7 +509,7 @@
     
     ScopeStack m_scopeStack;
     
-    const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) 
+    const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos)
     {
         return m_functionCache ? m_functionCache->get(openBracePos) : 0;
     }

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (136260 => 136261)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -151,6 +151,7 @@
     ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int) { return FunctionExpr; }
     int createFunctionBody(const JSTokenLocation&, bool) { return 1; }
+    void setFunctionStart(int, int) { }
     int createArguments() { return 1; }
     int createArguments(int) { return 1; }
     int createArgumentsList(const JSTokenLocation&, int) { return 1; }

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (136260 => 136261)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2012-11-30 21:09:21 UTC (rev 136261)
@@ -126,13 +126,29 @@
     body->destroyData();
     if (error.m_type != ParserError::ErrorNone)
         return 0;
-    m_cachedFunctionCode.add(result, Strong<UnlinkedFunctionCodeBlock>(globalData, result));
+    m_recentlyUsedFunctionCode.add(result, Strong<UnlinkedFunctionCodeBlock>(globalData, result));
     return result;
 }
 
 UnlinkedFunctionCodeBlock* CodeCache::getFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
 {
-    return generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error);
+    if (debuggerMode == DebuggerOn || profilerMode == ProfilerOn)
+        return generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error);
+
+    SourceCode functionSource(source.provider(), executable->functionStartOffset(), source.endOffset(), source.firstLine());
+    CodeBlockKey key = makeCodeBlockKey(functionSource, kind == CodeForCall ? FunctionCallType : FunctionConstructType, executable->isInStrictContext() ? JSParseStrict : JSParseNormal);
+    if (const Strong<UnlinkedFunctionCodeBlock>* cacheEntry = m_cachedFunctionExecutables.find(key)) {
+        if (cacheEntry) {
+            UnlinkedFunctionCodeBlock* unlinkedCode = cacheEntry->get();
+            unsigned firstLine = source.firstLine() + unlinkedCode->firstLine();
+            executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount());
+            m_recentlyUsedFunctionCode.add(unlinkedCode, *cacheEntry);
+            return unlinkedCode;
+        }
+    }
+    UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error);
+    m_cachedFunctionExecutables.add(key, Strong<UnlinkedFunctionCodeBlock>(globalData, result));
+    return result;
 }
 
 CodeCache::GlobalFunctionKey CodeCache::makeGlobalFunctionKey(const SourceCode& source, const String& name)
@@ -173,7 +189,7 @@
 
 void CodeCache::usedFunctionCode(JSGlobalData& globalData, UnlinkedFunctionCodeBlock* codeBlock)
 {
-    m_cachedFunctionCode.add(codeBlock, Strong<UnlinkedFunctionCodeBlock>(globalData, codeBlock));
+    m_recentlyUsedFunctionCode.add(codeBlock, Strong<UnlinkedFunctionCodeBlock>(globalData, codeBlock));
 }
 
 }

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.h (136260 => 136261)


--- trunk/Source/_javascript_Core/runtime/CodeCache.h	2012-11-30 20:49:09 UTC (rev 136260)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.h	2012-11-30 21:09:21 UTC (rev 136261)
@@ -40,6 +40,7 @@
 namespace JSC {
 
 class EvalExecutable;
+class FunctionBodyNode;
 class Identifier;
 class ProgramExecutable;
 class UnlinkedCodeBlock;
@@ -98,7 +99,7 @@
     void usedFunctionCode(JSGlobalData&, UnlinkedFunctionCodeBlock*);
     ~CodeCache();
 
-    enum CodeType { EvalType, ProgramType, FunctionType };
+    enum CodeType { EvalType, ProgramType, FunctionCallType, FunctionConstructType };
     typedef std::pair<String, unsigned> CodeBlockKey;
     typedef std::pair<String, String> GlobalFunctionKey;
 
@@ -118,8 +119,9 @@
     };
 
     CacheMap<CodeBlockKey, Strong<UnlinkedCodeBlock>, kMaxCodeBlockEntries> m_cachedCodeBlocks;
-    CacheMap<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions;
-    CacheMap<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_cachedFunctionCode;
+    CacheMap<CodeBlockKey, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_cachedFunctionExecutables;
+    CacheMap<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxFunctionCodeBlocks> m_cachedGlobalFunctions;
+    CacheMap<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_recentlyUsedFunctionCode;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to