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