Make SegmentedVector Noncopyable
[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 "ParserError.h"
41 #include "RegisterID.h"
42 #include "SymbolTable.h"
43 #include "Debugger.h"
44 #include "Nodes.h"
45 #include "StaticPropertyAnalyzer.h"
46 #include "UnlinkedCodeBlock.h"
47 #include <wtf/PassRefPtr.h>
48 #include <wtf/SegmentedVector.h>
49 #include <wtf/Vector.h>
50
51 namespace JSC {
52
53     class Identifier;
54     class Label;
55     class JSScope;
56
57     enum ExpectedFunction {
58         NoExpectedFunction,
59         ExpectObjectConstructor,
60         ExpectArrayConstructor
61     };
62
63     class CallArguments {
64     public:
65         CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
66
67         RegisterID* thisRegister() { return m_argv[0].get(); }
68         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
69         unsigned registerOffset() { return m_argv.last()->index() + CallFrame::offsetFor(argumentCountIncludingThis()); }
70         unsigned argumentCountIncludingThis() { return m_argv.size(); }
71         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
72         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
73
74     private:
75         void newArgument(BytecodeGenerator&);
76
77         RefPtr<RegisterID> m_profileHookRegister;
78         ArgumentsNode* m_argumentsNode;
79         Vector<RefPtr<RegisterID>, 8> m_argv;
80     };
81
82     struct FinallyContext {
83         StatementNode* finallyBlock;
84         unsigned scopeContextStackSize;
85         unsigned switchContextStackSize;
86         unsigned forInContextStackSize;
87         unsigned tryContextStackSize;
88         unsigned labelScopesSize;
89         int finallyDepth;
90         int dynamicScopeDepth;
91     };
92
93     struct ControlFlowContext {
94         bool isFinallyBlock;
95         FinallyContext finallyContext;
96     };
97
98     struct ForInContext {
99         RefPtr<RegisterID> expectedSubscriptRegister;
100         RefPtr<RegisterID> iterRegister;
101         RefPtr<RegisterID> indexRegister;
102         RefPtr<RegisterID> propertyRegister;
103     };
104
105     struct TryData {
106         RefPtr<Label> target;
107         unsigned targetScopeDepth;
108     };
109
110     struct TryContext {
111         RefPtr<Label> start;
112         TryData* tryData;
113     };
114
115     struct TryRange {
116         RefPtr<Label> start;
117         RefPtr<Label> end;
118         TryData* tryData;
119     };
120
121     class ResolveResult {
122     public:
123         enum Flags {
124             // The property is locally bound, in a register.
125             RegisterFlag = 0x1,
126             // We need to traverse the scope chain at runtime, checking for
127             // non-strict eval and/or `with' nodes.
128             DynamicFlag = 0x2,
129             // The resolved binding is immutable.
130             ReadOnlyFlag = 0x4,
131             // The property has a static location
132             StaticFlag = 0x8,
133             // Entry at scope distance "m_depth" and located at "m_index"
134             ScopedFlag = 0x10
135         };
136
137         enum Type {
138             // The property is local, and stored in a register.
139             Register = RegisterFlag | StaticFlag,
140             // A read-only local, created by "const".
141             ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,
142             // Lexically fixed location in the scope chain
143             Lexical = ScopedFlag | StaticFlag,
144             // A read-only Lexical, created by "const".
145             ReadOnlyLexical = ScopedFlag | ReadOnlyFlag | StaticFlag,
146             // Any other form of lookup
147             Dynamic = DynamicFlag,
148         };
149
150         static ResolveResult registerResolve(RegisterID *local, unsigned flags)
151         {
152             return ResolveResult(Register | flags, local);
153         }
154         static ResolveResult dynamicResolve()
155         {
156             return ResolveResult(Dynamic, 0);
157         }
158         static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)
159         {
160             if (flags & DynamicFlag)
161                 return dynamicResolve();
162             return ResolveResult(Lexical | flags, index, depth);
163         }
164         unsigned type() const { return m_type; }
165
166         // Returns the register corresponding to a local variable, or 0 if no
167         // such register exists. Registers returned by ResolveResult::local() do
168         // not require explicit reference counting.
169         RegisterID* local() const { return m_local; }
170
171         bool isRegister() const { return m_type & RegisterFlag; }
172         bool isStatic() const { return (m_type & StaticFlag) && !isDynamic(); }
173         bool isDynamic() const { return m_type & DynamicFlag; }
174         bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }
175
176         unsigned depth() const { ASSERT(isStatic()); return m_depth; }
177         int32_t index() const { ASSERT(isStatic()); return m_index; }
178
179     private:
180         ResolveResult(unsigned type, RegisterID* local)
181             : m_type(type)
182             , m_local(local)
183             , m_index(0)
184             , m_depth(0)
185         {
186 #ifndef NDEBUG
187             checkValidity();
188 #endif
189         }
190
191         ResolveResult(unsigned type, int index, unsigned depth)
192             : m_type(type)
193             , m_local(0)
194             , m_index(index)
195             , m_depth(depth)
196         {
197 #ifndef NDEBUG
198             checkValidity();
199 #endif
200         }
201
202 #ifndef NDEBUG
203         void checkValidity();
204 #endif
205
206         unsigned m_type;
207         RegisterID* m_local; // Local register, if RegisterFlag is set
208         int m_index;
209         unsigned m_depth;
210     };
211
212     struct NonlocalResolveInfo {
213         friend class BytecodeGenerator;
214         NonlocalResolveInfo()
215             : m_state(Unused)
216         {
217         }
218         ~NonlocalResolveInfo()
219         {
220             ASSERT(m_state == Put);
221         }
222     private:
223         void resolved(uint32_t putToBaseIndex)
224         {
225             ASSERT(putToBaseIndex);
226             ASSERT(m_state == Unused);
227             m_state = Resolved;
228             m_putToBaseIndex = putToBaseIndex;
229         }
230         uint32_t put()
231         {
232             ASSERT(m_state == Resolved);
233             m_state = Put;
234             return m_putToBaseIndex;
235         }
236         enum State { Unused, Resolved, Put };
237         State m_state;
238         uint32_t m_putToBaseIndex;
239     };
240
241     class BytecodeGenerator {
242         WTF_MAKE_FAST_ALLOCATED;
243     public:
244         typedef DeclarationStacks::VarStack VarStack;
245         typedef DeclarationStacks::FunctionStack FunctionStack;
246
247         BytecodeGenerator(JSGlobalData&, JSScope*, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
248         BytecodeGenerator(JSGlobalData&, JSScope*, FunctionBodyNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
249         BytecodeGenerator(JSGlobalData&, JSScope*, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
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->isConstructor(); }
257
258         ParserError 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         // The same as newTemporary(), but this function returns "suggestion" if
283         // "suggestion" is a temporary. This function is helpful in situations
284         // where you've put "suggestion" in a RefPtr, but you'd like to allow
285         // the next instruction to overwrite it anyway.
286         RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
287
288         // Functions for handling of dst register
289
290         RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
291
292         // Returns a place to write intermediate values of an operation
293         // which reuses dst if it is safe to do so.
294         RegisterID* tempDestination(RegisterID* dst)
295         {
296             return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
297         }
298
299         // Returns the place to write the final output of an operation.
300         RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
301         {
302             if (originalDst && originalDst != ignoredResult())
303                 return originalDst;
304             ASSERT(tempDst != ignoredResult());
305             if (tempDst && tempDst->isTemporary())
306                 return tempDst;
307             return newTemporary();
308         }
309
310         // Returns the place to write the final output of an operation.
311         RegisterID* finalDestinationOrIgnored(RegisterID* originalDst, RegisterID* tempDst = 0)
312         {
313             if (originalDst)
314                 return originalDst;
315             ASSERT(tempDst != ignoredResult());
316             if (tempDst && tempDst->isTemporary())
317                 return tempDst;
318             return newTemporary();
319         }
320
321         RegisterID* destinationForAssignResult(RegisterID* dst)
322         {
323             if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
324                 return dst->isTemporary() ? dst : newTemporary();
325             return 0;
326         }
327
328         // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
329         RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
330         {
331             return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
332         }
333
334         LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
335         PassRefPtr<Label> newLabel();
336
337         // The emitNode functions are just syntactic sugar for calling
338         // Node::emitCode. These functions accept a 0 for the register,
339         // meaning that the node should allocate a register, or ignoredResult(),
340         // meaning that the node need not put the result in a register.
341         // Other emit functions do not accept 0 or ignoredResult().
342         RegisterID* emitNode(RegisterID* dst, Node* n)
343         {
344             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
345             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
346             addLineInfo(n->lineNo());
347             return m_stack.isSafeToRecurse()
348                 ? n->emitBytecode(*this, dst)
349                 : emitThrowExpressionTooDeepException();
350         }
351
352         RegisterID* emitNode(Node* n)
353         {
354             return emitNode(0, n);
355         }
356
357         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
358         {
359             addLineInfo(n->lineNo());
360             if (m_stack.isSafeToRecurse())
361                 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
362             else
363                 emitThrowExpressionTooDeepException();
364         }
365
366         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
367         {
368             divot -= m_scopeNode->source().startOffset();
369             if (divot > ExpressionRangeInfo::MaxDivot) {
370                 // Overflow has occurred, we can only give line number info for errors for this region
371                 divot = 0;
372                 startOffset = 0;
373                 endOffset = 0;
374             } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
375                 // If the start offset is out of bounds we clear both offsets
376                 // so we only get the divot marker.  Error message will have to be reduced
377                 // to line and column number.
378                 startOffset = 0;
379                 endOffset = 0;
380             } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
381                 // The end offset is only used for additional context, and is much more likely
382                 // to overflow (eg. function call arguments) so we are willing to drop it without
383                 // dropping the rest of the range.
384                 endOffset = 0;
385             }
386             
387             ExpressionRangeInfo info;
388             info.instructionOffset = instructions().size();
389             info.divotPoint = divot;
390             info.startOffset = startOffset;
391             info.endOffset = endOffset;
392             m_codeBlock->addExpressionInfo(info);
393         }
394
395         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
396         {
397             return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
398         }
399
400         ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
401         {
402             if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
403                 PassRefPtr<RegisterID> dst = newTemporary();
404                 emitNode(dst.get(), n);
405                 return dst;
406             }
407
408             return emitNode(n);
409         }
410
411         RegisterID* emitLoad(RegisterID* dst, bool);
412         RegisterID* emitLoad(RegisterID* dst, double);
413         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
414         RegisterID* emitLoad(RegisterID* dst, JSValue);
415         RegisterID* emitLoadGlobalObject(RegisterID* dst);
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* emitCreateThis(RegisterID* dst);
423         RegisterID* emitNewObject(RegisterID* dst);
424         RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
425
426         RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body);
427         RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body);
428         RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck);
429         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
430         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
431
432         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
433
434         RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src); }
435         RegisterID* emitPreInc(RegisterID* srcDst);
436         RegisterID* emitPreDec(RegisterID* srcDst);
437         RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
438         RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
439
440         void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
441         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
442         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
443         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
444
445         RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&, const Identifier&);
446         RegisterID* emitPutStaticVar(const ResolveResult&, const Identifier&, RegisterID* value);
447         RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value);
448
449         RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
450         RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
451         RegisterID* emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property, NonlocalResolveInfo&);
452         RegisterID* emitResolveWithBaseForPut(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property, NonlocalResolveInfo&);
453         RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
454
455         RegisterID* emitPutToBase(RegisterID* base, const Identifier&, RegisterID* value, NonlocalResolveInfo&);
456
457         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
458         RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
459         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
460         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
461         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
462         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
463         RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
464         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
465         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
466         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
467         void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
468         
469         ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
470         RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
471         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
472         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, unsigned divot, unsigned startOffset, unsigned endOffset);
473         RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
474
475         RegisterID* emitReturn(RegisterID* src);
476         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
477
478         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
479         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
480         void emitToPrimitive(RegisterID* dst, RegisterID* src);
481
482         PassRefPtr<Label> emitLabel(Label*);
483         void emitLoopHint();
484         PassRefPtr<Label> emitJump(Label* target);
485         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
486         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
487         PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
488         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
489         PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
490
491         RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
492         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
493
494         void emitReadOnlyExceptionIfNeeded();
495
496         // Start a try block. 'start' must have been emitted.
497         TryData* pushTry(Label* start);
498         // End a try block. 'end' must have been emitted.
499         RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end);
500
501         void emitThrow(RegisterID* exc)
502         { 
503             m_usesExceptions = true;
504             emitUnaryNoDstOp(op_throw, exc);
505         }
506
507         void emitThrowReferenceError(const String& message);
508
509         void emitPushNameScope(const Identifier& property, RegisterID* value, unsigned attributes);
510
511         RegisterID* emitPushWithScope(RegisterID* scope);
512         void emitPopScope();
513
514         void emitDebugHook(DebugHookID, int firstLine, int lastLine, int column);
515
516         int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
517         bool hasFinaliser() { return m_finallyDepth != 0; }
518
519         void pushFinallyContext(StatementNode* finallyBlock);
520         void popFinallyContext();
521
522         void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
523         {
524             ForInContext context = { expectedBase, iter, index, propertyRegister };
525             m_forInContextStack.append(context);
526         }
527
528         void popOptimisedForIn()
529         {
530             m_forInContextStack.removeLast();
531         }
532
533         LabelScope* breakTarget(const Identifier&);
534         LabelScope* continueTarget(const Identifier&);
535
536         void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
537         void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
538
539         CodeType codeType() const { return m_codeType; }
540
541         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
542         
543         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
544
545     private:
546         friend class Label;
547         
548         void emitOpcode(OpcodeID);
549         UnlinkedArrayAllocationProfile newArrayAllocationProfile();
550         UnlinkedObjectAllocationProfile newObjectAllocationProfile();
551         UnlinkedArrayProfile newArrayProfile();
552         UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
553         int kill(RegisterID* dst)
554         {
555             int index = dst->index();
556             m_staticPropertyAnalyzer.kill(index);
557             return index;
558         }
559
560         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
561         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
562         ALWAYS_INLINE void rewindBinaryOp();
563         ALWAYS_INLINE void rewindUnaryOp();
564
565         PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
566
567         typedef HashMap<double, JSValue> NumberMap;
568         typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
569         typedef struct {
570             int resolveOperations;
571             int putOperations;
572         } ResolveCacheEntry;
573         typedef HashMap<StringImpl*, ResolveCacheEntry, IdentifierRepHash> IdentifierResolvePutMap;
574         typedef HashMap<StringImpl*, uint32_t, IdentifierRepHash> IdentifierResolveMap;
575         
576         // Helper for emitCall() and emitConstruct(). This works because the set of
577         // expected functions have identical behavior for both call and construct
578         // (i.e. "Object()" is identical to "new Object()").
579         ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
580         
581         RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
582
583         RegisterID* newRegister();
584
585         // Adds a var slot and maps it to the name ident in symbolTable().
586         RegisterID* addVar(const Identifier& ident, bool isConstant)
587         {
588             RegisterID* local;
589             addVar(ident, isConstant, local);
590             return local;
591         }
592
593         // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
594         bool addVar(const Identifier&, bool isConstant, RegisterID*&);
595         
596         // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
597         RegisterID* addVar()
598         {
599             ++m_codeBlock->m_numVars;
600             return newRegister();
601         }
602
603         // Returns the index of the added var.
604         void addParameter(const Identifier&, int parameterIndex);
605         RegisterID* resolveCallee(FunctionBodyNode*);
606         void addCallee(FunctionBodyNode*, RegisterID*);
607
608         void preserveLastVar();
609         bool shouldAvoidResolveGlobal();
610
611         RegisterID& registerFor(int index)
612         {
613             if (index >= 0)
614                 return m_calleeRegisters[index];
615
616             if (index == JSStack::Callee)
617                 return m_calleeRegister;
618
619             ASSERT(m_parameters.size());
620             return m_parameters[index + m_parameters.size() + JSStack::CallFrameHeaderSize];
621         }
622
623         unsigned addConstant(const Identifier&);
624         RegisterID* addConstantValue(JSValue);
625         RegisterID* addConstantEmptyValue();
626         unsigned addRegExp(RegExp*);
627
628         unsigned addConstantBuffer(unsigned length);
629         
630         UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
631         {
632             return UnlinkedFunctionExecutable::create(m_globalData, m_scopeNode->source(), body);
633         }
634
635         JSString* addStringConstant(const Identifier&);
636
637         void addLineInfo(unsigned lineNo)
638         {
639             m_codeBlock->addLineInfo(instructions().size(), lineNo - m_scopeNode->firstLine());
640         }
641
642         RegisterID* emitInitLazyRegister(RegisterID*);
643
644     public:
645         Vector<UnlinkedInstruction>& instructions() { return m_instructions; }
646
647         SharedSymbolTable& symbolTable() { return *m_symbolTable; }
648
649         bool shouldOptimizeLocals()
650         {
651             if (m_dynamicScopeDepth)
652                 return false;
653
654             if (m_codeType != FunctionCode)
655                 return false;
656
657             return true;
658         }
659
660         bool canOptimizeNonLocals()
661         {
662             if (m_dynamicScopeDepth)
663                 return false;
664
665             if (m_codeType == EvalCode)
666                 return false;
667
668             if (m_codeType == FunctionCode && m_codeBlock->usesEval())
669                 return false;
670
671             return true;
672         }
673
674         RegisterID* emitThrowExpressionTooDeepException();
675
676         void createArgumentsIfNecessary();
677         void createActivationIfNecessary();
678         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
679         
680         Vector<UnlinkedInstruction> m_instructions;
681
682         bool m_shouldEmitDebugHooks;
683         bool m_shouldEmitProfileHooks;
684
685         SharedSymbolTable* m_symbolTable;
686
687         ScopeNode* m_scopeNode;
688         Strong<JSScope> m_scope;
689         Strong<UnlinkedCodeBlock> m_codeBlock;
690
691         // Some of these objects keep pointers to one another. They are arranged
692         // to ensure a sane destruction order that avoids references to freed memory.
693         HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
694         RegisterID m_ignoredResultRegister;
695         RegisterID m_thisRegister;
696         RegisterID m_calleeRegister;
697         RegisterID* m_activationRegister;
698         RegisterID* m_emptyValueRegister;
699         RegisterID* m_globalObjectRegister;
700         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
701         SegmentedVector<RegisterID, 32> m_calleeRegisters;
702         SegmentedVector<RegisterID, 32> m_parameters;
703         SegmentedVector<Label, 32> m_labels;
704         LabelScopeStore m_labelScopes;
705         RefPtr<RegisterID> m_lastVar;
706         int m_finallyDepth;
707         int m_dynamicScopeDepth;
708         CodeType m_codeType;
709
710         Vector<ControlFlowContext> m_scopeContextStack;
711         Vector<SwitchInfo> m_switchContextStack;
712         Vector<ForInContext> m_forInContextStack;
713         Vector<TryContext> m_tryContextStack;
714         
715         Vector<TryRange> m_tryRanges;
716         SegmentedVector<TryData, 8> m_tryData;
717
718         int m_firstConstantIndex;
719         int m_nextConstantOffset;
720         unsigned m_globalConstantIndex;
721
722         int m_globalVarStorageOffset;
723
724         bool m_hasCreatedActivation;
725         int m_firstLazyFunction;
726         int m_lastLazyFunction;
727         HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
728         typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
729         FunctionOffsetMap m_functionOffsets;
730         
731         // Constant pool
732         IdentifierMap m_identifierMap;
733         JSValueMap m_jsValueMap;
734         NumberMap m_numberMap;
735         IdentifierStringMap m_stringMap;
736
737         uint32_t getResolveOperations(const Identifier& property)
738         {
739             if (m_dynamicScopeDepth)
740                 return m_codeBlock->addResolve();
741             IdentifierResolveMap::AddResult result = m_resolveCacheMap.add(property.impl(), 0);
742             if (result.isNewEntry)
743                 result.iterator->value = m_codeBlock->addResolve();
744             return result.iterator->value;
745         }
746
747         uint32_t getResolveWithThisOperations(const Identifier& property)
748         {
749             if (m_dynamicScopeDepth)
750                 return m_codeBlock->addResolve();
751             IdentifierResolveMap::AddResult result = m_resolveWithThisCacheMap.add(property.impl(), 0);
752             if (result.isNewEntry)
753                 result.iterator->value = m_codeBlock->addResolve();
754             return result.iterator->value;
755         }
756
757         uint32_t getResolveBaseOperations(IdentifierResolvePutMap& map, const Identifier& property, uint32_t& putToBaseOperation)
758         {
759             if (m_dynamicScopeDepth) {
760                 putToBaseOperation = m_codeBlock->addPutToBase();
761                 return m_codeBlock->addResolve();
762             }
763             ResolveCacheEntry entry = {-1, -1};
764             IdentifierResolvePutMap::AddResult result = map.add(property.impl(), entry);
765             if (result.isNewEntry)
766                 result.iterator->value.resolveOperations = m_codeBlock->addResolve();
767             if (result.iterator->value.putOperations == -1)
768                 result.iterator->value.putOperations = getPutToBaseOperation(property);
769             putToBaseOperation = result.iterator->value.putOperations;
770             return result.iterator->value.resolveOperations;
771         }
772
773         uint32_t getResolveBaseOperations(const Identifier& property)
774         {
775             uint32_t scratch;
776             return getResolveBaseOperations(m_resolveBaseMap, property, scratch);
777         }
778
779         uint32_t getResolveBaseForPutOperations(const Identifier& property, uint32_t& putToBaseOperation)
780         {
781             return getResolveBaseOperations(m_resolveBaseForPutMap, property, putToBaseOperation);
782         }
783
784         uint32_t getResolveWithBaseForPutOperations(const Identifier& property, uint32_t& putToBaseOperation)
785         {
786             return getResolveBaseOperations(m_resolveWithBaseForPutMap, property, putToBaseOperation);
787         }
788
789         uint32_t getPutToBaseOperation(const Identifier& property)
790         {
791             if (m_dynamicScopeDepth)
792                 return m_codeBlock->addPutToBase();
793             IdentifierResolveMap::AddResult result = m_putToBaseMap.add(property.impl(), 0);
794             if (result.isNewEntry)
795                 result.iterator->value = m_codeBlock->addPutToBase();
796             return result.iterator->value;
797         }
798
799         IdentifierResolveMap m_putToBaseMap;
800         IdentifierResolveMap m_resolveCacheMap;
801         IdentifierResolveMap m_resolveWithThisCacheMap;
802         IdentifierResolvePutMap m_resolveBaseMap;
803         IdentifierResolvePutMap m_resolveBaseForPutMap;
804         IdentifierResolvePutMap m_resolveWithBaseForPutMap;
805
806         StaticPropertyAnalyzer m_staticPropertyAnalyzer;
807
808         JSGlobalData* m_globalData;
809
810         OpcodeID m_lastOpcodeID;
811 #ifndef NDEBUG
812         size_t m_lastOpcodePosition;
813 #endif
814
815         StackBounds m_stack;
816
817         bool m_usesExceptions;
818         bool m_expressionTooDeep;
819     };
820
821 }
822
823 #endif // BytecodeGenerator_h