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