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, ConstructAbility constructAbility, 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_constructAbility(static_cast<unsigned>(constructAbility))
105 , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
106 , m_functionMode(node->functionMode())
108 ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
109 m_parentScopeTDZVariables.swap(parentScopeTDZVariables);
112 void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
114 UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);
115 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
116 Base::visitChildren(thisObject, visitor);
117 visitor.append(&thisObject->m_codeBlockForCall);
118 visitor.append(&thisObject->m_codeBlockForConstruct);
119 visitor.append(&thisObject->m_nameValue);
122 FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber)
124 SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource;
125 unsigned firstLine = source.firstLine() + m_firstLineOffset;
126 unsigned startOffset = source.startOffset() + m_startOffset;
127 unsigned lineCount = m_lineCount;
129 // Adjust to one-based indexing.
130 bool startColumnIsOnFirstSourceLine = !m_firstLineOffset;
131 unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1);
132 bool endColumnIsOnStartLine = !lineCount;
133 unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
135 SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn);
136 FunctionOverrides::OverrideInfo overrideInfo;
137 bool hasFunctionOverride = false;
139 if (UNLIKELY(Options::functionOverrides())) {
140 hasFunctionOverride = FunctionOverrides::initializeOverrideFor(code, overrideInfo);
141 if (hasFunctionOverride) {
142 firstLine = overrideInfo.firstLine;
143 lineCount = overrideInfo.lineCount;
144 startColumn = overrideInfo.startColumn;
145 endColumn = overrideInfo.endColumn;
146 code = overrideInfo.sourceCode;
150 FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn);
151 if (overrideLineNumber != -1)
152 result->setOverrideLineNumber(overrideLineNumber);
154 if (UNLIKELY(hasFunctionOverride)) {
155 result->overrideParameterAndTypeProfilingStartEndOffsets(
156 overrideInfo.parametersStartOffset,
157 overrideInfo.typeProfilingStartOffset,
158 overrideInfo.typeProfilingEndOffset);
164 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
165 const Identifier& name, ExecState& exec, const SourceCode& source,
166 JSObject*& exception, int overrideLineNumber)
170 CodeCache* codeCache = vm.codeCache();
171 UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error);
173 auto& globalObject = *exec.lexicalGlobalObject();
174 if (globalObject.hasDebugger())
175 globalObject.debugger()->sourceParsed(&exec, source.provider(), error.line(), error.message());
177 if (error.isValid()) {
178 exception = error.toErrorObject(&globalObject, source, overrideLineNumber);
185 UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(
186 VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind,
187 DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
189 switch (specializationKind) {
191 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get())
194 case CodeForConstruct:
195 if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get())
200 UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(
201 vm, this, source, specializationKind, debuggerMode, profilerMode,
202 isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction,
208 switch (specializationKind) {
210 m_codeBlockForCall.set(vm, this, result);
212 case CodeForConstruct:
213 m_codeBlockForConstruct.set(vm, this, result);
219 UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
220 : Base(*vm, structure)
222 , m_numCalleeRegisters(0)
225 , m_globalObjectRegister(VirtualRegister())
226 , m_needsFullScopeChain(info.needsActivation())
227 , m_usesEval(info.usesEval())
228 , m_isStrictMode(info.isStrictMode())
229 , m_isConstructor(info.isConstructor())
230 , m_hasCapturedVariables(false)
231 , m_isBuiltinFunction(info.isBuiltinFunction())
232 , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
235 , m_endColumn(UINT_MAX)
237 , m_codeType(codeType)
238 , m_arrayProfileCount(0)
239 , m_arrayAllocationProfileCount(0)
240 , m_objectAllocationProfileCount(0)
241 , m_valueProfileCount(0)
242 , m_llintCallLinkInfoCount(0)
243 #if ENABLE(BYTECODE_COMMENTS)
244 , m_bytecodeCommentIterator(0)
247 for (auto& constantRegisterIndex : m_linkTimeConstants)
248 constantRegisterIndex = 0;
249 ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
252 void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
254 UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
255 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
256 Base::visitChildren(thisObject, visitor);
257 visitor.append(&thisObject->m_symbolTable);
258 for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
260 for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
262 visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
263 if (thisObject->m_rareData) {
264 for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
265 visitor.append(&thisObject->m_rareData->m_regexps[i]);
269 int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
271 ASSERT(bytecodeOffset < instructions().count());
277 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
281 inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info,
282 unsigned& line, unsigned& column)
285 case ExpressionRangeInfo::FatLineMode:
286 info.decodeFatLineMode(line, column);
288 case ExpressionRangeInfo::FatColumnMode:
289 info.decodeFatColumnMode(line, column);
291 case ExpressionRangeInfo::FatLineAndColumnMode: {
292 unsigned fatIndex = info.position;
293 ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
295 column = fatPos.column;
302 static void dumpLineColumnEntry(size_t index, const UnlinkedInstructionStream& instructionStream, unsigned instructionOffset, unsigned line, unsigned column)
304 const auto& instructions = instructionStream.unpackForDebugging();
305 OpcodeID opcode = instructions[instructionOffset].u.opcode;
306 const char* event = "";
307 if (opcode == op_debug) {
308 switch (instructions[instructionOffset + 1].u.operand) {
309 case WillExecuteProgram: event = " WillExecuteProgram"; break;
310 case DidExecuteProgram: event = " DidExecuteProgram"; break;
311 case DidEnterCallFrame: event = " DidEnterCallFrame"; break;
312 case DidReachBreakpoint: event = " DidReachBreakpoint"; break;
313 case WillLeaveCallFrame: event = " WillLeaveCallFrame"; break;
314 case WillExecuteStatement: event = " WillExecuteStatement"; break;
317 dataLogF(" [%zu] pc %u @ line %u col %u : %s%s\n", index, instructionOffset, line, column, opcodeNames[opcode], event);
320 void UnlinkedCodeBlock::dumpExpressionRangeInfo()
322 Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
324 size_t size = m_expressionInfo.size();
325 dataLogF("UnlinkedCodeBlock %p expressionRangeInfo[%zu] {\n", this, size);
326 for (size_t i = 0; i < size; i++) {
327 ExpressionRangeInfo& info = expressionInfo[i];
330 getLineAndColumn(info, line, column);
331 dumpLineColumnEntry(i, instructions(), info.instructionOffset, line, column);
337 void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
338 int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
340 ASSERT(bytecodeOffset < instructions().count());
342 if (!m_expressionInfo.size()) {
351 Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
354 int high = expressionInfo.size();
356 int mid = low + (high - low) / 2;
357 if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
366 ExpressionRangeInfo& info = expressionInfo[low - 1];
367 startOffset = info.startOffset;
368 endOffset = info.endOffset;
369 divot = info.divotPoint;
370 getLineAndColumn(info, line, column);
373 void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
374 int divot, int startOffset, int endOffset, unsigned line, unsigned column)
376 if (divot > ExpressionRangeInfo::MaxDivot) {
377 // Overflow has occurred, we can only give line number info for errors for this region
381 } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
382 // If the start offset is out of bounds we clear both offsets
383 // so we only get the divot marker. Error message will have to be reduced
384 // to line and charPosition number.
387 } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
388 // The end offset is only used for additional context, and is much more likely
389 // to overflow (eg. function call arguments) so we are willing to drop it without
390 // dropping the rest of the range.
394 unsigned positionMode =
395 (line <= ExpressionRangeInfo::MaxFatLineModeLine && column <= ExpressionRangeInfo::MaxFatLineModeColumn)
396 ? ExpressionRangeInfo::FatLineMode
397 : (line <= ExpressionRangeInfo::MaxFatColumnModeLine && column <= ExpressionRangeInfo::MaxFatColumnModeColumn)
398 ? ExpressionRangeInfo::FatColumnMode
399 : ExpressionRangeInfo::FatLineAndColumnMode;
401 ExpressionRangeInfo info;
402 info.instructionOffset = instructionOffset;
403 info.divotPoint = divot;
404 info.startOffset = startOffset;
405 info.endOffset = endOffset;
407 info.mode = positionMode;
408 switch (positionMode) {
409 case ExpressionRangeInfo::FatLineMode:
410 info.encodeFatLineMode(line, column);
412 case ExpressionRangeInfo::FatColumnMode:
413 info.encodeFatColumnMode(line, column);
415 case ExpressionRangeInfo::FatLineAndColumnMode: {
416 createRareDataIfNecessary();
417 unsigned fatIndex = m_rareData->m_expressionInfoFatPositions.size();
418 ExpressionRangeInfo::FatPosition fatPos = { line, column };
419 m_rareData->m_expressionInfoFatPositions.append(fatPos);
420 info.position = fatIndex;
424 m_expressionInfo.append(info);
427 bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
429 static const bool verbose = false;
430 auto iter = m_typeProfilerInfoMap.find(bytecodeOffset);
431 if (iter == m_typeProfilerInfoMap.end()) {
433 dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
434 startDivot = UINT_MAX;
439 TypeProfilerExpressionRange& range = iter->value;
440 startDivot = range.m_startDivot;
441 endDivot = range.m_endDivot;
445 void UnlinkedCodeBlock::addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot)
447 TypeProfilerExpressionRange range;
448 range.m_startDivot = startDivot;
449 range.m_endDivot = endDivot;
450 m_typeProfilerInfoMap.set(instructionOffset, range);
453 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
455 UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
456 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
457 Base::visitChildren(thisObject, visitor);
460 UnlinkedCodeBlock::~UnlinkedCodeBlock()
464 void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
466 jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
469 void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
471 jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
474 void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
476 jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
479 void UnlinkedFunctionExecutable::destroy(JSCell* cell)
481 jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
484 void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions)
486 m_unlinkedInstructions = WTF::move(instructions);
489 const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const
491 ASSERT(m_unlinkedInstructions.get());
492 return *m_unlinkedInstructions;