2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "DFGArgumentsSimplificationPhase.h"
31 #include "DFGBasicBlock.h"
33 #include "DFGInsertionSet.h"
35 #include "DFGValidate.h"
36 #include "DFGVariableAccessDataDump.h"
37 #include "JSCInlines.h"
38 #include <wtf/HashSet.h>
39 #include <wtf/HashMap.h>
41 namespace JSC
{ namespace DFG
{
45 struct ArgumentsAliasingData
{
46 InlineCallFrame
* callContext
;
48 bool multipleCallContexts
;
50 bool assignedFromArguments
;
51 bool assignedFromManyThings
;
55 ArgumentsAliasingData()
57 , callContextSet(false)
58 , multipleCallContexts(false)
59 , assignedFromArguments(false)
60 , assignedFromManyThings(false)
65 void mergeCallContext(InlineCallFrame
* newCallContext
)
67 if (multipleCallContexts
)
70 if (!callContextSet
) {
71 callContext
= newCallContext
;
72 callContextSet
= true;
76 if (callContext
== newCallContext
)
79 multipleCallContexts
= true;
82 bool callContextIsValid()
84 return callContextSet
&& !multipleCallContexts
;
87 void mergeArgumentsAssignment()
89 assignedFromArguments
= true;
92 void mergeNonArgumentsAssignment()
94 assignedFromManyThings
= true;
97 bool argumentsAssignmentIsValid()
99 return assignedFromArguments
&& !assignedFromManyThings
;
104 return callContextIsValid() && argumentsAssignmentIsValid() && !escapes
;
108 } // end anonymous namespace
110 class ArgumentsSimplificationPhase
: public Phase
{
112 ArgumentsSimplificationPhase(Graph
& graph
)
113 : Phase(graph
, "arguments simplification")
119 if (!m_graph
.m_hasArguments
)
122 bool changed
= false;
124 // Record which arguments are known to escape no matter what.
125 for (InlineCallFrameSet::iterator iter
= m_graph
.m_plan
.inlineCallFrames
->begin(); !!iter
; ++iter
)
126 pruneObviousArgumentCreations(*iter
);
127 pruneObviousArgumentCreations(0); // the machine call frame.
129 // Create data for variable access datas that we will want to analyze.
130 for (unsigned i
= m_graph
.m_variableAccessData
.size(); i
--;) {
131 VariableAccessData
* variableAccessData
= &m_graph
.m_variableAccessData
[i
];
132 if (!variableAccessData
->isRoot())
134 if (variableAccessData
->isCaptured())
136 m_argumentsAliasing
.add(variableAccessData
, ArgumentsAliasingData());
139 // Figure out which variables are live, using a conservative approximation of
141 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
142 BasicBlock
* block
= m_graph
.block(blockIndex
);
145 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); ++indexInBlock
) {
146 Node
* node
= block
->at(indexInBlock
);
147 switch (node
->op()) {
151 m_isLive
.add(node
->variableAccessData());
159 // Figure out which variables alias the arguments and nothing else, and are
160 // used only for GetByVal and GetArrayLength accesses. At the same time,
161 // identify uses of CreateArguments that are not consistent with the arguments
162 // being aliased only to variables that satisfy these constraints.
163 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
164 BasicBlock
* block
= m_graph
.block(blockIndex
);
167 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); ++indexInBlock
) {
168 Node
* node
= block
->at(indexInBlock
);
169 switch (node
->op()) {
170 case CreateArguments
: {
171 // Ignore this op. If we see a lone CreateArguments then we want to
172 // completely ignore it because:
173 // 1) The default would be to see that the child is a GetLocal on the
174 // arguments register and conclude that we have an arguments escape.
175 // 2) The fact that a CreateArguments exists does not mean that it
176 // will continue to exist after we're done with this phase. As far
177 // as this phase is concerned, a CreateArguments only "exists" if it
178 // is used in a manner that necessitates its existance.
182 case TearOffArguments
: {
183 // Ignore arguments tear off, because it's only relevant if we actually
184 // need to create the arguments.
189 Node
* source
= node
->child1().node();
190 VariableAccessData
* variableAccessData
= node
->variableAccessData();
191 VirtualRegister argumentsRegister
=
192 m_graph
.uncheckedArgumentsRegisterFor(node
->origin
.semantic
);
193 if (source
->op() != CreateArguments
&& source
->op() != PhantomArguments
) {
194 // Make sure that the source of the SetLocal knows that if it's
195 // a variable that we think is aliased to the arguments, then it
196 // may escape at this point. In future, we could track transitive
197 // aliasing. But not yet.
198 observeBadArgumentsUse(source
);
200 // If this is an assignment to the arguments register, then
201 // pretend as if the arguments were created. We don't want to
202 // optimize code that explicitly assigns to the arguments,
203 // because that seems too ugly.
205 // But, before getting rid of CreateArguments, we will have
206 // an assignment to the arguments registers with JSValue().
207 // That's because CSE will refuse to get rid of the
208 // init_lazy_reg since it treats CreateArguments as reading
209 // local variables. That could be fixed, but it's easier to
210 // work around this here.
211 if (source
->op() == JSConstant
212 && !source
->valueOfJSConstant(codeBlock()))
215 // If the variable is totally dead, then ignore it.
216 if (!m_isLive
.contains(variableAccessData
))
219 if (argumentsRegister
.isValid()
220 && (variableAccessData
->local() == argumentsRegister
221 || variableAccessData
->local() == unmodifiedArgumentsRegister(argumentsRegister
))) {
222 m_createsArguments
.add(node
->origin
.semantic
.inlineCallFrame
);
226 if (variableAccessData
->isCaptured())
229 // Make sure that if it's a variable that we think is aliased to
230 // the arguments, that we know that it might actually not be.
231 ArgumentsAliasingData
& data
=
232 m_argumentsAliasing
.find(variableAccessData
)->value
;
233 data
.mergeNonArgumentsAssignment();
234 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
237 if (argumentsRegister
.isValid()
238 && (variableAccessData
->local() == argumentsRegister
239 || variableAccessData
->local() == unmodifiedArgumentsRegister(argumentsRegister
))) {
240 if (node
->origin
.semantic
.inlineCallFrame
== source
->origin
.semantic
.inlineCallFrame
)
242 m_createsArguments
.add(source
->origin
.semantic
.inlineCallFrame
);
245 if (variableAccessData
->isCaptured()) {
246 m_createsArguments
.add(source
->origin
.semantic
.inlineCallFrame
);
249 ArgumentsAliasingData
& data
=
250 m_argumentsAliasing
.find(variableAccessData
)->value
;
251 data
.mergeArgumentsAssignment();
252 // This ensures that the variable's uses are in the same context as
253 // the arguments it is aliasing.
254 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
255 data
.mergeCallContext(source
->origin
.semantic
.inlineCallFrame
);
260 case Phi
: /* FIXME: https://bugs.webkit.org/show_bug.cgi?id=108555 */ {
261 VariableAccessData
* variableAccessData
= node
->variableAccessData();
262 if (variableAccessData
->isCaptured())
264 ArgumentsAliasingData
& data
=
265 m_argumentsAliasing
.find(variableAccessData
)->value
;
266 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
271 VariableAccessData
* variableAccessData
= node
->variableAccessData();
272 if (variableAccessData
->isCaptured())
274 ArgumentsAliasingData
& data
=
275 m_argumentsAliasing
.find(variableAccessData
)->value
;
276 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
278 // If a variable is used in a flush then by definition it escapes.
284 VariableAccessData
* variableAccessData
= node
->variableAccessData();
285 if (variableAccessData
->isCaptured())
287 ArgumentsAliasingData
& data
=
288 m_argumentsAliasing
.find(variableAccessData
)->value
;
289 data
.mergeNonArgumentsAssignment();
290 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
295 if (node
->arrayMode().type() != Array::Arguments
) {
296 observeBadArgumentsUses(node
);
300 // That's so awful and pretty much impossible since it would
301 // imply that the arguments were predicted integer, but it's
302 // good to be defensive and thorough.
303 observeBadArgumentsUse(node
->child2().node());
304 observeProperArgumentsUse(node
, node
->child1());
308 case GetArrayLength
: {
309 if (node
->arrayMode().type() != Array::Arguments
) {
310 observeBadArgumentsUses(node
);
314 observeProperArgumentsUse(node
, node
->child1());
320 // We don't care about phantom uses, since phantom uses are all about
321 // just keeping things alive for OSR exit. If something - like the
322 // CreateArguments - is just being kept alive, then this transformation
323 // will not break this, since the Phantom will now just keep alive a
324 // PhantomArguments and OSR exit will still do the right things.
328 case StructureTransitionWatchpoint
:
330 // We don't care about these because if we get uses of the relevant
331 // variable then we can safely get rid of these, too. This of course
332 // relies on there not being any information transferred by the CFA
333 // from a CheckStructure on one variable to the information about the
334 // structures of another variable.
338 // We don't care about MovHints at all, since they represent what happens
339 // in bytecode. We rematerialize arguments objects on OSR exit anyway.
343 observeBadArgumentsUses(node
);
349 // Now we know which variables are aliased to arguments. But if any of them are
350 // found to have escaped, or were otherwise invalidated, then we need to mark
351 // the arguments as requiring creation. This is a property of SetLocals to
352 // variables that are neither the correct arguments register nor are marked as
353 // being arguments-aliased.
354 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
355 BasicBlock
* block
= m_graph
.block(blockIndex
);
358 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); ++indexInBlock
) {
359 Node
* node
= block
->at(indexInBlock
);
360 if (node
->op() != SetLocal
)
362 Node
* source
= node
->child1().node();
363 if (source
->op() != CreateArguments
)
365 VariableAccessData
* variableAccessData
= node
->variableAccessData();
366 if (variableAccessData
->isCaptured()) {
367 // The captured case would have already been taken care of in the
372 ArgumentsAliasingData
& data
=
373 m_argumentsAliasing
.find(variableAccessData
)->value
;
377 m_createsArguments
.add(source
->origin
.semantic
.inlineCallFrame
);
381 InsertionSet
insertionSet(m_graph
);
383 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
384 BasicBlock
* block
= m_graph
.block(blockIndex
);
387 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); indexInBlock
++) {
388 Node
* node
= block
->at(indexInBlock
);
389 switch (node
->op()) {
391 Node
* source
= node
->child1().node();
392 if (source
->op() != CreateArguments
)
395 if (m_createsArguments
.contains(source
->origin
.semantic
.inlineCallFrame
))
398 VariableAccessData
* variableAccessData
= node
->variableAccessData();
400 if (variableAccessData
->mergeIsArgumentsAlias(true)) {
403 // Make sure that the variable knows, that it may now hold non-cell values.
404 variableAccessData
->predict(SpecEmpty
);
407 // Make sure that the SetLocal doesn't check that the input is a Cell.
408 if (node
->child1().useKind() != UntypedUse
) {
409 node
->child1().setUseKind(UntypedUse
);
416 VariableAccessData
* variableAccessData
= node
->variableAccessData();
418 if (variableAccessData
->isCaptured()
419 || !m_argumentsAliasing
.find(variableAccessData
)->value
.isValid()
420 || m_createsArguments
.contains(node
->origin
.semantic
.inlineCallFrame
))
423 RELEASE_ASSERT_NOT_REACHED();
429 // It's highly likely that we will have a Phantom referencing either
430 // CreateArguments, or a local op for the arguments register, or a
431 // local op for an arguments-aliased variable. In any of those cases,
432 // we should remove the phantom reference, since:
433 // 1) Phantoms only exist to aid OSR exit. But arguments simplification
434 // has its own OSR exit story, which is to inform OSR exit to reify
435 // the arguments as necessary.
436 // 2) The Phantom may keep the CreateArguments node alive, which is
437 // precisely what we don't want.
438 for (unsigned i
= 0; i
< AdjacencyList::Size
; ++i
)
439 detypeArgumentsReferencingPhantomChild(node
, i
);
444 case StructureTransitionWatchpoint
:
446 // We can just get rid of this node, if it references a phantom argument.
447 if (!isOKToOptimize(node
->child1().node()))
449 node
->convertToPhantom();
454 if (node
->arrayMode().type() != Array::Arguments
)
457 // This can be simplified to GetMyArgumentByVal if we know that
458 // it satisfies either condition (1) or (2):
459 // 1) Its first child is a valid ArgumentsAliasingData and the
460 // InlineCallFrame* is not marked as creating arguments.
461 // 2) Its first child is CreateArguments and its InlineCallFrame*
462 // is not marked as creating arguments.
464 if (!isOKToOptimize(node
->child1().node()))
467 insertionSet
.insertNode(
468 indexInBlock
, SpecNone
, Phantom
, node
->origin
, node
->child1());
470 node
->child1() = node
->child2();
471 node
->child2() = Edge();
472 node
->setOpAndDefaultFlags(GetMyArgumentByVal
);
474 --indexInBlock
; // Force reconsideration of this op now that it's a GetMyArgumentByVal.
478 case GetArrayLength
: {
479 if (node
->arrayMode().type() != Array::Arguments
)
482 if (!isOKToOptimize(node
->child1().node()))
485 insertionSet
.insertNode(
486 indexInBlock
, SpecNone
, Phantom
, node
->origin
, node
->child1());
488 node
->child1() = Edge();
489 node
->setOpAndDefaultFlags(GetMyArgumentsLength
);
491 --indexInBlock
; // Force reconsideration of this op noew that it's a GetMyArgumentsLength.
495 case GetMyArgumentsLength
:
496 case GetMyArgumentsLengthSafe
: {
497 if (m_createsArguments
.contains(node
->origin
.semantic
.inlineCallFrame
)) {
498 ASSERT(node
->op() == GetMyArgumentsLengthSafe
);
501 if (node
->op() == GetMyArgumentsLengthSafe
) {
502 node
->setOp(GetMyArgumentsLength
);
506 NodeOrigin origin
= node
->origin
;
507 if (!origin
.semantic
.inlineCallFrame
)
510 // We know exactly what this will return. But only after we have checked
511 // that nobody has escaped our arguments.
512 insertionSet
.insertNode(
513 indexInBlock
, SpecNone
, CheckArgumentsNotCreated
, origin
);
515 m_graph
.convertToConstant(
516 node
, jsNumber(origin
.semantic
.inlineCallFrame
->arguments
.size() - 1));
521 case GetMyArgumentByVal
:
522 case GetMyArgumentByValSafe
: {
523 if (m_createsArguments
.contains(node
->origin
.semantic
.inlineCallFrame
)) {
524 ASSERT(node
->op() == GetMyArgumentByValSafe
);
527 if (node
->op() == GetMyArgumentByValSafe
) {
528 node
->setOp(GetMyArgumentByVal
);
531 if (!node
->origin
.semantic
.inlineCallFrame
)
533 if (!node
->child1()->hasConstant())
535 JSValue value
= node
->child1()->valueOfJSConstant(codeBlock());
536 if (!value
.isInt32())
538 int32_t index
= value
.asInt32();
540 || static_cast<size_t>(index
+ 1) >=
541 node
->origin
.semantic
.inlineCallFrame
->arguments
.size())
544 // We know which argument this is accessing. But only after we have checked
545 // that nobody has escaped our arguments. We also need to ensure that the
546 // index is kept alive. That's somewhat pointless since it's a constant, but
547 // it's important because this is one of those invariants that we like to
548 // have in the DFG. Note finally that we use the GetLocalUnlinked opcode
549 // here, since this is being done _after_ the prediction propagation phase
550 // has run - therefore it makes little sense to link the GetLocal operation
551 // into the VariableAccessData and Phi graphs.
553 NodeOrigin origin
= node
->origin
;
554 AdjacencyList children
= node
->children
;
556 node
->convertToGetLocalUnlinked(
558 origin
.semantic
.inlineCallFrame
->stackOffset
+
559 m_graph
.baselineCodeBlockFor(origin
.semantic
)->argumentIndexAfterCapture(index
)));
561 insertionSet
.insertNode(
562 indexInBlock
, SpecNone
, CheckArgumentsNotCreated
, origin
);
563 insertionSet
.insertNode(
564 indexInBlock
, SpecNone
, Phantom
, origin
, children
);
570 case TearOffArguments
: {
571 if (m_createsArguments
.contains(node
->origin
.semantic
.inlineCallFrame
))
574 node
->convertToPhantom();
582 insertionSet
.execute(block
);
585 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
586 BasicBlock
* block
= m_graph
.block(blockIndex
);
589 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); ++indexInBlock
) {
590 Node
* node
= block
->at(indexInBlock
);
591 if (node
->op() != CreateArguments
)
593 // If this is a CreateArguments for an InlineCallFrame* that does
594 // not create arguments, then replace it with a PhantomArguments.
595 // PhantomArguments is a non-executing node that just indicates
596 // that the node should be reified as an arguments object on OSR
598 if (m_createsArguments
.contains(node
->origin
.semantic
.inlineCallFrame
))
600 insertionSet
.insertNode(
601 indexInBlock
, SpecNone
, Phantom
, node
->origin
, node
->children
);
602 node
->setOpAndDefaultFlags(PhantomArguments
);
603 node
->children
.reset();
606 insertionSet
.execute(block
);
609 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
610 BasicBlock
* block
= m_graph
.block(blockIndex
);
613 for (unsigned indexInBlock
= 0; indexInBlock
< block
->size(); ++indexInBlock
) {
614 Node
* node
= block
->at(indexInBlock
);
615 if (node
->op() != Phantom
)
617 for (unsigned i
= 0; i
< AdjacencyList::Size
; ++i
)
618 detypeArgumentsReferencingPhantomChild(node
, i
);
624 m_graph
.m_form
= LoadStore
;
631 HashSet
<InlineCallFrame
*,
632 DefaultHash
<InlineCallFrame
*>::Hash
,
633 NullableHashTraits
<InlineCallFrame
*>> m_createsArguments
;
634 HashMap
<VariableAccessData
*, ArgumentsAliasingData
,
635 DefaultHash
<VariableAccessData
*>::Hash
,
636 NullableHashTraits
<VariableAccessData
*>> m_argumentsAliasing
;
637 HashSet
<VariableAccessData
*> m_isLive
;
639 void pruneObviousArgumentCreations(InlineCallFrame
* inlineCallFrame
)
641 ScriptExecutable
* executable
= m_graph
.executableFor(inlineCallFrame
);
642 if (m_graph
.m_executablesWhoseArgumentsEscaped
.contains(executable
)
643 || executable
->isStrictMode())
644 m_createsArguments
.add(inlineCallFrame
);
647 void observeBadArgumentsUse(Node
* node
)
652 switch (node
->op()) {
653 case CreateArguments
: {
654 m_createsArguments
.add(node
->origin
.semantic
.inlineCallFrame
);
659 VirtualRegister argumentsRegister
=
660 m_graph
.uncheckedArgumentsRegisterFor(node
->origin
.semantic
);
661 if (argumentsRegister
.isValid()
662 && (node
->local() == argumentsRegister
663 || node
->local() == unmodifiedArgumentsRegister(argumentsRegister
))) {
664 m_createsArguments
.add(node
->origin
.semantic
.inlineCallFrame
);
668 VariableAccessData
* variableAccessData
= node
->variableAccessData();
669 if (variableAccessData
->isCaptured())
672 ArgumentsAliasingData
& data
= m_argumentsAliasing
.find(variableAccessData
)->value
;
682 void observeBadArgumentsUses(Node
* node
)
684 for (unsigned i
= m_graph
.numChildren(node
); i
--;)
685 observeBadArgumentsUse(m_graph
.child(node
, i
).node());
688 void observeProperArgumentsUse(Node
* node
, Edge edge
)
690 if (edge
->op() != GetLocal
) {
691 // When can this happen? At least two cases that I can think
694 // 1) Aliased use of arguments in the same basic block,
697 // var a = arguments;
698 // var x = arguments[i];
700 // 2) If we're accessing arguments we got from the heap!
702 if (edge
->op() == CreateArguments
703 && node
->origin
.semantic
.inlineCallFrame
704 != edge
->origin
.semantic
.inlineCallFrame
)
705 m_createsArguments
.add(edge
->origin
.semantic
.inlineCallFrame
);
710 VariableAccessData
* variableAccessData
= edge
->variableAccessData();
711 if (edge
->local() == m_graph
.uncheckedArgumentsRegisterFor(edge
->origin
.semantic
)
712 && node
->origin
.semantic
.inlineCallFrame
!= edge
->origin
.semantic
.inlineCallFrame
) {
713 m_createsArguments
.add(edge
->origin
.semantic
.inlineCallFrame
);
717 if (variableAccessData
->isCaptured())
720 ArgumentsAliasingData
& data
= m_argumentsAliasing
.find(variableAccessData
)->value
;
721 data
.mergeCallContext(node
->origin
.semantic
.inlineCallFrame
);
724 bool isOKToOptimize(Node
* source
)
726 if (m_createsArguments
.contains(source
->origin
.semantic
.inlineCallFrame
))
729 switch (source
->op()) {
731 VariableAccessData
* variableAccessData
= source
->variableAccessData();
732 VirtualRegister argumentsRegister
=
733 m_graph
.uncheckedArgumentsRegisterFor(source
->origin
.semantic
);
734 if (!argumentsRegister
.isValid())
736 if (argumentsRegister
== variableAccessData
->local())
738 if (unmodifiedArgumentsRegister(argumentsRegister
) == variableAccessData
->local())
740 if (variableAccessData
->isCaptured())
742 ArgumentsAliasingData
& data
=
743 m_argumentsAliasing
.find(variableAccessData
)->value
;
750 case CreateArguments
: {
761 void detypeArgumentsReferencingPhantomChild(Node
* node
, unsigned edgeIndex
)
763 Edge edge
= node
->children
.child(edgeIndex
);
767 switch (edge
->op()) {
769 VariableAccessData
* variableAccessData
= edge
->variableAccessData();
770 if (!variableAccessData
->isArgumentsAlias())
772 node
->children
.child(edgeIndex
).setUseKind(UntypedUse
);
776 case PhantomArguments
: {
777 node
->children
.child(edgeIndex
).setUseKind(UntypedUse
);
787 bool performArgumentsSimplification(Graph
& graph
)
789 SamplingRegion
samplingRegion("DFG Arguments Simplification Phase");
790 return runPhase
<ArgumentsSimplificationPhase
>(graph
);
793 } } // namespace JSC::DFG
795 #endif // ENABLE(DFG_JIT)