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