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