[ES6][ES7] Drop Constructability of generator function
[WebKit-https.git] / Source / JavaScriptCore / bytecompiler / BytecodeGenerator.h
1 /*
2  * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  * Copyright (C) 2012 Igalia, S.L.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifndef BytecodeGenerator_h
32 #define BytecodeGenerator_h
33
34 #include "CodeBlock.h"
35 #include <wtf/HashTraits.h>
36 #include "Instruction.h"
37 #include "Label.h"
38 #include "LabelScope.h"
39 #include "Interpreter.h"
40 #include "ParserError.h"
41 #include "RegisterID.h"
42 #include "SetForScope.h"
43 #include "SymbolTable.h"
44 #include "Debugger.h"
45 #include "Nodes.h"
46 #include "StaticPropertyAnalyzer.h"
47 #include "TemplateRegistryKey.h"
48 #include "UnlinkedCodeBlock.h"
49
50 #include <functional>
51
52 #include <wtf/PassRefPtr.h>
53 #include <wtf/SegmentedVector.h>
54 #include <wtf/Vector.h>
55
56
57 namespace JSC {
58
59     class Identifier;
60     class JSTemplateRegistryKey;
61
62     enum ExpectedFunction {
63         NoExpectedFunction,
64         ExpectObjectConstructor,
65         ExpectArrayConstructor
66     };
67
68     enum class ThisResolutionType { Local, Scoped };
69     
70     class CallArguments {
71     public:
72         CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
73
74         RegisterID* thisRegister() { return m_argv[0].get(); }
75         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
76         unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
77         unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
78         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
79         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
80
81     private:
82         RefPtr<RegisterID> m_profileHookRegister;
83         ArgumentsNode* m_argumentsNode;
84         Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
85         unsigned m_padding;
86     };
87
88     struct FinallyContext {
89         StatementNode* finallyBlock;
90         RegisterID* iterator;
91         ThrowableExpressionData* enumerationNode;
92         unsigned scopeContextStackSize;
93         unsigned switchContextStackSize;
94         unsigned forInContextStackSize;
95         unsigned tryContextStackSize;
96         unsigned labelScopesSize;
97         unsigned symbolTableStackSize;
98         int finallyDepth;
99         int dynamicScopeDepth;
100     };
101
102     struct ControlFlowContext {
103         bool isFinallyBlock;
104         FinallyContext finallyContext;
105     };
106
107     class ForInContext {
108         WTF_MAKE_FAST_ALLOCATED;
109     public:
110         ForInContext(RegisterID* localRegister)
111             : m_localRegister(localRegister)
112             , m_isValid(true)
113         {
114         }
115
116         virtual ~ForInContext()
117         {
118         }
119
120         bool isValid() const { return m_isValid; }
121         void invalidate() { m_isValid = false; }
122
123         enum ForInContextType {
124             StructureForInContextType,
125             IndexedForInContextType
126         };
127         virtual ForInContextType type() const = 0;
128
129         RegisterID* local() const { return m_localRegister.get(); }
130
131     private:
132         RefPtr<RegisterID> m_localRegister;
133         bool m_isValid;
134     };
135
136     class StructureForInContext : public ForInContext {
137     public:
138         StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
139             : ForInContext(localRegister)
140             , m_indexRegister(indexRegister)
141             , m_propertyRegister(propertyRegister)
142             , m_enumeratorRegister(enumeratorRegister)
143         {
144         }
145
146         virtual ForInContextType type() const
147         {
148             return StructureForInContextType;
149         }
150
151         RegisterID* index() const { return m_indexRegister.get(); }
152         RegisterID* property() const { return m_propertyRegister.get(); }
153         RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
154
155     private:
156         RefPtr<RegisterID> m_indexRegister;
157         RefPtr<RegisterID> m_propertyRegister;
158         RefPtr<RegisterID> m_enumeratorRegister;
159     };
160
161     class IndexedForInContext : public ForInContext {
162     public:
163         IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
164             : ForInContext(localRegister)
165             , m_indexRegister(indexRegister)
166         {
167         }
168
169         virtual ForInContextType type() const
170         {
171             return IndexedForInContextType;
172         }
173
174         RegisterID* index() const { return m_indexRegister.get(); }
175
176     private:
177         RefPtr<RegisterID> m_indexRegister;
178     };
179
180     struct TryData {
181         RefPtr<Label> target;
182         HandlerType handlerType;
183     };
184
185     struct TryContext {
186         RefPtr<Label> start;
187         TryData* tryData;
188     };
189
190     class Variable {
191     public:
192         enum VariableKind { NormalVariable, SpecialVariable };
193
194         Variable()
195             : m_offset()
196             , m_local(nullptr)
197             , m_attributes(0)
198             , m_kind(NormalVariable)
199             , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
200             , m_isLexicallyScoped(false)
201         {
202         }
203         
204         Variable(const Identifier& ident)
205             : m_ident(ident)
206             , m_local(nullptr)
207             , m_attributes(0)
208             , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
209             , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
210             , m_isLexicallyScoped(false)
211         {
212         }
213
214         Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex, bool isLexicallyScoped)
215             : m_ident(ident)
216             , m_offset(offset)
217             , m_local(local)
218             , m_attributes(attributes)
219             , m_kind(kind)
220             , m_symbolTableConstantIndex(symbolTableConstantIndex)
221             , m_isLexicallyScoped(isLexicallyScoped)
222         {
223         }
224
225         // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
226         // a stack variable, a scoped variable in a local scope, or a variable captured in the
227         // direct arguments object.
228         bool isResolved() const { return !!m_offset; }
229         int symbolTableConstantIndex() const { ASSERT(isResolved() && !isSpecial()); return m_symbolTableConstantIndex; }
230         
231         const Identifier& ident() const { return m_ident; }
232         
233         VarOffset offset() const { return m_offset; }
234         bool isLocal() const { return m_offset.isStack(); }
235         RegisterID* local() const { return m_local; }
236
237         bool isReadOnly() const { return m_attributes & ReadOnly; }
238         bool isSpecial() const { return m_kind != NormalVariable; }
239         bool isConst() const { return isReadOnly() && m_isLexicallyScoped; }
240         void setIsReadOnly() { m_attributes |= ReadOnly; }
241
242     private:
243         Identifier m_ident;
244         VarOffset m_offset;
245         RegisterID* m_local;
246         unsigned m_attributes;
247         VariableKind m_kind;
248         int m_symbolTableConstantIndex;
249         bool m_isLexicallyScoped;
250     };
251
252     struct TryRange {
253         RefPtr<Label> start;
254         RefPtr<Label> end;
255         TryData* tryData;
256     };
257
258     enum ProfileTypeBytecodeFlag {
259         ProfileTypeBytecodeClosureVar,
260         ProfileTypeBytecodeLocallyResolved,
261         ProfileTypeBytecodeDoesNotHaveGlobalID,
262         ProfileTypeBytecodeFunctionArgument,
263         ProfileTypeBytecodeFunctionReturnStatement
264     };
265
266     class BytecodeGenerator {
267         WTF_MAKE_FAST_ALLOCATED;
268         WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
269     public:
270         typedef DeclarationStacks::FunctionStack FunctionStack;
271
272         BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
273         BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
274         BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
275         BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
276
277         ~BytecodeGenerator();
278         
279         VM* vm() const { return m_vm; }
280         ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
281         const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
282
283         bool isConstructor() const { return m_codeBlock->isConstructor(); }
284         bool isDerivedConstructorContext() const { return m_codeBlock->isDerivedConstructorContext(); }
285         bool usesArrowFunction() const { return m_scopeNode->usesArrowFunction(); }
286         bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; }
287         bool usesEval() const { return m_scopeNode->usesEval(); }
288         bool usesThis() const { return m_scopeNode->usesThis(); }
289         ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
290         SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
291
292         ParserError generate();
293
294         bool isArgumentNumber(const Identifier&, int);
295
296         Variable variable(const Identifier&, ThisResolutionType = ThisResolutionType::Local);
297         
298         enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
299         void createVariable(const Identifier&, VarKind, SymbolTable*, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
300         
301         // Returns the register storing "this"
302         RegisterID* thisRegister() { return &m_thisRegister; }
303         RegisterID* argumentsRegister() { return m_argumentsRegister; }
304         RegisterID* newTarget()
305         {
306             return !m_codeBlock->isArrowFunction() || m_isNewTargetLoadedInArrowFunction
307                 ? m_newTargetRegister : emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
308         }
309
310         RegisterID* scopeRegister() { return m_scopeRegister; }
311
312         RegisterID* generatorRegister() { return m_generatorRegister; }
313
314         // Returns the next available temporary register. Registers returned by
315         // newTemporary require a modified form of reference counting: any
316         // register with a refcount of 0 is considered "available", meaning that
317         // the next instruction may overwrite it.
318         RegisterID* newTemporary();
319
320         // The same as newTemporary(), but this function returns "suggestion" if
321         // "suggestion" is a temporary. This function is helpful in situations
322         // where you've put "suggestion" in a RefPtr, but you'd like to allow
323         // the next instruction to overwrite it anyway.
324         RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
325
326         // Functions for handling of dst register
327
328         RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
329
330         // This will be allocated in the temporary region of registers, but it will
331         // not be marked as a temporary. This will ensure that finalDestination() does
332         // not overwrite a block scope variable that it mistakes as a temporary. These
333         // registers can be (and are) reclaimed when the lexical scope they belong to
334         // is no longer on the symbol table stack.
335         RegisterID* newBlockScopeVariable();
336
337         // Returns a place to write intermediate values of an operation
338         // which reuses dst if it is safe to do so.
339         RegisterID* tempDestination(RegisterID* dst)
340         {
341             return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
342         }
343
344         // Returns the place to write the final output of an operation.
345         RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
346         {
347             if (originalDst && originalDst != ignoredResult())
348                 return originalDst;
349             ASSERT(tempDst != ignoredResult());
350             if (tempDst && tempDst->isTemporary())
351                 return tempDst;
352             return newTemporary();
353         }
354
355         RegisterID* destinationForAssignResult(RegisterID* dst)
356         {
357             if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
358                 return dst->isTemporary() ? dst : newTemporary();
359             return 0;
360         }
361
362         // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
363         RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
364         {
365             return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
366         }
367
368         LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
369         PassRefPtr<Label> newLabel();
370
371         void emitNode(RegisterID* dst, StatementNode* n)
372         {
373             SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
374             return emitNodeInTailPosition(dst, n);
375         }
376
377         void emitNodeInTailPosition(RegisterID* dst, StatementNode* n)
378         {
379             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
380             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
381             if (!m_vm->isSafeToRecurse()) {
382                 emitThrowExpressionTooDeepException();
383                 return;
384             }
385             n->emitBytecode(*this, dst);
386         }
387
388         void emitNode(StatementNode* n)
389         {
390             emitNode(nullptr, n);
391         }
392
393         void emitNodeInTailPosition(StatementNode* n)
394         {
395             emitNodeInTailPosition(nullptr, n);
396         }
397
398         RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
399         {
400             SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
401             return emitNodeInTailPosition(dst, n);
402         }
403
404         RegisterID* emitNodeInTailPosition(RegisterID* dst, ExpressionNode* n)
405         {
406             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
407             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
408             if (!m_vm->isSafeToRecurse())
409                 return emitThrowExpressionTooDeepException();
410             return n->emitBytecode(*this, dst);
411         }
412
413         RegisterID* emitNode(ExpressionNode* n)
414         {
415             return emitNode(nullptr, n);
416         }
417
418         RegisterID* emitNodeInTailPosition(ExpressionNode* n)
419         {
420             return emitNodeInTailPosition(nullptr, n);
421         }
422
423         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
424         {
425             if (!m_vm->isSafeToRecurse()) {
426                 emitThrowExpressionTooDeepException();
427                 return;
428             }
429
430             n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
431         }
432
433         void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
434         {            
435             ASSERT(divot.offset >= divotStart.offset);
436             ASSERT(divotEnd.offset >= divot.offset);
437
438             int sourceOffset = m_scopeNode->source().startOffset();
439             unsigned firstLine = m_scopeNode->source().firstLine();
440
441             int divotOffset = divot.offset - sourceOffset;
442             int startOffset = divot.offset - divotStart.offset;
443             int endOffset = divotEnd.offset - divot.offset;
444
445             unsigned line = divot.line;
446             ASSERT(line >= firstLine);
447             line -= firstLine;
448
449             int lineStart = divot.lineStartOffset;
450             if (lineStart > sourceOffset)
451                 lineStart -= sourceOffset;
452             else
453                 lineStart = 0;
454
455             if (divotOffset < lineStart)
456                 return;
457
458             unsigned column = divotOffset - lineStart;
459
460             unsigned instructionOffset = instructions().size();
461             if (!m_isBuiltinFunction)
462                 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
463         }
464
465
466         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
467         {
468             return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
469         }
470
471         ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
472         {
473             if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
474                 PassRefPtr<RegisterID> dst = newTemporary();
475                 emitNode(dst.get(), n);
476                 return dst;
477             }
478
479             return emitNode(n);
480         }
481
482     private:
483         void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
484     public:
485
486         // This doesn't emit expression info. If using this, make sure you shouldn't be emitting text offset.
487         void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag); 
488         // These variables are associated with variables in a program. They could be Locals, LocalClosureVar, or ClosureVar.
489         void emitProfileType(RegisterID* registerToProfile, const Variable&, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
490
491         void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
492         // These are not associated with variables and don't have a global id.
493         void emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
494
495         void emitProfileControlFlow(int);
496         
497         RegisterID* emitLoadArrowFunctionLexicalEnvironment();
498         void emitLoadThisFromArrowFunctionLexicalEnvironment();
499         RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
500
501         RegisterID* emitLoad(RegisterID* dst, bool);
502         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
503         RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
504         RegisterID* emitLoadGlobalObject(RegisterID* dst);
505
506         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
507         RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
508         RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
509         RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
510
511         RegisterID* emitCreateThis(RegisterID* dst);
512         void emitTDZCheck(RegisterID* target);
513         bool needsTDZCheck(const Variable&);
514         void emitTDZCheckIfNecessary(const Variable&, RegisterID* target, RegisterID* scope);
515         void liftTDZCheckIfPossible(const Variable&);
516         RegisterID* emitNewObject(RegisterID* dst);
517         RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
518         RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length);
519
520         RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
521         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
522         RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
523         RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
524         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
525
526         RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
527         RegisterID* emitMoveEmptyValue(RegisterID* dst);
528         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
529
530         RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
531         RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
532         RegisterID* emitInc(RegisterID* srcDst);
533         RegisterID* emitDec(RegisterID* srcDst);
534
535         RegisterID* emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue);
536         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
537         RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue);
538         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
539         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
540
541         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
542         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
543         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
544         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
545         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
546         RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
547         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
548         RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
549         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
550         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
551
552         RegisterID* emitAssert(RegisterID* condition, int line);
553
554         void emitPutGetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* getter);
555         void emitPutSetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* setter);
556         void emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter);
557         void emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* getter);
558         void emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* setter);
559         
560         ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
561         RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
562         RegisterID* emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
563         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
564         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
565         RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
566
567         enum PropertyDescriptorOption {
568             PropertyConfigurable = 1,
569             PropertyWritable     = 1 << 1,
570             PropertyEnumerable   = 1 << 2,
571         };
572         void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
573             RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
574
575         void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, VariableEnvironmentNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
576
577         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
578
579         RegisterID* emitReturn(RegisterID* src);
580         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
581
582         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
583         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
584         void emitToPrimitive(RegisterID* dst, RegisterID* src);
585
586         ResolveType resolveType();
587         RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
588         RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
589         RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
590         RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode, InitializationMode);
591         RegisterID* initializeVariable(const Variable&, RegisterID* value);
592
593         PassRefPtr<Label> emitLabel(Label*);
594         void emitLoopHint();
595         PassRefPtr<Label> emitJump(Label* target);
596         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
597         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
598         PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
599         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
600         void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
601
602         void emitEnter();
603         void emitWatchdog();
604
605         RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
606         RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
607         RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
608         RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
609         RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
610         RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
611         RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
612         RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
613         RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
614         RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
615
616         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
617         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
618         void emitRequireObjectCoercible(RegisterID* value, const String& error);
619
620         RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
621         RegisterID* emitIteratorNextWithValue(RegisterID* dst, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node);
622         void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
623
624         RegisterID* emitRestParameter(RegisterID* result, unsigned numParametersToSkip);
625
626         bool emitReadOnlyExceptionIfNeeded(const Variable&);
627
628         // Start a try block. 'start' must have been emitted.
629         TryData* pushTry(Label* start);
630         // End a try block. 'end' must have been emitted.
631         void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
632
633         void emitThrow(RegisterID* exc)
634         { 
635             m_usesExceptions = true;
636             emitUnaryNoDstOp(op_throw, exc);
637         }
638
639         void emitThrowReferenceError(const String& message);
640         void emitThrowTypeError(const String& message);
641
642         void emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment&);
643         void emitPopCatchScope(VariableEnvironment&);
644
645         void emitGetScope();
646         RegisterID* emitPushWithScope(RegisterID* objectScope);
647         void emitPopWithScope();
648         void emitPutThisToArrowFunctionContextScope();
649         void emitPutNewTargetToArrowFunctionContextScope();
650         void emitPutDerivedConstructorToArrowFunctionContextScope();
651         RegisterID* emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
652
653         void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
654
655         bool isInFinallyBlock() { return m_finallyDepth > 0; }
656
657         void pushFinallyContext(StatementNode* finallyBlock);
658         void popFinallyContext();
659         void pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
660         void popIteratorCloseContext();
661
662         void pushIndexedForInScope(RegisterID* local, RegisterID* index);
663         void popIndexedForInScope(RegisterID* local);
664         void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
665         void popStructureForInScope(RegisterID* local);
666         void invalidateForInContextForLocal(RegisterID* local);
667
668         LabelScopePtr breakTarget(const Identifier&);
669         LabelScopePtr continueTarget(const Identifier&);
670
671         void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
672         void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
673
674         void emitYieldPoint(RegisterID*);
675         void emitSave(Label* mergePoint, unsigned liveCalleeLocalsIndex);
676         void emitResume(Label* mergePoint, unsigned liveCalleeLocalsIndex);
677
678         void emitGeneratorStateLabel();
679         void emitGeneratorStateChange(int32_t state);
680         RegisterID* emitYield(RegisterID* argument);
681         RegisterID* emitDelegateYield(RegisterID* argument, ThrowableExpressionData*);
682         void beginGenerator(RegisterID*);
683         void endGenerator(Label* defaultLabel);
684         RegisterID* generatorStateRegister() { return &m_parameters[2]; }
685         RegisterID* generatorValueRegister() { return &m_parameters[3]; }
686         RegisterID* generatorResumeModeRegister() { return &m_parameters[4]; }
687
688         CodeType codeType() const { return m_codeType; }
689
690         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
691         bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
692         
693         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
694
695         SourceParseMode parseMode() const { return m_codeBlock->parseMode(); }
696         
697         bool isBuiltinFunction() const { return m_isBuiltinFunction; }
698
699         OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
700
701         enum class TDZCheckOptimization { Optimize, DoNotOptimize };
702         enum class NestedScopeType { IsNested, IsNotNested };
703     private:
704         enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
705         enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
706         enum class ScopeRegisterType { Var, Block };
707         void pushLexicalScopeInternal(VariableEnvironment&, TDZCheckOptimization, NestedScopeType, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
708         void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
709         template<typename LookUpVarKindFunctor>
710         bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
711         void emitPrefillStackTDZVariables(const VariableEnvironment&, SymbolTable*);
712         void emitPopScope(RegisterID* dst, RegisterID* scope);
713         RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
714         void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, bool isCaptured);
715         void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
716
717     public:
718         void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr);
719         void popLexicalScope(VariableEnvironmentNode*);
720         void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
721         int labelScopeDepth() const;
722
723     private:
724         void reclaimFreeRegisters();
725         Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int symbolTableConstantIndex, bool isLexicallyScoped);
726
727         void emitOpcode(OpcodeID);
728         UnlinkedArrayAllocationProfile newArrayAllocationProfile();
729         UnlinkedObjectAllocationProfile newObjectAllocationProfile();
730         UnlinkedArrayProfile newArrayProfile();
731         UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
732         int kill(RegisterID* dst)
733         {
734             int index = dst->index();
735             m_staticPropertyAnalyzer.kill(index);
736             return index;
737         }
738
739         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
740         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
741         ALWAYS_INLINE void rewindBinaryOp();
742         ALWAYS_INLINE void rewindUnaryOp();
743
744         void allocateCalleeSaveSpace();
745         void allocateAndEmitScope();
746         void emitComplexPopScopes(RegisterID*, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
747
748         typedef HashMap<double, JSValue> NumberMap;
749         typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
750         typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
751         
752         // Helper for emitCall() and emitConstruct(). This works because the set of
753         // expected functions have identical behavior for both call and construct
754         // (i.e. "Object()" is identical to "new Object()").
755         ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
756         
757         RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
758
759         RegisterID* newRegister();
760
761         // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable().
762         RegisterID* addVar()
763         {
764             ++m_codeBlock->m_numVars;
765             RegisterID* result = newRegister();
766             ASSERT(VirtualRegister(result->index()).toLocal() == m_codeBlock->m_numVars - 1);
767             result->ref(); // We should never free this slot.
768             return result;
769         }
770
771         // Initializes the stack form the parameter; does nothing for the symbol table.
772         RegisterID* initializeNextParameter();
773         UniquedStringImpl* visibleNameForParameter(DestructuringPatternNode*);
774         
775         RegisterID& registerFor(VirtualRegister reg)
776         {
777             if (reg.isLocal())
778                 return m_calleeLocals[reg.toLocal()];
779
780             if (reg.offset() == JSStack::Callee)
781                 return m_calleeRegister;
782
783             ASSERT(m_parameters.size());
784             return m_parameters[reg.toArgument()];
785         }
786
787         bool hasConstant(const Identifier&) const;
788         unsigned addConstant(const Identifier&);
789         RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
790         RegisterID* addConstantEmptyValue();
791         unsigned addRegExp(RegExp*);
792
793         unsigned addConstantBuffer(unsigned length);
794         
795         UnlinkedFunctionExecutable* makeFunction(FunctionMetadataNode* metadata)
796         {
797             bool newisDerivedConstructorContext = constructorKind() == ConstructorKind::Derived || (m_isDerivedConstructorContext && metadata->parseMode() == SourceParseMode::ArrowFunctionMode);
798
799             VariableEnvironment variablesUnderTDZ;
800             getVariablesUnderTDZ(variablesUnderTDZ);
801
802             // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
803             // https://bugs.webkit.org/show_bug.cgi?id=151547
804             SourceParseMode parseMode = metadata->parseMode();
805             ConstructAbility constructAbility = ConstructAbility::CanConstruct;
806             if (parseMode == SourceParseMode::GetterMode || parseMode == SourceParseMode::SetterMode || parseMode == SourceParseMode::ArrowFunctionMode || parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
807                 constructAbility = ConstructAbility::CannotConstruct;
808             else if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() == ConstructorKind::None)
809                 constructAbility = ConstructAbility::CannotConstruct;
810
811             return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, variablesUnderTDZ, newisDerivedConstructorContext);
812         }
813
814         void getVariablesUnderTDZ(VariableEnvironment&);
815
816         RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
817         RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
818
819         void initializeParameters(FunctionParameters&);
820         void initializeVarLexicalEnvironment(int symbolTableConstantIndex);
821         void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function<bool (UniquedStringImpl*)>& captures);
822         void initializeArrowFunctionContextScopeIfNeeded(SymbolTable* = nullptr);
823
824     public:
825         JSString* addStringConstant(const Identifier&);
826         JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
827
828         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
829
830         RegisterID* emitThrowExpressionTooDeepException();
831
832     private:
833         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
834
835         bool m_shouldEmitDebugHooks;
836         bool m_shouldEmitProfileHooks;
837
838         struct SymbolTableStackEntry {
839             Strong<SymbolTable> m_symbolTable;
840             RegisterID* m_scope;
841             bool m_isWithScope;
842             int m_symbolTableConstantIndex;
843         };
844         Vector<SymbolTableStackEntry> m_symbolTableStack;
845         Vector<std::pair<VariableEnvironment, bool>> m_TDZStack;
846
847         ScopeNode* const m_scopeNode;
848         Strong<UnlinkedCodeBlock> m_codeBlock;
849
850         // Some of these objects keep pointers to one another. They are arranged
851         // to ensure a sane destruction order that avoids references to freed memory.
852         HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> m_functions;
853         RegisterID m_ignoredResultRegister;
854         RegisterID m_thisRegister;
855         RegisterID m_calleeRegister;
856         RegisterID* m_scopeRegister { nullptr };
857         RegisterID* m_topMostScope { nullptr };
858         RegisterID* m_argumentsRegister { nullptr };
859         RegisterID* m_lexicalEnvironmentRegister { nullptr };
860         RegisterID* m_generatorRegister { nullptr };
861         RegisterID* m_emptyValueRegister { nullptr };
862         RegisterID* m_globalObjectRegister { nullptr };
863         RegisterID* m_newTargetRegister { nullptr };
864         RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
865         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
866
867         SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters;
868         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
869         SegmentedVector<RegisterID, 32> m_calleeLocals;
870         SegmentedVector<RegisterID, 32> m_parameters;
871         SegmentedVector<Label, 32> m_labels;
872         LabelScopeStore m_labelScopes;
873         int m_finallyDepth { 0 };
874         int m_localScopeDepth { 0 };
875         const CodeType m_codeType;
876
877         int localScopeDepth() const;
878         void pushScopedControlFlowContext();
879         void popScopedControlFlowContext();
880
881         Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
882         Vector<SwitchInfo> m_switchContextStack;
883         Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
884         Vector<TryContext> m_tryContextStack;
885         Vector<RefPtr<Label>> m_generatorResumeLabels;
886         enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
887         Vector<std::pair<FunctionMetadataNode*, FunctionVariableType>> m_functionsToInitialize;
888         bool m_needToInitializeArguments { false };
889         RestParameterNode* m_restParameter { nullptr };
890         
891         Vector<TryRange> m_tryRanges;
892         SegmentedVector<TryData, 8> m_tryData;
893
894         int m_nextConstantOffset { 0 };
895
896         typedef HashMap<FunctionMetadataNode*, unsigned> FunctionOffsetMap;
897         FunctionOffsetMap m_functionOffsets;
898         
899         // Constant pool
900         IdentifierMap m_identifierMap;
901
902         typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
903         JSValueMap m_jsValueMap;
904         IdentifierStringMap m_stringMap;
905         TemplateRegistryKeyMap m_templateRegistryKeyMap;
906
907         StaticPropertyAnalyzer m_staticPropertyAnalyzer { &m_instructions };
908
909         VM* m_vm;
910
911         OpcodeID m_lastOpcodeID = op_end;
912 #ifndef NDEBUG
913         size_t m_lastOpcodePosition { 0 };
914 #endif
915
916         bool m_usesExceptions { false };
917         bool m_expressionTooDeep { false };
918         bool m_isBuiltinFunction { false };
919         bool m_usesNonStrictEval { false };
920         bool m_inTailPosition { false };
921         bool m_isDerivedConstructorContext { false };
922         bool m_needsToUpdateArrowFunctionContext;
923         bool m_isNewTargetLoadedInArrowFunction { false };
924     };
925
926 }
927
928 #endif // BytecodeGenerator_h