123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- * 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
- * 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 "Operations.h"
- #include "Parser.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) };
- 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();
- 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)
- : Base(*vm, 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_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())
- , 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, &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(VM& vm, const SourceCode& source, size_t lineOffset, size_t sourceOffset)
- {
- unsigned firstLine = lineOffset + m_firstLineOffset;
- unsigned startOffset = sourceOffset + m_startOffset;
- 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->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;
- }
- return executable;
- }
- 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())
- return codeBlock;
- break;
- case CodeForConstruct:
- if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get())
- return codeBlock;
- break;
- }
- 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.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(", ");
- builder.append(parameters.at(pos).string());
- }
- return builder.toString();
- }
- UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
- : Base(*vm, structure)
- , m_numVars(0)
- , m_numCalleeRegisters(0)
- , m_numParameters(0)
- , m_vm(vm)
- , m_argumentsRegister(-1)
- , m_globalObjectRegister(-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_arrayAllocationProfileCount(0)
- , m_objectAllocationProfileCount(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());
- 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, unsigned& line, unsigned& column)
- {
- ASSERT(bytecodeOffset < instructions().size());
- if (!m_expressionInfo.size()) {
- startOffset = 0;
- endOffset = 0;
- divot = 0;
- line = 0;
- column = 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;
- }
- 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;
- } 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
- m_expressionInfo.append(info);
- }
- 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();
- }
- }
|