]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGGraph.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGGraph.cpp
CommitLineData
14957cd0 1/*
ed1e77d3 2 * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
14957cd0
A
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#include "DFGGraph.h"
28
81345200
A
29#if ENABLE(DFG_JIT)
30
ed1e77d3 31#include "BytecodeKills.h"
81345200 32#include "BytecodeLivenessAnalysisInlines.h"
14957cd0 33#include "CodeBlock.h"
93a37866 34#include "CodeBlockWithJITType.h"
ed1e77d3 35#include "DFGBlockWorklist.h"
81345200
A
36#include "DFGClobberSet.h"
37#include "DFGJITCode.h"
93a37866 38#include "DFGVariableAccessDataDump.h"
81345200 39#include "FullBytecodeLiveness.h"
93a37866 40#include "FunctionExecutableDump.h"
81345200 41#include "JIT.h"
ed1e77d3 42#include "JSLexicalEnvironment.h"
81345200
A
43#include "MaxFrameExtentForSlowPathCall.h"
44#include "OperandsInlines.h"
45#include "JSCInlines.h"
46#include "StackAlignment.h"
93a37866 47#include <wtf/CommaPrinter.h>
81345200 48#include <wtf/ListDump.h>
14957cd0
A
49
50namespace JSC { namespace DFG {
51
14957cd0
A
52// Creates an array of stringized names.
53static const char* dfgOpNames[] = {
54#define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
55 FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM)
56#undef STRINGIZE_DFG_OP_ENUM
57};
58
81345200 59Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
93a37866 60 : m_vm(vm)
81345200
A
61 , m_plan(plan)
62 , m_codeBlock(m_plan.codeBlock.get())
63 , m_profiledBlock(m_codeBlock->alternative())
64 , m_allocator(longLivedState.m_allocator)
81345200 65 , m_nextMachineLocal(0)
93a37866 66 , m_fixpointState(BeforeFixpoint)
ed1e77d3 67 , m_structureRegistrationState(HaveNotStartedRegistering)
93a37866
A
68 , m_form(LoadStore)
69 , m_unificationState(LocallyUnified)
70 , m_refCountState(EverythingIsLive)
6fe7ccc8 71{
93a37866 72 ASSERT(m_profiledBlock);
81345200 73
ed1e77d3
A
74 m_hasDebuggerEnabled = m_profiledBlock->globalObject()->hasDebugger()
75 || Options::forceDebuggerBytecodeGeneration();
6fe7ccc8
A
76}
77
93a37866 78Graph::~Graph()
6fe7ccc8 79{
ed1e77d3
A
80 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
81 BasicBlock* block = this->block(blockIndex);
82 if (!block)
83 continue;
84
85 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
86 m_allocator.free(block->phis[phiIndex]);
87 for (unsigned nodeIndex = block->size(); nodeIndex--;)
88 m_allocator.free(block->at(nodeIndex));
89 }
93a37866
A
90 m_allocator.freeAll();
91}
6fe7ccc8 92
93a37866
A
93const char *Graph::opName(NodeType op)
94{
95 return dfgOpNames[op];
6fe7ccc8
A
96}
97
93a37866 98static void printWhiteSpace(PrintStream& out, unsigned amount)
6fe7ccc8
A
99{
100 while (amount-- > 0)
93a37866 101 out.print(" ");
6fe7ccc8
A
102}
103
81345200 104bool Graph::dumpCodeOrigin(PrintStream& out, const char* prefix, Node* previousNode, Node* currentNode, DumpContext* context)
6fe7ccc8 105{
93a37866
A
106 if (!previousNode)
107 return false;
6fe7ccc8 108
81345200 109 if (previousNode->origin.semantic.inlineCallFrame == currentNode->origin.semantic.inlineCallFrame)
93a37866 110 return false;
6fe7ccc8 111
81345200
A
112 Vector<CodeOrigin> previousInlineStack = previousNode->origin.semantic.inlineStack();
113 Vector<CodeOrigin> currentInlineStack = currentNode->origin.semantic.inlineStack();
6fe7ccc8
A
114 unsigned commonSize = std::min(previousInlineStack.size(), currentInlineStack.size());
115 unsigned indexOfDivergence = commonSize;
116 for (unsigned i = 0; i < commonSize; ++i) {
117 if (previousInlineStack[i].inlineCallFrame != currentInlineStack[i].inlineCallFrame) {
118 indexOfDivergence = i;
119 break;
120 }
121 }
122
93a37866
A
123 bool hasPrinted = false;
124
6fe7ccc8
A
125 // Print the pops.
126 for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) {
93a37866
A
127 out.print(prefix);
128 printWhiteSpace(out, i * 2);
81345200 129 out.print("<-- ", inContext(*previousInlineStack[i].inlineCallFrame, context), "\n");
93a37866 130 hasPrinted = true;
6fe7ccc8
A
131 }
132
133 // Print the pushes.
134 for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) {
93a37866
A
135 out.print(prefix);
136 printWhiteSpace(out, i * 2);
81345200 137 out.print("--> ", inContext(*currentInlineStack[i].inlineCallFrame, context), "\n");
93a37866 138 hasPrinted = true;
6fe7ccc8 139 }
93a37866
A
140
141 return hasPrinted;
6fe7ccc8
A
142}
143
93a37866 144int Graph::amountOfNodeWhiteSpace(Node* node)
14957cd0 145{
81345200 146 return (node->origin.semantic.inlineDepth() - 1) * 2;
93a37866 147}
14957cd0 148
93a37866
A
149void Graph::printNodeWhiteSpace(PrintStream& out, Node* node)
150{
151 printWhiteSpace(out, amountOfNodeWhiteSpace(node));
152}
153
81345200 154void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext* context)
93a37866
A
155{
156 NodeType op = node->op();
157
158 unsigned refCount = node->refCount();
93a37866
A
159 bool mustGenerate = node->mustGenerate();
160 if (mustGenerate)
14957cd0 161 --refCount;
93a37866
A
162
163 out.print(prefix);
164 printNodeWhiteSpace(out, node);
14957cd0
A
165
166 // Example/explanation of dataflow dump output
167 //
168 // 14: <!2:7> GetByVal(@3, @13)
169 // ^1 ^2 ^3 ^4 ^5
170 //
171 // (1) The nodeIndex of this operation.
172 // (2) The reference count. The number printed is the 'real' count,
173 // not including the 'mustGenerate' ref. If the node is
174 // 'mustGenerate' then the count it prefixed with '!'.
175 // (3) The virtual register slot assigned to this node.
176 // (4) The name of the operation.
177 // (5) The arguments to the operation. The may be of the form:
178 // @# - a NodeIndex referencing a prior node in the graph.
179 // arg# - an argument number.
14957cd0
A
180 // id# - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
181 // var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
ed1e77d3
A
182 out.printf("% 4d:<%c%u:", (int)node->index(), mustGenerate ? '!' : ' ', refCount);
183 if (node->hasResult() && node->hasVirtualRegister() && node->virtualRegister().isValid())
93a37866 184 out.print(node->virtualRegister());
14957cd0 185 else
93a37866
A
186 out.print("-");
187 out.print(">\t", opName(op), "(");
188 CommaPrinter comma;
189 if (node->flags() & NodeHasVarArgs) {
190 for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
191 if (!m_varArgChildren[childIdx])
192 continue;
193 out.print(comma, m_varArgChildren[childIdx]);
6fe7ccc8
A
194 }
195 } else {
93a37866
A
196 if (!!node->child1() || !!node->child2() || !!node->child3())
197 out.print(comma, node->child1());
198 if (!!node->child2() || !!node->child3())
199 out.print(comma, node->child2());
200 if (!!node->child3())
201 out.print(comma, node->child3());
6fe7ccc8 202 }
14957cd0 203
93a37866
A
204 if (toCString(NodeFlagsDump(node->flags())) != "<empty>")
205 out.print(comma, NodeFlagsDump(node->flags()));
81345200
A
206 if (node->prediction())
207 out.print(comma, SpeculationDump(node->prediction()));
93a37866
A
208 if (node->hasArrayMode())
209 out.print(comma, node->arrayMode());
81345200
A
210 if (node->hasArithMode())
211 out.print(comma, node->arithMode());
ed1e77d3
A
212 if (node->hasScopeOffset())
213 out.print(comma, node->scopeOffset());
214 if (node->hasDirectArgumentsOffset())
215 out.print(comma, node->capturedArgumentsOffset());
93a37866 216 if (node->hasRegisterPointer())
ed1e77d3 217 out.print(comma, "global", globalObjectFor(node->origin.semantic)->findVariableIndex(node->variablePointer()), "(", RawPointer(node->variablePointer()), ")");
93a37866 218 if (node->hasIdentifier())
81345200 219 out.print(comma, "id", node->identifierNumber(), "{", identifiers()[node->identifierNumber()], "}");
ed1e77d3
A
220 if (node->hasPromotedLocationDescriptor())
221 out.print(comma, node->promotedLocationDescriptor());
81345200
A
222 if (node->hasStructureSet())
223 out.print(comma, inContext(node->structureSet(), context));
93a37866 224 if (node->hasStructure())
81345200 225 out.print(comma, inContext(*node->structure(), context));
ed1e77d3
A
226 if (node->hasTransition()) {
227 out.print(comma, pointerDumpInContext(node->transition(), context));
228#if USE(JSVALUE64)
229 out.print(", ID:", node->transition()->next->id());
230#else
231 out.print(", ID:", RawPointer(node->transition()->next));
232#endif
14957cd0 233 }
ed1e77d3
A
234 if (node->hasCellOperand()) {
235 if (!node->cellOperand()->value() || !node->cellOperand()->value().isCell())
236 out.print(comma, "invalid cell operand: ", node->cellOperand()->value());
237 else {
238 out.print(comma, pointerDump(node->cellOperand()->value().asCell()));
239 if (node->cellOperand()->value().isCell()) {
240 CallVariant variant(node->cellOperand()->value().asCell());
241 if (ExecutableBase* executable = variant.executable()) {
242 if (executable->isHostFunction())
243 out.print(comma, "<host function>");
244 else if (FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(executable))
245 out.print(comma, FunctionExecutableDump(functionExecutable));
246 else
247 out.print(comma, "<non-function executable>");
248 }
249 }
250 }
6fe7ccc8 251 }
93a37866 252 if (node->hasStorageAccessData()) {
ed1e77d3 253 StorageAccessData& storageAccessData = node->storageAccessData();
81345200 254 out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
93a37866 255 out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
14957cd0 256 }
81345200
A
257 if (node->hasMultiGetByOffsetData()) {
258 MultiGetByOffsetData& data = node->multiGetByOffsetData();
259 out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
260 for (unsigned i = 0; i < data.variants.size(); ++i)
261 out.print(comma, inContext(data.variants[i], context));
262 }
263 if (node->hasMultiPutByOffsetData()) {
264 MultiPutByOffsetData& data = node->multiPutByOffsetData();
265 out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
266 for (unsigned i = 0; i < data.variants.size(); ++i)
267 out.print(comma, inContext(data.variants[i], context));
268 }
269 ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
270 if (node->hasVariableAccessData(*this)) {
271 VariableAccessData* variableAccessData = node->tryGetVariableAccessData();
272 if (variableAccessData) {
273 VirtualRegister operand = variableAccessData->local();
ed1e77d3 274 out.print(comma, variableAccessData->local(), "(", VariableAccessDataDump(*this, variableAccessData), ")");
81345200 275 operand = variableAccessData->machineLocal();
ed1e77d3
A
276 if (operand.isValid())
277 out.print(comma, "machine:", operand);
81345200
A
278 }
279 }
ed1e77d3
A
280 if (node->hasStackAccessData()) {
281 StackAccessData* data = node->stackAccessData();
282 out.print(comma, data->local);
283 if (data->machineLocal.isValid())
284 out.print(comma, "machine:", data->machineLocal);
285 out.print(comma, data->format);
81345200 286 }
ed1e77d3
A
287 if (node->hasUnlinkedLocal())
288 out.print(comma, node->unlinkedLocal());
81345200
A
289 if (node->hasUnlinkedMachineLocal()) {
290 VirtualRegister operand = node->unlinkedMachineLocal();
ed1e77d3
A
291 if (operand.isValid())
292 out.print(comma, "machine:", operand);
14957cd0 293 }
93a37866
A
294 if (node->hasConstantBuffer()) {
295 out.print(comma);
296 out.print(node->startConstant(), ":[");
297 CommaPrinter anotherComma;
298 for (unsigned i = 0; i < node->numConstants(); ++i)
ed1e77d3 299 out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock->constantBuffer(node->startConstant())[i]), context));
93a37866 300 out.print("]");
14957cd0 301 }
93a37866
A
302 if (node->hasIndexingType())
303 out.print(comma, IndexingTypeDump(node->indexingType()));
81345200
A
304 if (node->hasTypedArrayType())
305 out.print(comma, node->typedArrayType());
306 if (node->hasPhi())
307 out.print(comma, "^", node->phi()->index());
93a37866
A
308 if (node->hasExecutionCounter())
309 out.print(comma, RawPointer(node->executionCounter()));
ed1e77d3
A
310 if (node->hasWatchpointSet())
311 out.print(comma, RawPointer(node->watchpointSet()));
81345200
A
312 if (node->hasStoragePointer())
313 out.print(comma, RawPointer(node->storagePointer()));
ed1e77d3
A
314 if (node->hasObjectMaterializationData())
315 out.print(comma, node->objectMaterializationData());
316 if (node->hasCallVarargsData())
317 out.print(comma, "firstVarArgOffset = ", node->callVarargsData()->firstVarArgOffset);
318 if (node->hasLoadVarargsData()) {
319 LoadVarargsData* data = node->loadVarargsData();
320 out.print(comma, "start = ", data->start, ", count = ", data->count);
321 if (data->machineStart.isValid())
322 out.print(", machineStart = ", data->machineStart);
323 if (data->machineCount.isValid())
324 out.print(", machineCount = ", data->machineCount);
325 out.print(", offset = ", data->offset, ", mandatoryMinimum = ", data->mandatoryMinimum);
326 out.print(", limit = ", data->limit);
14957cd0 327 }
ed1e77d3
A
328 if (node->isConstant())
329 out.print(comma, pointerDumpInContext(node->constant(), context));
81345200
A
330 if (node->isJump())
331 out.print(comma, "T:", *node->targetBlock());
93a37866 332 if (node->isBranch())
81345200
A
333 out.print(comma, "T:", node->branchData()->taken, ", F:", node->branchData()->notTaken);
334 if (node->isSwitch()) {
335 SwitchData* data = node->switchData();
336 out.print(comma, data->kind);
337 for (unsigned i = 0; i < data->cases.size(); ++i)
338 out.print(comma, inContext(data->cases[i].value, context), ":", data->cases[i].target);
339 out.print(comma, "default:", data->fallThrough);
340 }
341 ClobberSet reads;
342 ClobberSet writes;
343 addReadsAndWrites(*this, node, reads, writes);
344 if (!reads.isEmpty())
345 out.print(comma, "R:", sortedListDump(reads.direct(), ","));
346 if (!writes.isEmpty())
347 out.print(comma, "W:", sortedListDump(writes.direct(), ","));
ed1e77d3
A
348 if (node->origin.isSet()) {
349 out.print(comma, "bc#", node->origin.semantic.bytecodeIndex);
350 if (node->origin.semantic != node->origin.forExit)
351 out.print(comma, "exit: ", node->origin.forExit);
352 }
6fe7ccc8 353
93a37866 354 out.print(")");
14957cd0 355
ed1e77d3
A
356 if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
357 out.print(" predicting ", SpeculationDump(node->tryGetVariableAccessData()->prediction()));
358 else if (node->hasHeapPrediction())
359 out.print(" predicting ", SpeculationDump(node->getHeapPrediction()));
6fe7ccc8 360
93a37866
A
361 out.print("\n");
362}
363
ed1e77d3
A
364bool Graph::terminalsAreValid()
365{
366 for (BasicBlock* block : blocksInNaturalOrder()) {
367 if (!block->terminal())
368 return false;
369 }
370 return true;
371}
372
81345200 373void Graph::dumpBlockHeader(PrintStream& out, const char* prefix, BasicBlock* block, PhiNodeDumpMode phiNodeDumpMode, DumpContext* context)
93a37866 374{
ed1e77d3 375 out.print(prefix, "Block ", *block, " (", inContext(block->at(0)->origin.semantic, context), "):", block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "", "\n");
81345200
A
376 if (block->executionCount == block->executionCount)
377 out.print(prefix, " Execution count: ", block->executionCount, "\n");
93a37866 378 out.print(prefix, " Predecessors:");
81345200
A
379 for (size_t i = 0; i < block->predecessors.size(); ++i)
380 out.print(" ", *block->predecessors[i]);
93a37866 381 out.print("\n");
ed1e77d3
A
382 out.print(prefix, " Successors:");
383 if (block->terminal()) {
384 for (BasicBlock* successor : block->successors()) {
385 out.print(" ", *successor);
386 if (m_prePostNumbering.isValid())
387 out.print(" (", m_prePostNumbering.edgeKind(block, successor), ")");
93a37866 388 }
ed1e77d3
A
389 } else
390 out.print(" <invalid>");
391 out.print("\n");
392 if (m_dominators.isValid() && terminalsAreValid()) {
393 out.print(prefix, " Dominated by: ", m_dominators.dominatorsOf(block), "\n");
394 out.print(prefix, " Dominates: ", m_dominators.blocksDominatedBy(block), "\n");
395 out.print(prefix, " Dominance Frontier: ", m_dominators.dominanceFrontierOf(block), "\n");
396 out.print(prefix, " Iterated Dominance Frontier: ", m_dominators.iteratedDominanceFrontierOf(BlockList(1, block)), "\n");
93a37866 397 }
ed1e77d3
A
398 if (m_prePostNumbering.isValid())
399 out.print(prefix, " Pre/Post Numbering: ", m_prePostNumbering.preNumber(block), "/", m_prePostNumbering.postNumber(block), "\n");
81345200
A
400 if (m_naturalLoops.isValid()) {
401 if (const NaturalLoop* loop = m_naturalLoops.headerOf(block)) {
402 out.print(prefix, " Loop header, contains:");
403 Vector<BlockIndex> sortedBlockList;
404 for (unsigned i = 0; i < loop->size(); ++i)
405 sortedBlockList.append(loop->at(i)->index);
406 std::sort(sortedBlockList.begin(), sortedBlockList.end());
407 for (unsigned i = 0; i < sortedBlockList.size(); ++i)
408 out.print(" #", sortedBlockList[i]);
409 out.print("\n");
410 }
411
412 Vector<const NaturalLoop*> containingLoops =
413 m_naturalLoops.loopsOf(block);
414 if (!containingLoops.isEmpty()) {
415 out.print(prefix, " Containing loop headers:");
416 for (unsigned i = 0; i < containingLoops.size(); ++i)
417 out.print(" ", *containingLoops[i]->header());
418 out.print("\n");
419 }
420 }
421 if (!block->phis.isEmpty()) {
422 out.print(prefix, " Phi Nodes:");
423 for (size_t i = 0; i < block->phis.size(); ++i) {
424 Node* phiNode = block->phis[i];
425 if (!phiNode->shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly)
426 continue;
ed1e77d3 427 out.print(" @", phiNode->index(), "<", phiNode->local(), ",", phiNode->refCount(), ">->(");
81345200
A
428 if (phiNode->child1()) {
429 out.print("@", phiNode->child1()->index());
430 if (phiNode->child2()) {
431 out.print(", @", phiNode->child2()->index());
432 if (phiNode->child3())
433 out.print(", @", phiNode->child3()->index());
434 }
93a37866 435 }
81345200 436 out.print(")", i + 1 < block->phis.size() ? "," : "");
93a37866 437 }
81345200 438 out.print("\n");
93a37866 439 }
14957cd0
A
440}
441
81345200 442void Graph::dump(PrintStream& out, DumpContext* context)
14957cd0 443{
81345200
A
444 DumpContext myContext;
445 myContext.graph = this;
446 if (!context)
447 context = &myContext;
448
ed1e77d3
A
449 out.print("\n");
450 out.print("DFG for ", CodeBlockWithJITType(m_codeBlock, JITCode::DFGJIT), ":\n");
451 out.print(" Fixpoint state: ", m_fixpointState, "; Form: ", m_form, "; Unification state: ", m_unificationState, "; Ref count state: ", m_refCountState, "\n");
452 if (m_form == SSA)
453 out.print(" Argument formats: ", listDump(m_argumentFormats), "\n");
454 else
455 out.print(" Arguments: ", listDump(m_arguments), "\n");
456 out.print("\n");
81345200 457
93a37866 458 Node* lastNode = 0;
14957cd0 459 for (size_t b = 0; b < m_blocks.size(); ++b) {
6fe7ccc8 460 BasicBlock* block = m_blocks[b].get();
93a37866
A
461 if (!block)
462 continue;
81345200 463 dumpBlockHeader(out, "", block, DumpAllPhis, context);
ed1e77d3
A
464 out.print(" States: ", block->cfaStructureClobberStateAtHead);
465 if (!block->cfaHasVisited)
466 out.print(", CurrentlyCFAUnreachable");
467 if (!block->intersectionOfCFAHasVisited)
468 out.print(", CFAUnreachable");
469 out.print("\n");
81345200
A
470 switch (m_form) {
471 case LoadStore:
472 case ThreadedCPS: {
ed1e77d3 473 out.print(" Vars Before: ");
81345200
A
474 if (block->cfaHasVisited)
475 out.print(inContext(block->valuesAtHead, context));
476 else
477 out.print("<empty>");
478 out.print("\n");
ed1e77d3
A
479 out.print(" Intersected Vars Before: ");
480 if (block->intersectionOfCFAHasVisited)
481 out.print(inContext(block->intersectionOfPastValuesAtHead, context));
482 else
483 out.print("<empty>");
484 out.print("\n");
485 out.print(" Var Links: ", block->variablesAtHead, "\n");
81345200
A
486 break;
487 }
488
489 case SSA: {
490 RELEASE_ASSERT(block->ssa);
491 out.print(" Availability: ", block->ssa->availabilityAtHead, "\n");
492 out.print(" Live: ", nodeListDump(block->ssa->liveAtHead), "\n");
493 out.print(" Values: ", nodeMapDump(block->ssa->valuesAtHead, context), "\n");
494 break;
495 } }
6fe7ccc8 496 for (size_t i = 0; i < block->size(); ++i) {
81345200
A
497 dumpCodeOrigin(out, "", lastNode, block->at(i), context);
498 dump(out, "", block->at(i), context);
93a37866 499 lastNode = block->at(i);
6fe7ccc8 500 }
ed1e77d3
A
501 out.print(" States: ", block->cfaBranchDirection, ", ", block->cfaStructureClobberStateAtTail);
502 if (!block->cfaDidFinish)
503 out.print(", CFAInvalidated");
504 out.print("\n");
81345200
A
505 switch (m_form) {
506 case LoadStore:
507 case ThreadedCPS: {
ed1e77d3 508 out.print(" Vars After: ");
81345200
A
509 if (block->cfaHasVisited)
510 out.print(inContext(block->valuesAtTail, context));
511 else
512 out.print("<empty>");
513 out.print("\n");
ed1e77d3 514 out.print(" Var Links: ", block->variablesAtTail, "\n");
81345200
A
515 break;
516 }
517
518 case SSA: {
519 RELEASE_ASSERT(block->ssa);
520 out.print(" Availability: ", block->ssa->availabilityAtTail, "\n");
521 out.print(" Live: ", nodeListDump(block->ssa->liveAtTail), "\n");
522 out.print(" Values: ", nodeMapDump(block->ssa->valuesAtTail, context), "\n");
523 break;
524 } }
ed1e77d3
A
525 out.print("\n");
526 }
527
528 out.print("GC Values:\n");
529 for (FrozenValue* value : m_frozenValues) {
530 if (value->pointsToHeap())
531 out.print(" ", inContext(*value, &myContext), "\n");
81345200
A
532 }
533
534 if (!myContext.isEmpty()) {
ed1e77d3
A
535 myContext.dump(out);
536 out.print("\n");
14957cd0 537 }
14957cd0
A
538}
539
93a37866 540void Graph::dethread()
14957cd0 541{
81345200 542 if (m_form == LoadStore || m_form == SSA)
93a37866
A
543 return;
544
545 if (logCompilationChanges())
546 dataLog("Dethreading DFG graph.\n");
547
548 SamplingRegion samplingRegion("DFG Dethreading");
549
550 for (BlockIndex blockIndex = m_blocks.size(); blockIndex--;) {
551 BasicBlock* block = m_blocks[blockIndex].get();
552 if (!block)
553 continue;
554 for (unsigned phiIndex = block->phis.size(); phiIndex--;) {
555 Node* phi = block->phis[phiIndex];
556 phi->children.reset();
557 }
558 }
559
560 m_form = LoadStore;
6fe7ccc8 561}
14957cd0 562
81345200 563void Graph::handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock* block, BasicBlock* successor)
6fe7ccc8 564{
93a37866
A
565 if (!successor->isReachable) {
566 successor->isReachable = true;
81345200 567 worklist.append(successor);
93a37866
A
568 }
569
81345200 570 successor->predecessors.append(block);
6fe7ccc8 571}
14957cd0 572
93a37866 573void Graph::determineReachability()
6fe7ccc8 574{
81345200
A
575 Vector<BasicBlock*, 16> worklist;
576 worklist.append(block(0));
577 block(0)->isReachable = true;
93a37866 578 while (!worklist.isEmpty()) {
81345200
A
579 BasicBlock* block = worklist.takeLast();
580 for (unsigned i = block->numSuccessors(); i--;)
581 handleSuccessor(worklist, block, block->successor(i));
93a37866
A
582 }
583}
584
585void Graph::resetReachability()
586{
587 for (BlockIndex blockIndex = m_blocks.size(); blockIndex--;) {
588 BasicBlock* block = m_blocks[blockIndex].get();
589 if (!block)
590 continue;
591 block->isReachable = false;
81345200 592 block->predecessors.clear();
93a37866
A
593 }
594
595 determineReachability();
596}
597
ed1e77d3
A
598namespace {
599
600class RefCountCalculator {
601public:
602 RefCountCalculator(Graph& graph)
603 : m_graph(graph)
604 {
605 }
606
607 void calculate()
608 {
609 // First reset the counts to 0 for all nodes.
610 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
611 BasicBlock* block = m_graph.block(blockIndex);
612 if (!block)
613 continue;
614 for (unsigned indexInBlock = block->size(); indexInBlock--;)
615 block->at(indexInBlock)->setRefCount(0);
616 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
617 block->phis[phiIndex]->setRefCount(0);
618 }
619
620 // Now find the roots:
621 // - Nodes that are must-generate.
622 // - Nodes that are reachable from type checks.
623 // Set their ref counts to 1 and put them on the worklist.
624 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
625 BasicBlock* block = m_graph.block(blockIndex);
626 if (!block)
627 continue;
628 for (unsigned indexInBlock = block->size(); indexInBlock--;) {
629 Node* node = block->at(indexInBlock);
630 DFG_NODE_DO_TO_CHILDREN(m_graph, node, findTypeCheckRoot);
631 if (!(node->flags() & NodeMustGenerate))
632 continue;
633 if (!node->postfixRef())
634 m_worklist.append(node);
635 }
636 }
637
638 while (!m_worklist.isEmpty()) {
639 while (!m_worklist.isEmpty()) {
640 Node* node = m_worklist.last();
641 m_worklist.removeLast();
642 ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed.
643 DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge);
644 }
645
646 if (m_graph.m_form == SSA) {
647 // Find Phi->Upsilon edges, which are represented as meta-data in the
648 // Upsilon.
649 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
650 BasicBlock* block = m_graph.block(blockIndex);
651 if (!block)
652 continue;
653 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
654 Node* node = block->at(nodeIndex);
655 if (node->op() != Upsilon)
656 continue;
657 if (node->shouldGenerate())
658 continue;
659 if (node->phi()->shouldGenerate())
660 countNode(node);
661 }
662 }
663 }
664 }
665 }
666
667private:
668 void findTypeCheckRoot(Node*, Edge edge)
669 {
670 // We may have an "unproved" untyped use for code that is unreachable. The CFA
671 // will just not have gotten around to it.
672 if (edge.isProved() || edge.willNotHaveCheck())
673 return;
674 if (!edge->postfixRef())
675 m_worklist.append(edge.node());
676 }
677
678 void countNode(Node* node)
679 {
680 if (node->postfixRef())
681 return;
682 m_worklist.append(node);
683 }
684
685 void countEdge(Node*, Edge edge)
686 {
687 // Don't count edges that are already counted for their type checks.
688 if (!(edge.isProved() || edge.willNotHaveCheck()))
689 return;
690 countNode(edge.node());
691 }
692
693 Graph& m_graph;
694 Vector<Node*, 128> m_worklist;
695};
696
697} // anonymous namespace
698
699void Graph::computeRefCounts()
700{
701 RefCountCalculator calculator(*this);
702 calculator.calculate();
703}
704
81345200
A
705void Graph::killBlockAndItsContents(BasicBlock* block)
706{
707 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
708 m_allocator.free(block->phis[phiIndex]);
709 for (unsigned nodeIndex = block->size(); nodeIndex--;)
710 m_allocator.free(block->at(nodeIndex));
711
712 killBlock(block);
713}
714
715void Graph::killUnreachableBlocks()
716{
717 for (BlockIndex blockIndex = 0; blockIndex < numBlocks(); ++blockIndex) {
718 BasicBlock* block = this->block(blockIndex);
719 if (!block)
720 continue;
721 if (block->isReachable)
722 continue;
723
724 killBlockAndItsContents(block);
725 }
726}
727
81345200
A
728void Graph::invalidateCFG()
729{
730 m_dominators.invalidate();
731 m_naturalLoops.invalidate();
ed1e77d3 732 m_prePostNumbering.invalidate();
81345200
A
733}
734
735void Graph::substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal)
736{
81345200
A
737 for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
738 Node* node = block[indexInBlock];
739 bool shouldContinue = true;
740 switch (node->op()) {
741 case SetLocal: {
742 if (node->local() == variableAccessData->local())
743 shouldContinue = false;
744 break;
745 }
746
747 case GetLocal: {
748 if (node->variableAccessData() != variableAccessData)
749 continue;
750 substitute(block, indexInBlock, node, newGetLocal);
751 Node* oldTailNode = block.variablesAtTail.operand(variableAccessData->local());
752 if (oldTailNode == node)
753 block.variablesAtTail.operand(variableAccessData->local()) = newGetLocal;
754 shouldContinue = false;
755 break;
756 }
757
758 default:
759 break;
760 }
761 if (!shouldContinue)
762 break;
763 }
764}
765
ed1e77d3 766BlockList Graph::blocksInPreOrder()
81345200 767{
ed1e77d3
A
768 BlockList result;
769 BlockWorklist worklist;
770 worklist.push(block(0));
771 while (BasicBlock* block = worklist.pop()) {
772 result.append(block);
773 for (unsigned i = block->numSuccessors(); i--;)
774 worklist.push(block->successor(i));
775 }
776 return result;
81345200
A
777}
778
ed1e77d3 779BlockList Graph::blocksInPostOrder()
81345200 780{
ed1e77d3
A
781 BlockList result;
782 PostOrderBlockWorklist worklist;
783 worklist.push(block(0));
784 while (BlockWithOrder item = worklist.pop()) {
785 switch (item.order) {
786 case PreOrder:
787 worklist.pushPost(item.block);
788 for (unsigned i = item.block->numSuccessors(); i--;)
789 worklist.push(item.block->successor(i));
790 break;
791 case PostOrder:
792 result.append(item.block);
793 break;
794 }
81345200 795 }
ed1e77d3 796 return result;
81345200
A
797}
798
799void Graph::clearReplacements()
800{
801 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
802 BasicBlock* block = m_blocks[blockIndex].get();
803 if (!block)
804 continue;
805 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
ed1e77d3 806 block->phis[phiIndex]->setReplacement(nullptr);
81345200 807 for (unsigned nodeIndex = block->size(); nodeIndex--;)
ed1e77d3
A
808 block->at(nodeIndex)->setReplacement(nullptr);
809 }
810}
811
812void Graph::clearEpochs()
813{
814 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
815 BasicBlock* block = m_blocks[blockIndex].get();
816 if (!block)
817 continue;
818 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
819 block->phis[phiIndex]->setEpoch(Epoch());
820 for (unsigned nodeIndex = block->size(); nodeIndex--;)
821 block->at(nodeIndex)->setEpoch(Epoch());
81345200
A
822 }
823}
824
825void Graph::initializeNodeOwners()
826{
827 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
828 BasicBlock* block = m_blocks[blockIndex].get();
829 if (!block)
830 continue;
831 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
ed1e77d3 832 block->phis[phiIndex]->owner = block;
81345200 833 for (unsigned nodeIndex = block->size(); nodeIndex--;)
ed1e77d3 834 block->at(nodeIndex)->owner = block;
81345200
A
835 }
836}
837
838void Graph::clearFlagsOnAllNodes(NodeFlags flags)
839{
840 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
841 BasicBlock* block = m_blocks[blockIndex].get();
842 if (!block)
843 continue;
844 for (unsigned phiIndex = block->phis.size(); phiIndex--;)
845 block->phis[phiIndex]->clearFlags(flags);
846 for (unsigned nodeIndex = block->size(); nodeIndex--;)
847 block->at(nodeIndex)->clearFlags(flags);
848 }
849}
850
851FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
852{
853 HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
854 if (iter != m_bytecodeLiveness.end())
855 return *iter->value;
856
857 std::unique_ptr<FullBytecodeLiveness> liveness = std::make_unique<FullBytecodeLiveness>();
858 codeBlock->livenessAnalysis().computeFullLiveness(*liveness);
859 FullBytecodeLiveness& result = *liveness;
860 m_bytecodeLiveness.add(codeBlock, WTF::move(liveness));
861 return result;
862}
863
864FullBytecodeLiveness& Graph::livenessFor(InlineCallFrame* inlineCallFrame)
865{
866 return livenessFor(baselineCodeBlockFor(inlineCallFrame));
867}
868
ed1e77d3
A
869BytecodeKills& Graph::killsFor(CodeBlock* codeBlock)
870{
871 HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>>::iterator iter = m_bytecodeKills.find(codeBlock);
872 if (iter != m_bytecodeKills.end())
873 return *iter->value;
874
875 std::unique_ptr<BytecodeKills> kills = std::make_unique<BytecodeKills>();
876 codeBlock->livenessAnalysis().computeKills(*kills);
877 BytecodeKills& result = *kills;
878 m_bytecodeKills.add(codeBlock, WTF::move(kills));
879 return result;
880}
881
882BytecodeKills& Graph::killsFor(InlineCallFrame* inlineCallFrame)
883{
884 return killsFor(baselineCodeBlockFor(inlineCallFrame));
885}
886
81345200
A
887bool Graph::isLiveInBytecode(VirtualRegister operand, CodeOrigin codeOrigin)
888{
889 for (;;) {
890 VirtualRegister reg = VirtualRegister(
891 operand.offset() - codeOrigin.stackOffset());
892
893 if (operand.offset() < codeOrigin.stackOffset() + JSStack::CallFrameHeaderSize) {
894 if (reg.isArgument()) {
895 RELEASE_ASSERT(reg.offset() < JSStack::CallFrameHeaderSize);
896
ed1e77d3
A
897 if (codeOrigin.inlineCallFrame->isClosureCall
898 && reg.offset() == JSStack::Callee)
81345200 899 return true;
ed1e77d3
A
900
901 if (codeOrigin.inlineCallFrame->isVarargs()
902 && reg.offset() == JSStack::ArgumentCount)
81345200
A
903 return true;
904
905 return false;
906 }
907
908 return livenessFor(codeOrigin.inlineCallFrame).operandIsLive(
909 reg.offset(), codeOrigin.bytecodeIndex);
910 }
911
912 InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
913 if (!inlineCallFrame)
914 break;
915
916 // Arguments are always live. This would be redundant if it wasn't for our
917 // op_call_varargs inlining.
81345200
A
918 if (reg.isArgument()
919 && static_cast<size_t>(reg.toArgument()) < inlineCallFrame->arguments.size())
920 return true;
921
922 codeOrigin = inlineCallFrame->caller;
923 }
924
925 return true;
926}
927
ed1e77d3
A
928BitVector Graph::localsLiveInBytecode(CodeOrigin codeOrigin)
929{
930 BitVector result;
931 result.ensureSize(block(0)->variablesAtHead.numberOfLocals());
932 forAllLocalsLiveInBytecode(
933 codeOrigin,
934 [&] (VirtualRegister reg) {
935 ASSERT(reg.isLocal());
936 result.quickSet(reg.toLocal());
937 });
938 return result;
939}
940
81345200
A
941unsigned Graph::frameRegisterCount()
942{
943 unsigned result = m_nextMachineLocal + std::max(m_parameterSlots, static_cast<unsigned>(maxFrameExtentForSlowPathCallInRegisters));
944 return roundLocalRegisterCountForFramePointerOffset(result);
945}
946
947unsigned Graph::stackPointerOffset()
948{
949 return virtualRegisterForLocal(frameRegisterCount() - 1).offset();
950}
951
952unsigned Graph::requiredRegisterCountForExit()
953{
954 unsigned count = JIT::frameRegisterCountFor(m_profiledBlock);
955 for (InlineCallFrameSet::iterator iter = m_plan.inlineCallFrames->begin(); !!iter; ++iter) {
956 InlineCallFrame* inlineCallFrame = *iter;
957 CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
958 unsigned requiredCount = VirtualRegister(inlineCallFrame->stackOffset).toLocal() + 1 + JIT::frameRegisterCountFor(codeBlock);
959 count = std::max(count, requiredCount);
960 }
961 return count;
962}
963
964unsigned Graph::requiredRegisterCountForExecutionAndExit()
965{
966 return std::max(frameRegisterCount(), requiredRegisterCountForExit());
967}
968
ed1e77d3
A
969JSValue Graph::tryGetConstantProperty(
970 JSValue base, const StructureSet& structureSet, PropertyOffset offset)
81345200 971{
ed1e77d3
A
972 if (!base || !base.isObject())
973 return JSValue();
974
975 JSObject* object = asObject(base);
976
977 for (unsigned i = structureSet.size(); i--;) {
978 Structure* structure = structureSet[i];
979 WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset);
980 if (!set || !set->isStillValid())
981 return JSValue();
982
983 ASSERT(structure->isValidOffset(offset));
984 ASSERT(!structure->isUncacheableDictionary());
985
986 watchpoints().addLazily(set);
987 }
988
989 // What follows may require some extra thought. We need this load to load a valid JSValue. If
990 // our profiling makes sense and we're still on track to generate code that won't be
991 // invalidated, then we have nothing to worry about. We do, however, have to worry about
992 // loading - and then using - an invalid JSValue in the case that unbeknownst to us our code
993 // is doomed.
994 //
995 // One argument in favor of this code is that it should definitely work because the butterfly
996 // is always set before the structure. However, we don't currently have a fence between those
997 // stores. It's not clear if this matters, however. We don't ever shrink the property storage.
998 // So, for this to fail, you'd need an access on a constant object pointer such that the inline
999 // caches told us that the object had a structure that it did not *yet* have, and then later,
1000 // the object transitioned to that structure that the inline caches had alraedy seen. And then
1001 // the processor reordered the stores. Seems unlikely and difficult to test. I believe that
1002 // this is worth revisiting but it isn't worth losing sleep over. Filed:
1003 // https://bugs.webkit.org/show_bug.cgi?id=134641
1004 //
1005 // For now, we just do the minimal thing: defend against the structure right now being
1006 // incompatible with the getDirect we're trying to do. The easiest way to do that is to
1007 // determine if the structure belongs to the proven set.
1008
1009 if (!structureSet.contains(object->structure()))
1010 return JSValue();
1011
1012 return object->getDirect(offset);
1013}
1014
1015JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset)
1016{
1017 return tryGetConstantProperty(base, StructureSet(structure), offset);
81345200
A
1018}
1019
ed1e77d3
A
1020JSValue Graph::tryGetConstantProperty(
1021 JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
81345200 1022{
ed1e77d3
A
1023 if (structure.isTop() || structure.isClobbered())
1024 return JSValue();
1025
1026 return tryGetConstantProperty(base, structure.set(), offset);
1027}
1028
1029JSValue Graph::tryGetConstantProperty(const AbstractValue& base, PropertyOffset offset)
1030{
1031 return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1032}
1033
1034JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1035{
1036 // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
1037
1038 if (!base)
1039 return JSValue();
1040
1041 JSLexicalEnvironment* activation = jsDynamicCast<JSLexicalEnvironment*>(base);
81345200 1042 if (!activation)
ed1e77d3
A
1043 return JSValue();
1044
1045 SymbolTable* symbolTable = activation->symbolTable();
1046 JSValue value;
1047 WatchpointSet* set;
1048 {
1049 ConcurrentJITLocker locker(symbolTable->m_lock);
1050
1051 SymbolTableEntry* entry = symbolTable->entryFor(locker, offset);
1052 if (!entry)
1053 return JSValue();
1054
1055 set = entry->watchpointSet();
1056 if (!set)
1057 return JSValue();
1058
1059 if (set->state() != IsWatched)
1060 return JSValue();
1061
1062 ASSERT(entry->scopeOffset() == offset);
1063 value = activation->variableAt(offset).get();
1064 if (!value)
1065 return JSValue();
1066 }
1067
1068 watchpoints().addLazily(set);
1069
1070 return value;
81345200
A
1071}
1072
ed1e77d3
A
1073JSValue Graph::tryGetConstantClosureVar(const AbstractValue& value, ScopeOffset offset)
1074{
1075 return tryGetConstantClosureVar(value.m_value, offset);
1076}
1077
1078JSValue Graph::tryGetConstantClosureVar(Node* node, ScopeOffset offset)
81345200
A
1079{
1080 if (!node->hasConstant())
ed1e77d3
A
1081 return JSValue();
1082 return tryGetConstantClosureVar(node->asJSValue(), offset);
1083}
1084
1085JSArrayBufferView* Graph::tryGetFoldableView(JSValue value)
1086{
1087 if (!value)
1088 return nullptr;
1089 JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(value);
1090 if (!value)
1091 return nullptr;
1092 if (!view->length())
1093 return nullptr;
1094 WTF::loadLoadFence();
1095 watchpoints().addLazily(view);
81345200
A
1096 return view;
1097}
1098
ed1e77d3 1099JSArrayBufferView* Graph::tryGetFoldableView(JSValue value, ArrayMode arrayMode)
81345200
A
1100{
1101 if (arrayMode.typedArrayType() == NotTypedArray)
ed1e77d3
A
1102 return nullptr;
1103 return tryGetFoldableView(value);
81345200
A
1104}
1105
ed1e77d3 1106void Graph::registerFrozenValues()
81345200 1107{
ed1e77d3
A
1108 m_codeBlock->constants().resize(0);
1109 m_codeBlock->constantsSourceCodeRepresentation().resize(0);
1110 for (FrozenValue* value : m_frozenValues) {
1111 if (!value->pointsToHeap())
1112 continue;
1113
1114 ASSERT(value->structure());
1115 ASSERT(m_plan.weakReferences.contains(value->structure()));
1116
1117 switch (value->strength()) {
1118 case WeakValue: {
1119 m_plan.weakReferences.addLazily(value->value().asCell());
1120 break;
1121 }
1122 case StrongValue: {
1123 unsigned constantIndex = m_codeBlock->addConstantLazily();
1124 initializeLazyWriteBarrierForConstant(
1125 m_plan.writeBarriers,
1126 m_codeBlock->constants()[constantIndex],
1127 m_codeBlock,
1128 constantIndex,
1129 m_codeBlock->ownerExecutable(),
1130 value->value());
1131 break;
1132 } }
1133 }
1134 m_codeBlock->constants().shrinkToFit();
1135 m_codeBlock->constantsSourceCodeRepresentation().shrinkToFit();
81345200
A
1136}
1137
1138void Graph::visitChildren(SlotVisitor& visitor)
1139{
ed1e77d3
A
1140 for (FrozenValue* value : m_frozenValues) {
1141 visitor.appendUnbarrieredReadOnlyValue(value->value());
1142 visitor.appendUnbarrieredReadOnlyPointer(value->structure());
1143 }
1144
81345200
A
1145 for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
1146 BasicBlock* block = this->block(blockIndex);
1147 if (!block)
1148 continue;
1149
1150 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
1151 Node* node = block->at(nodeIndex);
1152
1153 switch (node->op()) {
81345200
A
1154 case CheckStructure:
1155 for (unsigned i = node->structureSet().size(); i--;)
1156 visitor.appendUnbarrieredReadOnlyPointer(node->structureSet()[i]);
1157 break;
1158
81345200
A
1159 case NewObject:
1160 case ArrayifyToStructure:
1161 case NewStringObject:
1162 visitor.appendUnbarrieredReadOnlyPointer(node->structure());
1163 break;
1164
1165 case PutStructure:
81345200
A
1166 case AllocatePropertyStorage:
1167 case ReallocatePropertyStorage:
1168 visitor.appendUnbarrieredReadOnlyPointer(
ed1e77d3 1169 node->transition()->previous);
81345200 1170 visitor.appendUnbarrieredReadOnlyPointer(
ed1e77d3
A
1171 node->transition()->next);
1172 break;
1173
1174 case MultiGetByOffset:
1175 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
1176 GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
1177 const StructureSet& set = variant.structureSet();
1178 for (unsigned j = set.size(); j--;)
1179 visitor.appendUnbarrieredReadOnlyPointer(set[j]);
1180
1181 // Don't need to mark anything in the structure chain because that would
1182 // have been decomposed into CheckStructure's. Don't need to mark the
1183 // callLinkStatus because we wouldn't use MultiGetByOffset if any of the
1184 // variants did that.
1185 ASSERT(!variant.callLinkStatus());
1186 }
1187 break;
1188
1189 case MultiPutByOffset:
1190 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1191 PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1192 const StructureSet& set = variant.oldStructure();
1193 for (unsigned j = set.size(); j--;)
1194 visitor.appendUnbarrieredReadOnlyPointer(set[j]);
1195 if (variant.kind() == PutByIdVariant::Transition)
1196 visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure());
1197 }
81345200
A
1198 break;
1199
1200 default:
1201 break;
1202 }
1203 }
1204 }
1205}
1206
ed1e77d3
A
1207FrozenValue* Graph::freeze(JSValue value)
1208{
1209 if (UNLIKELY(!value))
1210 return FrozenValue::emptySingleton();
1211
1212 auto result = m_frozenValueMap.add(JSValue::encode(value), nullptr);
1213 if (LIKELY(!result.isNewEntry))
1214 return result.iterator->value;
1215
1216 if (value.isUInt32())
1217 m_uint32ValuesInUse.append(value.asUInt32());
1218
1219 FrozenValue frozenValue = FrozenValue::freeze(value);
1220 if (Structure* structure = frozenValue.structure())
1221 registerStructure(structure);
1222
1223 return result.iterator->value = m_frozenValues.add(frozenValue);
1224}
1225
1226FrozenValue* Graph::freezeStrong(JSValue value)
1227{
1228 FrozenValue* result = freeze(value);
1229 result->strengthenTo(StrongValue);
1230 return result;
1231}
1232
1233void Graph::convertToConstant(Node* node, FrozenValue* value)
1234{
1235 if (value->structure())
1236 assertIsRegistered(value->structure());
1237 node->convertToConstant(value);
1238}
1239
1240void Graph::convertToConstant(Node* node, JSValue value)
1241{
1242 convertToConstant(node, freeze(value));
1243}
1244
1245void Graph::convertToStrongConstant(Node* node, JSValue value)
1246{
1247 convertToConstant(node, freezeStrong(value));
1248}
1249
1250StructureRegistrationResult Graph::registerStructure(Structure* structure)
1251{
1252 m_plan.weakReferences.addLazily(structure);
1253 if (m_plan.watchpoints.consider(structure))
1254 return StructureRegisteredAndWatched;
1255 return StructureRegisteredNormally;
1256}
1257
1258void Graph::assertIsRegistered(Structure* structure)
1259{
1260 // It's convenient to be able to call this with a maybe-null structure.
1261 if (!structure)
1262 return;
1263
1264 if (m_structureRegistrationState == HaveNotStartedRegistering)
1265 return;
1266
1267 DFG_ASSERT(*this, nullptr, m_plan.weakReferences.contains(structure));
1268
1269 if (!structure->dfgShouldWatch())
1270 return;
1271 if (watchpoints().isWatched(structure->transitionWatchpointSet()))
1272 return;
1273
1274 DFG_CRASH(*this, nullptr, toCString("Structure ", pointerDump(structure), " is watchable but isn't being watched.").data());
1275}
1276
1277NO_RETURN_DUE_TO_CRASH static void crash(
1278 Graph& graph, const CString& whileText, const char* file, int line, const char* function,
1279 const char* assertion)
1280{
1281 startCrashing();
1282 dataLog("DFG ASSERTION FAILED: ", assertion, "\n");
1283 dataLog(file, "(", line, ") : ", function, "\n");
1284 dataLog("\n");
1285 dataLog(whileText);
1286 dataLog("Graph at time of failure:\n");
1287 graph.dump();
1288 dataLog("\n");
1289 dataLog("DFG ASSERTION FAILED: ", assertion, "\n");
1290 dataLog(file, "(", line, ") : ", function, "\n");
1291 CRASH_WITH_SECURITY_IMPLICATION();
1292}
1293
1294void Graph::handleAssertionFailure(
1295 std::nullptr_t, const char* file, int line, const char* function, const char* assertion)
1296{
1297 crash(*this, "", file, line, function, assertion);
1298}
1299
1300void Graph::handleAssertionFailure(
1301 Node* node, const char* file, int line, const char* function, const char* assertion)
1302{
1303 crash(*this, toCString("While handling node ", node, "\n\n"), file, line, function, assertion);
1304}
1305
1306void Graph::handleAssertionFailure(
1307 BasicBlock* block, const char* file, int line, const char* function, const char* assertion)
1308{
1309 crash(*this, toCString("While handling block ", pointerDump(block), "\n\n"), file, line, function, assertion);
1310}
1311
1312ValueProfile* Graph::valueProfileFor(Node* node)
1313{
1314 if (!node)
1315 return nullptr;
1316
1317 CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
1318
1319 if (node->hasLocal(*this)) {
1320 if (!node->local().isArgument())
1321 return nullptr;
1322 int argument = node->local().toArgument();
1323 Node* argumentNode = m_arguments[argument];
1324 if (!argumentNode)
1325 return nullptr;
1326 if (node->variableAccessData() != argumentNode->variableAccessData())
1327 return nullptr;
1328 return profiledBlock->valueProfileForArgument(argument);
1329 }
1330
1331 if (node->hasHeapPrediction())
1332 return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
1333
1334 return nullptr;
1335}
1336
1337MethodOfGettingAValueProfile Graph::methodOfGettingAValueProfileFor(Node* node)
1338{
1339 if (!node)
1340 return MethodOfGettingAValueProfile();
1341
1342 if (ValueProfile* valueProfile = valueProfileFor(node))
1343 return MethodOfGettingAValueProfile(valueProfile);
1344
1345 if (node->op() == GetLocal) {
1346 CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
1347
1348 return MethodOfGettingAValueProfile::fromLazyOperand(
1349 profiledBlock,
1350 LazyOperandValueProfileKey(
1351 node->origin.semantic.bytecodeIndex, node->local()));
1352 }
1353
1354 return MethodOfGettingAValueProfile();
1355}
1356
14957cd0
A
1357} } // namespace JSC::DFG
1358
81345200 1359#endif // ENABLE(DFG_JIT)