diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | 192 |
1 files changed, 145 insertions, 47 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp index e98d4de0a..8aba1ff8b 100644 --- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,6 +32,8 @@ #include "CodeCache.h" #include "Executable.h" #include "JSString.h" +#include "Operations.h" +#include "Parser.h" #include "SourceProvider.h" #include "Structure.h" #include "SymbolTable.h" @@ -45,6 +47,29 @@ const ClassInfo UnlinkedProgramCodeBlock::s_info = { "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, JSScope* scope, 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(), body->lineNo(), body->lastLine()); + + UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct)); + OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, scope, 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(); @@ -55,8 +80,8 @@ unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v) return addConstant(v); } -UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(JSGlobalData* globalData, Structure* structure, const SourceCode& source, FunctionBodyNode* node) - : Base(*globalData, structure) +UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node) + : Base(*vm, structure) , m_numCapturedVariables(node->capturedVariableCount()) , m_forceUsesArguments(node->usesArguments()) , m_isInStrictContext(node->isStrictMode()) @@ -66,6 +91,8 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(JSGlobalData* globalData, , m_parameters(node->parameters()) , m_firstLineOffset(node->firstLine() - source.firstLine()) , m_lineCount(node->lastLine() - node->firstLine()) + , m_functionStartOffset(node->functionStart() - source.startOffset()) + , m_functionStartColumn(node->startColumn()) , m_startOffset(node->source().startOffset() - source.startOffset()) , m_sourceLength(node->source().length()) , m_features(node->features()) @@ -73,6 +100,11 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(JSGlobalData* globalData, { } +size_t UnlinkedFunctionExecutable::parameterCount() const +{ + return m_parameters->size(); +} + void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) { UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell); @@ -80,24 +112,31 @@ void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visito 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) +FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, 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); + unsigned startColumn = m_functionStartColumn + 1; // startColumn should start from 1, not 0. + SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); + return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn); } 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); + CodeCache* codeCache = exec->vm().codeCache(); + UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->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; @@ -106,36 +145,32 @@ UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Ide return executable; } -UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData& globalData, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(VM& vm, JSScope* scope, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { switch (specializationKind) { case CodeForCall: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) { - globalData.codeCache()->usedFunctionCode(globalData, codeBlock); + if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) return codeBlock; - } break; case CodeForConstruct: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) { - globalData.codeCache()->usedFunctionCode(globalData, codeBlock); + if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) return codeBlock; - } break; } - UnlinkedFunctionCodeBlock* result = globalData.codeCache()->getFunctionCodeBlock(globalData, this, source, specializationKind, debuggerMode, profilerMode, error); + UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, scope, this, source, specializationKind, debuggerMode, profilerMode, error); if (error.m_type != ParserError::ErrorNone) return 0; switch (specializationKind) { case CodeForCall: - m_codeBlockForCall = PassWeak<UnlinkedFunctionCodeBlock>(result); - m_symbolTableForCall.set(globalData, this, result->symbolTable()); + m_codeBlockForCall.set(vm, this, result); + m_symbolTableForCall.set(vm, this, result->symbolTable()); break; case CodeForConstruct: - m_codeBlockForConstruct = PassWeak<UnlinkedFunctionCodeBlock>(result); - m_symbolTableForConstruct.set(globalData, this, result->symbolTable()); + m_codeBlockForConstruct.set(vm, this, result); + m_symbolTableForConstruct.set(vm, this, result->symbolTable()); break; } return result; @@ -148,18 +183,19 @@ String UnlinkedFunctionExecutable::paramString() const for (size_t pos = 0; pos < parameters.size(); ++pos) { if (!builder.isEmpty()) builder.appendLiteral(", "); - builder.append(parameters[pos].string()); + builder.append(parameters.at(pos).string()); } return builder.toString(); } -UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info) - : Base(*globalData, structure) +UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) + : Base(*vm, structure) , m_numVars(0) , m_numCalleeRegisters(0) , m_numParameters(0) - , m_globalData(globalData) + , m_vm(vm) , m_argumentsRegister(-1) + , m_globalObjectRegister(-1) , m_needsFullScopeChain(info.m_needsActivation) , m_usesEval(info.m_usesEval) , m_isNumericCompareFunction(false) @@ -174,6 +210,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* struct , m_putToBaseOperationCount(1) , m_arrayProfileCount(0) , m_arrayAllocationProfileCount(0) + , m_objectAllocationProfileCount(0) , m_valueProfileCount(0) , m_llintCallLinkInfoCount(0) #if ENABLE(BYTECODE_COMMENTS) @@ -205,24 +242,17 @@ void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) 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; + int divot; + int startOffset; + int endOffset; + unsigned line; + unsigned column; + expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column); + return line; } -void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) +void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, + int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) { ASSERT(bytecodeOffset < instructions().size()); @@ -230,6 +260,8 @@ void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset startOffset = 0; endOffset = 0; divot = 0; + line = 0; + column = 0; return; } @@ -245,17 +277,83 @@ void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset high = mid; } - ASSERT(low); - if (!low) { + if (!low) + low = 1; + + ExpressionRangeInfo& info = expressionInfo[low - 1]; + startOffset = info.startOffset; + endOffset = info.endOffset; + divot = info.divotPoint; + + switch (info.mode) { + case ExpressionRangeInfo::FatLineMode: + info.decodeFatLineMode(line, column); + break; + case ExpressionRangeInfo::FatColumnMode: + info.decodeFatColumnMode(line, column); + break; + case ExpressionRangeInfo::FatLineAndColumnMode: { + unsigned fatIndex = info.position; + ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex]; + line = fatPos.line; + column = fatPos.column; + break; + } + } // switch +} + +void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset, + int divot, int startOffset, int endOffset, unsigned line, unsigned column) +{ + if (divot > ExpressionRangeInfo::MaxDivot) { + // Overflow has occurred, we can only give line number info for errors for this region + divot = 0; startOffset = 0; endOffset = 0; - divot = 0; - return; + } else if (startOffset > ExpressionRangeInfo::MaxOffset) { + // If the start offset is out of bounds we clear both offsets + // so we only get the divot marker. Error message will have to be reduced + // to line and charPosition number. + startOffset = 0; + endOffset = 0; + } else if (endOffset > ExpressionRangeInfo::MaxOffset) { + // The end offset is only used for additional context, and is much more likely + // to overflow (eg. function call arguments) so we are willing to drop it without + // dropping the rest of the range. + endOffset = 0; + } + + unsigned positionMode = + (line <= ExpressionRangeInfo::MaxFatLineModeLine && column <= ExpressionRangeInfo::MaxFatLineModeColumn) + ? ExpressionRangeInfo::FatLineMode + : (line <= ExpressionRangeInfo::MaxFatColumnModeLine && column <= ExpressionRangeInfo::MaxFatColumnModeColumn) + ? ExpressionRangeInfo::FatColumnMode + : ExpressionRangeInfo::FatLineAndColumnMode; + + ExpressionRangeInfo info; + info.instructionOffset = instructionOffset; + info.divotPoint = divot; + info.startOffset = startOffset; + info.endOffset = endOffset; + + info.mode = positionMode; + switch (positionMode) { + case ExpressionRangeInfo::FatLineMode: + info.encodeFatLineMode(line, column); + break; + case ExpressionRangeInfo::FatColumnMode: + info.encodeFatColumnMode(line, column); + break; + case ExpressionRangeInfo::FatLineAndColumnMode: { + createRareDataIfNecessary(); + unsigned fatIndex = m_rareData->m_expressionInfoFatPositions.size(); + ExpressionRangeInfo::FatPosition fatPos = { line, column }; + m_rareData->m_expressionInfoFatPositions.append(fatPos); + info.position = fatIndex; } + } // switch - startOffset = expressionInfo[low - 1].startOffset; - endOffset = expressionInfo[low - 1].endOffset; - divot = expressionInfo[low - 1].divotPoint; + m_expressionInfo.append(info); } void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) |