diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | 261 |
1 files changed, 87 insertions, 174 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp index 1dfb5ac6a..83d9054a3 100644 --- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved. + * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,8 +31,10 @@ #include "ClassInfo.h" #include "CodeCache.h" #include "Executable.h" +#include "ExecutableInfo.h" +#include "FunctionOverrides.h" #include "JSString.h" -#include "Operations.h" +#include "JSCInlines.h" #include "Parser.h" #include "SourceProvider.h" #include "Structure.h" @@ -42,177 +44,33 @@ namespace JSC { -const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) }; -const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) }; -const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) }; -const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) }; -const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) }; -const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) }; - -static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error); - - if (!body) { - ASSERT(error.m_type != ParserError::ErrorNone); - return 0; - } - - if (executable->forceUsesArguments()) - body->setUsesArguments(); - body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle()); - executable->recordParse(body->features(), body->hasCapturedVariables()); - - UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct)); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, body.get(), result, debuggerMode, profilerMode))); - error = generator->generate(); - body->destroyData(); - if (error.m_type != ParserError::ErrorNone) - return 0; - return result; -} - -unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v) -{ - unsigned numberOfConstants = numberOfConstantRegisters(); - for (unsigned i = 0; i < numberOfConstants; ++i) { - if (getConstant(FirstConstantRegisterIndex + i) == v) - return i; - } - return addConstant(v); -} - -UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode) - : Base(*vm, structure) - , m_numCapturedVariables(node->capturedVariableCount()) - , m_forceUsesArguments(node->usesArguments()) - , m_isInStrictContext(node->isStrictMode()) - , m_hasCapturedVariables(node->hasCapturedVariables()) - , m_isFromGlobalCode(isFromGlobalCode) - , m_name(node->ident()) - , m_inferredName(node->inferredName()) - , m_parameters(node->parameters()) - , m_firstLineOffset(node->firstLine() - source.firstLine()) - , m_lineCount(node->lastLine() - node->firstLine()) - , m_unlinkedFunctionNameStart(node->functionNameStart() - source.startOffset()) - , m_unlinkedBodyStartColumn(node->startColumn()) - , m_unlinkedBodyEndColumn(m_lineCount ? node->endColumn() : node->endColumn() - node->startColumn()) - , m_startOffset(node->source().startOffset() - source.startOffset()) - , m_sourceLength(node->source().length()) - , m_features(node->features()) - , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle()) -{ -} - -size_t UnlinkedFunctionExecutable::parameterCount() const -{ - return m_parameters->size(); -} - -void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_codeBlockForCall); - visitor.append(&thisObject->m_codeBlockForConstruct); - visitor.append(&thisObject->m_nameValue); - visitor.append(&thisObject->m_symbolTableForCall); - visitor.append(&thisObject->m_symbolTableForConstruct); -} - -FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& source, size_t lineOffset, size_t sourceOffset) -{ - unsigned firstLine = lineOffset + m_firstLineOffset; - unsigned startOffset = sourceOffset + m_startOffset; - bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; - unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); - bool endColumnIsOnStartLine = !m_lineCount; - unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); - SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); - return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn, endColumn); -} - -UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception) -{ - ParserError error; - VM& vm = exec->vm(); - CodeCache* codeCache = vm.codeCache(); - UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error); - - if (exec->lexicalGlobalObject()->hasDebugger()) - exec->lexicalGlobalObject()->debugger()->sourceParsed(exec, source.provider(), error.m_line, error.m_message); - - if (error.m_type != ParserError::ErrorNone) { - *exception = error.toErrorObject(exec->lexicalGlobalObject(), source); - return 0; - } - - return executable; -} - -UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - switch (specializationKind) { - case CodeForCall: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) - return codeBlock; - break; - case CodeForConstruct: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) - return codeBlock; - break; - } - - UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, this, source, specializationKind, debuggerMode, profilerMode, error); - - if (error.m_type != ParserError::ErrorNone) - return 0; - - switch (specializationKind) { - case CodeForCall: - m_codeBlockForCall.set(vm, this, result); - m_symbolTableForCall.set(vm, this, result->symbolTable()); - break; - case CodeForConstruct: - m_codeBlockForConstruct.set(vm, this, result); - m_symbolTableForConstruct.set(vm, this, result->symbolTable()); - break; - } - return result; -} - -String UnlinkedFunctionExecutable::paramString() const -{ - FunctionParameters& parameters = *m_parameters; - StringBuilder builder; - for (size_t pos = 0; pos < parameters.size(); ++pos) { - if (!builder.isEmpty()) - builder.appendLiteral(", "); - parameters.at(pos)->toString(builder); - } - return builder.toString(); -} +const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) }; +const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) }; +const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) }; +const ClassInfo UnlinkedModuleProgramCodeBlock::s_info = { "UnlinkedModuleProgramCodeBlock", &Base::s_info, nullptr, CREATE_METHOD_TABLE(UnlinkedModuleProgramCodeBlock) }; +const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) }; +const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) }; UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) : Base(*vm, structure) , m_numVars(0) - , m_numCalleeRegisters(0) + , m_numCalleeLocals(0) , m_numParameters(0) - , m_vm(vm) - , m_argumentsRegister(VirtualRegister()) , m_globalObjectRegister(VirtualRegister()) - , m_needsFullScopeChain(info.m_needsActivation) - , m_usesEval(info.m_usesEval) - , m_isNumericCompareFunction(false) - , m_isStrictMode(info.m_isStrictMode) - , m_isConstructor(info.m_isConstructor) + , m_usesEval(info.usesEval()) + , m_isStrictMode(info.isStrictMode()) + , m_isConstructor(info.isConstructor()) , m_hasCapturedVariables(false) + , m_isBuiltinFunction(info.isBuiltinFunction()) + , m_constructorKind(static_cast<unsigned>(info.constructorKind())) + , m_superBinding(static_cast<unsigned>(info.superBinding())) + , m_derivedContextType(static_cast<unsigned>(info.derivedContextType())) + , m_isArrowFunctionContext(info.isArrowFunctionContext()) + , m_isClassContext(info.isClassContext()) , m_firstLine(0) , m_lineCount(0) , m_endColumn(UINT_MAX) + , m_parseMode(info.parseMode()) , m_features(0) , m_codeType(codeType) , m_arrayProfileCount(0) @@ -220,32 +78,42 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code , m_objectAllocationProfileCount(0) , m_valueProfileCount(0) , m_llintCallLinkInfoCount(0) -#if ENABLE(BYTECODE_COMMENTS) - , m_bytecodeCommentIterator(0) -#endif { + for (auto& constantRegisterIndex : m_linkTimeConstants) + constantRegisterIndex = 0; + ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind())); +} +VM* UnlinkedCodeBlock::vm() const +{ + return MarkedBlock::blockFor(this)->vm(); } void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) { UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_symbolTable); for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr) visitor.append(ptr); for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr) visitor.append(ptr); visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size()); + if (thisObject->m_unlinkedInstructions) + visitor.reportExtraMemoryVisited(thisObject->m_unlinkedInstructions->sizeInBytes()); if (thisObject->m_rareData) { for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++) visitor.append(&thisObject->m_rareData->m_regexps[i]); } } +size_t UnlinkedCodeBlock::estimatedSize(JSCell* cell) +{ + UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); + size_t extraSize = thisObject->m_unlinkedInstructions ? thisObject->m_unlinkedInstructions->sizeInBytes() : 0; + return Base::estimatedSize(cell) + extraSize; +} + int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) { ASSERT(bytecodeOffset < instructions().count()); @@ -404,15 +272,53 @@ void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset, m_expressionInfo.append(info); } +bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot) +{ + static const bool verbose = false; + if (!m_rareData) { + if (verbose) + dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset); + startDivot = UINT_MAX; + endDivot = UINT_MAX; + return false; + } + + auto iter = m_rareData->m_typeProfilerInfoMap.find(bytecodeOffset); + if (iter == m_rareData->m_typeProfilerInfoMap.end()) { + if (verbose) + dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset); + startDivot = UINT_MAX; + endDivot = UINT_MAX; + return false; + } + + RareData::TypeProfilerExpressionRange& range = iter->value; + startDivot = range.m_startDivot; + endDivot = range.m_endDivot; + return true; +} + +void UnlinkedCodeBlock::addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot) +{ + createRareDataIfNecessary(); + RareData::TypeProfilerExpressionRange range; + range.m_startDivot = startDivot; + range.m_endDivot = endDivot; + m_rareData->m_typeProfilerInfoMap.set(instructionOffset, range); +} + void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) { UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); - for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++) - visitor.append(&thisObject->m_functionDeclarations[i].second); +} + +void UnlinkedModuleProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + UnlinkedModuleProgramCodeBlock* thisObject = jsCast<UnlinkedModuleProgramCodeBlock*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); } UnlinkedCodeBlock::~UnlinkedCodeBlock() @@ -424,6 +330,11 @@ void UnlinkedProgramCodeBlock::destroy(JSCell* cell) jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock(); } +void UnlinkedModuleProgramCodeBlock::destroy(JSCell* cell) +{ + jsCast<UnlinkedModuleProgramCodeBlock*>(cell)->~UnlinkedModuleProgramCodeBlock(); +} + void UnlinkedEvalCodeBlock::destroy(JSCell* cell) { jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock(); @@ -441,7 +352,9 @@ void UnlinkedFunctionExecutable::destroy(JSCell* cell) void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions) { - m_unlinkedInstructions = std::move(instructions); + ASSERT(instructions); + m_unlinkedInstructions = WTFMove(instructions); + Heap::heap(this)->reportExtraMemoryAllocated(m_unlinkedInstructions->sizeInBytes()); } const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const |