40a7a7f475a70714f14f8a5ce9abe8f8e6c3d414
[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 "SymbolTable.h"
43 #include "Debugger.h"
44 #include "Nodes.h"
45 #include "StaticPropertyAnalyzer.h"
46 #include "TemplateRegistryKey.h"
47 #include "UnlinkedCodeBlock.h"
48
49 #include <functional>
50
51 #include <wtf/PassRefPtr.h>
52 #include <wtf/SegmentedVector.h>
53 #include <wtf/Vector.h>
54
55
56 namespace JSC {
57
58     class Identifier;
59     class JSTemplateRegistryKey;
60
61     enum ExpectedFunction {
62         NoExpectedFunction,
63         ExpectObjectConstructor,
64         ExpectArrayConstructor
65     };
66
67     class CallArguments {
68     public:
69         CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
70
71         RegisterID* thisRegister() { return m_argv[0].get(); }
72         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
73         unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
74         unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
75         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
76         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
77
78     private:
79         RefPtr<RegisterID> m_profileHookRegister;
80         ArgumentsNode* m_argumentsNode;
81         Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
82         unsigned m_padding;
83     };
84
85     struct FinallyContext {
86         StatementNode* finallyBlock;
87         RegisterID* iterator;
88         ThrowableExpressionData* enumerationNode;
89         unsigned scopeContextStackSize;
90         unsigned switchContextStackSize;
91         unsigned forInContextStackSize;
92         unsigned tryContextStackSize;
93         unsigned labelScopesSize;
94         int finallyDepth;
95         int dynamicScopeDepth;
96     };
97
98     struct ControlFlowContext {
99         bool isFinallyBlock;
100         FinallyContext finallyContext;
101     };
102
103     class ForInContext {
104     public:
105         ForInContext(RegisterID* localRegister)
106             : m_localRegister(localRegister)
107             , m_isValid(true)
108         {
109         }
110
111         virtual ~ForInContext()
112         {
113         }
114
115         bool isValid() const { return m_isValid; }
116         void invalidate() { m_isValid = false; }
117
118         enum ForInContextType {
119             StructureForInContextType,
120             IndexedForInContextType
121         };
122         virtual ForInContextType type() const = 0;
123
124         RegisterID* local() const { return m_localRegister.get(); }
125
126     private:
127         RefPtr<RegisterID> m_localRegister;
128         bool m_isValid;
129     };
130
131     class StructureForInContext : public ForInContext {
132     public:
133         StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
134             : ForInContext(localRegister)
135             , m_indexRegister(indexRegister)
136             , m_propertyRegister(propertyRegister)
137             , m_enumeratorRegister(enumeratorRegister)
138         {
139         }
140
141         virtual ForInContextType type() const
142         {
143             return StructureForInContextType;
144         }
145
146         RegisterID* index() const { return m_indexRegister.get(); }
147         RegisterID* property() const { return m_propertyRegister.get(); }
148         RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
149
150     private:
151         RefPtr<RegisterID> m_indexRegister;
152         RefPtr<RegisterID> m_propertyRegister;
153         RefPtr<RegisterID> m_enumeratorRegister;
154     };
155
156     class IndexedForInContext : public ForInContext {
157     public:
158         IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
159             : ForInContext(localRegister)
160             , m_indexRegister(indexRegister)
161         {
162         }
163
164         virtual ForInContextType type() const
165         {
166             return IndexedForInContextType;
167         }
168
169         RegisterID* index() const { return m_indexRegister.get(); }
170
171     private:
172         RefPtr<RegisterID> m_indexRegister;
173     };
174
175     struct TryData {
176         RefPtr<Label> target;
177         unsigned targetScopeDepth;
178     };
179
180     struct TryContext {
181         RefPtr<Label> start;
182         TryData* tryData;
183     };
184
185     class Variable {
186     public:
187         enum VariableKind { NormalVariable, SpecialVariable };
188
189         Variable()
190             : m_offset()
191             , m_local(nullptr)
192             , m_attributes(0)
193             , m_kind(NormalVariable)
194         {
195         }
196         
197         Variable(const Identifier& ident)
198             : m_ident(ident)
199             , m_local(nullptr)
200             , m_attributes(0)
201             , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
202         {
203         }
204
205         Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind)
206             : m_ident(ident)
207             , m_offset(offset)
208             , m_local(local)
209             , m_attributes(attributes)
210             , m_kind(kind)
211         {
212         }
213
214         // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
215         // a stack variable, a scoped variable in the local scope, or a variable captured in the
216         // direct arguments object.
217         bool isResolved() const { return !!m_offset; }
218         
219         const Identifier& ident() const { return m_ident; }
220         
221         VarOffset offset() const { return m_offset; }
222         bool isLocal() const { return m_offset.isStack(); }
223         RegisterID* local() const { return m_local; }
224
225         bool isReadOnly() const { return m_attributes & ReadOnly; }
226         bool isSpecial() const { return m_kind != NormalVariable; }
227
228     private:
229         Identifier m_ident;
230         VarOffset m_offset;
231         RegisterID* m_local;
232         unsigned m_attributes;
233         VariableKind m_kind;
234     };
235
236     struct TryRange {
237         RefPtr<Label> start;
238         RefPtr<Label> end;
239         TryData* tryData;
240     };
241
242     enum ProfileTypeBytecodeFlag {
243         ProfileTypeBytecodePutToScope,
244         ProfileTypeBytecodeGetFromScope,
245         ProfileTypeBytecodePutToLocalScope,
246         ProfileTypeBytecodeGetFromLocalScope,
247         ProfileTypeBytecodeHasGlobalID,
248         ProfileTypeBytecodeDoesNotHaveGlobalID,
249         ProfileTypeBytecodeFunctionArgument,
250         ProfileTypeBytecodeFunctionReturnStatement
251     };
252
253     class BytecodeGenerator {
254         WTF_MAKE_FAST_ALLOCATED;
255         WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
256     public:
257         typedef DeclarationStacks::VarStack VarStack;
258         typedef DeclarationStacks::FunctionStack FunctionStack;
259
260         BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
261         BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
262         BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
263
264         ~BytecodeGenerator();
265         
266         VM* vm() const { return m_vm; }
267         ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
268         const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
269
270         bool isConstructor() const { return m_codeBlock->isConstructor(); }
271 #if ENABLE(ES6_CLASS_SYNTAX)
272         ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
273 #else
274         ConstructorKind constructorKind() const { return ConstructorKind::None; }
275 #endif
276
277         ParserError generate();
278
279         bool isArgumentNumber(const Identifier&, int);
280
281         Variable variable(const Identifier&);
282         
283         // Ignores the possibility of intervening scopes.
284         Variable variablePerSymbolTable(const Identifier&);
285         
286         enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
287         void createVariable(const Identifier&, VarKind, ConstantMode, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
288         
289         // Returns the register storing "this"
290         RegisterID* thisRegister() { return &m_thisRegister; }
291         RegisterID* argumentsRegister() { return m_argumentsRegister; }
292         RegisterID* newTarget() { return m_newTargetRegister; }
293
294         RegisterID* scopeRegister() { return m_scopeRegister; }
295
296         // Returns the next available temporary register. Registers returned by
297         // newTemporary require a modified form of reference counting: any
298         // register with a refcount of 0 is considered "available", meaning that
299         // the next instruction may overwrite it.
300         RegisterID* newTemporary();
301
302         // The same as newTemporary(), but this function returns "suggestion" if
303         // "suggestion" is a temporary. This function is helpful in situations
304         // where you've put "suggestion" in a RefPtr, but you'd like to allow
305         // the next instruction to overwrite it anyway.
306         RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
307
308         // Functions for handling of dst register
309
310         RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
311
312         // Returns a place to write intermediate values of an operation
313         // which reuses dst if it is safe to do so.
314         RegisterID* tempDestination(RegisterID* dst)
315         {
316             return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
317         }
318
319         // Returns the place to write the final output of an operation.
320         RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
321         {
322             if (originalDst && originalDst != ignoredResult())
323                 return originalDst;
324             ASSERT(tempDst != ignoredResult());
325             if (tempDst && tempDst->isTemporary())
326                 return tempDst;
327             return newTemporary();
328         }
329
330         RegisterID* destinationForAssignResult(RegisterID* dst)
331         {
332             if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
333                 return dst->isTemporary() ? dst : newTemporary();
334             return 0;
335         }
336
337         // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
338         RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
339         {
340             return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
341         }
342
343         LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
344         PassRefPtr<Label> newLabel();
345
346         void emitNode(RegisterID* dst, StatementNode* n)
347         {
348             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
349             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
350             if (!m_vm->isSafeToRecurse()) {
351                 emitThrowExpressionTooDeepException();
352                 return;
353             }
354             n->emitBytecode(*this, dst);
355         }
356
357         void emitNode(StatementNode* n)
358         {
359             emitNode(0, n);
360         }
361
362         RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
363         {
364             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
365             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
366             if (!m_vm->isSafeToRecurse())
367                 return emitThrowExpressionTooDeepException();
368             return n->emitBytecode(*this, dst);
369         }
370
371         RegisterID* emitNode(ExpressionNode* n)
372         {
373             return emitNode(0, n);
374         }
375
376         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
377         {
378             if (!m_vm->isSafeToRecurse()) {
379                 emitThrowExpressionTooDeepException();
380                 return;
381             }
382
383             n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
384         }
385
386         void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
387         {            
388             ASSERT(divot.offset >= divotStart.offset);
389             ASSERT(divotEnd.offset >= divot.offset);
390
391             int sourceOffset = m_scopeNode->source().startOffset();
392             unsigned firstLine = m_scopeNode->source().firstLine();
393
394             int divotOffset = divot.offset - sourceOffset;
395             int startOffset = divot.offset - divotStart.offset;
396             int endOffset = divotEnd.offset - divot.offset;
397
398             unsigned line = divot.line;
399             ASSERT(line >= firstLine);
400             line -= firstLine;
401
402             int lineStart = divot.lineStartOffset;
403             if (lineStart > sourceOffset)
404                 lineStart -= sourceOffset;
405             else
406                 lineStart = 0;
407
408             if (divotOffset < lineStart)
409                 return;
410
411             unsigned column = divotOffset - lineStart;
412
413             unsigned instructionOffset = instructions().size();
414             if (!m_isBuiltinFunction)
415                 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
416         }
417
418
419         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
420         {
421             return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
422         }
423
424         ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
425         {
426             if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
427                 PassRefPtr<RegisterID> dst = newTemporary();
428                 emitNode(dst.get(), n);
429                 return dst;
430             }
431
432             return emitNode(n);
433         }
434
435         void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
436         void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const Identifier*);
437
438         void emitProfileControlFlow(int);
439
440         RegisterID* emitLoad(RegisterID* dst, bool);
441         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
442         RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
443         RegisterID* emitLoadGlobalObject(RegisterID* dst);
444
445         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
446         RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
447         RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
448         RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
449
450         RegisterID* emitCreateThis(RegisterID* dst);
451         void emitTDZCheck(RegisterID* target);
452         RegisterID* emitNewObject(RegisterID* dst);
453         RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
454
455         RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode*);
456         RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index);
457         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
458         RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
459         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
460
461         RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
462         RegisterID* emitMoveEmptyValue(RegisterID* dst);
463         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
464
465         RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
466         RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
467         RegisterID* emitInc(RegisterID* srcDst);
468         RegisterID* emitDec(RegisterID* srcDst);
469
470         void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
471         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
472         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
473         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
474
475         RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value);
476
477         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
478         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
479         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
480         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
481         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
482         RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
483         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
484         RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
485         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
486         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
487
488         void emitPutGetterById(RegisterID* base, const Identifier& property, RegisterID* getter);
489         void emitPutSetterById(RegisterID* base, const Identifier& property, RegisterID* setter);
490         void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
491         
492         ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
493         RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
494         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
495         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);
496
497         enum PropertyDescriptorOption {
498             PropertyConfigurable = 1,
499             PropertyWritable     = 1 << 1,
500             PropertyEnumerable   = 1 << 2,
501         };
502         void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
503             RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
504
505         void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack);
506
507 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
508         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
509 #endif
510
511         RegisterID* emitReturn(RegisterID* src);
512         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
513
514         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
515         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
516         void emitToPrimitive(RegisterID* dst, RegisterID* src);
517
518         ResolveType resolveType();
519         RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
520         RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
521         RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
522         RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode);
523         RegisterID* initializeVariable(const Variable&, RegisterID* value);
524
525         PassRefPtr<Label> emitLabel(Label*);
526         void emitLoopHint();
527         PassRefPtr<Label> emitJump(Label* target);
528         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
529         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
530         PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
531         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
532         void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
533
534         RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
535         RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
536         RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
537         RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
538         RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
539         RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
540         RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
541         RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
542         RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
543         RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
544
545         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
546         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
547
548         void emitIteratorClose(RegisterID* iterator, ThrowableExpressionData* node);
549
550         void emitReadOnlyExceptionIfNeeded();
551
552         // Start a try block. 'start' must have been emitted.
553         TryData* pushTry(Label* start);
554         // End a try block. 'end' must have been emitted.
555         RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end);
556
557         void emitThrow(RegisterID* exc)
558         { 
559             m_usesExceptions = true;
560             emitUnaryNoDstOp(op_throw, exc);
561         }
562
563         void emitThrowReferenceError(const String& message);
564         void emitThrowTypeError(const String& message);
565
566         void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
567         void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
568
569         void emitGetScope();
570         RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope);
571         void emitPopScope(RegisterID* srcDst);
572
573         void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
574
575         int scopeDepth() { return m_localScopeDepth + m_finallyDepth; }
576         bool hasFinaliser() { return m_finallyDepth != 0; }
577
578         void pushFinallyContext(StatementNode* finallyBlock);
579         void popFinallyContext();
580         void pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
581         void popIteratorCloseContext();
582
583         void pushIndexedForInScope(RegisterID* local, RegisterID* index);
584         void popIndexedForInScope(RegisterID* local);
585         void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
586         void popStructureForInScope(RegisterID* local);
587         void invalidateForInContextForLocal(RegisterID* local);
588
589         LabelScopePtr breakTarget(const Identifier&);
590         LabelScopePtr continueTarget(const Identifier&);
591
592         void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
593         void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
594
595         CodeType codeType() const { return m_codeType; }
596
597         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
598         bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
599         
600         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
601         
602         bool isBuiltinFunction() const { return m_isBuiltinFunction; }
603
604         OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
605
606     private:
607         Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&);
608
609         void emitOpcode(OpcodeID);
610         UnlinkedArrayAllocationProfile newArrayAllocationProfile();
611         UnlinkedObjectAllocationProfile newObjectAllocationProfile();
612         UnlinkedArrayProfile newArrayProfile();
613         UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
614         int kill(RegisterID* dst)
615         {
616             int index = dst->index();
617             m_staticPropertyAnalyzer.kill(index);
618             return index;
619         }
620
621         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
622         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
623         ALWAYS_INLINE void rewindBinaryOp();
624         ALWAYS_INLINE void rewindUnaryOp();
625
626         void allocateAndEmitScope();
627         void emitComplexPopScopes(RegisterID*, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
628
629         typedef HashMap<double, JSValue> NumberMap;
630         typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
631         typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
632         
633         // Helper for emitCall() and emitConstruct(). This works because the set of
634         // expected functions have identical behavior for both call and construct
635         // (i.e. "Object()" is identical to "new Object()").
636         ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
637         
638         RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
639
640         RegisterID* newRegister();
641
642         // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable().
643         RegisterID* addVar()
644         {
645             ++m_codeBlock->m_numVars;
646             RegisterID* result = newRegister();
647             ASSERT(VirtualRegister(result->index()).toLocal() == m_codeBlock->m_numVars - 1);
648             result->ref(); // We should never free this slot.
649             return result;
650         }
651
652         // Initializes the stack form the parameter; does nothing for the symbol table.
653         RegisterID* initializeNextParameter();
654         StringImpl* visibleNameForParameter(DeconstructionPatternNode*);
655         
656         RegisterID& registerFor(VirtualRegister reg)
657         {
658             if (reg.isLocal())
659                 return m_calleeRegisters[reg.toLocal()];
660
661             if (reg.offset() == JSStack::Callee)
662                 return m_calleeRegister;
663
664             ASSERT(m_parameters.size());
665             return m_parameters[reg.toArgument()];
666         }
667
668         bool hasConstant(const Identifier&) const;
669         unsigned addConstant(const Identifier&);
670         RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
671         RegisterID* addConstantEmptyValue();
672         unsigned addRegExp(RegExp*);
673
674         unsigned addConstantBuffer(unsigned length);
675         
676         UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
677         {
678             return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction);
679         }
680
681         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);
682         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);
683
684     public:
685         JSString* addStringConstant(const Identifier&);
686         JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
687
688         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
689
690         SymbolTable& symbolTable() { return *m_symbolTable; }
691
692         bool shouldOptimizeLocals()
693         {
694             if (m_codeType != FunctionCode)
695                 return false;
696
697             if (m_localScopeDepth)
698                 return false;
699
700             return true;
701         }
702
703         bool canOptimizeNonLocals()
704         {
705             if (m_localScopeDepth)
706                 return false;
707
708             if (m_codeType == EvalCode)
709                 return false;
710
711             if (m_codeType == FunctionCode && m_codeBlock->usesEval())
712                 return false;
713
714             return true;
715         }
716
717         RegisterID* emitThrowExpressionTooDeepException();
718
719     private:
720         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
721
722         bool m_shouldEmitDebugHooks;
723         bool m_shouldEmitProfileHooks;
724
725         SymbolTable* m_symbolTable { nullptr };
726
727         ScopeNode* const m_scopeNode;
728         Strong<UnlinkedCodeBlock> m_codeBlock;
729
730         // Some of these objects keep pointers to one another. They are arranged
731         // to ensure a sane destruction order that avoids references to freed memory.
732         HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
733         RegisterID m_ignoredResultRegister;
734         RegisterID m_thisRegister;
735         RegisterID m_calleeRegister;
736         RegisterID* m_scopeRegister { nullptr };
737         RegisterID* m_argumentsRegister { nullptr };
738         RegisterID* m_lexicalEnvironmentRegister { nullptr };
739         RegisterID* m_emptyValueRegister { nullptr };
740         RegisterID* m_globalObjectRegister { nullptr };
741         RegisterID* m_newTargetRegister { nullptr };
742         RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
743
744         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
745         SegmentedVector<RegisterID, 32> m_calleeRegisters;
746         SegmentedVector<RegisterID, 32> m_parameters;
747         SegmentedVector<Label, 32> m_labels;
748         LabelScopeStore m_labelScopes;
749         int m_finallyDepth { 0 };
750         int m_localScopeDepth { 0 };
751         const CodeType m_codeType;
752
753         Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
754         Vector<SwitchInfo> m_switchContextStack;
755         Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
756         Vector<TryContext> m_tryContextStack;
757         Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
758         enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
759         Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
760         bool m_needToInitializeArguments { false };
761         
762         Vector<TryRange> m_tryRanges;
763         SegmentedVector<TryData, 8> m_tryData;
764
765         int m_nextConstantOffset { 0 };
766
767         typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
768         FunctionOffsetMap m_functionOffsets;
769         
770         // Constant pool
771         IdentifierMap m_identifierMap;
772
773         typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
774         JSValueMap m_jsValueMap;
775         IdentifierStringMap m_stringMap;
776         TemplateRegistryKeyMap m_templateRegistryKeyMap;
777
778         StaticPropertyAnalyzer m_staticPropertyAnalyzer { &m_instructions };
779
780         VM* m_vm;
781
782         OpcodeID m_lastOpcodeID = op_end;
783 #ifndef NDEBUG
784         size_t m_lastOpcodePosition { 0 };
785 #endif
786
787         bool m_usesExceptions { false };
788         bool m_expressionTooDeep { false };
789         bool m_isBuiltinFunction { false };
790     };
791
792 }
793
794 #endif // BytecodeGenerator_h