X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/81345200c95645a1b0d2635520f96ad55dfde63f..HEAD:/runtime/CodeCache.cpp diff --git a/runtime/CodeCache.cpp b/runtime/CodeCache.cpp index 442835b..298efc6 100644 --- a/runtime/CodeCache.cpp +++ b/runtime/CodeCache.cpp @@ -75,13 +75,14 @@ template <> struct CacheTypes { }; template -UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, + JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes::codeType, strictness); - CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); - bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff; - if (!addResult.isNewEntry && canCache) { - UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast(addResult.iterator->value.cell.get()); + SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes::codeType, builtinMode, strictMode, thisTDZMode); + SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); + bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff && !vm.typeProfiler() && !vm.controlFlowProfiler(); + if (cache && canCache) { + UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast(cache->cell.get()); unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine(); unsigned lineCount = unlinkedCodeBlock->lineCount(); unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn(); @@ -92,81 +93,88 @@ UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* exe } typedef typename CacheTypes::RootNode RootNode; - RefPtr rootNode = parse(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error); - if (!rootNode) { - m_sourceCode.remove(addResult.iterator); - return 0; - } - unsigned lineCount = rootNode->lastLine() - rootNode->lineNo(); + std::unique_ptr rootNode = parse( + &vm, source, 0, Identifier(), builtinMode, strictMode, + JSParserCodeType::Program, error, 0, ConstructorKind::None, thisTDZMode); + if (!rootNode) + return nullptr; + + unsigned lineCount = rootNode->lastLine() - rootNode->firstLine(); 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); + executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->firstLine(), rootNode->lastLine(), startColumn, endColumn); UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo()); - unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), lineCount, unlinkedEndColumn); + unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->firstLine() - source.firstLine(), lineCount, unlinkedEndColumn); - OwnPtr generator(adoptPtr(new BytecodeGenerator(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, profilerMode))); + auto generator = std::make_unique(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 (error.isValid()) + return nullptr; - if (!canCache) { - m_sourceCode.remove(addResult.iterator); + if (!canCache) return unlinkedCodeBlock; - } - addResult.iterator->value = SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()); + m_sourceCode.addCache(key, 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::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return getGlobalCodeBlock(vm, executable, source, strictness, debuggerMode, profilerMode, error); + return getGlobalCodeBlock(vm, executable, source, builtinMode, strictMode, ThisTDZMode::CheckIfNeeded, debuggerMode, profilerMode, error); } -UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return getGlobalCodeBlock(vm, executable, source, strictness, debuggerMode, profilerMode, error); + return getGlobalCodeBlock(vm, executable, source, builtinMode, strictMode, thisTDZMode, debuggerMode, profilerMode, error); } +// FIXME: There's no need to add the function's name to the key here. It's already in the source code. UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error) { - SourceCodeKey key = SourceCodeKey(source, name.string(), SourceCodeKey::FunctionType, JSParseNormal); - CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); - if (!addResult.isNewEntry) - return jsCast(addResult.iterator->value.cell.get()); + SourceCodeKey key = SourceCodeKey( + source, name.string(), SourceCodeKey::FunctionType, + JSParserBuiltinMode::NotBuiltin, + JSParserStrictMode::NotStrict); + SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); + if (cache) + return jsCast(cache->cell.get()); JSTextPosition positionBeforeLastNewline; - RefPtr program = parse(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline); + std::unique_ptr program = parse( + &vm, source, 0, Identifier(), JSParserBuiltinMode::NotBuiltin, + JSParserStrictMode::NotStrict, JSParserCodeType::Program, + error, &positionBeforeLastNewline); if (!program) { - RELEASE_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(); - RELEASE_ASSERT(exprStatement); - RELEASE_ASSERT(exprStatement->isExprStatement()); - ExpressionNode* funcExpr = static_cast(exprStatement)->expr(); - RELEASE_ASSERT(funcExpr); - RELEASE_ASSERT(funcExpr->isFuncExprNode()); - FunctionBodyNode* body = static_cast(funcExpr)->body(); - RELEASE_ASSERT(!program->hasCapturedVariables()); + // This function assumes an input string that would result in a single function declaration. + StatementNode* statement = program->singleStatement(); + ASSERT(statement); + ASSERT(statement->isBlock()); + if (!statement || !statement->isBlock()) + return nullptr; + + StatementNode* funcDecl = static_cast(statement)->singleStatement(); + ASSERT(funcDecl); + ASSERT(funcDecl->isFuncDeclNode()); + if (!funcDecl || !funcDecl->isFuncDeclNode()) + return nullptr; + + FunctionBodyNode* body = static_cast(funcDecl)->body(); + ASSERT(body); + if (!body) + return nullptr; body->setEndPosition(positionBeforeLastNewline); - RELEASE_ASSERT(body); - RELEASE_ASSERT(body->ident().isNull()); - UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body, UnlinkedNormalFunction); functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string())); - addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age()); + m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age())); return functionExecutable; }