2 * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "UnlinkedCodeBlock.h"
30 #include "BytecodeGenerator.h"
31 #include "ClassInfo.h"
32 #include "CodeCache.h"
33 #include "Executable.h"
34 #include "FunctionOverrides.h"
36 #include "JSCInlines.h"
38 #include "SourceProvider.h"
39 #include "Structure.h"
40 #include "SymbolTable.h"
41 #include "UnlinkedInstructionStream.h"
42 #include <wtf/DataLog.h>
46 static_assert(sizeof(UnlinkedFunctionExecutable) <= 256, "UnlinkedFunctionExecutable should fit in a 256-byte cell.");
48 const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
49 const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
50 const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
51 const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
52 const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
53 const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
55 static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(
56 VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source,
57 CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode,
58 UnlinkedFunctionKind functionKind, ParserError& error)
60 JSParserBuiltinMode builtinMode = executable->isBuiltinFunction() ? JSParserBuiltinMode::Builtin : JSParserBuiltinMode::NotBuiltin;
61 JSParserStrictMode strictMode = executable->isInStrictContext() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
62 std::unique_ptr<FunctionNode> function = parse<FunctionNode>(
63 &vm, source, executable->name(), builtinMode, strictMode,
64 JSParserCodeType::Function, error, nullptr, executable->parseMode());
67 ASSERT(error.isValid());
71 function->finishParsing(executable->name(), executable->functionMode());
72 executable->recordParse(function->features(), function->hasCapturedVariables());
74 UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
75 ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind()));
76 auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables()));
77 error = generator->generate();
83 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode* node, UnlinkedFunctionKind kind, VariableEnvironment& parentScopeTDZVariables)
84 : Base(*vm, structure)
85 , m_name(node->ident())
86 , m_inferredName(node->inferredName())
87 , m_sourceOverride(WTF::move(sourceOverride))
88 , m_firstLineOffset(node->firstLine() - source.firstLine())
89 , m_lineCount(node->lastLine() - node->firstLine())
90 , m_unlinkedFunctionNameStart(node->functionNameStart() - source.startOffset())
91 , m_unlinkedBodyStartColumn(node->startColumn())
92 , m_unlinkedBodyEndColumn(m_lineCount ? node->endColumn() : node->endColumn() - node->startColumn())
93 , m_startOffset(node->source().startOffset() - source.startOffset())
94 , m_sourceLength(node->source().length())
95 , m_parametersStartOffset(node->parametersStart())
96 , m_typeProfilingStartOffset(node->functionKeywordStart())
97 , m_typeProfilingEndOffset(node->startStartOffset() + node->source().length() - 1)
98 , m_parameterCount(node->parameterCount())
99 , m_parseMode(node->parseMode())
101 , m_isInStrictContext(node->isInStrictContext())
102 , m_hasCapturedVariables(false)
103 , m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
104 , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
105 , m_functionMode(node->functionMode())
107 ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
108 m_parentScopeTDZVariables.swap(parentScopeTDZVariables);
111 void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
113 UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);
114 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
115 Base::visitChildren(thisObject, visitor);
116 visitor.append(&thisObject->m_codeBlockForCall);
117 visitor.append(&thisObject->m_codeBlockForConstruct);
118 visitor.append(&thisObject->m_nameValue);
121 FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber)
123 SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource;
124 unsigned firstLine = source.firstLine() + m_firstLineOffset;
125 unsigned startOffset = source.startOffset() + m_startOffset;
126 unsigned lineCount = m_lineCount;
128 // Adjust to one-based indexing.
129 bool startColumnIsOnFirstSourceLine = !m_firstLineOffset;
130 unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1);
131 bool endColumnIsOnStartLine = !lineCount;
132 unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
134 SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn);
135 FunctionOverrides::OverrideInfo overrideInfo;
136 bool hasFunctionOverride = false;
138 if (UNLIKELY(Options::functionOverrides())) {
139 hasFunctionOverride = FunctionOverrides::initializeOverrideFor(code, overrideInfo);
140 if (hasFunctionOverride) {
141 firstLine = overrideInfo.firstLine;
142 lineCount = overrideInfo.lineCount;
143 startColumn = overrideInfo.startColumn;
144 endColumn = overrideInfo.endColumn;
145 code = overrideInfo.sourceCode;
149 FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn);
150 if (overrideLineNumber != -1)
151 result->setOverrideLineNumber(overrideLineNumber);
153 if (UNLIKELY(hasFunctionOverride)) {
154 result->overrideParameterAndTypeProfilingStartEndOffsets(
155 overrideInfo.parametersStartOffset,
156 overrideInfo.typeProfilingStartOffset,
157 overrideInfo.typeProfilingEndOffset);
163 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
164 const Identifier& name, ExecState& exec, const SourceCode& source,
165 JSObject*& exception, int overrideLineNumber)
169 CodeCache* codeCache = vm.codeCache();
170 UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error);
172 auto& globalObject = *exec.lexicalGlobalObject();
173 if (globalObject.hasDebugger())
174 globalObject.debugger()->sourceParsed(&exec, source.provider(), error.line(), error.message());
176 if (error.isValid()) {
177 exception = error.toErrorObject(&globalObject, source, overrideLineNumber);
184 UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(
185 VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind,
186 DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
188 switch (specializationKind) {
190 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get())
193 case CodeForConstruct:
194 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get())
199 UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(
200 vm, this, source, specializationKind, debuggerMode, profilerMode,
201 isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction,
207 switch (specializationKind) {
209 m_codeBlockForCall.set(vm, this, result);
211 case CodeForConstruct:
212 m_codeBlockForConstruct.set(vm, this, result);
218 UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
219 : Base(*vm, structure)
221 , m_numCalleeRegisters(0)
224 , m_globalObjectRegister(VirtualRegister())
225 , m_needsFullScopeChain(info.needsActivation())
226 , m_usesEval(info.usesEval())
227 , m_isStrictMode(info.isStrictMode())
228 , m_isConstructor(info.isConstructor())
229 , m_hasCapturedVariables(false)
230 , m_isBuiltinFunction(info.isBuiltinFunction())
231 , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
234 , m_endColumn(UINT_MAX)
236 , m_codeType(codeType)
237 , m_arrayProfileCount(0)
238 , m_arrayAllocationProfileCount(0)
239 , m_objectAllocationProfileCount(0)
240 , m_valueProfileCount(0)
241 , m_llintCallLinkInfoCount(0)
242 #if ENABLE(BYTECODE_COMMENTS)
243 , m_bytecodeCommentIterator(0)
246 for (auto& constantRegisterIndex : m_linkTimeConstants)
247 constantRegisterIndex = 0;
248 ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
251 void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
253 UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
254 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
255 Base::visitChildren(thisObject, visitor);
256 visitor.append(&thisObject->m_symbolTable);
257 for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
259 for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
261 visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
262 if (thisObject->m_rareData) {
263 for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
264 visitor.append(&thisObject->m_rareData->m_regexps[i]);
268 int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
270 ASSERT(bytecodeOffset < instructions().count());
276 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
280 inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info,
281 unsigned& line, unsigned& column)
284 case ExpressionRangeInfo::FatLineMode:
285 info.decodeFatLineMode(line, column);
287 case ExpressionRangeInfo::FatColumnMode:
288 info.decodeFatColumnMode(line, column);
290 case ExpressionRangeInfo::FatLineAndColumnMode: {
291 unsigned fatIndex = info.position;
292 ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
294 column = fatPos.column;
301 static void dumpLineColumnEntry(size_t index, const UnlinkedInstructionStream& instructionStream, unsigned instructionOffset, unsigned line, unsigned column)
303 const auto& instructions = instructionStream.unpackForDebugging();
304 OpcodeID opcode = instructions[instructionOffset].u.opcode;
305 const char* event = "";
306 if (opcode == op_debug) {
307 switch (instructions[instructionOffset + 1].u.operand) {
308 case WillExecuteProgram: event = " WillExecuteProgram"; break;
309 case DidExecuteProgram: event = " DidExecuteProgram"; break;
310 case DidEnterCallFrame: event = " DidEnterCallFrame"; break;
311 case DidReachBreakpoint: event = " DidReachBreakpoint"; break;
312 case WillLeaveCallFrame: event = " WillLeaveCallFrame"; break;
313 case WillExecuteStatement: event = " WillExecuteStatement"; break;
316 dataLogF(" [%zu] pc %u @ line %u col %u : %s%s\n", index, instructionOffset, line, column, opcodeNames[opcode], event);
319 void UnlinkedCodeBlock::dumpExpressionRangeInfo()
321 Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
323 size_t size = m_expressionInfo.size();
324 dataLogF("UnlinkedCodeBlock %p expressionRangeInfo[%zu] {\n", this, size);
325 for (size_t i = 0; i < size; i++) {
326 ExpressionRangeInfo& info = expressionInfo[i];
329 getLineAndColumn(info, line, column);
330 dumpLineColumnEntry(i, instructions(), info.instructionOffset, line, column);
336 void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
337 int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
339 ASSERT(bytecodeOffset < instructions().count());
341 if (!m_expressionInfo.size()) {
350 Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
353 int high = expressionInfo.size();
355 int mid = low + (high - low) / 2;
356 if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
365 ExpressionRangeInfo& info = expressionInfo[low - 1];
366 startOffset = info.startOffset;
367 endOffset = info.endOffset;
368 divot = info.divotPoint;
369 getLineAndColumn(info, line, column);
372 void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
373 int divot, int startOffset, int endOffset, unsigned line, unsigned column)
375 if (divot > ExpressionRangeInfo::MaxDivot) {
376 // Overflow has occurred, we can only give line number info for errors for this region
380 } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
381 // If the start offset is out of bounds we clear both offsets
382 // so we only get the divot marker. Error message will have to be reduced
383 // to line and charPosition number.
386 } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
387 // The end offset is only used for additional context, and is much more likely
388 // to overflow (eg. function call arguments) so we are willing to drop it without
389 // dropping the rest of the range.
393 unsigned positionMode =
394 (line <= ExpressionRangeInfo::MaxFatLineModeLine && column <= ExpressionRangeInfo::MaxFatLineModeColumn)
395 ? ExpressionRangeInfo::FatLineMode
396 : (line <= ExpressionRangeInfo::MaxFatColumnModeLine && column <= ExpressionRangeInfo::MaxFatColumnModeColumn)
397 ? ExpressionRangeInfo::FatColumnMode
398 : ExpressionRangeInfo::FatLineAndColumnMode;
400 ExpressionRangeInfo info;
401 info.instructionOffset = instructionOffset;
402 info.divotPoint = divot;
403 info.startOffset = startOffset;
404 info.endOffset = endOffset;
406 info.mode = positionMode;
407 switch (positionMode) {
408 case ExpressionRangeInfo::FatLineMode:
409 info.encodeFatLineMode(line, column);
411 case ExpressionRangeInfo::FatColumnMode:
412 info.encodeFatColumnMode(line, column);
414 case ExpressionRangeInfo::FatLineAndColumnMode: {
415 createRareDataIfNecessary();
416 unsigned fatIndex = m_rareData->m_expressionInfoFatPositions.size();
417 ExpressionRangeInfo::FatPosition fatPos = { line, column };
418 m_rareData->m_expressionInfoFatPositions.append(fatPos);
419 info.position = fatIndex;
423 m_expressionInfo.append(info);
426 bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
428 static const bool verbose = false;
429 auto iter = m_typeProfilerInfoMap.find(bytecodeOffset);
430 if (iter == m_typeProfilerInfoMap.end()) {
432 dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
433 startDivot = UINT_MAX;
438 TypeProfilerExpressionRange& range = iter->value;
439 startDivot = range.m_startDivot;
440 endDivot = range.m_endDivot;
444 void UnlinkedCodeBlock::addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot)
446 TypeProfilerExpressionRange range;
447 range.m_startDivot = startDivot;
448 range.m_endDivot = endDivot;
449 m_typeProfilerInfoMap.set(instructionOffset, range);
452 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
454 UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
455 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
456 Base::visitChildren(thisObject, visitor);
459 UnlinkedCodeBlock::~UnlinkedCodeBlock()
463 void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
465 jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
468 void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
470 jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
473 void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
475 jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
478 void UnlinkedFunctionExecutable::destroy(JSCell* cell)
480 jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
483 void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions)
485 m_unlinkedInstructions = WTF::move(instructions);
488 const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const
490 ASSERT(m_unlinkedInstructions.get());
491 return *m_unlinkedInstructions;