blob: 5d6329d28f5ff3bf65a1cfca47aa677416935e2f [file] [log] [blame]
fpizlo@apple.com3187c922012-05-18 21:47:53 +00001/*
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
fpizlo@apple.com3187c922012-05-18 21:47:53 +00003 *
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"
ossy@webkit.orgbeb0de42014-02-17 19:00:03 +000027#include "DFGConstantFoldingPhase.h"
fpizlo@apple.com3187c922012-05-18 21:47:53 +000028
29#if ENABLE(DFG_JIT)
30
oliver@apple.com55d32d92013-07-25 04:05:03 +000031#include "DFGAbstractInterpreterInlines.h"
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000032#include "DFGArgumentsUtilities.h"
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000033#include "DFGBasicBlockInlines.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000034#include "DFGGraph.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000035#include "DFGInPlaceAbstractState.h"
fpizlo@apple.com12835772015-09-21 20:49:04 +000036#include "DFGInferredTypeCheck.h"
fpizlo@apple.com3187c922012-05-18 21:47:53 +000037#include "DFGInsertionSet.h"
38#include "DFGPhase.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000039#include "GetByIdStatus.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000040#include "JSCInlines.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000041#include "PutByIdStatus.h"
fpizlo@apple.com3187c922012-05-18 21:47:53 +000042
43namespace JSC { namespace DFG {
44
45class ConstantFoldingPhase : public Phase {
46public:
47 ConstantFoldingPhase(Graph& graph)
48 : Phase(graph, "constant folding")
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +000049 , m_state(graph)
oliver@apple.com55d32d92013-07-25 04:05:03 +000050 , m_interpreter(graph, m_state)
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +000051 , m_insertionSet(graph)
fpizlo@apple.com3187c922012-05-18 21:47:53 +000052 {
53 }
54
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000055 bool run()
fpizlo@apple.com3187c922012-05-18 21:47:53 +000056 {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000057 bool changed = false;
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000058
59 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +000060 if (block->cfaFoundConstants)
oliver@apple.com426f5b02013-07-25 04:04:27 +000061 changed |= foldConstants(block);
fpizlo@apple.com3187c922012-05-18 21:47:53 +000062 }
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000063
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000064 if (changed && m_graph.m_form == SSA) {
65 // It's now possible that we have Upsilons pointed at JSConstants. Fix that.
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000066 for (BasicBlock* block : m_graph.blocksInNaturalOrder())
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000067 fixUpsilons(block);
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000068 }
69
70 if (m_graph.m_form == SSA) {
71 // It's now possible to simplify basic blocks by placing an Unreachable terminator right
72 // after anything that invalidates AI.
73 bool didClipBlock = false;
benjamin@webkit.org0628f232016-07-27 23:22:55 +000074 Vector<Node*> nodesToDelete;
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000075 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
76 m_state.beginBasicBlock(block);
77 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
78 if (block->at(nodeIndex)->isTerminal()) {
79 // It's possible that we have something after the terminal. It could be a
80 // no-op Check node, for example. We don't want the logic below to turn that
81 // node into Unreachable, since then we'd have two terminators.
82 break;
83 }
84 if (!m_state.isValid()) {
85 NodeOrigin origin = block->at(nodeIndex)->origin;
86 for (unsigned killIndex = nodeIndex; killIndex < block->size(); ++killIndex)
benjamin@webkit.org0628f232016-07-27 23:22:55 +000087 nodesToDelete.append(block->at(killIndex));
fpizlo@apple.comead5edd2015-10-09 00:13:58 +000088 block->resize(nodeIndex);
89 block->appendNode(m_graph, SpecNone, Unreachable, origin);
90 didClipBlock = true;
91 break;
92 }
93 m_interpreter.execute(nodeIndex);
94 }
95 m_state.reset();
96 }
97
98 if (didClipBlock) {
99 changed = true;
benjamin@webkit.org0628f232016-07-27 23:22:55 +0000100
101 m_graph.invalidateNodeLiveness();
102
103 for (Node* node : nodesToDelete)
commit-queue@webkit.orgaa93e082016-07-28 01:36:44 +0000104 m_graph.deleteNode(node);
benjamin@webkit.org0628f232016-07-27 23:22:55 +0000105
fpizlo@apple.comead5edd2015-10-09 00:13:58 +0000106 m_graph.invalidateCFG();
107 m_graph.resetReachability();
108 m_graph.killUnreachableBlocks();
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000109 }
110 }
111
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000112 return changed;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000113 }
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000114
115private:
oliver@apple.com426f5b02013-07-25 04:04:27 +0000116 bool foldConstants(BasicBlock* block)
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000117 {
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000118 bool changed = false;
119 m_state.beginBasicBlock(block);
120 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000121 if (!m_state.isValid())
122 break;
123
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000124 Node* node = block->at(indexInBlock);
125
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000126 bool alreadyHandled = false;
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000127 bool eliminated = false;
128
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000129 switch (node->op()) {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000130 case BooleanToNumber: {
131 if (node->child1().useKind() == UntypedUse
132 && !m_interpreter.needsTypeCheck(node->child1(), SpecBoolean))
133 node->child1().setUseKind(BooleanUse);
134 break;
135 }
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +0000136
137 case CompareEq: {
138 if (!m_interpreter.needsTypeCheck(node->child1(), SpecOther))
139 node->child1().setUseKind(OtherUse);
140 if (!m_interpreter.needsTypeCheck(node->child2(), SpecOther))
141 node->child2().setUseKind(OtherUse);
142 break;
143 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000144
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +0000145 case CheckStructure:
fpizlo@apple.com99f37622012-10-29 04:02:08 +0000146 case ArrayifyToStructure: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000147 AbstractValue& value = m_state.forNode(node->child1());
fpizlo@apple.com99f37622012-10-29 04:02:08 +0000148 StructureSet set;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000149 if (node->op() == ArrayifyToStructure)
150 set = node->structure();
fpizlo@apple.com99f37622012-10-29 04:02:08 +0000151 else
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000152 set = node->structureSet();
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000153 if (value.m_structure.isSubsetOf(set)) {
oliver@apple.com55d32d92013-07-25 04:05:03 +0000154 m_interpreter.execute(indexInBlock); // Catch the fact that we may filter on cell.
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000155 node->remove();
fpizlo@apple.com99f37622012-10-29 04:02:08 +0000156 eliminated = true;
157 break;
158 }
fpizlo@apple.comeb3323d2012-08-20 06:11:24 +0000159 break;
160 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000161
fpizlo@apple.com93373ba2015-04-07 22:09:15 +0000162 case GetIndexedPropertyStorage: {
163 JSArrayBufferView* view = m_graph.tryGetFoldableView(
164 m_state.forNode(node->child1()).m_value, node->arrayMode());
165 if (!view)
166 break;
167
168 if (view->mode() == FastTypedArray) {
169 // FIXME: It would be awesome to be able to fold the property storage for
170 // these GC-allocated typed arrays. For now it doesn't matter because the
171 // most common use-cases for constant typed arrays involve large arrays with
172 // aliased buffer views.
173 // https://bugs.webkit.org/show_bug.cgi?id=125425
174 break;
175 }
176
177 m_interpreter.execute(indexInBlock);
178 eliminated = true;
179
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000180 m_insertionSet.insertCheck(indexInBlock, node->origin, node->children);
fpizlo@apple.com93373ba2015-04-07 22:09:15 +0000181 node->convertToConstantStoragePointer(view->vector());
182 break;
183 }
184
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000185 case CheckStructureImmediate: {
186 AbstractValue& value = m_state.forNode(node->child1());
187 StructureSet& set = node->structureSet();
188
189 if (value.value()) {
190 if (Structure* structure = jsDynamicCast<Structure*>(value.value())) {
191 if (set.contains(structure)) {
192 m_interpreter.execute(indexInBlock);
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000193 node->remove();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000194 eliminated = true;
195 break;
196 }
197 }
198 }
199
200 if (PhiChildren* phiChildren = m_interpreter.phiChildren()) {
201 bool allGood = true;
202 phiChildren->forAllTransitiveIncomingValues(
203 node,
204 [&] (Node* incoming) {
205 if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) {
206 if (set.contains(structure))
207 return;
208 }
209 allGood = false;
210 });
211 if (allGood) {
212 m_interpreter.execute(indexInBlock);
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000213 node->remove();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000214 eliminated = true;
215 break;
216 }
217 }
218 break;
219 }
220
fpizlo@apple.com99f37622012-10-29 04:02:08 +0000221 case CheckArray:
222 case Arrayify: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000223 if (!node->arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node->child1())))
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000224 break;
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000225 node->remove();
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000226 eliminated = true;
227 break;
228 }
229
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000230 case PutStructure: {
231 if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next)
232 break;
233
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000234 node->remove();
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000235 eliminated = true;
236 break;
237 }
238
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000239 case CheckCell: {
240 if (m_state.forNode(node->child1()).value() != node->cellOperand()->value())
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +0000241 break;
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000242 node->remove();
fpizlo@apple.com18e7bc12012-11-12 22:52:32 +0000243 eliminated = true;
244 break;
245 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000246
247 case CheckNotEmpty: {
248 if (m_state.forNode(node->child1()).m_type & SpecEmpty)
249 break;
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000250 node->remove();
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000251 eliminated = true;
252 break;
253 }
254
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +0000255 case CheckStringIdent: {
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +0000256 UniquedStringImpl* uid = node->uidOperand();
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +0000257 const UniquedStringImpl* constantUid = nullptr;
utatane.tea@gmail.comb4dc1e12015-10-13 16:03:22 +0000258
259 JSValue childConstant = m_state.forNode(node->child1()).value();
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +0000260 if (childConstant) {
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +0000261 if (childConstant.isString()) {
262 if (const auto* impl = asString(childConstant)->tryGetValueImpl()) {
263 // Edge filtering requires that a value here should be StringIdent.
264 // However, a constant value propagated in DFG is not filtered.
265 // So here, we check the propagated value is actually an atomic string.
266 // And if it's not, we just ignore.
267 if (impl->isAtomic())
268 constantUid = static_cast<const UniquedStringImpl*>(impl);
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +0000269 }
270 }
271 }
272
273 if (constantUid == uid) {
274 node->remove();
275 eliminated = true;
276 }
277 break;
278 }
279
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000280 case CheckInBounds: {
281 JSValue left = m_state.forNode(node->child1()).value();
282 JSValue right = m_state.forNode(node->child2()).value();
283 if (left && right && left.isInt32() && right.isInt32()
284 && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32())) {
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000285 node->remove();
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000286 eliminated = true;
287 break;
288 }
289
290 break;
291 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000292
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +0000293 case GetMyArgumentByVal:
294 case GetMyArgumentByValOutOfBounds: {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000295 JSValue index = m_state.forNode(node->child2()).value();
296 if (!index || !index.isInt32())
297 break;
298
299 Node* arguments = node->child1().node();
300 InlineCallFrame* inlineCallFrame = arguments->origin.semantic.inlineCallFrame;
301
302 // Don't try to do anything if the index is known to be outside our static bounds. Note
303 // that our static bounds are usually strictly larger than the dynamic bounds. The
304 // exception is something like this, assuming foo() is not inlined:
305 //
306 // function foo() { return arguments[5]; }
307 //
308 // Here the static bound on number of arguments is 0, and we're accessing index 5. We
309 // will not strength-reduce this to GetStack because GetStack is otherwise assumed by the
310 // compiler to access those variables that are statically accounted for; for example if
311 // we emitted a GetStack on arg6 we would have out-of-bounds access crashes anywhere that
312 // uses an Operands<> map. There is not much cost to continuing to use a
313 // GetMyArgumentByVal in such statically-out-of-bounds accesses; we just lose CFA unless
314 // GCSE removes the access entirely.
315 if (inlineCallFrame) {
fpizlo@apple.coma40cca72015-03-26 04:52:14 +0000316 if (index.asUInt32() >= inlineCallFrame->arguments.size() - 1)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000317 break;
318 } else {
fpizlo@apple.coma40cca72015-03-26 04:52:14 +0000319 if (index.asUInt32() >= m_state.variables().numberOfArguments() - 1)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000320 break;
321 }
322
323 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
324
325 StackAccessData* data;
326 if (inlineCallFrame) {
327 data = m_graph.m_stackAccessData.add(
fpizlo@apple.com308b6652015-03-26 07:17:08 +0000328 VirtualRegister(
329 inlineCallFrame->stackOffset +
330 CallFrame::argumentOffset(index.asInt32())),
331 FlushedJSValue);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000332 } else {
333 data = m_graph.m_stackAccessData.add(
334 virtualRegisterForArgument(index.asInt32() + 1), FlushedJSValue);
335 }
336
337 if (inlineCallFrame && !inlineCallFrame->isVarargs()
338 && index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
339 node->convertToGetStack(data);
340 eliminated = true;
341 break;
342 }
343
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +0000344 if (node->op() == GetMyArgumentByValOutOfBounds)
345 break;
346
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000347 Node* length = emitCodeToGetArgumentsArrayLength(
348 m_insertionSet, arguments, indexInBlock, node->origin);
349 m_insertionSet.insertNode(
350 indexInBlock, SpecNone, CheckInBounds, node->origin,
351 node->child2(), Edge(length, Int32Use));
352 node->convertToGetStack(data);
353 eliminated = true;
354 break;
355 }
356
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000357 case MultiGetByOffset: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000358 Edge baseEdge = node->child1();
359 Node* base = baseEdge.node();
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000360 MultiGetByOffsetData& data = node->multiGetByOffsetData();
361
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000362 // First prune the variants, then check if the MultiGetByOffset can be
363 // strength-reduced to a GetByOffset.
364
365 AbstractValue baseValue = m_state.forNode(base);
366
367 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000368 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000369
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000370 for (unsigned i = 0; i < data.cases.size(); ++i) {
371 MultiGetByOffsetCase& getCase = data.cases[i];
372 getCase.set().filter(baseValue);
373 if (getCase.set().isEmpty()) {
374 data.cases[i--] = data.cases.last();
375 data.cases.removeLast();
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000376 changed = true;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000377 }
378 }
379
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000380 if (data.cases.size() != 1)
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000381 break;
382
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000383 emitGetByOffset(indexInBlock, node, baseValue, data.cases[0], data.identifierNumber);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000384 changed = true;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000385 break;
386 }
fpizlo@apple.com43219522014-02-25 02:02:50 +0000387
388 case MultiPutByOffset: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000389 Edge baseEdge = node->child1();
390 Node* base = baseEdge.node();
fpizlo@apple.com43219522014-02-25 02:02:50 +0000391 MultiPutByOffsetData& data = node->multiPutByOffsetData();
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000392
393 AbstractValue baseValue = m_state.forNode(base);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000394
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000395 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000396 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000397
398
399 for (unsigned i = 0; i < data.variants.size(); ++i) {
400 PutByIdVariant& variant = data.variants[i];
401 variant.oldStructure().filter(baseValue);
402
403 if (variant.oldStructure().isEmpty()) {
404 data.variants[i--] = data.variants.last();
405 data.variants.removeLast();
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000406 changed = true;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000407 continue;
408 }
409
410 if (variant.kind() == PutByIdVariant::Transition
411 && variant.oldStructure().onlyStructure() == variant.newStructure()) {
412 variant = PutByIdVariant::replace(
413 variant.oldStructure(),
fpizlo@apple.com12835772015-09-21 20:49:04 +0000414 variant.offset(),
415 variant.requiredType());
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000416 changed = true;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000417 }
418 }
419
420 if (data.variants.size() != 1)
fpizlo@apple.com43219522014-02-25 02:02:50 +0000421 break;
422
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000423 emitPutByOffset(
424 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000425 changed = true;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000426 break;
427 }
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000428
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000429 case GetById:
430 case GetByIdFlush: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000431 Edge childEdge = node->child1();
432 Node* child = childEdge.node();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000433 unsigned identifierNumber = node->identifierNumber();
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000434
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000435 AbstractValue baseValue = m_state.forNode(child);
fpizlo@apple.com9f624432014-07-26 19:06:44 +0000436
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000437 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000438 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000439
440 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
441 || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
442 break;
fpizlo@apple.com60d1abd2014-07-26 05:18:16 +0000443
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000444 GetByIdStatus status = GetByIdStatus::computeFor(
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000445 baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000446 if (!status.isSimple())
447 break;
448
449 for (unsigned i = status.numVariants(); i--;) {
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000450 if (!status[i].conditionSet().isEmpty()) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000451 // FIXME: We could handle prototype cases.
452 // https://bugs.webkit.org/show_bug.cgi?id=110386
453 break;
454 }
455 }
456
457 if (status.numVariants() == 1) {
458 emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000459 changed = true;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000460 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000461 }
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000462
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000463 if (!isFTL(m_graph.m_plan.mode))
464 break;
465
466 MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000467 for (const GetByIdVariant& variant : status.variants()) {
468 data->cases.append(
469 MultiGetByOffsetCase(
470 variant.structureSet(),
471 GetByOffsetMethod::load(variant.offset())));
472 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000473 data->identifierNumber = identifierNumber;
474 node->convertToMultiGetByOffset(data);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000475 changed = true;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000476 break;
477 }
478
479 case PutById:
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000480 case PutByIdDirect:
481 case PutByIdFlush: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000482 NodeOrigin origin = node->origin;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000483 Edge childEdge = node->child1();
484 Node* child = childEdge.node();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000485 unsigned identifierNumber = node->identifierNumber();
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000486
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000487 ASSERT(childEdge.useKind() == CellUse);
488
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000489 AbstractValue baseValue = m_state.forNode(child);
fpizlo@apple.com12835772015-09-21 20:49:04 +0000490 AbstractValue valueValue = m_state.forNode(node->child2());
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000491
492 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000493 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000494
495 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000496 break;
497
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000498 PutByIdStatus status = PutByIdStatus::computeFor(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000499 m_graph.globalObjectFor(origin.semantic),
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000500 baseValue.m_structure.set(),
oliver@apple.com90fce822013-07-25 04:00:13 +0000501 m_graph.identifiers()[identifierNumber],
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000502 node->op() == PutByIdDirect);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000503
fpizlo@apple.com43219522014-02-25 02:02:50 +0000504 if (!status.isSimple())
505 break;
fpizlo@apple.com12835772015-09-21 20:49:04 +0000506
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000507 ASSERT(status.numVariants());
508
509 if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
510 break;
511
512 changed = true;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000513
514 bool allGood = true;
515 for (const PutByIdVariant& variant : status.variants()) {
516 if (!allGood)
517 break;
518 for (const ObjectPropertyCondition& condition : variant.conditionSet()) {
519 if (m_graph.watchCondition(condition))
520 continue;
521
522 Structure* structure = condition.object()->structure();
523 if (!condition.structureEnsuresValidity(structure)) {
524 allGood = false;
525 break;
526 }
527
528 m_insertionSet.insertNode(
529 indexInBlock, SpecNone, CheckStructure, node->origin,
530 OpInfo(m_graph.addStructureSet(structure)),
531 m_insertionSet.insertConstantForUse(
532 indexInBlock, node->origin, condition.object(), KnownCellUse));
533 }
534 }
535
536 if (!allGood)
537 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000538
539 if (status.numVariants() == 1) {
540 emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
541 break;
542 }
543
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000544 ASSERT(isFTL(m_graph.m_plan.mode));
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000545
546 MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
547 data->variants = status.variants();
548 data->identifierNumber = identifierNumber;
549 node->convertToMultiPutByOffset(data);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000550 break;
551 }
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000552
fpizlo@apple.com6e550a42014-02-17 20:23:34 +0000553 case ToPrimitive: {
utatane.tea@gmail.com23c2df72015-05-14 17:36:12 +0000554 if (m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))
fpizlo@apple.com6e550a42014-02-17 20:23:34 +0000555 break;
556
557 node->convertToIdentity();
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000558 changed = true;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000559 break;
560 }
utatane.tea@gmail.com44616d02016-01-31 23:05:10 +0000561
keith_miller@apple.comd1a5d2f2016-05-02 17:38:15 +0000562 case ToThis: {
563 if (!isToThisAnIdentity(m_graph.executableFor(node->origin.semantic)->isStrictMode(), m_state.forNode(node->child1())))
564 break;
565
566 node->convertToIdentity();
567 changed = true;
568 break;
569 }
570
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +0000571 case ToNumber: {
572 if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
573 break;
574
575 node->convertToIdentity();
576 changed = true;
577 break;
578 }
579
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000580 case Check: {
581 alreadyHandled = true;
582 m_interpreter.execute(indexInBlock);
583 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
584 Edge edge = node->children.child(i);
585 if (!edge)
586 break;
587 if (edge.isProved() || edge.willNotHaveCheck()) {
588 node->children.removeEdge(i--);
589 changed = true;
590 }
591 }
592 break;
593 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000594
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000595 default:
596 break;
597 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000598
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000599 if (eliminated) {
600 changed = true;
601 continue;
602 }
603
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000604 if (alreadyHandled)
605 continue;
606
oliver@apple.com55d32d92013-07-25 04:05:03 +0000607 m_interpreter.execute(indexInBlock);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000608 if (!m_state.isValid()) {
609 // If we invalidated then we shouldn't attempt to constant-fold. Here's an
610 // example:
611 //
612 // c: JSConstant(4.2)
613 // x: ValueToInt32(Check:Int32:@const)
614 //
615 // It would be correct for an analysis to assume that execution cannot
616 // proceed past @x. Therefore, constant-folding @x could be rather bad. But,
617 // the CFA may report that it found a constant even though it also reported
618 // that everything has been invalidated. This will only happen in a couple of
619 // the constant folding cases; most of them are also separately defensive
620 // about such things.
621 break;
622 }
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000623 if (!node->shouldGenerate() || m_state.didClobber() || node->hasConstant())
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000624 continue;
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000625
626 // Interesting fact: this freezing that we do right here may turn an fragile value into
627 // a weak value. See DFGValueStrength.h.
628 FrozenValue* value = m_graph.freeze(m_state.forNode(node).value());
629 if (!*value)
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000630 continue;
fpizlo@apple.comefa80dc2013-10-12 01:35:49 +0000631
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000632 if (node->op() == GetLocal) {
633 // Need to preserve bytecode liveness in ThreadedCPS form. This wouldn't be necessary
634 // if it wasn't for https://bugs.webkit.org/show_bug.cgi?id=144086.
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000635 m_insertionSet.insertNode(
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000636 indexInBlock, SpecNone, PhantomLocal, node->origin,
637 OpInfo(node->variableAccessData()));
638 m_graph.dethread();
639 } else
640 m_insertionSet.insertCheck(indexInBlock, node->origin, node->children);
641 m_graph.convertToConstant(node, value);
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000642
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000643 changed = true;
644 }
645 m_state.reset();
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +0000646 m_insertionSet.execute(block);
fpizlo@apple.comedcb7a92012-07-13 05:31:05 +0000647
648 return changed;
649 }
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000650
651 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const MultiGetByOffsetCase& getCase, unsigned identifierNumber)
652 {
653 // When we get to here we have already emitted all of the requisite checks for everything.
654 // So, we just need to emit what the method object tells us to emit.
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000655
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000656 addBaseCheck(indexInBlock, node, baseValue, getCase.set());
657
658 GetByOffsetMethod method = getCase.method();
659
660 switch (method.kind()) {
661 case GetByOffsetMethod::Invalid:
662 RELEASE_ASSERT_NOT_REACHED();
663 return;
664
665 case GetByOffsetMethod::Constant:
666 m_graph.convertToConstant(node, method.constant());
667 return;
668
669 case GetByOffsetMethod::Load:
670 emitGetByOffset(indexInBlock, node, node->child1(), identifierNumber, method.offset());
671 return;
672
673 case GetByOffsetMethod::LoadFromPrototype: {
674 Node* child = m_insertionSet.insertConstant(
675 indexInBlock, node->origin, method.prototype());
676 emitGetByOffset(
677 indexInBlock, node, Edge(child, KnownCellUse), identifierNumber, method.offset());
678 return;
679 } }
680
681 RELEASE_ASSERT_NOT_REACHED();
682 }
683
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000684 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000685 {
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000686 Edge childEdge = node->child1();
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000687
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000688 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000689
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000690 // We aren't set up to handle prototype stuff.
691 DFG_ASSERT(m_graph, node, variant.conditionSet().isEmpty());
692
693 if (JSValue value = m_graph.tryGetConstantProperty(baseValue.m_value, variant.structureSet(), variant.offset())) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000694 m_graph.convertToConstant(node, m_graph.freeze(value));
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000695 return;
696 }
697
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000698 emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
699 }
700
fpizlo@apple.com12835772015-09-21 20:49:04 +0000701 void emitGetByOffset(
702 unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber,
703 PropertyOffset offset, const InferredType::Descriptor& inferredType = InferredType::Top)
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000704 {
705 childEdge.setUseKind(KnownCellUse);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000706
707 Edge propertyStorage;
708
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000709 if (isInlineOffset(offset))
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000710 propertyStorage = childEdge;
711 else {
712 propertyStorage = Edge(m_insertionSet.insertNode(
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000713 indexInBlock, SpecNone, GetButterfly, node->origin, childEdge));
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000714 }
715
fpizlo@apple.com9800ede2014-09-20 17:59:58 +0000716 StorageAccessData& data = *m_graph.m_storageAccessData.add();
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000717 data.offset = offset;
fpizlo@apple.com9800ede2014-09-20 17:59:58 +0000718 data.identifierNumber = identifierNumber;
fpizlo@apple.com12835772015-09-21 20:49:04 +0000719 data.inferredType = inferredType;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000720
fpizlo@apple.comf224cdd2016-06-10 02:03:33 +0000721 node->convertToGetByOffset(data, propertyStorage, childEdge);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000722 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +0000723
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000724 void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)
fpizlo@apple.com43219522014-02-25 02:02:50 +0000725 {
726 NodeOrigin origin = node->origin;
727 Edge childEdge = node->child1();
fpizlo@apple.com12835772015-09-21 20:49:04 +0000728
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000729 addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
fpizlo@apple.com12835772015-09-21 20:49:04 +0000730 insertInferredTypeCheck(
731 m_insertionSet, indexInBlock, origin, node->child2().node(), variant.requiredType());
fpizlo@apple.com43219522014-02-25 02:02:50 +0000732
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000733 node->child1().setUseKind(KnownCellUse);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000734 childEdge.setUseKind(KnownCellUse);
735
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000736 Transition* transition = 0;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000737 if (variant.kind() == PutByIdVariant::Transition) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000738 transition = m_graph.m_transitions.add(
739 variant.oldStructureForTransition(), variant.newStructure());
fpizlo@apple.com43219522014-02-25 02:02:50 +0000740 }
741
742 Edge propertyStorage;
743
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000744 DFG_ASSERT(m_graph, node, origin.exitOK);
745 bool canExit = true;
746
fpizlo@apple.com43219522014-02-25 02:02:50 +0000747 if (isInlineOffset(variant.offset()))
748 propertyStorage = childEdge;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000749 else if (!variant.reallocatesStorage()) {
fpizlo@apple.com43219522014-02-25 02:02:50 +0000750 propertyStorage = Edge(m_insertionSet.insertNode(
751 indexInBlock, SpecNone, GetButterfly, origin, childEdge));
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000752 } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
fpizlo@apple.com43219522014-02-25 02:02:50 +0000753 ASSERT(variant.newStructure()->outOfLineCapacity());
754 ASSERT(!isInlineOffset(variant.offset()));
755 Node* allocatePropertyStorage = m_insertionSet.insertNode(
756 indexInBlock, SpecNone, AllocatePropertyStorage,
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000757 origin.takeValidExit(canExit), OpInfo(transition), childEdge);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000758 propertyStorage = Edge(allocatePropertyStorage);
759 } else {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000760 ASSERT(variant.oldStructureForTransition()->outOfLineCapacity());
761 ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity());
fpizlo@apple.com43219522014-02-25 02:02:50 +0000762 ASSERT(!isInlineOffset(variant.offset()));
763
764 Node* reallocatePropertyStorage = m_insertionSet.insertNode(
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000765 indexInBlock, SpecNone, ReallocatePropertyStorage, origin.takeValidExit(canExit),
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000766 OpInfo(transition), childEdge,
fpizlo@apple.com43219522014-02-25 02:02:50 +0000767 Edge(m_insertionSet.insertNode(
768 indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
fpizlo@apple.com43219522014-02-25 02:02:50 +0000769 propertyStorage = Edge(reallocatePropertyStorage);
770 }
771
fpizlo@apple.com9800ede2014-09-20 17:59:58 +0000772 StorageAccessData& data = *m_graph.m_storageAccessData.add();
773 data.offset = variant.offset();
774 data.identifierNumber = identifierNumber;
775
fpizlo@apple.comf224cdd2016-06-10 02:03:33 +0000776 node->convertToPutByOffset(data, propertyStorage, childEdge);
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000777 node->origin.exitOK = canExit;
fpizlo@apple.com3beeb7f2015-03-20 23:26:26 +0000778
779 if (variant.kind() == PutByIdVariant::Transition) {
780 // FIXME: PutStructure goes last until we fix either
781 // https://bugs.webkit.org/show_bug.cgi?id=142921 or
782 // https://bugs.webkit.org/show_bug.cgi?id=142924.
783 m_insertionSet.insertNode(
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000784 indexInBlock + 1, SpecNone, PutStructure, origin.withInvalidExit(), OpInfo(transition),
785 childEdge);
fpizlo@apple.com3beeb7f2015-03-20 23:26:26 +0000786 }
fpizlo@apple.com43219522014-02-25 02:02:50 +0000787 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000788
789 void addBaseCheck(
790 unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set)
791 {
792 if (!baseValue.m_structure.isSubsetOf(set)) {
793 // Arises when we prune MultiGetByOffset. We could have a
794 // MultiGetByOffset with a single variant that checks for structure S,
795 // and the input has structures S and T, for example.
fpizlo@apple.com12835772015-09-21 20:49:04 +0000796 ASSERT(node->child1());
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000797 m_insertionSet.insertNode(
798 indexInBlock, SpecNone, CheckStructure, node->origin,
799 OpInfo(m_graph.addStructureSet(set)), node->child1());
800 return;
801 }
802
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000803 if (baseValue.m_type & ~SpecCell)
804 m_insertionSet.insertCheck(indexInBlock, node->origin, node->child1());
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000805 }
806
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000807 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000808 {
fpizlo@apple.com920c1672014-08-19 00:55:31 +0000809 if (m_graph.registerStructure(cell->structure()) == StructureRegisteredAndWatched)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000810 return;
fpizlo@apple.com920c1672014-08-19 00:55:31 +0000811
812 m_graph.registerStructure(structure);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000813
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000814 Node* weakConstant = m_insertionSet.insertNode(
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000815 indexInBlock, speculationFromValue(cell), JSConstant, origin,
816 OpInfo(m_graph.freeze(cell)));
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000817
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +0000818 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000819 indexInBlock, SpecNone, CheckStructure, origin,
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000820 OpInfo(m_graph.addStructureSet(structure)), Edge(weakConstant, CellUse));
821 }
822
823 void fixUpsilons(BasicBlock* block)
824 {
825 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
826 Node* node = block->at(nodeIndex);
827 if (node->op() != Upsilon)
828 continue;
829 switch (node->phi()->op()) {
830 case Phi:
831 break;
832 case JSConstant:
833 case DoubleConstant:
834 case Int52Constant:
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000835 node->remove();
fpizlo@apple.comb41e6822014-07-25 20:55:17 +0000836 break;
837 default:
838 DFG_CRASH(m_graph, node, "Bad Upsilon phi() pointer");
839 break;
840 }
841 }
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000842 }
843
oliver@apple.com55d32d92013-07-25 04:05:03 +0000844 InPlaceAbstractState m_state;
845 AbstractInterpreter<InPlaceAbstractState> m_interpreter;
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +0000846 InsertionSet m_insertionSet;
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000847};
848
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000849bool performConstantFolding(Graph& graph)
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000850{
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000851 return runPhase<ConstantFoldingPhase>(graph);
fpizlo@apple.com3187c922012-05-18 21:47:53 +0000852}
853
854} } // namespace JSC::DFG
855
856#endif // ENABLE(DFG_JIT)
857
858