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