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;
};
}