summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/CodeCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/CodeCache.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/CodeCache.cpp184
1 files changed, 89 insertions, 95 deletions
diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp
index 510e383fa..6c1c0c05c 100644
--- a/Source/JavaScriptCore/runtime/CodeCache.cpp
+++ b/Source/JavaScriptCore/runtime/CodeCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,15 +24,9 @@
*/
#include "config.h"
-
#include "CodeCache.h"
-#include "BytecodeGenerator.h"
-#include "CodeSpecializationKind.h"
-#include "Operations.h"
-#include "Parser.h"
-#include "StrongInlines.h"
-#include "UnlinkedCodeBlock.h"
+#include "IndirectEvalExecutable.h"
namespace JSC {
@@ -54,117 +48,117 @@ void CodeCacheMap::pruneSlowCase()
}
}
-CodeCache::CodeCache()
-{
-}
-
-CodeCache::~CodeCache()
-{
-}
-
-template <typename T> struct CacheTypes { };
-
-template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
- typedef JSC::ProgramNode RootNode;
- static const SourceCodeKey::CodeType codeType = SourceCodeKey::ProgramType;
-};
-
-template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
- typedef JSC::EvalNode RootNode;
- static const SourceCodeKey::CodeType codeType = SourceCodeKey::EvalType;
-};
-
template <class UnlinkedCodeBlockType, class ExecutableType>
-UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType)
{
- SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictness);
- CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue());
- bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff;
- if (!addResult.isNewEntry && canCache) {
- UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(addResult.iterator->value.cell.get());
- unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine();
+ DerivedContextType derivedContextType = executable->derivedContextType();
+ bool isArrowFunctionContext = executable->isArrowFunctionContext();
+ SourceCodeKey key(
+ source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictMode, scriptMode,
+ derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode,
+ vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
+ vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+ SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
+ if (cache && Options::useCodeCache()) {
+ UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
unsigned lineCount = unlinkedCodeBlock->lineCount();
- unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn();
+ unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn().oneBasedInt();
bool endColumnIsOnStartLine = !lineCount;
unsigned endColumn = unlinkedCodeBlock->endColumn() + (endColumnIsOnStartLine ? startColumn : 1);
- executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), firstLine, firstLine + lineCount, startColumn, endColumn);
+ executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), source.firstLine().oneBasedInt() + lineCount, endColumn);
+ source.provider()->setSourceURLDirective(unlinkedCodeBlock->sourceURLDirective());
+ source.provider()->setSourceMappingURLDirective(unlinkedCodeBlock->sourceMappingURLDirective());
return unlinkedCodeBlock;
}
+
+ VariableEnvironment variablesUnderTDZ;
+ UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
- typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
- RefPtr<RootNode> rootNode = parse<RootNode>(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error);
- if (!rootNode) {
- m_sourceCode.remove(addResult.iterator);
- return 0;
- }
- unsigned lineCount = rootNode->lastLine() - rootNode->lineNo();
- unsigned startColumn = rootNode->startColumn() + 1;
- bool endColumnIsOnStartLine = !lineCount;
- unsigned unlinkedEndColumn = rootNode->endColumn();
- unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
- executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine(), startColumn, endColumn);
-
- UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo());
- unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), lineCount, unlinkedEndColumn);
-
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, profilerMode)));
- error = generator->generate();
- rootNode->destroyData();
- if (error.m_type != ParserError::ErrorNone) {
- m_sourceCode.remove(addResult.iterator);
- return 0;
- }
-
- if (!canCache) {
- m_sourceCode.remove(addResult.iterator);
- return unlinkedCodeBlock;
- }
+ if (unlinkedCodeBlock && Options::useCodeCache())
+ m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
- addResult.iterator->value = SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age());
return unlinkedCodeBlock;
}
-UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+UnlinkedProgramCodeBlock* CodeCache::getUnlinkedProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error)
{
- return getGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
+ return getUnlinkedGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, strictMode, JSParserScriptMode::Classic, debuggerMode, error, EvalContextType::None);
}
-UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+UnlinkedEvalCodeBlock* CodeCache::getUnlinkedEvalCodeBlock(VM& vm, IndirectEvalExecutable* executable, const SourceCode& source, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType)
{
- return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictness, debuggerMode, profilerMode, error);
+ return getUnlinkedGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictMode, JSParserScriptMode::Classic, debuggerMode, error, evalContextType);
}
-UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error)
+UnlinkedModuleProgramCodeBlock* CodeCache::getUnlinkedModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, DebuggerMode debuggerMode, ParserError& error)
{
- SourceCodeKey key = SourceCodeKey(source, name.string(), SourceCodeKey::FunctionType, JSParseNormal);
- CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue());
- if (!addResult.isNewEntry)
- return jsCast<UnlinkedFunctionExecutable*>(addResult.iterator->value.cell.get());
+ return getUnlinkedGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, JSParserStrictMode::Strict, JSParserScriptMode::Module, debuggerMode, error, EvalContextType::None);
+}
+
+UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, ParserError& error)
+{
+ bool isArrowFunctionContext = false;
+ SourceCodeKey key(
+ source, name.string(), SourceCodeType::FunctionType,
+ JSParserStrictMode::NotStrict,
+ JSParserScriptMode::Classic,
+ DerivedContextType::None,
+ EvalContextType::None,
+ isArrowFunctionContext,
+ debuggerMode,
+ vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
+ vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+ SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
+ if (cache && Options::useCodeCache()) {
+ UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
+ source.provider()->setSourceURLDirective(executable->sourceURLDirective());
+ source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
+ return executable;
+ }
JSTextPosition positionBeforeLastNewline;
- RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline);
+ std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
+ &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin,
+ JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded,
+ error, &positionBeforeLastNewline);
if (!program) {
- ASSERT(error.m_type != ParserError::ErrorNone);
- m_sourceCode.remove(addResult.iterator);
- return 0;
+ RELEASE_ASSERT(error.isValid());
+ return nullptr;
}
- // This function assumes an input string that would result in a single anonymous function expression.
- StatementNode* exprStatement = program->singleStatement();
- ASSERT(exprStatement);
- ASSERT(exprStatement->isExprStatement());
- ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
- ASSERT(funcExpr);
- RELEASE_ASSERT(funcExpr->isFuncExprNode());
- FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
- body->setEndPosition(positionBeforeLastNewline);
- ASSERT(body);
- ASSERT(body->ident().isNull());
-
- UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body, true);
- functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string()));
-
- addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age());
+ // This function assumes an input string that would result in a single function declaration.
+ StatementNode* statement = program->singleStatement();
+ if (UNLIKELY(!statement)) {
+ JSToken token;
+ error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
+ return nullptr;
+ }
+ ASSERT(statement->isBlock());
+
+ StatementNode* funcDecl = static_cast<BlockNode*>(statement)->singleStatement();
+ if (UNLIKELY(!funcDecl)) {
+ JSToken token;
+ error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
+ return nullptr;
+ }
+ ASSERT(funcDecl->isFuncDeclNode());
+
+ FunctionMetadataNode* metadata = static_cast<FuncDeclNode*>(funcDecl)->metadata();
+ ASSERT(metadata);
+ if (!metadata)
+ return nullptr;
+
+ metadata->overrideName(name);
+ metadata->setEndPosition(positionBeforeLastNewline);
+ // The Function constructor only has access to global variables, so no variables will be under TDZ.
+ VariableEnvironment emptyTDZVariables;
+ ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode());
+ UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, emptyTDZVariables, DerivedContextType::None);
+
+ functionExecutable->setSourceURLDirective(source.provider()->sourceURL());
+ functionExecutable->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
+
+ m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age()));
return functionExecutable;
}