diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-07 11:22:47 +0100 |
commit | cfd86b747d32ac22246a1aa908eaa720c63a88c1 (patch) | |
tree | 24d68c6f61c464ecba1e05670b80390ea3b0e50c /Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | |
parent | 69d7c744c9de19d152dbe2d8e46eb7dfd4511d1a (diff) | |
download | qtwebkit-cfd86b747d32ac22246a1aa908eaa720c63a88c1.tar.gz |
Imported WebKit commit 20271caf2e2c016d5cef40184cddeefeac4f1876 (http://svn.webkit.org/repository/webkit/trunk@133733)
New snapshot that contains all previous fixes as well as build fix for latest QtMultimedia API changes.
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp new file mode 100644 index 000000000..8aa48404a --- /dev/null +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "UnlinkedCodeBlock.h" + +#include "BytecodeGenerator.h" +#include "ClassInfo.h" +#include "CodeCache.h" +#include "Executable.h" +#include "JSString.h" +#include "SourceProvider.h" +#include "Structure.h" +#include "SymbolTable.h" + +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) }; + +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(JSGlobalData* globalData, Structure* structure, const SourceCode& source, FunctionBodyNode* node) + : Base(*globalData, structure) + , m_numCapturedVariables(node->capturedVariableCount()) + , m_forceUsesArguments(node->usesArguments()) + , m_isInStrictContext(node->isStrictMode()) + , m_hasCapturedVariables(node->hasCapturedVariables()) + , 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_startOffset(node->source().startOffset() - source.startOffset()) + , m_sourceLength(node->source().length()) + , m_features(node->features()) + , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle()) +{ +} + +void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_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(JSGlobalData& globalData, const SourceCode& source, size_t lineOffset, size_t sourceOffset) +{ + unsigned firstLine = lineOffset + m_firstLineOffset; + unsigned startOffset = sourceOffset + m_startOffset; + SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine); + return FunctionExecutable::create(globalData, code, this, firstLine, firstLine + m_lineCount); +} + +UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception) +{ + ParserError error; + CodeCache* codeCache = exec->globalData().codeCache(); + UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->globalData(), name, source, error); + if (error.m_type != ParserError::ErrorNone) { + *exception = error.toErrorObject(exec->lexicalGlobalObject(), source); + return 0; + } + + return executable; +} + +UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData& globalData, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +{ + switch (specializationKind) { + case CodeForCall: + if (m_codeBlockForCall) + return m_codeBlockForCall.get(); + break; + case CodeForConstruct: + if (m_codeBlockForConstruct) + return m_codeBlockForConstruct.get(); + break; + } + + UnlinkedFunctionCodeBlock* result = globalData.codeCache()->getFunctionCodeBlock(globalData, this, source, specializationKind, debuggerMode, profilerMode, error); + + if (error.m_type != ParserError::ErrorNone) + return 0; + + switch (specializationKind) { + case CodeForCall: + m_codeBlockForCall.set(globalData, this, result); + m_symbolTableForCall.set(globalData, this, result->symbolTable()); + break; + case CodeForConstruct: + m_codeBlockForConstruct.set(globalData, this, result); + m_symbolTableForConstruct.set(globalData, 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(", "); + builder.append(parameters[pos].string()); + } + return builder.toString(); +} + +UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info) + : Base(*globalData, structure) + , m_numVars(0) + , m_numCalleeRegisters(0) + , m_numParameters(0) + , m_globalData(globalData) + , m_argumentsRegister(-1) + , m_needsFullScopeChain(info.m_needsActivation) + , m_usesEval(info.m_usesEval) + , m_isNumericCompareFunction(false) + , m_isStrictMode(info.m_isStrictMode) + , m_isConstructor(info.m_isConstructor) + , m_hasCapturedVariables(false) + , m_firstLine(0) + , m_lineCount(0) + , m_features(0) + , m_codeType(codeType) + , m_resolveOperationCount(0) + , m_putToBaseOperationCount(1) + , m_arrayProfileCount(0) + , m_valueProfileCount(0) + , m_llintCallLinkInfoCount(0) +#if ENABLE(BYTECODE_COMMENTS) + , m_bytecodeCommentIterator(0) +#endif +{ + +} + +void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_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_rareData) { + for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++) + visitor.append(&thisObject->m_rareData->m_regexps[i]); + } +} + +int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) +{ + ASSERT(bytecodeOffset < instructions().size()); + Vector<LineInfo>& lineInfo = m_lineInfo; + + int low = 0; + int high = lineInfo.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (lineInfo[mid].instructionOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + if (!low) + return 0; + return lineInfo[low - 1].lineNumber; +} + +void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) +{ + ASSERT(bytecodeOffset < instructions().size()); + + if (!m_expressionInfo.size()) { + startOffset = 0; + endOffset = 0; + divot = 0; + return; + } + + Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo; + + int low = 0; + int high = expressionInfo.size(); + while (low < high) { + int mid = low + (high - low) / 2; + if (expressionInfo[mid].instructionOffset <= bytecodeOffset) + low = mid + 1; + else + high = mid; + } + + ASSERT(low); + if (!low) { + startOffset = 0; + endOffset = 0; + divot = 0; + return; + } + + startOffset = expressionInfo[low - 1].startOffset; + endOffset = expressionInfo[low - 1].endOffset; + divot = expressionInfo[low - 1].divotPoint; +} + +void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_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); +} + +UnlinkedCodeBlock::~UnlinkedCodeBlock() +{ +} + +void UnlinkedProgramCodeBlock::destroy(JSCell* cell) +{ + jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock(); +} + +void UnlinkedEvalCodeBlock::destroy(JSCell* cell) +{ + jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock(); +} + +void UnlinkedFunctionCodeBlock::destroy(JSCell* cell) +{ + jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock(); +} + +void UnlinkedFunctionExecutable::destroy(JSCell* cell) +{ + jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable(); +} + +} + |