53256f318812f50a5a55e488a5bc873db503784c
[WebKit-https.git] / Source / JavaScriptCore / bytecompiler / BytecodeGenerator.h
1 /*
2  * Copyright (C) 2008, 2009, 2012 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 Computer, 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 "RegisterID.h"
41 #include "SymbolTable.h"
42 #include "Debugger.h"
43 #include "Nodes.h"
44 #include <wtf/PassRefPtr.h>
45 #include <wtf/SegmentedVector.h>
46 #include <wtf/Vector.h>
47
48 namespace JSC {
49
50     class Identifier;
51     class Label;
52     class ScopeChainNode;
53
54     class CallArguments {
55     public:
56         CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
57
58         RegisterID* thisRegister() { return m_argv[0].get(); }
59         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
60         unsigned registerOffset() { return m_argv.last()->index() + CallFrame::offsetFor(argumentCountIncludingThis()); }
61         unsigned argumentCountIncludingThis() { return m_argv.size(); }
62         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
63         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
64
65     private:
66         void newArgument(BytecodeGenerator&);
67
68         RefPtr<RegisterID> m_profileHookRegister;
69         ArgumentsNode* m_argumentsNode;
70         Vector<RefPtr<RegisterID>, 8> m_argv;
71     };
72
73     struct FinallyContext {
74         StatementNode* finallyBlock;
75         unsigned scopeContextStackSize;
76         unsigned switchContextStackSize;
77         unsigned forInContextStackSize;
78         unsigned labelScopesSize;
79         int finallyDepth;
80         int dynamicScopeDepth;
81     };
82
83     struct ControlFlowContext {
84         bool isFinallyBlock;
85         FinallyContext finallyContext;
86     };
87
88     struct ForInContext {
89         RefPtr<RegisterID> expectedSubscriptRegister;
90         RefPtr<RegisterID> iterRegister;
91         RefPtr<RegisterID> indexRegister;
92         RefPtr<RegisterID> propertyRegister;
93     };
94
95     class ResolveResult {
96     public:
97         enum Flags {
98             // The property is locally bound, in a register.
99             RegisterFlag = 0x1,
100             // We need to traverse the scope chain at runtime, checking for
101             // non-strict eval and/or `with' nodes.
102             DynamicFlag = 0x2,
103             // The property was resolved to a definite location, and the
104             // identifier is not needed any more.
105             StaticFlag = 0x4,
106             // Once we have the base object, the property will be located at a
107             // known index.
108             IndexedFlag = 0x8,
109             // Skip some number of objects in the scope chain, given by "depth".
110             ScopedFlag = 0x10,
111             // The resolved binding is immutable.
112             ReadOnlyFlag = 0x20,
113             // The base object is the global object.
114             GlobalFlag = 0x40
115         };
116         enum Type {
117             // The property is local, and stored in a register.
118             Register = RegisterFlag | StaticFlag,
119             // A read-only local, created by "const".
120             ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,
121             // The property is statically scoped free variable. Its coordinates
122             // are in "index" and "depth".
123             Lexical = IndexedFlag | ScopedFlag | StaticFlag,
124             // A read-only Lexical, created by "const".
125             ReadOnlyLexical = IndexedFlag | ScopedFlag | ReadOnlyFlag | StaticFlag,
126             // The property was not bound lexically, so at runtime we should
127             // look directly in the global object.
128             Global = GlobalFlag,
129             // Like Global, but we could actually resolve the property to a
130             // DontDelete property in the global object, for instance, any
131             // binding created with "var" at the top level. At runtime we'll
132             // just index into the global object.
133             IndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag,
134             // Like IndexedGlobal, but the property is also read-only, like NaN,
135             // Infinity, or undefined.
136             ReadOnlyIndexedGlobal = IndexedFlag | ReadOnlyFlag | GlobalFlag | StaticFlag,
137             // The property could not be resolved statically, due to the
138             // presence of `with' blocks. At runtime we'll have to walk the
139             // scope chain. ScopedFlag is set to indicate that "depth" will
140             // hold some number of nodes to skip in the scope chain, before
141             // beginning the search.
142             Dynamic = DynamicFlag | ScopedFlag,
143             // The property was located as a statically scoped free variable,
144             // but while traversing the scope chain, there was an intermediate
145             // activation that used non-strict `eval'. At runtime we'll have to
146             // check for the absence of this property in those intervening
147             // scopes.
148             DynamicLexical = DynamicFlag | IndexedFlag | ScopedFlag,
149             // Like ReadOnlyLexical, but with intervening non-strict `eval'.
150             DynamicReadOnlyLexical = DynamicFlag | IndexedFlag | ScopedFlag | ReadOnlyFlag,
151             // Like Global, but with intervening non-strict `eval'. As with 
152             // Dynamic, ScopeFlag is set to indicate that "depth" does indeed
153             // store a number of frames to skip before doing the dynamic checks.
154             DynamicGlobal = DynamicFlag | GlobalFlag | ScopedFlag,
155             // Like IndexedGlobal, but with intervening non-strict `eval'.
156             DynamicIndexedGlobal = DynamicFlag | IndexedFlag | GlobalFlag | ScopedFlag,
157             // Like ReadOnlyIndexedGlobal, but with intervening non-strict
158             // `eval'.
159             DynamicReadOnlyIndexedGlobal = DynamicFlag | IndexedFlag | ReadOnlyFlag | GlobalFlag | ScopedFlag,
160         };
161
162         static ResolveResult registerResolve(RegisterID *local, unsigned flags)
163         {
164             return ResolveResult(Register | flags, local, missingSymbolMarker(), 0, 0);
165         }
166         static ResolveResult dynamicResolve(size_t depth)
167         {
168             return ResolveResult(Dynamic, 0, missingSymbolMarker(), depth, 0);
169         }
170         static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)
171         {
172             unsigned type = (flags & DynamicFlag) ? DynamicLexical : Lexical;
173             return ResolveResult(type | flags, 0, index, depth, 0);
174         }
175         static ResolveResult indexedGlobalResolve(int index, JSObject *globalObject, unsigned flags)
176         {
177             return ResolveResult(IndexedGlobal | flags, 0, index, 0, globalObject);
178         }
179         static ResolveResult dynamicIndexedGlobalResolve(int index, size_t depth, JSObject *globalObject, unsigned flags)
180         {
181             return ResolveResult(DynamicIndexedGlobal | flags, 0, index, depth, globalObject);
182         }
183         static ResolveResult globalResolve(JSObject *globalObject)
184         {
185             return ResolveResult(Global, 0, missingSymbolMarker(), 0, globalObject);
186         }
187         static ResolveResult dynamicGlobalResolve(size_t dynamicDepth, JSObject *globalObject)
188         {
189             return ResolveResult(DynamicGlobal, 0, missingSymbolMarker(), dynamicDepth, globalObject);
190         }
191
192         unsigned type() const { return m_type; }
193         // Returns the register corresponding to a local variable, or 0 if no
194         // such register exists. Registers returned by ResolveResult::local() do
195         // not require explicit reference counting.
196         RegisterID* local() const { return m_local; }
197         int index() const { ASSERT (isIndexed() || isRegister()); return m_index; }
198         size_t depth() const { ASSERT(isScoped()); return m_depth; }
199         JSObject* globalObject() const { ASSERT(isGlobal()); ASSERT(m_globalObject); return m_globalObject; }
200         WriteBarrier<Unknown>* registerPointer() const;
201
202         bool isRegister() const { return m_type & RegisterFlag; }
203         bool isDynamic() const { return m_type & DynamicFlag; }
204         bool isStatic() const { return m_type & StaticFlag; }
205         bool isIndexed() const { return m_type & IndexedFlag; }
206         bool isScoped() const { return m_type & ScopedFlag; }
207         bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }
208         bool isGlobal() const { return m_type & GlobalFlag; }
209
210     private:
211         ResolveResult(unsigned type, RegisterID* local, int index, size_t depth, JSObject* globalObject)
212             : m_type(type)
213             , m_index(index)
214             , m_local(local)
215             , m_depth(depth)
216             , m_globalObject(globalObject)
217         {
218 #ifndef NDEBUG
219             checkValidity();
220 #endif
221         }
222
223 #ifndef NDEBUG
224         void checkValidity();
225 #endif
226
227         unsigned m_type;
228         int m_index; // Index in scope, if IndexedFlag is set
229         RegisterID* m_local; // Local register, if RegisterFlag is set
230         size_t m_depth; // Depth in scope chain, if ScopedFlag is set
231         JSObject* m_globalObject; // If GlobalFlag is set.
232     };
233
234     class BytecodeGenerator {
235         WTF_MAKE_FAST_ALLOCATED;
236     public:
237         typedef DeclarationStacks::VarStack VarStack;
238         typedef DeclarationStacks::FunctionStack FunctionStack;
239
240         JS_EXPORT_PRIVATE static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
241         static bool dumpsGeneratedCode();
242
243         BytecodeGenerator(ProgramNode*, ScopeChainNode*, SymbolTable*, ProgramCodeBlock*, CompilationKind);
244         BytecodeGenerator(FunctionBodyNode*, ScopeChainNode*, SymbolTable*, CodeBlock*, CompilationKind);
245         BytecodeGenerator(EvalNode*, ScopeChainNode*, SymbolTable*, EvalCodeBlock*, CompilationKind);
246
247         ~BytecodeGenerator();
248         
249         JSGlobalData* globalData() const { return m_globalData; }
250         const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
251
252         bool isConstructor() { return m_codeBlock->m_isConstructor; }
253
254         JSObject* generate();
255
256         bool isArgumentNumber(const Identifier&, int);
257
258         void setIsNumericCompareFunction(bool isNumericCompareFunction);
259
260         bool willResolveToArguments(const Identifier&);
261         RegisterID* uncheckedRegisterForArguments();
262
263         // Resolve an identifier, given the current compile-time scope chain.
264         ResolveResult resolve(const Identifier&);
265         // Behaves as resolve does, but ignores dynamic scope as
266         // dynamic scope should not interfere with const initialisation
267         ResolveResult resolveConstDecl(const Identifier&);
268
269         // Returns the register storing "this"
270         RegisterID* thisRegister() { return &m_thisRegister; }
271
272         // Returns the next available temporary register. Registers returned by
273         // newTemporary require a modified form of reference counting: any
274         // register with a refcount of 0 is considered "available", meaning that
275         // the next instruction may overwrite it.
276         RegisterID* newTemporary();
277
278         RegisterID* highestUsedRegister();
279
280         // The same as newTemporary(), but this function returns "suggestion" if
281         // "suggestion" is a temporary. This function is helpful in situations
282         // where you've put "suggestion" in a RefPtr, but you'd like to allow
283         // the next instruction to overwrite it anyway.
284         RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
285
286         // Functions for handling of dst register
287
288         RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
289
290         // Returns a place to write intermediate values of an operation
291         // which reuses dst if it is safe to do so.
292         RegisterID* tempDestination(RegisterID* dst)
293         {
294             return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
295         }
296
297         // Returns the place to write the final output of an operation.
298         RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
299         {
300             if (originalDst && originalDst != ignoredResult())
301                 return originalDst;
302             ASSERT(tempDst != ignoredResult());
303             if (tempDst && tempDst->isTemporary())
304                 return tempDst;
305             return newTemporary();
306         }
307
308         // Returns the place to write the final output of an operation.
309         RegisterID* finalDestinationOrIgnored(RegisterID* originalDst, RegisterID* tempDst = 0)
310         {
311             if (originalDst)
312                 return originalDst;
313             ASSERT(tempDst != ignoredResult());
314             if (tempDst && tempDst->isTemporary())
315                 return tempDst;
316             return newTemporary();
317         }
318
319         RegisterID* destinationForAssignResult(RegisterID* dst)
320         {
321             if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
322                 return dst->isTemporary() ? dst : newTemporary();
323             return 0;
324         }
325
326         // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
327         RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
328         {
329             return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
330         }
331
332         PassRefPtr<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0);
333         PassRefPtr<Label> newLabel();
334
335         // The emitNode functions are just syntactic sugar for calling
336         // Node::emitCode. These functions accept a 0 for the register,
337         // meaning that the node should allocate a register, or ignoredResult(),
338         // meaning that the node need not put the result in a register.
339         // Other emit functions do not accept 0 or ignoredResult().
340         RegisterID* emitNode(RegisterID* dst, Node* n)
341         {
342             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
343             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
344             addLineInfo(n->lineNo());
345             return m_stack.recursionCheck()
346                 ? n->emitBytecode(*this, dst)
347                 : emitThrowExpressionTooDeepException();
348         }
349
350         RegisterID* emitNode(Node* n)
351         {
352             return emitNode(0, n);
353         }
354
355         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
356         {
357             addLineInfo(n->lineNo());
358             if (m_stack.recursionCheck())
359                 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
360             else
361                 emitThrowExpressionTooDeepException();
362         }
363
364         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
365         {
366             if (!m_shouldEmitRichSourceInfo)
367                 return;
368
369             divot -= m_codeBlock->sourceOffset();
370             if (divot > ExpressionRangeInfo::MaxDivot) {
371                 // Overflow has occurred, we can only give line number info for errors for this region
372                 divot = 0;
373                 startOffset = 0;
374                 endOffset = 0;
375             } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
376                 // If the start offset is out of bounds we clear both offsets
377                 // so we only get the divot marker.  Error message will have to be reduced
378                 // to line and column number.
379                 startOffset = 0;
380                 endOffset = 0;
381             } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
382                 // The end offset is only used for additional context, and is much more likely
383                 // to overflow (eg. function call arguments) so we are willing to drop it without
384                 // dropping the rest of the range.
385                 endOffset = 0;
386             }
387             
388             ExpressionRangeInfo info;
389             info.instructionOffset = instructions().size();
390             info.divotPoint = divot;
391             info.startOffset = startOffset;
392             info.endOffset = endOffset;
393             m_codeBlock->addExpressionInfo(info);
394         }
395
396         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
397         {
398             return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
399         }
400
401         ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
402         {
403             if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
404                 PassRefPtr<RegisterID> dst = newTemporary();
405                 emitNode(dst.get(), n);
406                 return dst;
407             }
408
409             return emitNode(n);
410         }
411
412         RegisterID* emitLoad(RegisterID* dst, bool);
413         RegisterID* emitLoad(RegisterID* dst, double);
414         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
415         RegisterID* emitLoad(RegisterID* dst, JSValue);
416
417         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
418         RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
419         RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
420         RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
421
422         RegisterID* emitNewObject(RegisterID* dst);
423         RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
424
425         RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body);
426         RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body);
427         RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck);
428         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
429         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
430
431         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
432
433         RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src); }
434         RegisterID* emitPreInc(RegisterID* srcDst);
435         RegisterID* emitPreDec(RegisterID* srcDst);
436         RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
437         RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
438
439         void emitCheckHasInstance(RegisterID* base);
440         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
441         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
442         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
443
444         RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&);
445         RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);
446
447         RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
448         RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
449         RegisterID* emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property);
450         RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
451         RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
452
453         void emitMethodCheck();
454
455         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
456         RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
457         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
458         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
459         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
460         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
461         RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
462         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
463         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
464         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
465         void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
466
467         RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
468         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
469         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, unsigned divot, unsigned startOffset, unsigned endOffset);
470         RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
471
472         RegisterID* emitReturn(RegisterID* src);
473         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
474
475         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
476         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
477         void emitToPrimitive(RegisterID* dst, RegisterID* src);
478
479         PassRefPtr<Label> emitLabel(Label*);
480         void emitLoopHint();
481         PassRefPtr<Label> emitJump(Label* target);
482         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
483         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
484         PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
485         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
486         PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
487
488         RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
489         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
490
491         RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
492         void emitThrow(RegisterID* exc)
493         { 
494             m_usesExceptions = true;
495             emitUnaryNoDstOp(op_throw, exc);
496         }
497
498         void emitThrowReferenceError(const UString& message);
499
500         void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
501
502         RegisterID* emitPushScope(RegisterID* scope);
503         void emitPopScope();
504
505         void emitDebugHook(DebugHookID, int firstLine, int lastLine);
506
507         int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
508         bool hasFinaliser() { return m_finallyDepth != 0; }
509
510         void pushFinallyContext(StatementNode* finallyBlock);
511         void popFinallyContext();
512
513         void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
514         {
515             ForInContext context = { expectedBase, iter, index, propertyRegister };
516             m_forInContextStack.append(context);
517         }
518
519         void popOptimisedForIn()
520         {
521             m_forInContextStack.removeLast();
522         }
523
524         LabelScope* breakTarget(const Identifier&);
525         LabelScope* continueTarget(const Identifier&);
526
527         void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
528         void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
529
530         CodeType codeType() const { return m_codeType; }
531
532         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
533         
534         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
535         
536         ScopeChainNode* scopeChain() const { return m_scopeChain.get(); }
537
538     private:
539         friend class Label;
540         
541         void emitOpcode(OpcodeID);
542         ValueProfile* emitProfiledOpcode(OpcodeID);
543         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
544         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
545         void retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex);
546         ALWAYS_INLINE void rewindBinaryOp();
547         ALWAYS_INLINE void rewindUnaryOp();
548
549         PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
550
551         typedef HashMap<double, JSValue> NumberMap;
552         typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
553         
554         RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
555
556         RegisterID* newRegister();
557
558         // Adds a var slot and maps it to the name ident in symbolTable().
559         RegisterID* addVar(const Identifier& ident, bool isConstant)
560         {
561             RegisterID* local;
562             addVar(ident, isConstant, local);
563             return local;
564         }
565
566         // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
567         bool addVar(const Identifier&, bool isConstant, RegisterID*&);
568         
569         // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
570         RegisterID* addVar()
571         {
572             ++m_codeBlock->m_numVars;
573             return newRegister();
574         }
575
576         // Returns the index of the added var.
577         int addGlobalVar(const Identifier&, bool isConstant);
578
579         void addParameter(const Identifier&, int parameterIndex);
580         
581         void preserveLastVar();
582         bool shouldAvoidResolveGlobal();
583
584         RegisterID& registerFor(int index)
585         {
586             if (index >= 0)
587                 return m_calleeRegisters[index];
588
589             ASSERT(m_parameters.size());
590             return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
591         }
592
593         unsigned addConstant(const Identifier&);
594         RegisterID* addConstantValue(JSValue);
595         unsigned addRegExp(RegExp*);
596
597         unsigned addConstantBuffer(unsigned length);
598         
599         FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
600         {
601             return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
602         }
603
604         FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
605         {
606             return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
607         }
608
609         JSString* addStringConstant(const Identifier&);
610
611         void addLineInfo(unsigned lineNo)
612         {
613 #if !ENABLE(OPCODE_SAMPLING)
614             if (m_shouldEmitRichSourceInfo)
615 #endif
616                 m_codeBlock->addLineInfo(instructions().size(), lineNo);
617         }
618
619         RegisterID* emitInitLazyRegister(RegisterID*);
620
621         Vector<Instruction>& instructions() { return m_instructions; }
622         SymbolTable& symbolTable() { return *m_symbolTable; }
623
624         bool shouldOptimizeLocals()
625         {
626             if (m_dynamicScopeDepth)
627                 return false;
628
629             if (m_codeType != FunctionCode)
630                 return false;
631
632             return true;
633         }
634
635         bool canOptimizeNonLocals()
636         {
637             if (m_dynamicScopeDepth)
638                 return false;
639
640             if (m_codeType == EvalCode)
641                 return false;
642
643             if (m_codeType == FunctionCode && m_codeBlock->usesEval())
644                 return false;
645
646             return true;
647         }
648
649         RegisterID* emitThrowExpressionTooDeepException();
650
651         void createArgumentsIfNecessary();
652         void createActivationIfNecessary();
653         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
654         
655         Vector<Instruction> m_instructions;
656
657         bool m_shouldEmitDebugHooks;
658         bool m_shouldEmitProfileHooks;
659         bool m_shouldEmitRichSourceInfo;
660
661         Strong<ScopeChainNode> m_scopeChain;
662         SymbolTable* m_symbolTable;
663
664         ScopeNode* m_scopeNode;
665         CodeBlock* m_codeBlock;
666
667         // Some of these objects keep pointers to one another. They are arranged
668         // to ensure a sane destruction order that avoids references to freed memory.
669         HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
670         RegisterID m_ignoredResultRegister;
671         RegisterID m_thisRegister;
672         RegisterID* m_activationRegister;
673         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
674         SegmentedVector<RegisterID, 32> m_calleeRegisters;
675         SegmentedVector<RegisterID, 32> m_parameters;
676         SegmentedVector<Label, 32> m_labels;
677         SegmentedVector<LabelScope, 8> m_labelScopes;
678         RefPtr<RegisterID> m_lastVar;
679         int m_finallyDepth;
680         int m_dynamicScopeDepth;
681         int m_baseScopeDepth;
682         CodeType m_codeType;
683
684         Vector<ControlFlowContext> m_scopeContextStack;
685         Vector<SwitchInfo> m_switchContextStack;
686         Vector<ForInContext> m_forInContextStack;
687
688         int m_firstConstantIndex;
689         int m_nextConstantOffset;
690         unsigned m_globalConstantIndex;
691
692         int m_globalVarStorageOffset;
693
694         bool m_hasCreatedActivation;
695         int m_firstLazyFunction;
696         int m_lastLazyFunction;
697         HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
698         typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
699         FunctionOffsetMap m_functionOffsets;
700         
701         // Constant pool
702         IdentifierMap m_identifierMap;
703         JSValueMap m_jsValueMap;
704         NumberMap m_numberMap;
705         IdentifierStringMap m_stringMap;
706
707         JSGlobalData* m_globalData;
708
709         OpcodeID m_lastOpcodeID;
710 #ifndef NDEBUG
711         size_t m_lastOpcodePosition;
712 #endif
713
714         StackBounds m_stack;
715
716         bool m_usesExceptions;
717         bool m_expressionTooDeep;
718     };
719
720 }
721
722 #endif // BytecodeGenerator_h