a308d83ae2d14e5690e05c3ebae58e8986f53276
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / full-codegen.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_FULL_CODEGEN_H_
29 #define V8_FULL_CODEGEN_H_
30
31 #include "v8.h"
32
33 #include "allocation.h"
34 #include "ast.h"
35 #include "code-stubs.h"
36 #include "codegen.h"
37 #include "compiler.h"
38
39 namespace v8 {
40 namespace internal {
41
42 // Forward declarations.
43 class JumpPatchSite;
44
45 // AST node visitor which can tell whether a given statement will be breakable
46 // when the code is compiled by the full compiler in the debugger. This means
47 // that there will be an IC (load/store/call) in the code generated for the
48 // debugger to piggybag on.
49 class BreakableStatementChecker: public AstVisitor {
50  public:
51   BreakableStatementChecker() : is_breakable_(false) {}
52
53   void Check(Statement* stmt);
54   void Check(Expression* stmt);
55
56   bool is_breakable() { return is_breakable_; }
57
58  private:
59   // AST node visit functions.
60 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
61   AST_NODE_LIST(DECLARE_VISIT)
62 #undef DECLARE_VISIT
63
64   bool is_breakable_;
65
66   DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
67 };
68
69
70 // -----------------------------------------------------------------------------
71 // Full code generator.
72
73 class FullCodeGenerator: public AstVisitor {
74  public:
75   enum State {
76     NO_REGISTERS,
77     TOS_REG
78   };
79
80   FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info)
81       : masm_(masm),
82         info_(info),
83         scope_(info->scope()),
84         nesting_stack_(NULL),
85         loop_depth_(0),
86         global_count_(0),
87         context_(NULL),
88         bailout_entries_(info->HasDeoptimizationSupport()
89                          ? info->function()->ast_node_count() : 0),
90         stack_checks_(2),  // There's always at least one.
91         type_feedback_cells_(info->HasDeoptimizationSupport()
92                              ? info->function()->ast_node_count() : 0),
93         ic_total_count_(0) { }
94
95   static bool MakeCode(CompilationInfo* info);
96
97   // Encode state and pc-offset as a BitField<type, start, size>.
98   // Only use 30 bits because we encode the result as a smi.
99   class StateField : public BitField<State, 0, 1> { };
100   class PcField    : public BitField<unsigned, 1, 30-1> { };
101
102   static const char* State2String(State state) {
103     switch (state) {
104       case NO_REGISTERS: return "NO_REGISTERS";
105       case TOS_REG: return "TOS_REG";
106     }
107     UNREACHABLE();
108     return NULL;
109   }
110
111  private:
112   class Breakable;
113   class Iteration;
114
115   class TestContext;
116
117   class NestedStatement BASE_EMBEDDED {
118    public:
119     explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
120       // Link into codegen's nesting stack.
121       previous_ = codegen->nesting_stack_;
122       codegen->nesting_stack_ = this;
123     }
124     virtual ~NestedStatement() {
125       // Unlink from codegen's nesting stack.
126       ASSERT_EQ(this, codegen_->nesting_stack_);
127       codegen_->nesting_stack_ = previous_;
128     }
129
130     virtual Breakable* AsBreakable() { return NULL; }
131     virtual Iteration* AsIteration() { return NULL; }
132
133     virtual bool IsContinueTarget(Statement* target) { return false; }
134     virtual bool IsBreakTarget(Statement* target) { return false; }
135
136     // Notify the statement that we are exiting it via break, continue, or
137     // return and give it a chance to generate cleanup code.  Return the
138     // next outer statement in the nesting stack.  We accumulate in
139     // *stack_depth the amount to drop the stack and in *context_length the
140     // number of context chain links to unwind as we traverse the nesting
141     // stack from an exit to its target.
142     virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
143       return previous_;
144     }
145
146    protected:
147     MacroAssembler* masm() { return codegen_->masm(); }
148
149     FullCodeGenerator* codegen_;
150     NestedStatement* previous_;
151
152    private:
153     DISALLOW_COPY_AND_ASSIGN(NestedStatement);
154   };
155
156   // A breakable statement such as a block.
157   class Breakable : public NestedStatement {
158    public:
159     Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
160         : NestedStatement(codegen), statement_(statement) {
161     }
162     virtual ~Breakable() {}
163
164     virtual Breakable* AsBreakable() { return this; }
165     virtual bool IsBreakTarget(Statement* target) {
166       return statement() == target;
167     }
168
169     BreakableStatement* statement() { return statement_; }
170     Label* break_label() { return &break_label_; }
171
172    private:
173     BreakableStatement* statement_;
174     Label break_label_;
175   };
176
177   // An iteration statement such as a while, for, or do loop.
178   class Iteration : public Breakable {
179    public:
180     Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
181         : Breakable(codegen, statement) {
182     }
183     virtual ~Iteration() {}
184
185     virtual Iteration* AsIteration() { return this; }
186     virtual bool IsContinueTarget(Statement* target) {
187       return statement() == target;
188     }
189
190     Label* continue_label() { return &continue_label_; }
191
192    private:
193     Label continue_label_;
194   };
195
196   // A nested block statement.
197   class NestedBlock : public Breakable {
198    public:
199     NestedBlock(FullCodeGenerator* codegen, Block* block)
200         : Breakable(codegen, block) {
201     }
202     virtual ~NestedBlock() {}
203
204     virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
205       if (statement()->AsBlock()->block_scope() != NULL) {
206         ++(*context_length);
207       }
208       return previous_;
209     };
210   };
211
212   // The try block of a try/catch statement.
213   class TryCatch : public NestedStatement {
214    public:
215     explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
216     }
217     virtual ~TryCatch() {}
218
219     virtual NestedStatement* Exit(int* stack_depth, int* context_length);
220   };
221
222   // The try block of a try/finally statement.
223   class TryFinally : public NestedStatement {
224    public:
225     TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
226         : NestedStatement(codegen), finally_entry_(finally_entry) {
227     }
228     virtual ~TryFinally() {}
229
230     virtual NestedStatement* Exit(int* stack_depth, int* context_length);
231
232    private:
233     Label* finally_entry_;
234   };
235
236   // The finally block of a try/finally statement.
237   class Finally : public NestedStatement {
238    public:
239     static const int kElementCount = 2;
240
241     explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
242     virtual ~Finally() {}
243
244     virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
245       *stack_depth += kElementCount;
246       return previous_;
247     }
248   };
249
250   // The body of a for/in loop.
251   class ForIn : public Iteration {
252    public:
253     static const int kElementCount = 5;
254
255     ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
256         : Iteration(codegen, statement) {
257     }
258     virtual ~ForIn() {}
259
260     virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
261       *stack_depth += kElementCount;
262       return previous_;
263     }
264   };
265
266
267   // The body of a with or catch.
268   class WithOrCatch : public NestedStatement {
269    public:
270     explicit WithOrCatch(FullCodeGenerator* codegen)
271         : NestedStatement(codegen) {
272     }
273     virtual ~WithOrCatch() {}
274
275     virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
276       ++(*context_length);
277       return previous_;
278     }
279   };
280
281   // Type of a member function that generates inline code for a native function.
282   typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
283
284   static const InlineFunctionGenerator kInlineFunctionGenerators[];
285
286   // A platform-specific utility to overwrite the accumulator register
287   // with a GC-safe value.
288   void ClearAccumulator();
289
290   // Determine whether or not to inline the smi case for the given
291   // operation.
292   bool ShouldInlineSmiCase(Token::Value op);
293
294   // Helper function to convert a pure value into a test context.  The value
295   // is expected on the stack or the accumulator, depending on the platform.
296   // See the platform-specific implementation for details.
297   void DoTest(Expression* condition,
298               Label* if_true,
299               Label* if_false,
300               Label* fall_through);
301   void DoTest(const TestContext* context);
302
303   // Helper function to split control flow and avoid a branch to the
304   // fall-through label if it is set up.
305 #ifdef V8_TARGET_ARCH_MIPS
306   void Split(Condition cc,
307              Register lhs,
308              const Operand&  rhs,
309              Label* if_true,
310              Label* if_false,
311              Label* fall_through);
312 #else  // All non-mips arch.
313   void Split(Condition cc,
314              Label* if_true,
315              Label* if_false,
316              Label* fall_through);
317 #endif  // V8_TARGET_ARCH_MIPS
318
319   // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
320   // a register.  Emits a context chain walk if if necessary (so does
321   // SetVar) so avoid calling both on the same variable.
322   void GetVar(Register destination, Variable* var);
323
324   // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable.  If it's in
325   // the context, the write barrier will be emitted and source, scratch0,
326   // scratch1 will be clobbered.  Emits a context chain walk if if necessary
327   // (so does GetVar) so avoid calling both on the same variable.
328   void SetVar(Variable* var,
329               Register source,
330               Register scratch0,
331               Register scratch1);
332
333   // An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
334   // variable.  Writing does not need the write barrier.
335   MemOperand StackOperand(Variable* var);
336
337   // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
338   // variable.  May emit code to traverse the context chain, loading the
339   // found context into the scratch register.  Writing to this operand will
340   // need the write barrier if location is CONTEXT.
341   MemOperand VarOperand(Variable* var, Register scratch);
342
343   void VisitForEffect(Expression* expr) {
344     EffectContext context(this);
345     Visit(expr);
346     PrepareForBailout(expr, NO_REGISTERS);
347   }
348
349   void VisitForAccumulatorValue(Expression* expr) {
350     AccumulatorValueContext context(this);
351     Visit(expr);
352     PrepareForBailout(expr, TOS_REG);
353   }
354
355   void VisitForStackValue(Expression* expr) {
356     StackValueContext context(this);
357     Visit(expr);
358     PrepareForBailout(expr, NO_REGISTERS);
359   }
360
361   void VisitForControl(Expression* expr,
362                        Label* if_true,
363                        Label* if_false,
364                        Label* fall_through) {
365     TestContext context(this, expr, if_true, if_false, fall_through);
366     Visit(expr);
367     // For test contexts, we prepare for bailout before branching, not at
368     // the end of the entire expression.  This happens as part of visiting
369     // the expression.
370   }
371
372   void VisitInDuplicateContext(Expression* expr);
373
374   void VisitDeclarations(ZoneList<Declaration*>* declarations);
375   void DeclareGlobals(Handle<FixedArray> pairs);
376   int DeclareGlobalsFlags();
377
378   // Try to perform a comparison as a fast inlined literal compare if
379   // the operands allow it.  Returns true if the compare operations
380   // has been matched and all code generated; false otherwise.
381   bool TryLiteralCompare(CompareOperation* compare);
382
383   // Platform-specific code for comparing the type of a value with
384   // a given literal string.
385   void EmitLiteralCompareTypeof(Expression* expr,
386                                 Expression* sub_expr,
387                                 Handle<String> check);
388
389   // Platform-specific code for equality comparison with a nil-like value.
390   void EmitLiteralCompareNil(CompareOperation* expr,
391                              Expression* sub_expr,
392                              NilValue nil);
393
394   // Bailout support.
395   void PrepareForBailout(Expression* node, State state);
396   void PrepareForBailoutForId(unsigned id, State state);
397
398   // Cache cell support.  This associates AST ids with global property cells
399   // that will be cleared during GC and collected by the type-feedback oracle.
400   void RecordTypeFeedbackCell(unsigned id, Handle<JSGlobalPropertyCell> cell);
401
402   // Record a call's return site offset, used to rebuild the frame if the
403   // called function was inlined at the site.
404   void RecordJSReturnSite(Call* call);
405
406   // Prepare for bailout before a test (or compare) and branch.  If
407   // should_normalize, then the following comparison will not handle the
408   // canonical JS true value so we will insert a (dead) test against true at
409   // the actual bailout target from the optimized code. If not
410   // should_normalize, the true and false labels are ignored.
411   void PrepareForBailoutBeforeSplit(Expression* expr,
412                                     bool should_normalize,
413                                     Label* if_true,
414                                     Label* if_false);
415
416   // Platform-specific code for a variable, constant, or function
417   // declaration.  Functions have an initial value.
418   // Increments global_count_ for unallocated variables.
419   void EmitDeclaration(VariableProxy* proxy,
420                        VariableMode mode,
421                        FunctionLiteral* function);
422
423   // Platform-specific code for checking the stack limit at the back edge of
424   // a loop.
425   // This is meant to be called at loop back edges, |back_edge_target| is
426   // the jump target of the back edge and is used to approximate the amount
427   // of code inside the loop.
428   void EmitStackCheck(IterationStatement* stmt, Label* back_edge_target);
429   // Record the OSR AST id corresponding to a stack check in the code.
430   void RecordStackCheck(unsigned osr_ast_id);
431   // Emit a table of stack check ids and pcs into the code stream.  Return
432   // the offset of the start of the table.
433   unsigned EmitStackCheckTable();
434
435   void EmitProfilingCounterDecrement(int delta);
436   void EmitProfilingCounterReset();
437
438   // Platform-specific return sequence
439   void EmitReturnSequence();
440
441   // Platform-specific code sequences for calls
442   void EmitCallWithStub(Call* expr, CallFunctionFlags flags);
443   void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
444   void EmitKeyedCallWithIC(Call* expr, Expression* key);
445
446   // Platform-specific code for inline runtime calls.
447   InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id);
448
449   void EmitInlineRuntimeCall(CallRuntime* expr);
450
451 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
452   void Emit##name(CallRuntime* expr);
453   INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
454   INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
455 #undef EMIT_INLINE_RUNTIME_CALL
456
457   // Platform-specific code for loading variables.
458   void EmitLoadGlobalCheckExtensions(Variable* var,
459                                      TypeofState typeof_state,
460                                      Label* slow);
461   MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow);
462   void EmitDynamicLookupFastCase(Variable* var,
463                                  TypeofState typeof_state,
464                                  Label* slow,
465                                  Label* done);
466   void EmitVariableLoad(VariableProxy* proxy);
467
468   void EmitAccessor(Expression* expression);
469
470   // Expects the arguments and the function already pushed.
471   void EmitResolvePossiblyDirectEval(int arg_count);
472
473   // Platform-specific support for allocating a new closure based on
474   // the given function info.
475   void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
476
477   // Platform-specific support for compiling assignments.
478
479   // Load a value from a named property.
480   // The receiver is left on the stack by the IC.
481   void EmitNamedPropertyLoad(Property* expr);
482
483   // Load a value from a keyed property.
484   // The receiver and the key is left on the stack by the IC.
485   void EmitKeyedPropertyLoad(Property* expr);
486
487   // Apply the compound assignment operator. Expects the left operand on top
488   // of the stack and the right one in the accumulator.
489   void EmitBinaryOp(BinaryOperation* expr,
490                     Token::Value op,
491                     OverwriteMode mode);
492
493   // Helper functions for generating inlined smi code for certain
494   // binary operations.
495   void EmitInlineSmiBinaryOp(BinaryOperation* expr,
496                              Token::Value op,
497                              OverwriteMode mode,
498                              Expression* left,
499                              Expression* right);
500
501   // Assign to the given expression as if via '='. The right-hand-side value
502   // is expected in the accumulator.
503   void EmitAssignment(Expression* expr);
504
505   // Complete a variable assignment.  The right-hand-side value is expected
506   // in the accumulator.
507   void EmitVariableAssignment(Variable* var,
508                               Token::Value op);
509
510   // Complete a named property assignment.  The receiver is expected on top
511   // of the stack and the right-hand-side value in the accumulator.
512   void EmitNamedPropertyAssignment(Assignment* expr);
513
514   // Complete a keyed property assignment.  The receiver and key are
515   // expected on top of the stack and the right-hand-side value in the
516   // accumulator.
517   void EmitKeyedPropertyAssignment(Assignment* expr);
518
519   void CallIC(Handle<Code> code,
520               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
521               unsigned ast_id = kNoASTId);
522
523   void SetFunctionPosition(FunctionLiteral* fun);
524   void SetReturnPosition(FunctionLiteral* fun);
525   void SetStatementPosition(Statement* stmt);
526   void SetExpressionPosition(Expression* expr, int pos);
527   void SetStatementPosition(int pos);
528   void SetSourcePosition(int pos);
529
530   // Non-local control flow support.
531   void EnterFinallyBlock();
532   void ExitFinallyBlock();
533
534   // Loop nesting counter.
535   int loop_depth() { return loop_depth_; }
536   void increment_loop_depth() { loop_depth_++; }
537   void decrement_loop_depth() {
538     ASSERT(loop_depth_ > 0);
539     loop_depth_--;
540   }
541
542   MacroAssembler* masm() { return masm_; }
543
544   class ExpressionContext;
545   const ExpressionContext* context() { return context_; }
546   void set_new_context(const ExpressionContext* context) { context_ = context; }
547
548   Handle<Script> script() { return info_->script(); }
549   bool is_eval() { return info_->is_eval(); }
550   bool is_native() { return info_->is_native(); }
551   bool is_classic_mode() {
552     return language_mode() == CLASSIC_MODE;
553   }
554   LanguageMode language_mode() {
555     return function()->language_mode();
556   }
557   FunctionLiteral* function() { return info_->function(); }
558   Scope* scope() { return scope_; }
559
560   static Register result_register();
561   static Register context_register();
562
563   // Set fields in the stack frame. Offsets are the frame pointer relative
564   // offsets defined in, e.g., StandardFrameConstants.
565   void StoreToFrameField(int frame_offset, Register value);
566
567   // Load a value from the current context. Indices are defined as an enum
568   // in v8::internal::Context.
569   void LoadContextField(Register dst, int context_index);
570
571   // Push the function argument for the runtime functions PushWithContext
572   // and PushCatchContext.
573   void PushFunctionArgumentForContextAllocation();
574
575   // AST node visit functions.
576 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
577   AST_NODE_LIST(DECLARE_VISIT)
578 #undef DECLARE_VISIT
579
580   void EmitUnaryOperation(UnaryOperation* expr, const char* comment);
581
582   void VisitComma(BinaryOperation* expr);
583   void VisitLogicalExpression(BinaryOperation* expr);
584   void VisitArithmeticExpression(BinaryOperation* expr);
585
586   void VisitForTypeofValue(Expression* expr);
587
588   void Generate();
589   void PopulateDeoptimizationData(Handle<Code> code);
590   void PopulateTypeFeedbackInfo(Handle<Code> code);
591   void PopulateTypeFeedbackCells(Handle<Code> code);
592
593   Handle<FixedArray> handler_table() { return handler_table_; }
594
595   struct BailoutEntry {
596     unsigned id;
597     unsigned pc_and_state;
598   };
599
600   struct TypeFeedbackCellEntry {
601     unsigned ast_id;
602     Handle<JSGlobalPropertyCell> cell;
603   };
604
605
606   class ExpressionContext BASE_EMBEDDED {
607    public:
608     explicit ExpressionContext(FullCodeGenerator* codegen)
609         : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
610       codegen->set_new_context(this);
611     }
612
613     virtual ~ExpressionContext() {
614       codegen_->set_new_context(old_);
615     }
616
617     Isolate* isolate() const { return codegen_->isolate(); }
618
619     // Convert constant control flow (true or false) to the result expected for
620     // this expression context.
621     virtual void Plug(bool flag) const = 0;
622
623     // Emit code to convert a pure value (in a register, known variable
624     // location, as a literal, or on top of the stack) into the result
625     // expected according to this expression context.
626     virtual void Plug(Register reg) const = 0;
627     virtual void Plug(Variable* var) const = 0;
628     virtual void Plug(Handle<Object> lit) const = 0;
629     virtual void Plug(Heap::RootListIndex index) const = 0;
630     virtual void PlugTOS() const = 0;
631
632     // Emit code to convert pure control flow to a pair of unbound labels into
633     // the result expected according to this expression context.  The
634     // implementation will bind both labels unless it's a TestContext, which
635     // won't bind them at this point.
636     virtual void Plug(Label* materialize_true,
637                       Label* materialize_false) const = 0;
638
639     // Emit code to discard count elements from the top of stack, then convert
640     // a pure value into the result expected according to this expression
641     // context.
642     virtual void DropAndPlug(int count, Register reg) const = 0;
643
644     // Set up branch labels for a test expression.  The three Label** parameters
645     // are output parameters.
646     virtual void PrepareTest(Label* materialize_true,
647                              Label* materialize_false,
648                              Label** if_true,
649                              Label** if_false,
650                              Label** fall_through) const = 0;
651
652     // Returns true if we are evaluating only for side effects (i.e. if the
653     // result will be discarded).
654     virtual bool IsEffect() const { return false; }
655
656     // Returns true if we are evaluating for the value (in accu/on stack).
657     virtual bool IsAccumulatorValue() const { return false; }
658     virtual bool IsStackValue() const { return false; }
659
660     // Returns true if we are branching on the value rather than materializing
661     // it.  Only used for asserts.
662     virtual bool IsTest() const { return false; }
663
664    protected:
665     FullCodeGenerator* codegen() const { return codegen_; }
666     MacroAssembler* masm() const { return masm_; }
667     MacroAssembler* masm_;
668
669    private:
670     const ExpressionContext* old_;
671     FullCodeGenerator* codegen_;
672   };
673
674   class AccumulatorValueContext : public ExpressionContext {
675    public:
676     explicit AccumulatorValueContext(FullCodeGenerator* codegen)
677         : ExpressionContext(codegen) { }
678
679     virtual void Plug(bool flag) const;
680     virtual void Plug(Register reg) const;
681     virtual void Plug(Label* materialize_true, Label* materialize_false) const;
682     virtual void Plug(Variable* var) const;
683     virtual void Plug(Handle<Object> lit) const;
684     virtual void Plug(Heap::RootListIndex) const;
685     virtual void PlugTOS() const;
686     virtual void DropAndPlug(int count, Register reg) const;
687     virtual void PrepareTest(Label* materialize_true,
688                              Label* materialize_false,
689                              Label** if_true,
690                              Label** if_false,
691                              Label** fall_through) const;
692     virtual bool IsAccumulatorValue() const { return true; }
693   };
694
695   class StackValueContext : public ExpressionContext {
696    public:
697     explicit StackValueContext(FullCodeGenerator* codegen)
698         : ExpressionContext(codegen) { }
699
700     virtual void Plug(bool flag) const;
701     virtual void Plug(Register reg) const;
702     virtual void Plug(Label* materialize_true, Label* materialize_false) const;
703     virtual void Plug(Variable* var) const;
704     virtual void Plug(Handle<Object> lit) const;
705     virtual void Plug(Heap::RootListIndex) const;
706     virtual void PlugTOS() const;
707     virtual void DropAndPlug(int count, Register reg) const;
708     virtual void PrepareTest(Label* materialize_true,
709                              Label* materialize_false,
710                              Label** if_true,
711                              Label** if_false,
712                              Label** fall_through) const;
713     virtual bool IsStackValue() const { return true; }
714   };
715
716   class TestContext : public ExpressionContext {
717    public:
718     TestContext(FullCodeGenerator* codegen,
719                 Expression* condition,
720                 Label* true_label,
721                 Label* false_label,
722                 Label* fall_through)
723         : ExpressionContext(codegen),
724           condition_(condition),
725           true_label_(true_label),
726           false_label_(false_label),
727           fall_through_(fall_through) { }
728
729     static const TestContext* cast(const ExpressionContext* context) {
730       ASSERT(context->IsTest());
731       return reinterpret_cast<const TestContext*>(context);
732     }
733
734     Expression* condition() const { return condition_; }
735     Label* true_label() const { return true_label_; }
736     Label* false_label() const { return false_label_; }
737     Label* fall_through() const { return fall_through_; }
738
739     virtual void Plug(bool flag) const;
740     virtual void Plug(Register reg) const;
741     virtual void Plug(Label* materialize_true, Label* materialize_false) const;
742     virtual void Plug(Variable* var) const;
743     virtual void Plug(Handle<Object> lit) const;
744     virtual void Plug(Heap::RootListIndex) const;
745     virtual void PlugTOS() const;
746     virtual void DropAndPlug(int count, Register reg) const;
747     virtual void PrepareTest(Label* materialize_true,
748                              Label* materialize_false,
749                              Label** if_true,
750                              Label** if_false,
751                              Label** fall_through) const;
752     virtual bool IsTest() const { return true; }
753
754    private:
755     Expression* condition_;
756     Label* true_label_;
757     Label* false_label_;
758     Label* fall_through_;
759   };
760
761   class EffectContext : public ExpressionContext {
762    public:
763     explicit EffectContext(FullCodeGenerator* codegen)
764         : ExpressionContext(codegen) { }
765
766     virtual void Plug(bool flag) const;
767     virtual void Plug(Register reg) const;
768     virtual void Plug(Label* materialize_true, Label* materialize_false) const;
769     virtual void Plug(Variable* var) const;
770     virtual void Plug(Handle<Object> lit) const;
771     virtual void Plug(Heap::RootListIndex) const;
772     virtual void PlugTOS() const;
773     virtual void DropAndPlug(int count, Register reg) const;
774     virtual void PrepareTest(Label* materialize_true,
775                              Label* materialize_false,
776                              Label** if_true,
777                              Label** if_false,
778                              Label** fall_through) const;
779     virtual bool IsEffect() const { return true; }
780   };
781
782   MacroAssembler* masm_;
783   CompilationInfo* info_;
784   Scope* scope_;
785   Label return_label_;
786   NestedStatement* nesting_stack_;
787   int loop_depth_;
788   int global_count_;
789   const ExpressionContext* context_;
790   ZoneList<BailoutEntry> bailout_entries_;
791   ZoneList<BailoutEntry> stack_checks_;
792   ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
793   int ic_total_count_;
794   Handle<FixedArray> handler_table_;
795   Handle<JSGlobalPropertyCell> profiling_counter_;
796
797   friend class NestedStatement;
798
799   DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
800 };
801
802
803 // A map from property names to getter/setter pairs allocated in the zone.
804 class AccessorTable: public TemplateHashMap<Literal,
805                                             ObjectLiteral::Accessors,
806                                             ZoneListAllocationPolicy> {
807  public:
808   explicit AccessorTable(Zone* zone) :
809       TemplateHashMap<Literal,
810                       ObjectLiteral::Accessors,
811                       ZoneListAllocationPolicy>(Literal::Match),
812       zone_(zone) { }
813
814   Iterator lookup(Literal* literal) {
815     Iterator it = find(literal, true);
816     if (it->second == NULL) it->second = new(zone_) ObjectLiteral::Accessors();
817     return it;
818   }
819
820  private:
821   Zone* zone_;
822 };
823
824
825 } }  // namespace v8::internal
826
827 #endif  // V8_FULL_CODEGEN_H_