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