DFG should have adaptive structure watchpoints
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGByteCodeParser.cpp
1 /*
2  * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGByteCodeParser.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "ArrayConstructor.h"
32 #include "BasicBlockLocation.h"
33 #include "CallLinkStatus.h"
34 #include "CodeBlock.h"
35 #include "CodeBlockWithJITType.h"
36 #include "DFGArrayMode.h"
37 #include "DFGCapabilities.h"
38 #include "DFGGraph.h"
39 #include "DFGJITCode.h"
40 #include "GetByIdStatus.h"
41 #include "Heap.h"
42 #include "JSLexicalEnvironment.h"
43 #include "JSCInlines.h"
44 #include "PreciseJumpTargets.h"
45 #include "PutByIdStatus.h"
46 #include "StackAlignment.h"
47 #include "StringConstructor.h"
48 #include <wtf/CommaPrinter.h>
49 #include <wtf/HashMap.h>
50 #include <wtf/MathExtras.h>
51 #include <wtf/StdLibExtras.h>
52
53 namespace JSC { namespace DFG {
54
55 static const bool verbose = false;
56
57 class ConstantBufferKey {
58 public:
59     ConstantBufferKey()
60         : m_codeBlock(0)
61         , m_index(0)
62     {
63     }
64     
65     ConstantBufferKey(WTF::HashTableDeletedValueType)
66         : m_codeBlock(0)
67         , m_index(1)
68     {
69     }
70     
71     ConstantBufferKey(CodeBlock* codeBlock, unsigned index)
72         : m_codeBlock(codeBlock)
73         , m_index(index)
74     {
75     }
76     
77     bool operator==(const ConstantBufferKey& other) const
78     {
79         return m_codeBlock == other.m_codeBlock
80             && m_index == other.m_index;
81     }
82     
83     unsigned hash() const
84     {
85         return WTF::PtrHash<CodeBlock*>::hash(m_codeBlock) ^ m_index;
86     }
87     
88     bool isHashTableDeletedValue() const
89     {
90         return !m_codeBlock && m_index;
91     }
92     
93     CodeBlock* codeBlock() const { return m_codeBlock; }
94     unsigned index() const { return m_index; }
95     
96 private:
97     CodeBlock* m_codeBlock;
98     unsigned m_index;
99 };
100
101 struct ConstantBufferKeyHash {
102     static unsigned hash(const ConstantBufferKey& key) { return key.hash(); }
103     static bool equal(const ConstantBufferKey& a, const ConstantBufferKey& b)
104     {
105         return a == b;
106     }
107     
108     static const bool safeToCompareToEmptyOrDeleted = true;
109 };
110
111 } } // namespace JSC::DFG
112
113 namespace WTF {
114
115 template<typename T> struct DefaultHash;
116 template<> struct DefaultHash<JSC::DFG::ConstantBufferKey> {
117     typedef JSC::DFG::ConstantBufferKeyHash Hash;
118 };
119
120 template<typename T> struct HashTraits;
121 template<> struct HashTraits<JSC::DFG::ConstantBufferKey> : SimpleClassHashTraits<JSC::DFG::ConstantBufferKey> { };
122
123 } // namespace WTF
124
125 namespace JSC { namespace DFG {
126
127 // === ByteCodeParser ===
128 //
129 // This class is used to compile the dataflow graph from a CodeBlock.
130 class ByteCodeParser {
131 public:
132     ByteCodeParser(Graph& graph)
133         : m_vm(&graph.m_vm)
134         , m_codeBlock(graph.m_codeBlock)
135         , m_profiledBlock(graph.m_profiledBlock)
136         , m_graph(graph)
137         , m_currentBlock(0)
138         , m_currentIndex(0)
139         , m_constantUndefined(graph.freeze(jsUndefined()))
140         , m_constantNull(graph.freeze(jsNull()))
141         , m_constantNaN(graph.freeze(jsNumber(PNaN)))
142         , m_constantOne(graph.freeze(jsNumber(1)))
143         , m_numArguments(m_codeBlock->numParameters())
144         , m_numLocals(m_codeBlock->m_numCalleeRegisters)
145         , m_parameterSlots(0)
146         , m_numPassedVarArgs(0)
147         , m_inlineStackTop(0)
148         , m_currentInstruction(0)
149         , m_hasDebuggerEnabled(graph.hasDebuggerEnabled())
150     {
151         ASSERT(m_profiledBlock);
152     }
153     
154     // Parse a full CodeBlock of bytecode.
155     bool parse();
156     
157 private:
158     struct InlineStackEntry;
159
160     // Just parse from m_currentIndex to the end of the current CodeBlock.
161     void parseCodeBlock();
162     
163     void ensureLocals(unsigned newNumLocals)
164     {
165         if (newNumLocals <= m_numLocals)
166             return;
167         m_numLocals = newNumLocals;
168         for (size_t i = 0; i < m_graph.numBlocks(); ++i)
169             m_graph.block(i)->ensureLocals(newNumLocals);
170     }
171
172     // Helper for min and max.
173     template<typename ChecksFunctor>
174     bool handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks);
175     
176     // Handle calls. This resolves issues surrounding inlining and intrinsics.
177     void handleCall(
178         int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
179         Node* callTarget, int argCount, int registerOffset, CallLinkStatus,
180         SpeculatedType prediction);
181     void handleCall(
182         int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
183         Node* callTarget, int argCount, int registerOffset, CallLinkStatus);
184     void handleCall(int result, NodeType op, CodeSpecializationKind, unsigned instructionSize, int callee, int argCount, int registerOffset);
185     void handleCall(Instruction* pc, NodeType op, CodeSpecializationKind);
186     void handleVarargsCall(Instruction* pc, NodeType op, CodeSpecializationKind);
187     void emitFunctionChecks(CallVariant, Node* callTarget, VirtualRegister thisArgumnt);
188     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis);
189     unsigned inliningCost(CallVariant, int argumentCountIncludingThis, CodeSpecializationKind); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
190     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
191     bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
192     enum CallerLinkability { CallerDoesNormalLinking, CallerLinksManually };
193     template<typename ChecksFunctor>
194     bool attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, CallerLinkability, SpeculatedType prediction, unsigned& inliningBalance, const ChecksFunctor& insertChecks);
195     template<typename ChecksFunctor>
196     void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, CallerLinkability, const ChecksFunctor& insertChecks);
197     void cancelLinkingForBlock(InlineStackEntry*, BasicBlock*); // Only works when the given block is the last one to have been added for that inline stack entry.
198     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
199     template<typename ChecksFunctor>
200     bool handleIntrinsic(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
201     template<typename ChecksFunctor>
202     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
203     template<typename ChecksFunctor>
204     bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
205     Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
206     Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
207     Node* handleGetByOffset(SpeculatedType, Node* base, const StructureSet&, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
208     Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
209
210     // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
211     // check the validity of the condition, but it may return a null one if it encounters a contradiction.
212     ObjectPropertyCondition presenceLike(
213         JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
214     
215     // Attempt to watch the presence of a property. It will watch that the property is present in the same
216     // way as in all of the structures in the set. It may emit code instead of just setting a watchpoint.
217     // Returns true if this all works out.
218     bool checkPresenceLike(JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
219     void checkPresenceLike(Node* base, UniquedStringImpl*, PropertyOffset, const StructureSet&);
220     
221     // Works with both GetByIdVariant and the setter form of PutByIdVariant.
222     template<typename VariantType>
223     Node* load(SpeculatedType, Node* base, unsigned identifierNumber, const VariantType&);
224
225     Node* store(Node* base, unsigned identifier, const PutByIdVariant&, Node* value);
226         
227     void handleGetById(
228         int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
229         const GetByIdStatus&);
230     void emitPutById(
231         Node* base, unsigned identifierNumber, Node* value,  const PutByIdStatus&, bool isDirect);
232     void handlePutById(
233         Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
234         bool isDirect);
235     
236     // Either register a watchpoint or emit a check for this condition. Returns false if the
237     // condition no longer holds, and therefore no reasonable check can be emitted.
238     bool check(const ObjectPropertyCondition&);
239     
240     GetByOffsetMethod promoteToConstant(GetByOffsetMethod);
241     
242     // Either register a watchpoint or emit a check for this condition. It must be a Presence
243     // condition. It will attempt to promote a Presence condition to an Equivalence condition.
244     // Emits code for the loaded value that the condition guards, and returns a node containing
245     // the loaded value. Returns null if the condition no longer holds.
246     GetByOffsetMethod planLoad(const ObjectPropertyCondition&);
247     Node* load(SpeculatedType, unsigned identifierNumber, const GetByOffsetMethod&, NodeType = GetByOffset);
248     Node* load(SpeculatedType, const ObjectPropertyCondition&, NodeType = GetByOffset);
249     
250     // Calls check() for each condition in the set: that is, it either emits checks or registers
251     // watchpoints (or a combination of the two) to make the conditions hold. If any of those
252     // conditions are no longer checkable, returns false.
253     bool check(const ObjectPropertyConditionSet&);
254     
255     // Calls check() for those conditions that aren't the slot base, and calls load() for the slot
256     // base. Does a combination of watchpoint registration and check emission to guard the
257     // conditions, and emits code to load the value from the slot base. Returns a node containing
258     // the loaded value. Returns null if any of the conditions were no longer checkable.
259     GetByOffsetMethod planLoad(const ObjectPropertyConditionSet&);
260     Node* load(SpeculatedType, const ObjectPropertyConditionSet&, NodeType = GetByOffset);
261
262     void prepareToParseBlock();
263     void clearCaches();
264
265     // Parse a single basic block of bytecode instructions.
266     bool parseBlock(unsigned limit);
267     // Link block successors.
268     void linkBlock(BasicBlock*, Vector<BasicBlock*>& possibleTargets);
269     void linkBlocks(Vector<UnlinkedBlock>& unlinkedBlocks, Vector<BasicBlock*>& possibleTargets);
270     
271     VariableAccessData* newVariableAccessData(VirtualRegister operand)
272     {
273         ASSERT(!operand.isConstant());
274         
275         m_graph.m_variableAccessData.append(VariableAccessData(operand));
276         return &m_graph.m_variableAccessData.last();
277     }
278     
279     // Get/Set the operands/result of a bytecode instruction.
280     Node* getDirect(VirtualRegister operand)
281     {
282         ASSERT(!operand.isConstant());
283
284         // Is this an argument?
285         if (operand.isArgument())
286             return getArgument(operand);
287
288         // Must be a local.
289         return getLocal(operand);
290     }
291
292     Node* get(VirtualRegister operand)
293     {
294         if (operand.isConstant()) {
295             unsigned constantIndex = operand.toConstantIndex();
296             unsigned oldSize = m_constants.size();
297             if (constantIndex >= oldSize || !m_constants[constantIndex]) {
298                 const CodeBlock& codeBlock = *m_inlineStackTop->m_codeBlock;
299                 JSValue value = codeBlock.getConstant(operand.offset());
300                 SourceCodeRepresentation sourceCodeRepresentation = codeBlock.constantSourceCodeRepresentation(operand.offset());
301                 if (constantIndex >= oldSize) {
302                     m_constants.grow(constantIndex + 1);
303                     for (unsigned i = oldSize; i < m_constants.size(); ++i)
304                         m_constants[i] = nullptr;
305                 }
306
307                 Node* constantNode = nullptr;
308                 if (sourceCodeRepresentation == SourceCodeRepresentation::Double)
309                     constantNode = addToGraph(DoubleConstant, OpInfo(m_graph.freezeStrong(jsDoubleNumber(value.asNumber()))));
310                 else
311                     constantNode = addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(value)));
312                 m_constants[constantIndex] = constantNode;
313             }
314             ASSERT(m_constants[constantIndex]);
315             return m_constants[constantIndex];
316         }
317         
318         if (inlineCallFrame()) {
319             if (!inlineCallFrame()->isClosureCall) {
320                 JSFunction* callee = inlineCallFrame()->calleeConstant();
321                 if (operand.offset() == JSStack::Callee)
322                     return weakJSConstant(callee);
323             }
324         } else if (operand.offset() == JSStack::Callee) {
325             // We have to do some constant-folding here because this enables CreateThis folding. Note
326             // that we don't have such watchpoint-based folding for inlined uses of Callee, since in that
327             // case if the function is a singleton then we already know it.
328             if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) {
329                 InferredValue* singleton = executable->singletonFunction();
330                 if (JSValue value = singleton->inferredValue()) {
331                     m_graph.watchpoints().addLazily(singleton);
332                     JSFunction* function = jsCast<JSFunction*>(value);
333                     return weakJSConstant(function);
334                 }
335             }
336             return addToGraph(GetCallee);
337         }
338         
339         return getDirect(m_inlineStackTop->remapOperand(operand));
340     }
341     
342     enum SetMode {
343         // A normal set which follows a two-phase commit that spans code origins. During
344         // the current code origin it issues a MovHint, and at the start of the next
345         // code origin there will be a SetLocal. If the local needs flushing, the second
346         // SetLocal will be preceded with a Flush.
347         NormalSet,
348         
349         // A set where the SetLocal happens immediately and there is still a Flush. This
350         // is relevant when assigning to a local in tricky situations for the delayed
351         // SetLocal logic but where we know that we have not performed any side effects
352         // within this code origin. This is a safe replacement for NormalSet anytime we
353         // know that we have not yet performed side effects in this code origin.
354         ImmediateSetWithFlush,
355         
356         // A set where the SetLocal happens immediately and we do not Flush it even if
357         // this is a local that is marked as needing it. This is relevant when
358         // initializing locals at the top of a function.
359         ImmediateNakedSet
360     };
361     Node* setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
362     {
363         addToGraph(MovHint, OpInfo(operand.offset()), value);
364
365         DelayedSetLocal delayed(currentCodeOrigin(), operand, value);
366         
367         if (setMode == NormalSet) {
368             m_setLocalQueue.append(delayed);
369             return 0;
370         }
371         
372         return delayed.execute(this, setMode);
373     }
374     
375     void processSetLocalQueue()
376     {
377         for (unsigned i = 0; i < m_setLocalQueue.size(); ++i)
378             m_setLocalQueue[i].execute(this);
379         m_setLocalQueue.resize(0);
380     }
381
382     Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
383     {
384         return setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
385     }
386     
387     Node* injectLazyOperandSpeculation(Node* node)
388     {
389         ASSERT(node->op() == GetLocal);
390         ASSERT(node->origin.semantic.bytecodeIndex == m_currentIndex);
391         ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
392         LazyOperandValueProfileKey key(m_currentIndex, node->local());
393         SpeculatedType prediction = m_inlineStackTop->m_lazyOperands.prediction(locker, key);
394         node->variableAccessData()->predict(prediction);
395         return node;
396     }
397
398     // Used in implementing get/set, above, where the operand is a local variable.
399     Node* getLocal(VirtualRegister operand)
400     {
401         unsigned local = operand.toLocal();
402
403         Node* node = m_currentBlock->variablesAtTail.local(local);
404         
405         // This has two goals: 1) link together variable access datas, and 2)
406         // try to avoid creating redundant GetLocals. (1) is required for
407         // correctness - no other phase will ensure that block-local variable
408         // access data unification is done correctly. (2) is purely opportunistic
409         // and is meant as an compile-time optimization only.
410         
411         VariableAccessData* variable;
412         
413         if (node) {
414             variable = node->variableAccessData();
415             
416             switch (node->op()) {
417             case GetLocal:
418                 return node;
419             case SetLocal:
420                 return node->child1().node();
421             default:
422                 break;
423             }
424         } else
425             variable = newVariableAccessData(operand);
426         
427         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
428         m_currentBlock->variablesAtTail.local(local) = node;
429         return node;
430     }
431
432     Node* setLocal(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
433     {
434         CodeOrigin oldSemanticOrigin = m_currentSemanticOrigin;
435         m_currentSemanticOrigin = semanticOrigin;
436
437         unsigned local = operand.toLocal();
438         
439         if (setMode != ImmediateNakedSet) {
440             ArgumentPosition* argumentPosition = findArgumentPositionForLocal(operand);
441             if (argumentPosition)
442                 flushDirect(operand, argumentPosition);
443             else if (m_hasDebuggerEnabled && operand == m_codeBlock->scopeRegister())
444                 flush(operand);
445         }
446
447         VariableAccessData* variableAccessData = newVariableAccessData(operand);
448         variableAccessData->mergeStructureCheckHoistingFailed(
449             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
450         variableAccessData->mergeCheckArrayHoistingFailed(
451             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
452         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
453         m_currentBlock->variablesAtTail.local(local) = node;
454
455         m_currentSemanticOrigin = oldSemanticOrigin;
456         return node;
457     }
458
459     // Used in implementing get/set, above, where the operand is an argument.
460     Node* getArgument(VirtualRegister operand)
461     {
462         unsigned argument = operand.toArgument();
463         ASSERT(argument < m_numArguments);
464         
465         Node* node = m_currentBlock->variablesAtTail.argument(argument);
466
467         VariableAccessData* variable;
468         
469         if (node) {
470             variable = node->variableAccessData();
471             
472             switch (node->op()) {
473             case GetLocal:
474                 return node;
475             case SetLocal:
476                 return node->child1().node();
477             default:
478                 break;
479             }
480         } else
481             variable = newVariableAccessData(operand);
482         
483         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
484         m_currentBlock->variablesAtTail.argument(argument) = node;
485         return node;
486     }
487     Node* setArgument(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
488     {
489         CodeOrigin oldSemanticOrigin = m_currentSemanticOrigin;
490         m_currentSemanticOrigin = semanticOrigin;
491
492         unsigned argument = operand.toArgument();
493         ASSERT(argument < m_numArguments);
494         
495         VariableAccessData* variableAccessData = newVariableAccessData(operand);
496
497         // Always flush arguments, except for 'this'. If 'this' is created by us,
498         // then make sure that it's never unboxed.
499         if (argument) {
500             if (setMode != ImmediateNakedSet)
501                 flushDirect(operand);
502         } else if (m_codeBlock->specializationKind() == CodeForConstruct)
503             variableAccessData->mergeShouldNeverUnbox(true);
504         
505         variableAccessData->mergeStructureCheckHoistingFailed(
506             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
507         variableAccessData->mergeCheckArrayHoistingFailed(
508             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
509         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
510         m_currentBlock->variablesAtTail.argument(argument) = node;
511
512         m_currentSemanticOrigin = oldSemanticOrigin;
513         return node;
514     }
515     
516     ArgumentPosition* findArgumentPositionForArgument(int argument)
517     {
518         InlineStackEntry* stack = m_inlineStackTop;
519         while (stack->m_inlineCallFrame)
520             stack = stack->m_caller;
521         return stack->m_argumentPositions[argument];
522     }
523     
524     ArgumentPosition* findArgumentPositionForLocal(VirtualRegister operand)
525     {
526         for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) {
527             InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
528             if (!inlineCallFrame)
529                 break;
530             if (operand.offset() < static_cast<int>(inlineCallFrame->stackOffset + JSStack::CallFrameHeaderSize))
531                 continue;
532             if (operand.offset() == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
533                 continue;
534             if (operand.offset() >= static_cast<int>(inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset() + inlineCallFrame->arguments.size()))
535                 continue;
536             int argument = VirtualRegister(operand.offset() - inlineCallFrame->stackOffset).toArgument();
537             return stack->m_argumentPositions[argument];
538         }
539         return 0;
540     }
541     
542     ArgumentPosition* findArgumentPosition(VirtualRegister operand)
543     {
544         if (operand.isArgument())
545             return findArgumentPositionForArgument(operand.toArgument());
546         return findArgumentPositionForLocal(operand);
547     }
548
549     void flush(VirtualRegister operand)
550     {
551         flushDirect(m_inlineStackTop->remapOperand(operand));
552     }
553     
554     void flushDirect(VirtualRegister operand)
555     {
556         flushDirect(operand, findArgumentPosition(operand));
557     }
558     
559     void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition)
560     {
561         ASSERT(!operand.isConstant());
562         
563         Node* node = m_currentBlock->variablesAtTail.operand(operand);
564         
565         VariableAccessData* variable;
566         
567         if (node)
568             variable = node->variableAccessData();
569         else
570             variable = newVariableAccessData(operand);
571         
572         node = addToGraph(Flush, OpInfo(variable));
573         m_currentBlock->variablesAtTail.operand(operand) = node;
574         if (argumentPosition)
575             argumentPosition->addVariable(variable);
576     }
577     
578     void flush(InlineStackEntry* inlineStackEntry)
579     {
580         int numArguments;
581         if (InlineCallFrame* inlineCallFrame = inlineStackEntry->m_inlineCallFrame) {
582             ASSERT(!m_hasDebuggerEnabled);
583             numArguments = inlineCallFrame->arguments.size();
584             if (inlineCallFrame->isClosureCall)
585                 flushDirect(inlineStackEntry->remapOperand(VirtualRegister(JSStack::Callee)));
586             if (inlineCallFrame->isVarargs())
587                 flushDirect(inlineStackEntry->remapOperand(VirtualRegister(JSStack::ArgumentCount)));
588         } else
589             numArguments = inlineStackEntry->m_codeBlock->numParameters();
590         for (unsigned argument = numArguments; argument-- > 1;)
591             flushDirect(inlineStackEntry->remapOperand(virtualRegisterForArgument(argument)));
592         if (m_hasDebuggerEnabled)
593             flush(m_codeBlock->scopeRegister());
594     }
595
596     void flushForTerminal()
597     {
598         for (InlineStackEntry* inlineStackEntry = m_inlineStackTop; inlineStackEntry; inlineStackEntry = inlineStackEntry->m_caller)
599             flush(inlineStackEntry);
600     }
601
602     void flushForReturn()
603     {
604         flush(m_inlineStackTop);
605     }
606     
607     void flushIfTerminal(SwitchData& data)
608     {
609         if (data.fallThrough.bytecodeIndex() > m_currentIndex)
610             return;
611         
612         for (unsigned i = data.cases.size(); i--;) {
613             if (data.cases[i].target.bytecodeIndex() > m_currentIndex)
614                 return;
615         }
616         
617         flushForTerminal();
618     }
619
620     // Assumes that the constant should be strongly marked.
621     Node* jsConstant(JSValue constantValue)
622     {
623         return addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(constantValue)));
624     }
625
626     Node* weakJSConstant(JSValue constantValue)
627     {
628         return addToGraph(JSConstant, OpInfo(m_graph.freeze(constantValue)));
629     }
630
631     // Helper functions to get/set the this value.
632     Node* getThis()
633     {
634         return get(m_inlineStackTop->m_codeBlock->thisRegister());
635     }
636
637     void setThis(Node* value)
638     {
639         set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
640     }
641
642     InlineCallFrame* inlineCallFrame()
643     {
644         return m_inlineStackTop->m_inlineCallFrame;
645     }
646
647     CodeOrigin currentCodeOrigin()
648     {
649         return CodeOrigin(m_currentIndex, inlineCallFrame());
650     }
651
652     NodeOrigin currentNodeOrigin()
653     {
654         // FIXME: We should set the forExit origin only on those nodes that can exit.
655         // https://bugs.webkit.org/show_bug.cgi?id=145204
656         if (m_currentSemanticOrigin.isSet())
657             return NodeOrigin(m_currentSemanticOrigin, currentCodeOrigin());
658         return NodeOrigin(currentCodeOrigin());
659     }
660     
661     BranchData* branchData(unsigned taken, unsigned notTaken)
662     {
663         // We assume that branches originating from bytecode always have a fall-through. We
664         // use this assumption to avoid checking for the creation of terminal blocks.
665         ASSERT((taken > m_currentIndex) || (notTaken > m_currentIndex));
666         BranchData* data = m_graph.m_branchData.add();
667         *data = BranchData::withBytecodeIndices(taken, notTaken);
668         return data;
669     }
670     
671     Node* addToGraph(Node* node)
672     {
673         if (Options::verboseDFGByteCodeParsing())
674             dataLog("        appended ", node, " ", Graph::opName(node->op()), "\n");
675         m_currentBlock->append(node);
676         return node;
677     }
678     
679     Node* addToGraph(NodeType op, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
680     {
681         Node* result = m_graph.addNode(
682             SpecNone, op, currentNodeOrigin(), Edge(child1), Edge(child2),
683             Edge(child3));
684         return addToGraph(result);
685     }
686     Node* addToGraph(NodeType op, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
687     {
688         Node* result = m_graph.addNode(
689             SpecNone, op, currentNodeOrigin(), child1, child2, child3);
690         return addToGraph(result);
691     }
692     Node* addToGraph(NodeType op, OpInfo info, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
693     {
694         Node* result = m_graph.addNode(
695             SpecNone, op, currentNodeOrigin(), info, Edge(child1), Edge(child2),
696             Edge(child3));
697         return addToGraph(result);
698     }
699     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
700     {
701         Node* result = m_graph.addNode(
702             SpecNone, op, currentNodeOrigin(), info1, info2,
703             Edge(child1), Edge(child2), Edge(child3));
704         return addToGraph(result);
705     }
706     
707     Node* addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2)
708     {
709         Node* result = m_graph.addNode(
710             SpecNone, Node::VarArg, op, currentNodeOrigin(), info1, info2,
711             m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs);
712         addToGraph(result);
713         
714         m_numPassedVarArgs = 0;
715         
716         return result;
717     }
718     
719     void addVarArgChild(Node* child)
720     {
721         m_graph.m_varArgChildren.append(Edge(child));
722         m_numPassedVarArgs++;
723     }
724     
725     Node* addCallWithoutSettingResult(
726         NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
727         SpeculatedType prediction)
728     {
729         addVarArgChild(callee);
730         size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount;
731         if (parameterSlots > m_parameterSlots)
732             m_parameterSlots = parameterSlots;
733
734         for (int i = 0; i < argCount; ++i)
735             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
736
737         return addToGraph(Node::VarArg, op, opInfo, OpInfo(prediction));
738     }
739     
740     Node* addCall(
741         int result, NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
742         SpeculatedType prediction)
743     {
744         Node* call = addCallWithoutSettingResult(
745             op, opInfo, callee, argCount, registerOffset, prediction);
746         VirtualRegister resultReg(result);
747         if (resultReg.isValid())
748             set(resultReg, call);
749         return call;
750     }
751     
752     Node* cellConstantWithStructureCheck(JSCell* object, Structure* structure)
753     {
754         // FIXME: This should route to emitPropertyCheck, not the other way around. But currently,
755         // this gets no profit from using emitPropertyCheck() since we'll non-adaptively watch the
756         // object's structure as soon as we make it a weakJSCosntant.
757         Node* objectNode = weakJSConstant(object);
758         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectNode);
759         return objectNode;
760     }
761     
762     SpeculatedType getPredictionWithoutOSRExit(unsigned bytecodeIndex)
763     {
764         ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
765         return m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(locker, bytecodeIndex);
766     }
767
768     SpeculatedType getPrediction(unsigned bytecodeIndex)
769     {
770         SpeculatedType prediction = getPredictionWithoutOSRExit(bytecodeIndex);
771         
772         if (prediction == SpecNone) {
773             // We have no information about what values this node generates. Give up
774             // on executing this code, since we're likely to do more damage than good.
775             addToGraph(ForceOSRExit);
776         }
777         
778         return prediction;
779     }
780     
781     SpeculatedType getPredictionWithoutOSRExit()
782     {
783         return getPredictionWithoutOSRExit(m_currentIndex);
784     }
785     
786     SpeculatedType getPrediction()
787     {
788         return getPrediction(m_currentIndex);
789     }
790     
791     ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
792     {
793         ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
794         profile->computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
795         bool makeSafe = profile->outOfBounds(locker);
796         return ArrayMode::fromObserved(locker, profile, action, makeSafe);
797     }
798     
799     ArrayMode getArrayMode(ArrayProfile* profile)
800     {
801         return getArrayMode(profile, Array::Read);
802     }
803     
804     Node* makeSafe(Node* node)
805     {
806         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
807             node->mergeFlags(NodeMayOverflowInDFG);
808         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
809             node->mergeFlags(NodeMayNegZeroInDFG);
810         
811         if (!isX86() && node->op() == ArithMod)
812             return node;
813
814         if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
815             return node;
816         
817         switch (node->op()) {
818         case UInt32ToNumber:
819         case ArithAdd:
820         case ArithSub:
821         case ValueAdd:
822         case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
823             node->mergeFlags(NodeMayOverflowInBaseline);
824             break;
825             
826         case ArithNegate:
827             // Currently we can't tell the difference between a negation overflowing
828             // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow
829             // path then we assume that it did both of those things.
830             node->mergeFlags(NodeMayOverflowInBaseline);
831             node->mergeFlags(NodeMayNegZeroInBaseline);
832             break;
833
834         case ArithMul:
835             // FIXME: We should detect cases where we only overflowed but never created
836             // negative zero.
837             // https://bugs.webkit.org/show_bug.cgi?id=132470
838             if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)
839                 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
840                 node->mergeFlags(NodeMayOverflowInBaseline | NodeMayNegZeroInBaseline);
841             else if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
842                 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
843                 node->mergeFlags(NodeMayNegZeroInBaseline);
844             break;
845             
846         default:
847             RELEASE_ASSERT_NOT_REACHED();
848             break;
849         }
850         
851         return node;
852     }
853     
854     Node* makeDivSafe(Node* node)
855     {
856         ASSERT(node->op() == ArithDiv);
857         
858         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
859             node->mergeFlags(NodeMayOverflowInDFG);
860         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
861             node->mergeFlags(NodeMayNegZeroInDFG);
862         
863         // The main slow case counter for op_div in the old JIT counts only when
864         // the operands are not numbers. We don't care about that since we already
865         // have speculations in place that take care of that separately. We only
866         // care about when the outcome of the division is not an integer, which
867         // is what the special fast case counter tells us.
868         
869         if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex))
870             return node;
871         
872         // FIXME: It might be possible to make this more granular.
873         node->mergeFlags(NodeMayOverflowInBaseline | NodeMayNegZeroInBaseline);
874         
875         return node;
876     }
877     
878     void noticeArgumentsUse()
879     {
880         // All of the arguments in this function need to be formatted as JSValues because we will
881         // load from them in a random-access fashion and we don't want to have to switch on
882         // format.
883         
884         for (ArgumentPosition* argument : m_inlineStackTop->m_argumentPositions)
885             argument->mergeShouldNeverUnbox(true);
886     }
887     
888     VM* m_vm;
889     CodeBlock* m_codeBlock;
890     CodeBlock* m_profiledBlock;
891     Graph& m_graph;
892
893     // The current block being generated.
894     BasicBlock* m_currentBlock;
895     // The bytecode index of the current instruction being generated.
896     unsigned m_currentIndex;
897     // The semantic origin of the current node if different from the current Index.
898     CodeOrigin m_currentSemanticOrigin;
899
900     FrozenValue* m_constantUndefined;
901     FrozenValue* m_constantNull;
902     FrozenValue* m_constantNaN;
903     FrozenValue* m_constantOne;
904     Vector<Node*, 16> m_constants;
905
906     // The number of arguments passed to the function.
907     unsigned m_numArguments;
908     // The number of locals (vars + temporaries) used in the function.
909     unsigned m_numLocals;
910     // The number of slots (in units of sizeof(Register)) that we need to
911     // preallocate for arguments to outgoing calls from this frame. This
912     // number includes the CallFrame slots that we initialize for the callee
913     // (but not the callee-initialized CallerFrame and ReturnPC slots).
914     // This number is 0 if and only if this function is a leaf.
915     unsigned m_parameterSlots;
916     // The number of var args passed to the next var arg node.
917     unsigned m_numPassedVarArgs;
918
919     HashMap<ConstantBufferKey, unsigned> m_constantBufferCache;
920     
921     struct InlineStackEntry {
922         ByteCodeParser* m_byteCodeParser;
923         
924         CodeBlock* m_codeBlock;
925         CodeBlock* m_profiledBlock;
926         InlineCallFrame* m_inlineCallFrame;
927         
928         ScriptExecutable* executable() { return m_codeBlock->ownerExecutable(); }
929         
930         QueryableExitProfile m_exitProfile;
931         
932         // Remapping of identifier and constant numbers from the code block being
933         // inlined (inline callee) to the code block that we're inlining into
934         // (the machine code block, which is the transitive, though not necessarily
935         // direct, caller).
936         Vector<unsigned> m_identifierRemap;
937         Vector<unsigned> m_constantBufferRemap;
938         Vector<unsigned> m_switchRemap;
939         
940         // Blocks introduced by this code block, which need successor linking.
941         // May include up to one basic block that includes the continuation after
942         // the callsite in the caller. These must be appended in the order that they
943         // are created, but their bytecodeBegin values need not be in order as they
944         // are ignored.
945         Vector<UnlinkedBlock> m_unlinkedBlocks;
946         
947         // Potential block linking targets. Must be sorted by bytecodeBegin, and
948         // cannot have two blocks that have the same bytecodeBegin.
949         Vector<BasicBlock*> m_blockLinkingTargets;
950         
951         // If the callsite's basic block was split into two, then this will be
952         // the head of the callsite block. It needs its successors linked to the
953         // m_unlinkedBlocks, but not the other way around: there's no way for
954         // any blocks in m_unlinkedBlocks to jump back into this block.
955         BasicBlock* m_callsiteBlockHead;
956         
957         // Does the callsite block head need linking? This is typically true
958         // but will be false for the machine code block's inline stack entry
959         // (since that one is not inlined) and for cases where an inline callee
960         // did the linking for us.
961         bool m_callsiteBlockHeadNeedsLinking;
962         
963         VirtualRegister m_returnValue;
964         
965         // Speculations about variable types collected from the profiled code block,
966         // which are based on OSR exit profiles that past DFG compilatins of this
967         // code block had gathered.
968         LazyOperandValueProfileParser m_lazyOperands;
969         
970         CallLinkInfoMap m_callLinkInfos;
971         StubInfoMap m_stubInfos;
972         
973         // Did we see any returns? We need to handle the (uncommon but necessary)
974         // case where a procedure that does not return was inlined.
975         bool m_didReturn;
976         
977         // Did we have any early returns?
978         bool m_didEarlyReturn;
979         
980         // Pointers to the argument position trackers for this slice of code.
981         Vector<ArgumentPosition*> m_argumentPositions;
982         
983         InlineStackEntry* m_caller;
984         
985         InlineStackEntry(
986             ByteCodeParser*,
987             CodeBlock*,
988             CodeBlock* profiledBlock,
989             BasicBlock* callsiteBlockHead,
990             JSFunction* callee, // Null if this is a closure call.
991             VirtualRegister returnValueVR,
992             VirtualRegister inlineCallFrameStart,
993             int argumentCountIncludingThis,
994             InlineCallFrame::Kind);
995         
996         ~InlineStackEntry()
997         {
998             m_byteCodeParser->m_inlineStackTop = m_caller;
999         }
1000         
1001         VirtualRegister remapOperand(VirtualRegister operand) const
1002         {
1003             if (!m_inlineCallFrame)
1004                 return operand;
1005             
1006             ASSERT(!operand.isConstant());
1007
1008             return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
1009         }
1010     };
1011     
1012     InlineStackEntry* m_inlineStackTop;
1013     
1014     struct DelayedSetLocal {
1015         CodeOrigin m_origin;
1016         VirtualRegister m_operand;
1017         Node* m_value;
1018         
1019         DelayedSetLocal() { }
1020         DelayedSetLocal(const CodeOrigin& origin, VirtualRegister operand, Node* value)
1021             : m_origin(origin)
1022             , m_operand(operand)
1023             , m_value(value)
1024         {
1025         }
1026         
1027         Node* execute(ByteCodeParser* parser, SetMode setMode = NormalSet)
1028         {
1029             if (m_operand.isArgument())
1030                 return parser->setArgument(m_origin, m_operand, m_value, setMode);
1031             return parser->setLocal(m_origin, m_operand, m_value, setMode);
1032         }
1033     };
1034     
1035     Vector<DelayedSetLocal, 2> m_setLocalQueue;
1036
1037     CodeBlock* m_dfgCodeBlock;
1038     CallLinkStatus::ContextMap m_callContextMap;
1039     StubInfoMap m_dfgStubInfos;
1040     
1041     Instruction* m_currentInstruction;
1042     bool m_hasDebuggerEnabled;
1043 };
1044
1045 #define NEXT_OPCODE(name) \
1046     m_currentIndex += OPCODE_LENGTH(name); \
1047     continue
1048
1049 #define LAST_OPCODE(name) \
1050     m_currentIndex += OPCODE_LENGTH(name); \
1051     return shouldContinueParsing
1052
1053 void ByteCodeParser::handleCall(Instruction* pc, NodeType op, CodeSpecializationKind kind)
1054 {
1055     ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
1056     handleCall(
1057         pc[1].u.operand, op, kind, OPCODE_LENGTH(op_call),
1058         pc[2].u.operand, pc[3].u.operand, -pc[4].u.operand);
1059 }
1060
1061 void ByteCodeParser::handleCall(
1062     int result, NodeType op, CodeSpecializationKind kind, unsigned instructionSize,
1063     int callee, int argumentCountIncludingThis, int registerOffset)
1064 {
1065     Node* callTarget = get(VirtualRegister(callee));
1066     
1067     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1068         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1069         m_inlineStackTop->m_callLinkInfos, m_callContextMap);
1070     
1071     handleCall(
1072         result, op, InlineCallFrame::kindFor(kind), instructionSize, callTarget,
1073         argumentCountIncludingThis, registerOffset, callLinkStatus);
1074 }
1075     
1076 void ByteCodeParser::handleCall(
1077     int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
1078     Node* callTarget, int argumentCountIncludingThis, int registerOffset,
1079     CallLinkStatus callLinkStatus)
1080 {
1081     handleCall(
1082         result, op, kind, instructionSize, callTarget, argumentCountIncludingThis,
1083         registerOffset, callLinkStatus, getPrediction());
1084 }
1085
1086 void ByteCodeParser::handleCall(
1087     int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
1088     Node* callTarget, int argumentCountIncludingThis, int registerOffset,
1089     CallLinkStatus callLinkStatus, SpeculatedType prediction)
1090 {
1091     ASSERT(registerOffset <= 0);
1092     
1093     if (callTarget->isCellConstant())
1094         callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell()));
1095     
1096     if (Options::verboseDFGByteCodeParsing())
1097         dataLog("    Handling call at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1098     
1099     if (!callLinkStatus.canOptimize()) {
1100         // Oddly, this conflates calls that haven't executed with calls that behaved sufficiently polymorphically
1101         // that we cannot optimize them.
1102         
1103         addCall(result, op, OpInfo(), callTarget, argumentCountIncludingThis, registerOffset, prediction);
1104         return;
1105     }
1106     
1107     unsigned nextOffset = m_currentIndex + instructionSize;
1108     
1109     OpInfo callOpInfo;
1110     
1111     if (handleInlining(callTarget, result, callLinkStatus, registerOffset, virtualRegisterForArgument(0, registerOffset), VirtualRegister(), 0, argumentCountIncludingThis, nextOffset, op, kind, prediction)) {
1112         if (m_graph.compilation())
1113             m_graph.compilation()->noticeInlinedCall();
1114         return;
1115     }
1116     
1117     addCall(result, op, callOpInfo, callTarget, argumentCountIncludingThis, registerOffset, prediction);
1118 }
1119
1120 void ByteCodeParser::handleVarargsCall(Instruction* pc, NodeType op, CodeSpecializationKind kind)
1121 {
1122     ASSERT(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_construct_varargs));
1123     
1124     int result = pc[1].u.operand;
1125     int callee = pc[2].u.operand;
1126     int thisReg = pc[3].u.operand;
1127     int arguments = pc[4].u.operand;
1128     int firstFreeReg = pc[5].u.operand;
1129     int firstVarArgOffset = pc[6].u.operand;
1130     
1131     SpeculatedType prediction = getPrediction();
1132     
1133     Node* callTarget = get(VirtualRegister(callee));
1134     
1135     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1136         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1137         m_inlineStackTop->m_callLinkInfos, m_callContextMap);
1138     if (callTarget->isCellConstant())
1139         callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell()));
1140     
1141     if (Options::verboseDFGByteCodeParsing())
1142         dataLog("    Varargs call link status at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1143     
1144     if (callLinkStatus.canOptimize()
1145         && handleInlining(callTarget, result, callLinkStatus, firstFreeReg, VirtualRegister(thisReg), VirtualRegister(arguments), firstVarArgOffset, 0, m_currentIndex + OPCODE_LENGTH(op_call_varargs), op, InlineCallFrame::varargsKindFor(kind), prediction)) {
1146         if (m_graph.compilation())
1147             m_graph.compilation()->noticeInlinedCall();
1148         return;
1149     }
1150     
1151     CallVarargsData* data = m_graph.m_callVarargsData.add();
1152     data->firstVarArgOffset = firstVarArgOffset;
1153     
1154     Node* thisChild = get(VirtualRegister(thisReg));
1155     
1156     Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, get(VirtualRegister(arguments)), thisChild);
1157     VirtualRegister resultReg(result);
1158     if (resultReg.isValid())
1159         set(resultReg, call);
1160 }
1161
1162 void ByteCodeParser::emitFunctionChecks(CallVariant callee, Node* callTarget, VirtualRegister thisArgumentReg)
1163 {
1164     Node* thisArgument;
1165     if (thisArgumentReg.isValid())
1166         thisArgument = get(thisArgumentReg);
1167     else
1168         thisArgument = 0;
1169
1170     JSCell* calleeCell;
1171     Node* callTargetForCheck;
1172     if (callee.isClosureCall()) {
1173         calleeCell = callee.executable();
1174         callTargetForCheck = addToGraph(GetExecutable, callTarget);
1175     } else {
1176         calleeCell = callee.nonExecutableCallee();
1177         callTargetForCheck = callTarget;
1178     }
1179     
1180     ASSERT(calleeCell);
1181     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck, thisArgument);
1182 }
1183
1184 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
1185 {
1186     for (int i = 0; i < argumentCountIncludingThis; ++i)
1187         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
1188 }
1189
1190 unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, CodeSpecializationKind kind)
1191 {
1192     if (verbose)
1193         dataLog("Considering inlining ", callee, " into ", currentCodeOrigin(), "\n");
1194     
1195     if (m_hasDebuggerEnabled) {
1196         if (verbose)
1197             dataLog("    Failing because the debugger is in use.\n");
1198         return UINT_MAX;
1199     }
1200
1201     FunctionExecutable* executable = callee.functionExecutable();
1202     if (!executable) {
1203         if (verbose)
1204             dataLog("    Failing because there is no function executable.\n");
1205         return UINT_MAX;
1206     }
1207     
1208     // Does the number of arguments we're passing match the arity of the target? We currently
1209     // inline only if the number of arguments passed is greater than or equal to the number
1210     // arguments expected.
1211     if (static_cast<int>(executable->parameterCount()) + 1 > argumentCountIncludingThis) {
1212         if (verbose)
1213             dataLog("    Failing because of arity mismatch.\n");
1214         return UINT_MAX;
1215     }
1216     
1217     // Do we have a code block, and does the code block's size match the heuristics/requirements for
1218     // being an inline candidate? We might not have a code block (1) if code was thrown away,
1219     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
1220     // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
1221     // to inline it if we had a static proof of what was being called; this might happen for example
1222     // if you call a global function, where watchpointing gives us static information. Overall,
1223     // it's a rare case because we expect that any hot callees would have already been compiled.
1224     CodeBlock* codeBlock = executable->baselineCodeBlockFor(kind);
1225     if (!codeBlock) {
1226         if (verbose)
1227             dataLog("    Failing because no code block available.\n");
1228         return UINT_MAX;
1229     }
1230     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
1231         codeBlock, kind, callee.isClosureCall());
1232     if (verbose) {
1233         dataLog("    Kind: ", kind, "\n");
1234         dataLog("    Is closure call: ", callee.isClosureCall(), "\n");
1235         dataLog("    Capability level: ", capabilityLevel, "\n");
1236         dataLog("    Might inline function: ", mightInlineFunctionFor(codeBlock, kind), "\n");
1237         dataLog("    Might compile function: ", mightCompileFunctionFor(codeBlock, kind), "\n");
1238         dataLog("    Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n");
1239         dataLog("    Needs activation: ", codeBlock->ownerExecutable()->needsActivation(), "\n");
1240         dataLog("    Is inlining candidate: ", codeBlock->ownerExecutable()->isInliningCandidate(), "\n");
1241     }
1242     if (!canInline(capabilityLevel)) {
1243         if (verbose)
1244             dataLog("    Failing because the function is not inlineable.\n");
1245         return UINT_MAX;
1246     }
1247     
1248     // Check if the caller is already too large. We do this check here because that's just
1249     // where we happen to also have the callee's code block, and we want that for the
1250     // purpose of unsetting SABI.
1251     if (!isSmallEnoughToInlineCodeInto(m_codeBlock)) {
1252         codeBlock->m_shouldAlwaysBeInlined = false;
1253         if (verbose)
1254             dataLog("    Failing because the caller is too large.\n");
1255         return UINT_MAX;
1256     }
1257     
1258     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
1259     // this function.
1260     // https://bugs.webkit.org/show_bug.cgi?id=127627
1261     
1262     // FIXME: We currently inline functions that have run in LLInt but not in Baseline. These
1263     // functions have very low fidelity profiling, and presumably they weren't very hot if they
1264     // haven't gotten to Baseline yet. Consider not inlining these functions.
1265     // https://bugs.webkit.org/show_bug.cgi?id=145503
1266     
1267     // Have we exceeded inline stack depth, or are we trying to inline a recursive call to
1268     // too many levels? If either of these are detected, then don't inline. We adjust our
1269     // heuristics if we are dealing with a function that cannot otherwise be compiled.
1270     
1271     unsigned depth = 0;
1272     unsigned recursion = 0;
1273     
1274     for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
1275         ++depth;
1276         if (depth >= Options::maximumInliningDepth()) {
1277             if (verbose)
1278                 dataLog("    Failing because depth exceeded.\n");
1279             return UINT_MAX;
1280         }
1281         
1282         if (entry->executable() == executable) {
1283             ++recursion;
1284             if (recursion >= Options::maximumInliningRecursion()) {
1285                 if (verbose)
1286                     dataLog("    Failing because recursion detected.\n");
1287                 return UINT_MAX;
1288             }
1289         }
1290     }
1291     
1292     if (verbose)
1293         dataLog("    Inlining should be possible.\n");
1294     
1295     // It might be possible to inline.
1296     return codeBlock->instructionCount();
1297 }
1298
1299 template<typename ChecksFunctor>
1300 void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, CallerLinkability callerLinkability, const ChecksFunctor& insertChecks)
1301 {
1302     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1303     
1304     ASSERT(inliningCost(callee, argumentCountIncludingThis, specializationKind) != UINT_MAX);
1305     
1306     CodeBlock* codeBlock = callee.functionExecutable()->baselineCodeBlockFor(specializationKind);
1307     insertChecks(codeBlock);
1308
1309     // FIXME: Don't flush constants!
1310     
1311     int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset() + JSStack::CallFrameHeaderSize;
1312     
1313     ensureLocals(
1314         VirtualRegister(inlineCallFrameStart).toLocal() + 1 +
1315         JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters);
1316     
1317     size_t argumentPositionStart = m_graph.m_argumentPositions.size();
1318
1319     VirtualRegister resultReg(resultOperand);
1320     if (resultReg.isValid())
1321         resultReg = m_inlineStackTop->remapOperand(resultReg);
1322     
1323     InlineStackEntry inlineStackEntry(
1324         this, codeBlock, codeBlock, m_graph.lastBlock(), callee.function(), resultReg,
1325         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
1326     
1327     // This is where the actual inlining really happens.
1328     unsigned oldIndex = m_currentIndex;
1329     m_currentIndex = 0;
1330
1331     InlineVariableData inlineVariableData;
1332     inlineVariableData.inlineCallFrame = m_inlineStackTop->m_inlineCallFrame;
1333     inlineVariableData.argumentPositionStart = argumentPositionStart;
1334     inlineVariableData.calleeVariable = 0;
1335     
1336     RELEASE_ASSERT(
1337         m_inlineStackTop->m_inlineCallFrame->isClosureCall
1338         == callee.isClosureCall());
1339     if (callee.isClosureCall()) {
1340         VariableAccessData* calleeVariable =
1341             set(VirtualRegister(JSStack::Callee), callTargetNode, ImmediateNakedSet)->variableAccessData();
1342         
1343         calleeVariable->mergeShouldNeverUnbox(true);
1344         
1345         inlineVariableData.calleeVariable = calleeVariable;
1346     }
1347     
1348     m_graph.m_inlineVariableData.append(inlineVariableData);
1349     
1350     parseCodeBlock();
1351     clearCaches(); // Reset our state now that we're back to the outer code.
1352     
1353     m_currentIndex = oldIndex;
1354     
1355     // If the inlined code created some new basic blocks, then we have linking to do.
1356     if (inlineStackEntry.m_callsiteBlockHead != m_graph.lastBlock()) {
1357         
1358         ASSERT(!inlineStackEntry.m_unlinkedBlocks.isEmpty());
1359         if (inlineStackEntry.m_callsiteBlockHeadNeedsLinking)
1360             linkBlock(inlineStackEntry.m_callsiteBlockHead, inlineStackEntry.m_blockLinkingTargets);
1361         else
1362             ASSERT(inlineStackEntry.m_callsiteBlockHead->isLinked);
1363         
1364         if (callerLinkability == CallerDoesNormalLinking)
1365             cancelLinkingForBlock(inlineStackEntry.m_caller, inlineStackEntry.m_callsiteBlockHead);
1366         
1367         linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
1368     } else
1369         ASSERT(inlineStackEntry.m_unlinkedBlocks.isEmpty());
1370     
1371     BasicBlock* lastBlock = m_graph.lastBlock();
1372     // If there was a return, but no early returns, then we're done. We allow parsing of
1373     // the caller to continue in whatever basic block we're in right now.
1374     if (!inlineStackEntry.m_didEarlyReturn && inlineStackEntry.m_didReturn) {
1375         if (Options::verboseDFGByteCodeParsing())
1376             dataLog("    Allowing parsing to continue in last inlined block.\n");
1377         
1378         ASSERT(lastBlock->isEmpty() || !lastBlock->terminal());
1379         
1380         // If we created new blocks then the last block needs linking, but in the
1381         // caller. It doesn't need to be linked to, but it needs outgoing links.
1382         if (!inlineStackEntry.m_unlinkedBlocks.isEmpty()) {
1383             // For debugging purposes, set the bytecodeBegin. Note that this doesn't matter
1384             // for release builds because this block will never serve as a potential target
1385             // in the linker's binary search.
1386             if (Options::verboseDFGByteCodeParsing())
1387                 dataLog("        Repurposing last block from ", lastBlock->bytecodeBegin, " to ", m_currentIndex, "\n");
1388             lastBlock->bytecodeBegin = m_currentIndex;
1389             if (callerLinkability == CallerDoesNormalLinking) {
1390                 if (verbose)
1391                     dataLog("Adding unlinked block ", RawPointer(m_graph.lastBlock()), " (one return)\n");
1392                 m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.lastBlock()));
1393             }
1394         }
1395         
1396         m_currentBlock = m_graph.lastBlock();
1397         return;
1398     }
1399     
1400     if (Options::verboseDFGByteCodeParsing())
1401         dataLog("    Creating new block after inlining.\n");
1402
1403     // If we get to this point then all blocks must end in some sort of terminals.
1404     ASSERT(lastBlock->terminal());
1405
1406     // Need to create a new basic block for the continuation at the caller.
1407     RefPtr<BasicBlock> block = adoptRef(new BasicBlock(nextOffset, m_numArguments, m_numLocals, PNaN));
1408
1409     // Link the early returns to the basic block we're about to create.
1410     for (size_t i = 0; i < inlineStackEntry.m_unlinkedBlocks.size(); ++i) {
1411         if (!inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking)
1412             continue;
1413         BasicBlock* blockToLink = inlineStackEntry.m_unlinkedBlocks[i].m_block;
1414         ASSERT(!blockToLink->isLinked);
1415         Node* node = blockToLink->terminal();
1416         ASSERT(node->op() == Jump);
1417         ASSERT(!node->targetBlock());
1418         node->targetBlock() = block.get();
1419         inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking = false;
1420         if (verbose)
1421             dataLog("Marking ", RawPointer(blockToLink), " as linked (jumps to return)\n");
1422         blockToLink->didLink();
1423     }
1424     
1425     m_currentBlock = block.get();
1426     ASSERT(m_inlineStackTop->m_caller->m_blockLinkingTargets.isEmpty() || m_inlineStackTop->m_caller->m_blockLinkingTargets.last()->bytecodeBegin < nextOffset);
1427     if (verbose)
1428         dataLog("Adding unlinked block ", RawPointer(block.get()), " (many returns)\n");
1429     if (callerLinkability == CallerDoesNormalLinking) {
1430         m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(block.get()));
1431         m_inlineStackTop->m_caller->m_blockLinkingTargets.append(block.get());
1432     }
1433     m_graph.appendBlock(block);
1434     prepareToParseBlock();
1435 }
1436
1437 void ByteCodeParser::cancelLinkingForBlock(InlineStackEntry* inlineStackEntry, BasicBlock* block)
1438 {
1439     // It's possible that the callsite block head is not owned by the caller.
1440     if (!inlineStackEntry->m_unlinkedBlocks.isEmpty()) {
1441         // It's definitely owned by the caller, because the caller created new blocks.
1442         // Assert that this all adds up.
1443         ASSERT_UNUSED(block, inlineStackEntry->m_unlinkedBlocks.last().m_block == block);
1444         ASSERT(inlineStackEntry->m_unlinkedBlocks.last().m_needsNormalLinking);
1445         inlineStackEntry->m_unlinkedBlocks.last().m_needsNormalLinking = false;
1446     } else {
1447         // It's definitely not owned by the caller. Tell the caller that he does not
1448         // need to link his callsite block head, because we did it for him.
1449         ASSERT(inlineStackEntry->m_callsiteBlockHeadNeedsLinking);
1450         ASSERT_UNUSED(block, inlineStackEntry->m_callsiteBlockHead == block);
1451         inlineStackEntry->m_callsiteBlockHeadNeedsLinking = false;
1452     }
1453 }
1454
1455 template<typename ChecksFunctor>
1456 bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, CallerLinkability callerLinkability, SpeculatedType prediction, unsigned& inliningBalance, const ChecksFunctor& insertChecks)
1457 {
1458     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1459     
1460     if (!inliningBalance)
1461         return false;
1462     
1463     bool didInsertChecks = false;
1464     auto insertChecksWithAccounting = [&] () {
1465         insertChecks(nullptr);
1466         didInsertChecks = true;
1467     };
1468     
1469     if (verbose)
1470         dataLog("    Considering callee ", callee, "\n");
1471     
1472     // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because
1473     // we currently don't have any way of getting profiling information for arguments to non-JS varargs
1474     // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow,
1475     // and there are no callsite value profiles and native function won't have callee value profiles for
1476     // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to
1477     // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without
1478     // calling LoadVarargs twice.
1479     if (!InlineCallFrame::isVarargs(kind)) {
1480         if (InternalFunction* function = callee.internalFunction()) {
1481             if (handleConstantInternalFunction(resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, insertChecksWithAccounting)) {
1482                 RELEASE_ASSERT(didInsertChecks);
1483                 addToGraph(Phantom, callTargetNode);
1484                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1485                 inliningBalance--;
1486                 return true;
1487             }
1488             RELEASE_ASSERT(!didInsertChecks);
1489             return false;
1490         }
1491     
1492         Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
1493         if (intrinsic != NoIntrinsic) {
1494             if (handleIntrinsic(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1495                 RELEASE_ASSERT(didInsertChecks);
1496                 addToGraph(Phantom, callTargetNode);
1497                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1498                 inliningBalance--;
1499                 return true;
1500             }
1501             RELEASE_ASSERT(!didInsertChecks);
1502             return false;
1503         }
1504     }
1505     
1506     unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, specializationKind);
1507     if (myInliningCost > inliningBalance)
1508         return false;
1509
1510     Instruction* savedCurrentInstruction = m_currentInstruction;
1511     inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, callerLinkability, insertChecks);
1512     inliningBalance -= myInliningCost;
1513     m_currentInstruction = savedCurrentInstruction;
1514     return true;
1515 }
1516
1517 bool ByteCodeParser::handleInlining(
1518     Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus,
1519     int registerOffsetOrFirstFreeReg, VirtualRegister thisArgument,
1520     VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis,
1521     unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
1522 {
1523     if (verbose) {
1524         dataLog("Handling inlining...\n");
1525         dataLog("Stack: ", currentCodeOrigin(), "\n");
1526     }
1527     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1528     
1529     if (!callLinkStatus.size()) {
1530         if (verbose)
1531             dataLog("Bailing inlining.\n");
1532         return false;
1533     }
1534     
1535     if (InlineCallFrame::isVarargs(kind)
1536         && callLinkStatus.maxNumArguments() > Options::maximumVarargsForInlining()) {
1537         if (verbose)
1538             dataLog("Bailing inlining because of varargs.\n");
1539         return false;
1540     }
1541         
1542     unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
1543     if (specializationKind == CodeForConstruct)
1544         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
1545     if (callLinkStatus.isClosureCall())
1546         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
1547     
1548     // First check if we can avoid creating control flow. Our inliner does some CFG
1549     // simplification on the fly and this helps reduce compile times, but we can only leverage
1550     // this in cases where we don't need control flow diamonds to check the callee.
1551     if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
1552         int registerOffset;
1553         
1554         // Only used for varargs calls.
1555         unsigned mandatoryMinimum = 0;
1556         unsigned maxNumArguments = 0;
1557
1558         if (InlineCallFrame::isVarargs(kind)) {
1559             if (FunctionExecutable* functionExecutable = callLinkStatus[0].functionExecutable())
1560                 mandatoryMinimum = functionExecutable->parameterCount();
1561             else
1562                 mandatoryMinimum = 0;
1563             
1564             // includes "this"
1565             maxNumArguments = std::max(
1566                 callLinkStatus.maxNumArguments(),
1567                 mandatoryMinimum + 1);
1568             
1569             // We sort of pretend that this *is* the number of arguments that were passed.
1570             argumentCountIncludingThis = maxNumArguments;
1571             
1572             registerOffset = registerOffsetOrFirstFreeReg + 1;
1573             registerOffset -= maxNumArguments; // includes "this"
1574             registerOffset -= JSStack::CallFrameHeaderSize;
1575             registerOffset = -WTF::roundUpToMultipleOf(
1576                 stackAlignmentRegisters(),
1577                 -registerOffset);
1578         } else
1579             registerOffset = registerOffsetOrFirstFreeReg;
1580         
1581         bool result = attemptToInlineCall(
1582             callTargetNode, resultOperand, callLinkStatus[0], registerOffset,
1583             argumentCountIncludingThis, nextOffset, kind, CallerDoesNormalLinking, prediction,
1584             inliningBalance, [&] (CodeBlock* codeBlock) {
1585                 emitFunctionChecks(callLinkStatus[0], callTargetNode, thisArgument);
1586
1587                 // If we have a varargs call, we want to extract the arguments right now.
1588                 if (InlineCallFrame::isVarargs(kind)) {
1589                     int remappedRegisterOffset =
1590                         m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset();
1591                     
1592                     ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal());
1593                     
1594                     int argumentStart = registerOffset + JSStack::CallFrameHeaderSize;
1595                     int remappedArgumentStart =
1596                         m_inlineStackTop->remapOperand(VirtualRegister(argumentStart)).offset();
1597
1598                     LoadVarargsData* data = m_graph.m_loadVarargsData.add();
1599                     data->start = VirtualRegister(remappedArgumentStart + 1);
1600                     data->count = VirtualRegister(remappedRegisterOffset + JSStack::ArgumentCount);
1601                     data->offset = argumentsOffset;
1602                     data->limit = maxNumArguments;
1603                     data->mandatoryMinimum = mandatoryMinimum;
1604             
1605                     addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
1606
1607                     // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
1608                     // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
1609                     // callTargetNode because the other 2 are still in use and alive at this point.
1610                     addToGraph(Phantom, callTargetNode);
1611
1612                     // In DFG IR before SSA, we cannot insert control flow between after the
1613                     // LoadVarargs and the last SetArgument. This isn't a problem once we get to DFG
1614                     // SSA. Fortunately, we also have other reasons for not inserting control flow
1615                     // before SSA.
1616             
1617                     VariableAccessData* countVariable = newVariableAccessData(
1618                         VirtualRegister(remappedRegisterOffset + JSStack::ArgumentCount));
1619                     // This is pretty lame, but it will force the count to be flushed as an int. This doesn't
1620                     // matter very much, since our use of a SetArgument and Flushes for this local slot is
1621                     // mostly just a formality.
1622                     countVariable->predict(SpecInt32);
1623                     countVariable->mergeIsProfitableToUnbox(true);
1624                     Node* setArgumentCount = addToGraph(SetArgument, OpInfo(countVariable));
1625                     m_currentBlock->variablesAtTail.setOperand(countVariable->local(), setArgumentCount);
1626
1627                     set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
1628                     for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
1629                         VariableAccessData* variable = newVariableAccessData(
1630                             VirtualRegister(remappedArgumentStart + argument));
1631                         variable->mergeShouldNeverUnbox(true); // We currently have nowhere to put the type check on the LoadVarargs. LoadVarargs is effectful, so after it finishes, we cannot exit.
1632                         
1633                         // For a while it had been my intention to do things like this inside the
1634                         // prediction injection phase. But in this case it's really best to do it here,
1635                         // because it's here that we have access to the variable access datas for the
1636                         // inlining we're about to do.
1637                         //
1638                         // Something else that's interesting here is that we'd really love to get
1639                         // predictions from the arguments loaded at the callsite, rather than the
1640                         // arguments received inside the callee. But that probably won't matter for most
1641                         // calls.
1642                         if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
1643                             ConcurrentJITLocker locker(codeBlock->m_lock);
1644                             if (ValueProfile* profile = codeBlock->valueProfileForArgument(argument))
1645                                 variable->predict(profile->computeUpdatedPrediction(locker));
1646                         }
1647                         
1648                         Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
1649                         m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
1650                     }
1651                 }
1652             });
1653         if (verbose) {
1654             dataLog("Done inlining (simple).\n");
1655             dataLog("Stack: ", currentCodeOrigin(), "\n");
1656             dataLog("Result: ", result, "\n");
1657         }
1658         return result;
1659     }
1660     
1661     // We need to create some kind of switch over callee. For now we only do this if we believe that
1662     // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
1663     // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
1664     // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
1665     // we could improve that aspect of this by doing polymorphic inlining but having the profiling
1666     // also.
1667     if (!isFTL(m_graph.m_plan.mode) || !Options::enablePolymorphicCallInlining()
1668         || InlineCallFrame::isVarargs(kind)) {
1669         if (verbose) {
1670             dataLog("Bailing inlining (hard).\n");
1671             dataLog("Stack: ", currentCodeOrigin(), "\n");
1672         }
1673         return false;
1674     }
1675     
1676     unsigned oldOffset = m_currentIndex;
1677     
1678     bool allAreClosureCalls = true;
1679     bool allAreDirectCalls = true;
1680     for (unsigned i = callLinkStatus.size(); i--;) {
1681         if (callLinkStatus[i].isClosureCall())
1682             allAreDirectCalls = false;
1683         else
1684             allAreClosureCalls = false;
1685     }
1686     
1687     Node* thingToSwitchOn;
1688     if (allAreDirectCalls)
1689         thingToSwitchOn = callTargetNode;
1690     else if (allAreClosureCalls)
1691         thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
1692     else {
1693         // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
1694         // where it would be beneficial. It might be best to handle these cases as if all calls were
1695         // closure calls.
1696         // https://bugs.webkit.org/show_bug.cgi?id=136020
1697         if (verbose) {
1698             dataLog("Bailing inlining (mix).\n");
1699             dataLog("Stack: ", currentCodeOrigin(), "\n");
1700         }
1701         return false;
1702     }
1703     
1704     if (verbose) {
1705         dataLog("Doing hard inlining...\n");
1706         dataLog("Stack: ", currentCodeOrigin(), "\n");
1707     }
1708     
1709     int registerOffset = registerOffsetOrFirstFreeReg;
1710     
1711     // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
1712     // store the callee so that it will be accessible to all of the blocks we're about to create. We
1713     // get away with doing an immediate-set here because we wouldn't have performed any side effects
1714     // yet.
1715     if (verbose)
1716         dataLog("Register offset: ", registerOffset);
1717     VirtualRegister calleeReg(registerOffset + JSStack::Callee);
1718     calleeReg = m_inlineStackTop->remapOperand(calleeReg);
1719     if (verbose)
1720         dataLog("Callee is going to be ", calleeReg, "\n");
1721     setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
1722     
1723     SwitchData& data = *m_graph.m_switchData.add();
1724     data.kind = SwitchCell;
1725     addToGraph(Switch, OpInfo(&data), thingToSwitchOn);
1726     
1727     BasicBlock* originBlock = m_currentBlock;
1728     if (verbose)
1729         dataLog("Marking ", RawPointer(originBlock), " as linked (origin of poly inline)\n");
1730     originBlock->didLink();
1731     cancelLinkingForBlock(m_inlineStackTop, originBlock);
1732     
1733     // Each inlined callee will have a landing block that it returns at. They should all have jumps
1734     // to the continuation block, which we create last.
1735     Vector<BasicBlock*> landingBlocks;
1736     
1737     // We may force this true if we give up on inlining any of the edges.
1738     bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
1739     
1740     if (verbose)
1741         dataLog("About to loop over functions at ", currentCodeOrigin(), ".\n");
1742     
1743     for (unsigned i = 0; i < callLinkStatus.size(); ++i) {
1744         m_currentIndex = oldOffset;
1745         RefPtr<BasicBlock> block = adoptRef(new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
1746         m_currentBlock = block.get();
1747         m_graph.appendBlock(block);
1748         prepareToParseBlock();
1749         
1750         Node* myCallTargetNode = getDirect(calleeReg);
1751         
1752         bool inliningResult = attemptToInlineCall(
1753             myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
1754             argumentCountIncludingThis, nextOffset, kind, CallerLinksManually, prediction,
1755             inliningBalance, [&] (CodeBlock*) { });
1756         
1757         if (!inliningResult) {
1758             // That failed so we let the block die. Nothing interesting should have been added to
1759             // the block. We also give up on inlining any of the (less frequent) callees.
1760             ASSERT(m_currentBlock == block.get());
1761             ASSERT(m_graph.m_blocks.last() == block);
1762             m_graph.killBlockAndItsContents(block.get());
1763             m_graph.m_blocks.removeLast();
1764             
1765             // The fact that inlining failed means we need a slow path.
1766             couldTakeSlowPath = true;
1767             break;
1768         }
1769         
1770         JSCell* thingToCaseOn;
1771         if (allAreDirectCalls)
1772             thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
1773         else {
1774             ASSERT(allAreClosureCalls);
1775             thingToCaseOn = callLinkStatus[i].executable();
1776         }
1777         data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), block.get()));
1778         m_currentIndex = nextOffset;
1779         processSetLocalQueue(); // This only comes into play for intrinsics, since normal inlined code will leave an empty queue.
1780         addToGraph(Jump);
1781         if (verbose)
1782             dataLog("Marking ", RawPointer(m_currentBlock), " as linked (tail of poly inlinee)\n");
1783         m_currentBlock->didLink();
1784         landingBlocks.append(m_currentBlock);
1785
1786         if (verbose)
1787             dataLog("Finished inlining ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
1788     }
1789     
1790     RefPtr<BasicBlock> slowPathBlock = adoptRef(
1791         new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
1792     m_currentIndex = oldOffset;
1793     data.fallThrough = BranchTarget(slowPathBlock.get());
1794     m_graph.appendBlock(slowPathBlock);
1795     if (verbose)
1796         dataLog("Marking ", RawPointer(slowPathBlock.get()), " as linked (slow path block)\n");
1797     slowPathBlock->didLink();
1798     prepareToParseBlock();
1799     m_currentBlock = slowPathBlock.get();
1800     Node* myCallTargetNode = getDirect(calleeReg);
1801     if (couldTakeSlowPath) {
1802         addCall(
1803             resultOperand, callOp, OpInfo(), myCallTargetNode, argumentCountIncludingThis,
1804             registerOffset, prediction);
1805     } else {
1806         addToGraph(CheckBadCell);
1807         addToGraph(Phantom, myCallTargetNode);
1808         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1809         
1810         set(VirtualRegister(resultOperand), addToGraph(BottomValue));
1811     }
1812
1813     m_currentIndex = nextOffset;
1814     processSetLocalQueue();
1815     addToGraph(Jump);
1816     landingBlocks.append(m_currentBlock);
1817     
1818     RefPtr<BasicBlock> continuationBlock = adoptRef(
1819         new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
1820     m_graph.appendBlock(continuationBlock);
1821     if (verbose)
1822         dataLog("Adding unlinked block ", RawPointer(continuationBlock.get()), " (continuation)\n");
1823     m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(continuationBlock.get()));
1824     prepareToParseBlock();
1825     m_currentBlock = continuationBlock.get();
1826     
1827     for (unsigned i = landingBlocks.size(); i--;)
1828         landingBlocks[i]->terminal()->targetBlock() = continuationBlock.get();
1829     
1830     m_currentIndex = oldOffset;
1831     
1832     if (verbose) {
1833         dataLog("Done inlining (hard).\n");
1834         dataLog("Stack: ", currentCodeOrigin(), "\n");
1835     }
1836     return true;
1837 }
1838
1839 template<typename ChecksFunctor>
1840 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks)
1841 {
1842     if (argumentCountIncludingThis == 1) { // Math.min()
1843         insertChecks();
1844         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
1845         return true;
1846     }
1847      
1848     if (argumentCountIncludingThis == 2) { // Math.min(x)
1849         insertChecks();
1850         Node* result = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
1851         addToGraph(Phantom, Edge(result, NumberUse));
1852         set(VirtualRegister(resultOperand), result);
1853         return true;
1854     }
1855     
1856     if (argumentCountIncludingThis == 3) { // Math.min(x, y)
1857         insertChecks();
1858         set(VirtualRegister(resultOperand), addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
1859         return true;
1860     }
1861     
1862     // Don't handle >=3 arguments for now.
1863     return false;
1864 }
1865
1866 template<typename ChecksFunctor>
1867 bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
1868 {
1869     switch (intrinsic) {
1870     case AbsIntrinsic: {
1871         if (argumentCountIncludingThis == 1) { // Math.abs()
1872             insertChecks();
1873             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
1874             return true;
1875         }
1876
1877         if (!MacroAssembler::supportsFloatingPointAbs())
1878             return false;
1879
1880         insertChecks();
1881         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
1882         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
1883             node->mergeFlags(NodeMayOverflowInDFG);
1884         set(VirtualRegister(resultOperand), node);
1885         return true;
1886     }
1887
1888     case MinIntrinsic:
1889         return handleMinMax(resultOperand, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
1890         
1891     case MaxIntrinsic:
1892         return handleMinMax(resultOperand, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
1893
1894     case SqrtIntrinsic:
1895     case CosIntrinsic:
1896     case SinIntrinsic:
1897     case LogIntrinsic: {
1898         if (argumentCountIncludingThis == 1) {
1899             insertChecks();
1900             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
1901             return true;
1902         }
1903         
1904         switch (intrinsic) {
1905         case SqrtIntrinsic:
1906             insertChecks();
1907             set(VirtualRegister(resultOperand), addToGraph(ArithSqrt, get(virtualRegisterForArgument(1, registerOffset))));
1908             return true;
1909             
1910         case CosIntrinsic:
1911             insertChecks();
1912             set(VirtualRegister(resultOperand), addToGraph(ArithCos, get(virtualRegisterForArgument(1, registerOffset))));
1913             return true;
1914             
1915         case SinIntrinsic:
1916             insertChecks();
1917             set(VirtualRegister(resultOperand), addToGraph(ArithSin, get(virtualRegisterForArgument(1, registerOffset))));
1918             return true;
1919
1920         case LogIntrinsic:
1921             insertChecks();
1922             set(VirtualRegister(resultOperand), addToGraph(ArithLog, get(virtualRegisterForArgument(1, registerOffset))));
1923             return true;
1924             
1925         default:
1926             RELEASE_ASSERT_NOT_REACHED();
1927             return false;
1928         }
1929     }
1930
1931     case PowIntrinsic: {
1932         if (argumentCountIncludingThis < 3) {
1933             // Math.pow() and Math.pow(x) return NaN.
1934             insertChecks();
1935             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
1936             return true;
1937         }
1938         insertChecks();
1939         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
1940         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
1941         set(VirtualRegister(resultOperand), addToGraph(ArithPow, get(xOperand), get(yOperand)));
1942         return true;
1943     }
1944         
1945     case ArrayPushIntrinsic: {
1946         if (argumentCountIncludingThis != 2)
1947             return false;
1948         
1949         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
1950         if (!arrayMode.isJSArray())
1951             return false;
1952         switch (arrayMode.type()) {
1953         case Array::Undecided:
1954         case Array::Int32:
1955         case Array::Double:
1956         case Array::Contiguous:
1957         case Array::ArrayStorage: {
1958             insertChecks();
1959             Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
1960             set(VirtualRegister(resultOperand), arrayPush);
1961             
1962             return true;
1963         }
1964             
1965         default:
1966             return false;
1967         }
1968     }
1969         
1970     case ArrayPopIntrinsic: {
1971         if (argumentCountIncludingThis != 1)
1972             return false;
1973         
1974         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
1975         if (!arrayMode.isJSArray())
1976             return false;
1977         switch (arrayMode.type()) {
1978         case Array::Int32:
1979         case Array::Double:
1980         case Array::Contiguous:
1981         case Array::ArrayStorage: {
1982             insertChecks();
1983             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
1984             set(VirtualRegister(resultOperand), arrayPop);
1985             return true;
1986         }
1987             
1988         default:
1989             return false;
1990         }
1991     }
1992
1993     case CharCodeAtIntrinsic: {
1994         if (argumentCountIncludingThis != 2)
1995             return false;
1996
1997         insertChecks();
1998         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
1999         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2000         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2001
2002         set(VirtualRegister(resultOperand), charCode);
2003         return true;
2004     }
2005
2006     case CharAtIntrinsic: {
2007         if (argumentCountIncludingThis != 2)
2008             return false;
2009
2010         insertChecks();
2011         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2012         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2013         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2014
2015         set(VirtualRegister(resultOperand), charCode);
2016         return true;
2017     }
2018     case Clz32Intrinsic: {
2019         insertChecks();
2020         if (argumentCountIncludingThis == 1)
2021             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
2022         else {
2023             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2024             set(VirtualRegister(resultOperand), addToGraph(ArithClz32, operand));
2025         }
2026         return true;
2027     }
2028     case FromCharCodeIntrinsic: {
2029         if (argumentCountIncludingThis != 2)
2030             return false;
2031
2032         insertChecks();
2033         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2034         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
2035
2036         set(VirtualRegister(resultOperand), charCode);
2037
2038         return true;
2039     }
2040
2041     case RegExpExecIntrinsic: {
2042         if (argumentCountIncludingThis != 2)
2043             return false;
2044         
2045         insertChecks();
2046         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2047         set(VirtualRegister(resultOperand), regExpExec);
2048         
2049         return true;
2050     }
2051         
2052     case RegExpTestIntrinsic: {
2053         if (argumentCountIncludingThis != 2)
2054             return false;
2055         
2056         insertChecks();
2057         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2058         set(VirtualRegister(resultOperand), regExpExec);
2059         
2060         return true;
2061     }
2062     case RoundIntrinsic: {
2063         if (argumentCountIncludingThis == 1) {
2064             insertChecks();
2065             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2066             return true;
2067         }
2068         if (argumentCountIncludingThis == 2) {
2069             insertChecks();
2070             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2071             Node* roundNode = addToGraph(ArithRound, OpInfo(0), OpInfo(prediction), operand);
2072             set(VirtualRegister(resultOperand), roundNode);
2073             return true;
2074         }
2075         return false;
2076     }
2077     case IMulIntrinsic: {
2078         if (argumentCountIncludingThis != 3)
2079             return false;
2080         insertChecks();
2081         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
2082         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
2083         Node* left = get(leftOperand);
2084         Node* right = get(rightOperand);
2085         set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
2086         return true;
2087     }
2088         
2089     case FRoundIntrinsic: {
2090         if (argumentCountIncludingThis != 2)
2091             return false;
2092         insertChecks();
2093         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2094         set(VirtualRegister(resultOperand), addToGraph(ArithFRound, get(operand)));
2095         return true;
2096     }
2097         
2098     case DFGTrueIntrinsic: {
2099         insertChecks();
2100         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2101         return true;
2102     }
2103         
2104     case OSRExitIntrinsic: {
2105         insertChecks();
2106         addToGraph(ForceOSRExit);
2107         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2108         return true;
2109     }
2110         
2111     case IsFinalTierIntrinsic: {
2112         insertChecks();
2113         set(VirtualRegister(resultOperand),
2114             jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
2115         return true;
2116     }
2117         
2118     case SetInt32HeapPredictionIntrinsic: {
2119         insertChecks();
2120         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2121             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2122             if (node->hasHeapPrediction())
2123                 node->setHeapPrediction(SpecInt32);
2124         }
2125         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2126         return true;
2127     }
2128         
2129     case CheckInt32Intrinsic: {
2130         insertChecks();
2131         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2132             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2133             addToGraph(Phantom, Edge(node, Int32Use));
2134         }
2135         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2136         return true;
2137     }
2138         
2139     case FiatInt52Intrinsic: {
2140         if (argumentCountIncludingThis != 2)
2141             return false;
2142         insertChecks();
2143         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2144         if (enableInt52())
2145             set(VirtualRegister(resultOperand), addToGraph(FiatInt52, get(operand)));
2146         else
2147             set(VirtualRegister(resultOperand), get(operand));
2148         return true;
2149     }
2150         
2151     default:
2152         return false;
2153     }
2154 }
2155
2156 template<typename ChecksFunctor>
2157 bool ByteCodeParser::handleTypedArrayConstructor(
2158     int resultOperand, InternalFunction* function, int registerOffset,
2159     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
2160 {
2161     if (!isTypedView(type))
2162         return false;
2163     
2164     if (function->classInfo() != constructorClassInfoForType(type))
2165         return false;
2166     
2167     if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
2168         return false;
2169     
2170     // We only have an intrinsic for the case where you say:
2171     //
2172     // new FooArray(blah);
2173     //
2174     // Of course, 'blah' could be any of the following:
2175     //
2176     // - Integer, indicating that you want to allocate an array of that length.
2177     //   This is the thing we're hoping for, and what we can actually do meaningful
2178     //   optimizations for.
2179     //
2180     // - Array buffer, indicating that you want to create a view onto that _entire_
2181     //   buffer.
2182     //
2183     // - Non-buffer object, indicating that you want to create a copy of that
2184     //   object by pretending that it quacks like an array.
2185     //
2186     // - Anything else, indicating that you want to have an exception thrown at
2187     //   you.
2188     //
2189     // The intrinsic, NewTypedArray, will behave as if it could do any of these
2190     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
2191     // predicted Int32, then we lock it in as a normal typed array allocation.
2192     // Otherwise, NewTypedArray turns into a totally opaque function call that
2193     // may clobber the world - by virtue of it accessing properties on what could
2194     // be an object.
2195     //
2196     // Note that although the generic form of NewTypedArray sounds sort of awful,
2197     // it is actually quite likely to be more efficient than a fully generic
2198     // Construct. So, we might want to think about making NewTypedArray variadic,
2199     // or else making Construct not super slow.
2200     
2201     if (argumentCountIncludingThis != 2)
2202         return false;
2203
2204     insertChecks();
2205     set(VirtualRegister(resultOperand),
2206         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
2207     return true;
2208 }
2209
2210 template<typename ChecksFunctor>
2211 bool ByteCodeParser::handleConstantInternalFunction(
2212     int resultOperand, InternalFunction* function, int registerOffset,
2213     int argumentCountIncludingThis, CodeSpecializationKind kind, const ChecksFunctor& insertChecks)
2214 {
2215     if (verbose)
2216         dataLog("    Handling constant internal function ", JSValue(function), "\n");
2217     
2218     // If we ever find that we have a lot of internal functions that we specialize for,
2219     // then we should probably have some sort of hashtable dispatch, or maybe even
2220     // dispatch straight through the MethodTable of the InternalFunction. But for now,
2221     // it seems that this case is hit infrequently enough, and the number of functions
2222     // we know about is small enough, that having just a linear cascade of if statements
2223     // is good enough.
2224     
2225     if (function->classInfo() == ArrayConstructor::info()) {
2226         if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
2227             return false;
2228         
2229         insertChecks();
2230         if (argumentCountIncludingThis == 2) {
2231             set(VirtualRegister(resultOperand),
2232                 addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(virtualRegisterForArgument(1, registerOffset))));
2233             return true;
2234         }
2235         
2236         // FIXME: Array constructor should use "this" as newTarget.
2237         for (int i = 1; i < argumentCountIncludingThis; ++i)
2238             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
2239         set(VirtualRegister(resultOperand),
2240             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
2241         return true;
2242     }
2243     
2244     if (function->classInfo() == StringConstructor::info()) {
2245         insertChecks();
2246         
2247         Node* result;
2248         
2249         if (argumentCountIncludingThis <= 1)
2250             result = jsConstant(m_vm->smallStrings.emptyString());
2251         else
2252             result = addToGraph(CallStringConstructor, get(virtualRegisterForArgument(1, registerOffset)));
2253         
2254         if (kind == CodeForConstruct)
2255             result = addToGraph(NewStringObject, OpInfo(function->globalObject()->stringObjectStructure()), result);
2256         
2257         set(VirtualRegister(resultOperand), result);
2258         return true;
2259     }
2260     
2261     for (unsigned typeIndex = 0; typeIndex < NUMBER_OF_TYPED_ARRAY_TYPES; ++typeIndex) {
2262         bool result = handleTypedArrayConstructor(
2263             resultOperand, function, registerOffset, argumentCountIncludingThis,
2264             indexToTypedArrayType(typeIndex), insertChecks);
2265         if (result)
2266             return true;
2267     }
2268     
2269     return false;
2270 }
2271
2272 Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2273 {
2274     Node* propertyStorage;
2275     if (isInlineOffset(offset))
2276         propertyStorage = base;
2277     else
2278         propertyStorage = addToGraph(GetButterfly, base);
2279     
2280     StorageAccessData* data = m_graph.m_storageAccessData.add();
2281     data->offset = offset;
2282     data->identifierNumber = identifierNumber;
2283     
2284     Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2285
2286     return getByOffset;
2287 }
2288
2289 Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, const StructureSet& structureSet, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2290 {
2291     if (base->hasConstant()) {
2292         if (JSValue constant = m_graph.tryGetConstantProperty(base->asJSValue(), structureSet, offset)) {
2293             addToGraph(Phantom, base);
2294             return weakJSConstant(constant);
2295         }
2296     }
2297     
2298     return handleGetByOffset(prediction, base, identifierNumber, offset, op);
2299 }
2300
2301 Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
2302 {
2303     Node* propertyStorage;
2304     if (isInlineOffset(offset))
2305         propertyStorage = base;
2306     else
2307         propertyStorage = addToGraph(GetButterfly, base);
2308     
2309     StorageAccessData* data = m_graph.m_storageAccessData.add();
2310     data->offset = offset;
2311     data->identifierNumber = identifier;
2312     
2313     Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2314     
2315     return result;
2316 }
2317
2318 bool ByteCodeParser::check(const ObjectPropertyCondition& condition)
2319 {
2320     if (m_graph.watchCondition(condition))
2321         return true;
2322     
2323     Structure* structure = condition.object()->structure();
2324     if (!condition.structureEnsuresValidity(structure))
2325         return false;
2326     
2327     addToGraph(
2328         CheckStructure,
2329         OpInfo(m_graph.addStructureSet(structure)),
2330         weakJSConstant(condition.object()));
2331     return true;
2332 }
2333
2334 GetByOffsetMethod ByteCodeParser::promoteToConstant(GetByOffsetMethod method)
2335 {
2336     if (method.kind() == GetByOffsetMethod::LoadFromPrototype
2337         && method.prototype()->structure()->dfgShouldWatch()) {
2338         if (JSValue constant = m_graph.tryGetConstantProperty(method.prototype()->value(), method.prototype()->structure(), method.offset()))
2339             return GetByOffsetMethod::constant(m_graph.freeze(constant));
2340     }
2341     
2342     return method;
2343 }
2344
2345 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyCondition& condition)
2346 {
2347     if (verbose)
2348         dataLog("Planning a load: ", condition, "\n");
2349     
2350     // We might promote this to Equivalence, and a later DFG pass might also do such promotion
2351     // even if we fail, but for simplicity this cannot be asked to load an equivalence condition.
2352     // None of the clients of this method will request a load of an Equivalence condition anyway,
2353     // and supporting it would complicate the heuristics below.
2354     RELEASE_ASSERT(condition.kind() == PropertyCondition::Presence);
2355     
2356     // Here's the ranking of how to handle this, from most preferred to least preferred:
2357     //
2358     // 1) Watchpoint on an equivalence condition and return a constant node for the loaded value.
2359     //    No other code is emitted, and the structure of the base object is never registered.
2360     //    Hence this results in zero code and we won't jettison this compilation if the object
2361     //    transitions, even if the structure is watchable right now.
2362     //
2363     // 2) Need to emit a load, and the current structure of the base is going to be watched by the
2364     //    DFG anyway (i.e. dfgShouldWatch). Watch the structure and emit the load. Don't watch the
2365     //    condition, since the act of turning the base into a constant in IR will cause the DFG to
2366     //    watch the structure anyway and doing so would subsume watching the condition.
2367     //
2368     // 3) Need to emit a load, and the current structure of the base is watchable but not by the
2369     //    DFG (i.e. transitionWatchpointSetIsStillValid() and !dfgShouldWatchIfPossible()). Watch
2370     //    the condition, and emit a load.
2371     //
2372     // 4) Need to emit a load, and the current structure of the base is not watchable. Emit a
2373     //    structure check, and emit a load.
2374     //
2375     // 5) The condition does not hold. Give up and return null.
2376     
2377     // First, try to promote Presence to Equivalence. We do this before doing anything else
2378     // because it's the most profitable. Also, there are cases where the presence is watchable but
2379     // we don't want to watch it unless it became an equivalence (see the relationship between
2380     // (1), (2), and (3) above).
2381     ObjectPropertyCondition equivalenceCondition = condition.attemptToMakeEquivalenceWithoutBarrier();
2382     if (m_graph.watchCondition(equivalenceCondition))
2383         return GetByOffsetMethod::constant(m_graph.freeze(equivalenceCondition.requiredValue()));
2384     
2385     // At this point, we'll have to materialize the condition's base as a constant in DFG IR. Once
2386     // we do this, the frozen value will have its own idea of what the structure is. Use that from
2387     // now on just because it's less confusing.
2388     FrozenValue* base = m_graph.freeze(condition.object());
2389     Structure* structure = base->structure();
2390     
2391     // Check if the structure that we've registered makes the condition hold. If not, just give
2392     // up. This is case (5) above.
2393     if (!condition.structureEnsuresValidity(structure))
2394         return GetByOffsetMethod();
2395     
2396     // If the structure is watched by the DFG already, then just use this fact to emit the load.
2397     // This is case (2) above.
2398     if (structure->dfgShouldWatch())
2399         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
2400     
2401     // If we can watch the condition right now, then we can emit the load after watching it. This
2402     // is case (3) above.
2403     if (m_graph.watchCondition(condition))
2404         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
2405     
2406     // We can't watch anything but we know that the current structure satisfies the condition. So,
2407     // check for that structure and then emit the load.
2408     addToGraph(
2409         CheckStructure, 
2410         OpInfo(m_graph.addStructureSet(structure)),
2411         addToGraph(JSConstant, OpInfo(base)));
2412     return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
2413 }
2414
2415 Node* ByteCodeParser::load(
2416     SpeculatedType prediction, unsigned identifierNumber, const GetByOffsetMethod& method,
2417     NodeType op)
2418 {
2419     switch (method.kind()) {
2420     case GetByOffsetMethod::Invalid:
2421         return nullptr;
2422     case GetByOffsetMethod::Constant:
2423         return addToGraph(JSConstant, OpInfo(method.constant()));
2424     case GetByOffsetMethod::LoadFromPrototype: {
2425         Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2426         return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
2427     }
2428     case GetByOffsetMethod::Load:
2429         // Will never see this from planLoad().
2430         RELEASE_ASSERT_NOT_REACHED();
2431         return nullptr;
2432     }
2433     
2434     RELEASE_ASSERT_NOT_REACHED();
2435     return nullptr;
2436 }
2437
2438 Node* ByteCodeParser::load(
2439     SpeculatedType prediction, const ObjectPropertyCondition& condition, NodeType op)
2440 {
2441     GetByOffsetMethod method = planLoad(condition);
2442     return load(prediction, m_graph.identifiers().ensure(condition.uid()), method, op);
2443 }
2444
2445 bool ByteCodeParser::check(const ObjectPropertyConditionSet& conditionSet)
2446 {
2447     for (const ObjectPropertyCondition condition : conditionSet) {
2448         if (!check(condition))
2449             return false;
2450     }
2451     return true;
2452 }
2453
2454 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyConditionSet& conditionSet)
2455 {
2456     if (verbose)
2457         dataLog("conditionSet = ", conditionSet, "\n");
2458     
2459     GetByOffsetMethod result;
2460     for (const ObjectPropertyCondition condition : conditionSet) {
2461         switch (condition.kind()) {
2462         case PropertyCondition::Presence:
2463             RELEASE_ASSERT(!result); // Should only see exactly one of these.
2464             result = planLoad(condition);
2465             if (!result)
2466                 return GetByOffsetMethod();
2467             break;
2468         default:
2469             if (!check(condition))
2470                 return GetByOffsetMethod();
2471             break;
2472         }
2473     }
2474     RELEASE_ASSERT(!!result);
2475     return result;
2476 }
2477
2478 Node* ByteCodeParser::load(
2479     SpeculatedType prediction, const ObjectPropertyConditionSet& conditionSet, NodeType op)
2480 {
2481     GetByOffsetMethod method = planLoad(conditionSet);
2482     return load(
2483         prediction,
2484         m_graph.identifiers().ensure(conditionSet.slotBaseCondition().uid()),
2485         method, op);
2486 }
2487
2488 ObjectPropertyCondition ByteCodeParser::presenceLike(
2489     JSObject* knownBase, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
2490 {
2491     if (set.isEmpty())
2492         return ObjectPropertyCondition();
2493     unsigned attributes;
2494     PropertyOffset firstOffset = set[0]->getConcurrently(uid, attributes);
2495     if (firstOffset != offset)
2496         return ObjectPropertyCondition();
2497     for (unsigned i = 1; i < set.size(); ++i) {
2498         unsigned otherAttributes;
2499         PropertyOffset otherOffset = set[i]->getConcurrently(uid, otherAttributes);
2500         if (otherOffset != offset || otherAttributes != attributes)
2501             return ObjectPropertyCondition();
2502     }
2503     return ObjectPropertyCondition::presenceWithoutBarrier(knownBase, uid, offset, attributes);
2504 }
2505
2506 bool ByteCodeParser::checkPresenceLike(
2507     JSObject* knownBase, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
2508 {
2509     return check(presenceLike(knownBase, uid, offset, set));
2510 }
2511
2512 void ByteCodeParser::checkPresenceLike(
2513     Node* base, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
2514 {
2515     if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2516         if (checkPresenceLike(knownBase, uid, offset, set))
2517             return;
2518     }
2519
2520     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(set)), base);
2521 }
2522
2523 template<typename VariantType>
2524 Node* ByteCodeParser::load(
2525     SpeculatedType prediction, Node* base, unsigned identifierNumber, const VariantType& variant)
2526 {
2527     // Make sure backwards propagation knows that we've used base.
2528     addToGraph(Phantom, base);
2529     
2530     bool needStructureCheck = true;
2531     
2532     if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2533         // Try to optimize away the structure check. Note that it's not worth doing anything about this
2534         // if the base's structure is watched.
2535         Structure* structure = base->constant()->structure();
2536         if (!structure->dfgShouldWatch()) {
2537             UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2538             
2539             if (!variant.conditionSet().isEmpty()) {
2540                 // This means that we're loading from a prototype. We expect the base not to have the
2541                 // property. We can only use ObjectPropertyCondition if all of the structures in the
2542                 // variant.structureSet() agree on the prototype (it would be hilariously rare if they
2543                 // didn't). Note that we are relying on structureSet() having at least one element. That
2544                 // will always be true here because of how GetByIdStatus/PutByIdStatus work.
2545                 JSObject* prototype = variant.structureSet()[0]->storedPrototypeObject();
2546                 bool allAgree = true;
2547                 for (unsigned i = 1; i < variant.structureSet().size(); ++i) {
2548                     if (variant.structureSet()[i]->storedPrototypeObject() != prototype) {
2549                         allAgree = false;
2550                         break;
2551                     }
2552                 }
2553                 if (allAgree) {
2554                     ObjectPropertyCondition condition = ObjectPropertyCondition::absenceWithoutBarrier(
2555                         knownBase, uid, prototype);
2556                     if (check(condition))
2557                         needStructureCheck = false;
2558                 }
2559             } else {
2560                 // This means we're loading directly from base. We can avoid all of the code that follows
2561                 // if we can prove that the property is a constant. Otherwise, we try to prove that the
2562                 // property is watchably present, in which case we get rid of the structure check.
2563
2564                 ObjectPropertyCondition presenceCondition =
2565                     presenceLike(knownBase, uid, variant.offset(), variant.structureSet());
2566
2567                 ObjectPropertyCondition equivalenceCondition =
2568                     presenceCondition.attemptToMakeEquivalenceWithoutBarrier();
2569                 if (m_graph.watchCondition(equivalenceCondition))
2570                     return weakJSConstant(equivalenceCondition.requiredValue());
2571
2572                 if (check(presenceCondition))
2573                     needStructureCheck = false;
2574             }
2575         }
2576     }
2577
2578     if (needStructureCheck)
2579         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
2580     
2581     SpeculatedType loadPrediction;
2582     NodeType loadOp;
2583     if (variant.callLinkStatus()) {
2584         loadPrediction = SpecCellOther;
2585         loadOp = GetGetterSetterByOffset;
2586     } else {
2587         loadPrediction = prediction;
2588         loadOp = GetByOffset;
2589     }
2590     
2591     Node* loadedValue;
2592     if (!variant.conditionSet().isEmpty())
2593         loadedValue = load(loadPrediction, variant.conditionSet(), loadOp);
2594     else {
2595         loadedValue = handleGetByOffset(
2596             loadPrediction, base, variant.structureSet(), identifierNumber, variant.offset(),
2597             loadOp);
2598     }
2599
2600     return loadedValue;
2601 }
2602
2603 Node* ByteCodeParser::store(Node* base, unsigned identifier, const PutByIdVariant& variant, Node* value)
2604 {
2605     RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2606
2607     checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2608     return handlePutByOffset(base, identifier, variant.offset(), value);
2609 }
2610
2611 void ByteCodeParser::handleGetById(
2612     int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
2613     const GetByIdStatus& getByIdStatus)
2614 {
2615     NodeType getById = getByIdStatus.makesCalls() ? GetByIdFlush : GetById;
2616     
2617     if (!getByIdStatus.isSimple() || !getByIdStatus.numVariants() || !Options::enableAccessInlining()) {
2618         set(VirtualRegister(destinationOperand),
2619             addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
2620         return;
2621     }
2622     
2623     if (getByIdStatus.numVariants() > 1) {
2624         if (getByIdStatus.makesCalls() || !isFTL(m_graph.m_plan.mode)
2625             || !Options::enablePolymorphicAccessInlining()) {
2626             set(VirtualRegister(destinationOperand),
2627                 addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
2628             return;
2629         }
2630         
2631         Vector<MultiGetByOffsetCase, 2> cases;
2632         
2633         // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
2634         //    optimal, if there is some rarely executed case in the chain that requires a lot
2635         //    of checks and those checks are not watchpointable.
2636         for (const GetByIdVariant& variant : getByIdStatus.variants()) {
2637             if (variant.conditionSet().isEmpty()) {
2638                 cases.append(
2639                     MultiGetByOffsetCase(
2640                         variant.structureSet(),
2641                         GetByOffsetMethod::load(variant.offset())));
2642                 continue;
2643             }
2644             
2645             GetByOffsetMethod method = planLoad(variant.conditionSet());
2646             if (!method) {
2647                 set(VirtualRegister(destinationOperand),
2648                     addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
2649                 return;
2650             }
2651             
2652             cases.append(MultiGetByOffsetCase(variant.structureSet(), method));
2653         }
2654
2655         if (m_graph.compilation())
2656             m_graph.compilation()->noticeInlinedGetById();
2657     
2658         // 2) Emit a MultiGetByOffset
2659         MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
2660         data->cases = cases;
2661         data->identifierNumber = identifierNumber;
2662         set(VirtualRegister(destinationOperand),
2663             addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base));
2664         return;
2665     }
2666     
2667     ASSERT(getByIdStatus.numVariants() == 1);
2668     GetByIdVariant variant = getByIdStatus[0];
2669                 
2670     Node* loadedValue = load(prediction, base, identifierNumber, variant);
2671     if (!loadedValue) {
2672         set(VirtualRegister(destinationOperand),
2673             addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
2674         return;
2675     }
2676
2677     if (m_graph.compilation())
2678         m_graph.compilation()->noticeInlinedGetById();
2679     
2680     if (!variant.callLinkStatus()) {
2681         set(VirtualRegister(destinationOperand), loadedValue);
2682         return;
2683     }
2684     
2685     Node* getter = addToGraph(GetGetter, loadedValue);
2686     
2687     // Make a call. We don't try to get fancy with using the smallest operand number because
2688     // the stack layout phase should compress the stack anyway.
2689     
2690     unsigned numberOfParameters = 0;
2691     numberOfParameters++; // The 'this' argument.
2692     numberOfParameters++; // True return PC.
2693     
2694     // Start with a register offset that corresponds to the last in-use register.
2695     int registerOffset = virtualRegisterForLocal(
2696         m_inlineStackTop->m_profiledBlock->m_numCalleeRegisters - 1).offset();
2697     registerOffset -= numberOfParameters;
2698     registerOffset -= JSStack::CallFrameHeaderSize;
2699     
2700     // Get the alignment right.
2701     registerOffset = -WTF::roundUpToMultipleOf(
2702         stackAlignmentRegisters(),
2703         -registerOffset);
2704     
2705     ensureLocals(
2706         m_inlineStackTop->remapOperand(
2707             VirtualRegister(registerOffset)).toLocal());
2708     
2709     // Issue SetLocals. This has two effects:
2710     // 1) That's how handleCall() sees the arguments.
2711     // 2) If we inline then this ensures that the arguments are flushed so that if you use
2712     //    the dreaded arguments object on the getter, the right things happen. Well, sort of -
2713     //    since we only really care about 'this' in this case. But we're not going to take that
2714     //    shortcut.
2715     int nextRegister = registerOffset + JSStack::CallFrameHeaderSize;
2716     set(VirtualRegister(nextRegister++), base, ImmediateNakedSet);
2717     
2718     handleCall(
2719         destinationOperand, Call, InlineCallFrame::GetterCall, OPCODE_LENGTH(op_get_by_id),
2720         getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus(), prediction);
2721 }
2722
2723 void ByteCodeParser::emitPutById(
2724     Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus& putByIdStatus, bool isDirect)
2725 {
2726     if (isDirect)
2727         addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
2728     else
2729         addToGraph(putByIdStatus.makesCalls() ? PutByIdFlush : PutById, OpInfo(identifierNumber), base, value);
2730 }
2731
2732 void ByteCodeParser::handlePutById(
2733     Node* base, unsigned identifierNumber, Node* value,
2734     const PutByIdStatus& putByIdStatus, bool isDirect)
2735 {
2736     if (!putByIdStatus.isSimple() || !putByIdStatus.numVariants() || !Options::enableAccessInlining()) {
2737         if (!putByIdStatus.isSet())
2738             addToGraph(ForceOSRExit);
2739         emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2740         return;
2741     }
2742     
2743     if (putByIdStatus.numVariants() > 1) {
2744         if (!isFTL(m_graph.m_plan.mode) || putByIdStatus.makesCalls()
2745             || !Options::enablePolymorphicAccessInlining()) {
2746             emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2747             return;
2748         }
2749         
2750         if (!isDirect) {
2751             for (unsigned variantIndex = putByIdStatus.numVariants(); variantIndex--;) {
2752                 if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition)
2753                     continue;
2754                 if (!check(putByIdStatus[variantIndex].conditionSet())) {
2755                     emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2756                     return;
2757                 }
2758             }
2759         }
2760         
2761         if (m_graph.compilation())
2762             m_graph.compilation()->noticeInlinedPutById();
2763         
2764         MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
2765         data->variants = putByIdStatus.variants();
2766         data->identifierNumber = identifierNumber;
2767         addToGraph(MultiPutByOffset, OpInfo(data), base, value);
2768         return;
2769     }
2770     
2771     ASSERT(putByIdStatus.numVariants() == 1);
2772     const PutByIdVariant& variant = putByIdStatus[0];
2773     
2774     switch (variant.kind()) {
2775     case PutByIdVariant::Replace: {
2776         store(base, identifierNumber, variant, value);
2777         if (m_graph.compilation())
2778             m_graph.compilation()->noticeInlinedPutById();
2779         return;
2780     }
2781     
2782     case PutByIdVariant::Transition: {
2783         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
2784         if (!check(variant.conditionSet())) {
2785             emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2786             return;
2787         }
2788
2789         ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated());
2790     
2791         Node* propertyStorage;
2792         Transition* transition = m_graph.m_transitions.add(
2793             variant.oldStructureForTransition(), variant.newStructure());
2794
2795         if (variant.reallocatesStorage()) {
2796
2797             // If we're growing the property storage then it must be because we're
2798             // storing into the out-of-line storage.
2799             ASSERT(!isInlineOffset(variant.offset()));
2800
2801             if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
2802                 propertyStorage = addToGraph(
2803                     AllocatePropertyStorage, OpInfo(transition), base);
2804             } else {
2805                 propertyStorage = addToGraph(
2806                     ReallocatePropertyStorage, OpInfo(transition),
2807                     base, addToGraph(GetButterfly, base));
2808             }
2809         } else {
2810             if (isInlineOffset(variant.offset()))
2811                 propertyStorage = base;
2812             else
2813                 propertyStorage = addToGraph(GetButterfly, base);
2814         }
2815
2816         StorageAccessData* data = m_graph.m_storageAccessData.add();
2817         data->offset = variant.offset();
2818         data->identifierNumber = identifierNumber;
2819         
2820         addToGraph(
2821             PutByOffset,
2822             OpInfo(data),
2823             propertyStorage,
2824             base,
2825             value);
2826
2827         // FIXME: PutStructure goes last until we fix either
2828         // https://bugs.webkit.org/show_bug.cgi?id=142921 or
2829         // https://bugs.webkit.org/show_bug.cgi?id=142924.
2830         addToGraph(PutStructure, OpInfo(transition), base);
2831
2832         if (m_graph.compilation())
2833             m_graph.compilation()->noticeInlinedPutById();
2834         return;
2835     }
2836         
2837     case PutByIdVariant::Setter: {
2838         Node* loadedValue = load(SpecCellOther, base, identifierNumber, variant);
2839         if (!loadedValue) {
2840             emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2841             return;
2842         }
2843         
2844         Node* setter = addToGraph(GetSetter, loadedValue);
2845         
2846         // Make a call. We don't try to get fancy with using the smallest operand number because
2847         // the stack layout phase should compress the stack anyway.
2848     
2849         unsigned numberOfParameters = 0;
2850         numberOfParameters++; // The 'this' argument.
2851         numberOfParameters++; // The new value.
2852         numberOfParameters++; // True return PC.
2853     
2854         // Start with a register offset that corresponds to the last in-use register.
2855         int registerOffset = virtualRegisterForLocal(
2856             m_inlineStackTop->m_profiledBlock->m_numCalleeRegisters - 1).offset();
2857         registerOffset -= numberOfParameters;
2858         registerOffset -= JSStack::CallFrameHeaderSize;
2859     
2860         // Get the alignment right.
2861         registerOffset = -WTF::roundUpToMultipleOf(
2862             stackAlignmentRegisters(),
2863             -registerOffset);
2864     
2865         ensureLocals(
2866             m_inlineStackTop->remapOperand(
2867                 VirtualRegister(registerOffset)).toLocal());
2868     
2869         int nextRegister = registerOffset + JSStack::CallFrameHeaderSize;
2870         set(VirtualRegister(nextRegister++), base, ImmediateNakedSet);
2871         set(VirtualRegister(nextRegister++), value, ImmediateNakedSet);
2872     
2873         handleCall(
2874             VirtualRegister().offset(), Call, InlineCallFrame::SetterCall,
2875             OPCODE_LENGTH(op_put_by_id), setter, numberOfParameters - 1, registerOffset,
2876             *variant.callLinkStatus(), SpecOther);
2877         return;
2878     }
2879     
2880     default: {
2881         emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
2882         return;
2883     } }
2884 }
2885
2886 void ByteCodeParser::prepareToParseBlock()
2887 {
2888     clearCaches();
2889     ASSERT(m_setLocalQueue.isEmpty());
2890 }
2891
2892 void ByteCodeParser::clearCaches()
2893 {
2894     m_constants.resize(0);
2895 }
2896
2897 bool ByteCodeParser::parseBlock(unsigned limit)
2898 {
2899     bool shouldContinueParsing = true;
2900
2901     Interpreter* interpreter = m_vm->interpreter;
2902     Instruction* instructionsBegin = m_inlineStackTop->m_codeBlock->instructions().begin();
2903     unsigned blockBegin = m_currentIndex;
2904     
2905     // If we are the first basic block, introduce markers for arguments. This allows
2906     // us to track if a use of an argument may use the actual argument passed, as
2907     // opposed to using a value we set explicitly.
2908     if (m_currentBlock == m_graph.block(0) && !inlineCallFrame()) {
2909         m_graph.m_arguments.resize(m_numArguments);
2910         for (unsigned argument = 0; argument < m_numArguments; ++argument) {
2911             VariableAccessData* variable = newVariableAccessData(
2912                 virtualRegisterForArgument(argument));
2913             variable->mergeStructureCheckHoistingFailed(
2914                 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
2915             variable->mergeCheckArrayHoistingFailed(
2916                 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
2917             
2918             Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
2919             m_graph.m_arguments[argument] = setArgument;
2920             m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument);
2921         }
2922     }
2923
2924     while (true) {
2925         processSetLocalQueue();
2926         
2927         // Don't extend over jump destinations.
2928         if (m_currentIndex == limit) {
2929             // Ordinarily we want to plant a jump. But refuse to do this if the block is
2930             // empty. This is a special case for inlining, which might otherwise create
2931             // some empty blocks in some cases. When parseBlock() returns with an empty
2932             // block, it will get repurposed instead of creating a new one. Note that this
2933             // logic relies on every bytecode resulting in one or more nodes, which would
2934             // be true anyway except for op_loop_hint, which emits a Phantom to force this
2935             // to be true.
2936             if (!m_currentBlock->isEmpty())
2937                 addToGraph(Jump, OpInfo(m_currentIndex));
2938             return shouldContinueParsing;
2939         }
2940         
2941         // Switch on the current bytecode opcode.
2942         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
2943         m_currentInstruction = currentInstruction; // Some methods want to use this, and we'd rather not thread it through calls.
2944         OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
2945         
2946         if (Options::verboseDFGByteCodeParsing())
2947             dataLog("    parsing ", currentCodeOrigin(), "\n");
2948         
2949         if (m_graph.compilation()) {
2950             addToGraph(CountExecution, OpInfo(m_graph.compilation()->executionCounterFor(
2951                 Profiler::OriginStack(*m_vm->m_perBytecodeProfiler, m_codeBlock, currentCodeOrigin()))));
2952         }
2953         
2954         switch (opcodeID) {
2955
2956         // === Function entry opcodes ===
2957
2958         case op_enter: {
2959             Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
2960             // Initialize all locals to undefined.
2961             for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i)
2962                 set(virtualRegisterForLocal(i), undefined, ImmediateNakedSet);
2963             NEXT_OPCODE(op_enter);
2964         }
2965             
2966         case op_to_this: {
2967             Node* op1 = getThis();
2968             if (op1->op() != ToThis) {
2969                 Structure* cachedStructure = currentInstruction[2].u.structure.get();
2970                 if (currentInstruction[2].u.toThisStatus != ToThisOK
2971                     || !cachedStructure
2972                     || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis
2973                     || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
2974                     || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
2975                     || (op1->op() == GetLocal && op1->variableAccessData()->structureCheckHoistingFailed())) {
2976                     setThis(addToGraph(ToThis, op1));
2977                 } else {
2978                     addToGraph(
2979                         CheckStructure,
2980                         OpInfo(m_graph.addStructureSet(cachedStructure)),
2981                         op1);
2982                 }
2983             }
2984             NEXT_OPCODE(op_to_this);
2985         }
2986
2987         case op_create_this: {
2988             int calleeOperand = currentInstruction[2].u.operand;
2989             Node* callee = get(VirtualRegister(calleeOperand));
2990
2991             JSFunction* function = callee->dynamicCastConstant<JSFunction*>();
2992             if (!function) {
2993                 JSCell* cachedFunction = currentInstruction[4].u.jsCell.unvalidatedGet();
2994                 if (cachedFunction
2995                     && cachedFunction != JSCell::seenMultipleCalleeObjects()
2996                     && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
2997                     ASSERT(cachedFunction->inherits(JSFunction::info()));
2998
2999                     FrozenValue* frozen = m_graph.freeze(cachedFunction);
3000                     addToGraph(CheckCell, OpInfo(frozen), callee);
3001                     set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(JSConstant, OpInfo(frozen)));
3002
3003                     function = static_cast<JSFunction*>(cachedFunction);
3004                 }
3005             }
3006
3007             bool alreadyEmitted = false;
3008             if (function) {
3009                 if (FunctionRareData* rareData = function->rareData()) {
3010                     if (Structure* structure = rareData->allocationStructure()) {
3011                         m_graph.freeze(rareData);
3012                         m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
3013                         // The callee is still live up to this point.
3014                         addToGraph(Phantom, callee);
3015                         set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewObject, OpInfo(structure)));
3016                         alreadyEmitted = true;
3017                     }
3018                 }
3019             }
3020             if (!alreadyEmitted) {
3021                 set(VirtualRegister(currentInstruction[1].u.operand),
3022                     addToGraph(CreateThis, OpInfo(currentInstruction[3].u.operand), callee));
3023             }
3024             NEXT_OPCODE(op_create_this);
3025         }
3026
3027         case op_new_object: {
3028             set(VirtualRegister(currentInstruction[1].u.operand),
3029                 addToGraph(NewObject,
3030                     OpInfo(currentInstruction[3].u.objectAllocationProfile->structure())));
3031             NEXT_OPCODE(op_new_object);
3032         }
3033             
3034         case op_new_array: {
3035             int startOperand = currentInstruction[2].u.operand;
3036             int numOperands = currentInstruction[3].u.operand;
3037             ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile;
3038             for (int operandIdx = startOperand; operandIdx > startOperand - numOperands; --operandIdx)
3039                 addVarArgChild(get(VirtualRegister(operandIdx)));
3040             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0)));
3041             NEXT_OPCODE(op_new_array);
3042         }
3043             
3044         case op_new_array_with_size: {
3045             int lengthOperand = currentInstruction[2].u.operand;
3046             ArrayAllocationProfile* profile = currentInstruction[3].u.arrayAllocationProfile;
3047             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayWithSize, OpInfo(profile->selectIndexingType()), get(VirtualRegister(lengthOperand))));
3048             NEXT_OPCODE(op_new_array_with_size);
3049         }
3050             
3051         case op_new_array_buffer: {
3052             int startConstant = currentInstruction[2].u.operand;
3053             int numConstants = currentInstruction[3].u.operand;
3054             ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile;
3055             NewArrayBufferData data;
3056             data.startConstant = m_inlineStackTop->m_constantBufferRemap[startConstant];
3057             data.numConstants = numConstants;
3058             data.indexingType = profile->selectIndexingType();
3059
3060             // If this statement has never executed, we'll have the wrong indexing type in the profile.
3061             for (int i = 0; i < numConstants; ++i) {
3062                 data.indexingType =
3063                     leastUpperBoundOfIndexingTypeAndValue(
3064                         data.indexingType,
3065                         m_codeBlock->constantBuffer(data.startConstant)[i]);
3066             }
3067             
3068             m_graph.m_newArrayBufferData.append(data);
3069             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
3070             NEXT_OPCODE(op_new_array_buffer);
3071         }
3072             
3073         case op_new_regexp: {
3074             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
3075             NEXT_OPCODE(op_new_regexp);
3076         }
3077             
3078         // === Bitwise operations ===
3079
3080         case op_bitand: {
3081             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3082             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3083             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitAnd, op1, op2));
3084             NEXT_OPCODE(op_bitand);
3085         }
3086
3087         case op_bitor: {
3088             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3089             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3090             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitOr, op1, op2));
3091             NEXT_OPCODE(op_bitor);
3092         }
3093
3094         case op_bitxor: {
3095             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3096             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3097             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitXor, op1, op2));
3098             NEXT_OPCODE(op_bitxor);
3099         }
3100
3101         case op_rshift: {
3102             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3103             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3104             set(VirtualRegister(currentInstruction[1].u.operand),
3105                 addToGraph(BitRShift, op1, op2));
3106             NEXT_OPCODE(op_rshift);
3107         }
3108
3109         case op_lshift: {
3110             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3111             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3112             set(VirtualRegister(currentInstruction[1].u.operand),
3113                 addToGraph(BitLShift, op1, op2));
3114             NEXT_OPCODE(op_lshift);
3115         }
3116
3117         case op_urshift: {
3118             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3119             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
3120             set(VirtualRegister(currentInstruction[1].u.operand),
3121                 addToGraph(BitURShift, op1, op2));
3122             NEXT_OPCODE(op_urshift);
3123         }
3124             
3125         case op_unsigned: {
3126             set(VirtualRegister(currentInstruction[1].u.operand),
3127                 makeSafe(addToGraph(UInt32ToNumber, get(VirtualRegister(currentInstruction[2].u.operand)))));
3128             NEXT_OPCODE(op_unsigned);
3129         }
3130
3131         // === Increment/Decrement opcodes ===
3132
3133         case op_inc: {
3134             int srcDst = currentInstruction[1].u.operand;
3135             VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
3136             Node* op = get(srcDstVirtualRegister);
3137             set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, addToGraph(JSConstant, OpInfo(m_constantOne)))));
3138             NEXT_OPCODE(op_inc);
3139         }
3140
3141         case op_dec: {
3142             int srcDst = currentInstruction[1].u.operand;
3143             VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
3144             Node* op = get(srcDstVirtualRegister);
3145             set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, addToGraph(JSConstant, OpInfo(m_constantOne)))));
3146             NEXT_OPCODE(op_dec);
3147         }
3148
3149         // === Arithmetic operations ===
3150
3151         case op_add: {
3152             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
3153  &nbs