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