Hook up ShadowChicken to the debugger to show tail deleted frames
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.cpp
1 /*
2  * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27
28 #include "UnlinkedCodeBlock.h"
29
30 #include "BytecodeGenerator.h"
31 #include "ClassInfo.h"
32 #include "CodeCache.h"
33 #include "Executable.h"
34 #include "ExecutableInfo.h"
35 #include "FunctionOverrides.h"
36 #include "JSString.h"
37 #include "JSCInlines.h"
38 #include "Parser.h"
39 #include "SourceProvider.h"
40 #include "Structure.h"
41 #include "SymbolTable.h"
42 #include "UnlinkedInstructionStream.h"
43 #include <wtf/DataLog.h>
44
45 namespace JSC {
46
47 const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
48 const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
49 const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
50 const ClassInfo UnlinkedModuleProgramCodeBlock::s_info = { "UnlinkedModuleProgramCodeBlock", &Base::s_info, nullptr, CREATE_METHOD_TABLE(UnlinkedModuleProgramCodeBlock) };
51 const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
52 const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
53
54 UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode)
55     : Base(*vm, structure)
56     , m_numVars(0)
57     , m_numCalleeLocals(0)
58     , m_numParameters(0)
59     , m_globalObjectRegister(VirtualRegister())
60     , m_usesEval(info.usesEval())
61     , m_isStrictMode(info.isStrictMode())
62     , m_isConstructor(info.isConstructor())
63     , m_hasCapturedVariables(false)
64     , m_isBuiltinFunction(info.isBuiltinFunction())
65     , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
66     , m_superBinding(static_cast<unsigned>(info.superBinding()))
67     , m_derivedContextType(static_cast<unsigned>(info.derivedContextType()))
68     , m_evalContextType(static_cast<unsigned>(info.evalContextType()))
69     , m_isArrowFunctionContext(info.isArrowFunctionContext())
70     , m_isClassContext(info.isClassContext())
71     , m_wasCompiledWithDebuggingOpcodes(debuggerMode == DebuggerMode::DebuggerOn)
72     , m_firstLine(0)
73     , m_lineCount(0)
74     , m_endColumn(UINT_MAX)
75     , m_parseMode(info.parseMode())
76     , m_features(0)
77     , m_codeType(codeType)
78     , m_arrayProfileCount(0)
79     , m_arrayAllocationProfileCount(0)
80     , m_objectAllocationProfileCount(0)
81     , m_valueProfileCount(0)
82     , m_llintCallLinkInfoCount(0)
83 {
84     for (auto& constantRegisterIndex : m_linkTimeConstants)
85         constantRegisterIndex = 0;
86     ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
87 }
88
89 VM* UnlinkedCodeBlock::vm() const
90 {
91     return MarkedBlock::blockFor(this)->vm();
92 }
93
94 void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
95 {
96     UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
97     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
98     Base::visitChildren(thisObject, visitor);
99     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
100         visitor.append(ptr);
101     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
102         visitor.append(ptr);
103     visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
104     if (thisObject->m_unlinkedInstructions)
105         visitor.reportExtraMemoryVisited(thisObject->m_unlinkedInstructions->sizeInBytes());
106     if (thisObject->m_rareData) {
107         for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
108             visitor.append(&thisObject->m_rareData->m_regexps[i]);
109     }
110 }
111
112 size_t UnlinkedCodeBlock::estimatedSize(JSCell* cell)
113 {
114     UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
115     size_t extraSize = thisObject->m_unlinkedInstructions ? thisObject->m_unlinkedInstructions->sizeInBytes() : 0;
116     return Base::estimatedSize(cell) + extraSize;
117 }
118
119 int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
120 {
121     ASSERT(bytecodeOffset < instructions().count());
122     int divot;
123     int startOffset;
124     int endOffset;
125     unsigned line;
126     unsigned column;
127     expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
128     return line;
129 }
130
131 inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info,
132     unsigned& line, unsigned& column)
133 {
134     switch (info.mode) {
135     case ExpressionRangeInfo::FatLineMode:
136         info.decodeFatLineMode(line, column);
137         break;
138     case ExpressionRangeInfo::FatColumnMode:
139         info.decodeFatColumnMode(line, column);
140         break;
141     case ExpressionRangeInfo::FatLineAndColumnMode: {
142         unsigned fatIndex = info.position;
143         ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
144         line = fatPos.line;
145         column = fatPos.column;
146         break;
147     }
148     } // switch
149 }
150
151 #ifndef NDEBUG
152 static void dumpLineColumnEntry(size_t index, const UnlinkedInstructionStream& instructionStream, unsigned instructionOffset, unsigned line, unsigned column)
153 {
154     const auto& instructions = instructionStream.unpackForDebugging();
155     OpcodeID opcode = instructions[instructionOffset].u.opcode;
156     const char* event = "";
157     if (opcode == op_debug) {
158         switch (instructions[instructionOffset + 1].u.operand) {
159         case WillExecuteProgram: event = " WillExecuteProgram"; break;
160         case DidExecuteProgram: event = " DidExecuteProgram"; break;
161         case DidEnterCallFrame: event = " DidEnterCallFrame"; break;
162         case DidReachBreakpoint: event = " DidReachBreakpoint"; break;
163         case WillLeaveCallFrame: event = " WillLeaveCallFrame"; break;
164         case WillExecuteStatement: event = " WillExecuteStatement"; break;
165         }
166     }
167     dataLogF("  [%zu] pc %u @ line %u col %u : %s%s\n", index, instructionOffset, line, column, opcodeNames[opcode], event);
168 }
169
170 void UnlinkedCodeBlock::dumpExpressionRangeInfo()
171 {
172     Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
173
174     size_t size = m_expressionInfo.size();
175     dataLogF("UnlinkedCodeBlock %p expressionRangeInfo[%zu] {\n", this, size);
176     for (size_t i = 0; i < size; i++) {
177         ExpressionRangeInfo& info = expressionInfo[i];
178         unsigned line;
179         unsigned column;
180         getLineAndColumn(info, line, column);
181         dumpLineColumnEntry(i, instructions(), info.instructionOffset, line, column);
182     }
183     dataLog("}\n");
184 }
185 #endif
186
187 void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
188     int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
189 {
190     ASSERT(bytecodeOffset < instructions().count());
191
192     if (!m_expressionInfo.size()) {
193         startOffset = 0;
194         endOffset = 0;
195         divot = 0;
196         line = 0;
197         column = 0;
198         return;
199     }
200
201     Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
202
203     int low = 0;
204     int high = expressionInfo.size();
205     while (low < high) {
206         int mid = low + (high - low) / 2;
207         if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
208             low = mid + 1;
209         else
210             high = mid;
211     }
212
213     if (!low)
214         low = 1;
215
216     ExpressionRangeInfo& info = expressionInfo[low - 1];
217     startOffset = info.startOffset;
218     endOffset = info.endOffset;
219     divot = info.divotPoint;
220     getLineAndColumn(info, line, column);
221 }
222
223 void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
224     int divot, int startOffset, int endOffset, unsigned line, unsigned column)
225 {
226     if (divot > ExpressionRangeInfo::MaxDivot) {
227         // Overflow has occurred, we can only give line number info for errors for this region
228         divot = 0;
229         startOffset = 0;
230         endOffset = 0;
231     } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
232         // If the start offset is out of bounds we clear both offsets
233         // so we only get the divot marker. Error message will have to be reduced
234         // to line and charPosition number.
235         startOffset = 0;
236         endOffset = 0;
237     } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
238         // The end offset is only used for additional context, and is much more likely
239         // to overflow (eg. function call arguments) so we are willing to drop it without
240         // dropping the rest of the range.
241         endOffset = 0;
242     }
243
244     unsigned positionMode =
245         (line <= ExpressionRangeInfo::MaxFatLineModeLine && column <= ExpressionRangeInfo::MaxFatLineModeColumn) 
246         ? ExpressionRangeInfo::FatLineMode
247         : (line <= ExpressionRangeInfo::MaxFatColumnModeLine && column <= ExpressionRangeInfo::MaxFatColumnModeColumn)
248         ? ExpressionRangeInfo::FatColumnMode
249         : ExpressionRangeInfo::FatLineAndColumnMode;
250
251     ExpressionRangeInfo info;
252     info.instructionOffset = instructionOffset;
253     info.divotPoint = divot;
254     info.startOffset = startOffset;
255     info.endOffset = endOffset;
256
257     info.mode = positionMode;
258     switch (positionMode) {
259     case ExpressionRangeInfo::FatLineMode:
260         info.encodeFatLineMode(line, column);
261         break;
262     case ExpressionRangeInfo::FatColumnMode:
263         info.encodeFatColumnMode(line, column);
264         break;
265     case ExpressionRangeInfo::FatLineAndColumnMode: {
266         createRareDataIfNecessary();
267         unsigned fatIndex = m_rareData->m_expressionInfoFatPositions.size();
268         ExpressionRangeInfo::FatPosition fatPos = { line, column };
269         m_rareData->m_expressionInfoFatPositions.append(fatPos);
270         info.position = fatIndex;
271     }
272     } // switch
273
274     m_expressionInfo.append(info);
275 }
276
277 bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
278 {
279     static const bool verbose = false;
280     if (!m_rareData) {
281         if (verbose)
282             dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
283         startDivot = UINT_MAX;
284         endDivot = UINT_MAX;
285         return false;
286     }
287
288     auto iter = m_rareData->m_typeProfilerInfoMap.find(bytecodeOffset);
289     if (iter == m_rareData->m_typeProfilerInfoMap.end()) {
290         if (verbose)
291             dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
292         startDivot = UINT_MAX;
293         endDivot = UINT_MAX;
294         return false;
295     }
296     
297     RareData::TypeProfilerExpressionRange& range = iter->value;
298     startDivot = range.m_startDivot;
299     endDivot = range.m_endDivot;
300     return true;
301 }
302
303 void UnlinkedCodeBlock::addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot)
304 {
305     createRareDataIfNecessary();
306     RareData::TypeProfilerExpressionRange range;
307     range.m_startDivot = startDivot;
308     range.m_endDivot = endDivot;
309     m_rareData->m_typeProfilerInfoMap.set(instructionOffset, range);
310 }
311
312 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
313 {
314     UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
315     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
316     Base::visitChildren(thisObject, visitor);
317 }
318
319 void UnlinkedModuleProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
320 {
321     UnlinkedModuleProgramCodeBlock* thisObject = jsCast<UnlinkedModuleProgramCodeBlock*>(cell);
322     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
323     Base::visitChildren(thisObject, visitor);
324 }
325
326 UnlinkedCodeBlock::~UnlinkedCodeBlock()
327 {
328 }
329
330 void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
331 {
332     jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
333 }
334
335 void UnlinkedModuleProgramCodeBlock::destroy(JSCell* cell)
336 {
337     jsCast<UnlinkedModuleProgramCodeBlock*>(cell)->~UnlinkedModuleProgramCodeBlock();
338 }
339
340 void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
341 {
342     jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
343 }
344
345 void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
346 {
347     jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
348 }
349
350 void UnlinkedFunctionExecutable::destroy(JSCell* cell)
351 {
352     jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
353 }
354
355 void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions)
356 {
357     ASSERT(instructions);
358     m_unlinkedInstructions = WTFMove(instructions);
359     Heap::heap(this)->reportExtraMemoryAllocated(m_unlinkedInstructions->sizeInBytes());
360 }
361
362 const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const
363 {
364     ASSERT(m_unlinkedInstructions.get());
365     return *m_unlinkedInstructions;
366 }
367
368 }
369