• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2009 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 "ast.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 class FullCodeGenSyntaxChecker: public AstVisitor {
39  public:
FullCodeGenSyntaxChecker()40   FullCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
41 
42   void Check(FunctionLiteral* fun);
43 
has_supported_syntax()44   bool has_supported_syntax() { return has_supported_syntax_; }
45 
46  private:
47   void VisitDeclarations(ZoneList<Declaration*>* decls);
48   void VisitStatements(ZoneList<Statement*>* stmts);
49 
50   // AST node visit functions.
51 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
52   AST_NODE_LIST(DECLARE_VISIT)
53 #undef DECLARE_VISIT
54 
55   bool has_supported_syntax_;
56 
57   DISALLOW_COPY_AND_ASSIGN(FullCodeGenSyntaxChecker);
58 };
59 
60 
61 // -----------------------------------------------------------------------------
62 // Full code generator.
63 
64 class FullCodeGenerator: public AstVisitor {
65  public:
66   enum Mode {
67     PRIMARY,
68     SECONDARY
69   };
70 
FullCodeGenerator(MacroAssembler * masm)71   explicit FullCodeGenerator(MacroAssembler* masm)
72       : masm_(masm),
73         info_(NULL),
74         nesting_stack_(NULL),
75         loop_depth_(0),
76         location_(kStack),
77         true_label_(NULL),
78         false_label_(NULL) {
79   }
80 
81   static Handle<Code> MakeCode(CompilationInfo* info);
82 
83   void Generate(CompilationInfo* info, Mode mode);
84 
85  private:
86   class Breakable;
87   class Iteration;
88   class TryCatch;
89   class TryFinally;
90   class Finally;
91   class ForIn;
92 
93   class NestedStatement BASE_EMBEDDED {
94    public:
NestedStatement(FullCodeGenerator * codegen)95     explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
96       // Link into codegen's nesting stack.
97       previous_ = codegen->nesting_stack_;
98       codegen->nesting_stack_ = this;
99     }
~NestedStatement()100     virtual ~NestedStatement() {
101       // Unlink from codegen's nesting stack.
102       ASSERT_EQ(this, codegen_->nesting_stack_);
103       codegen_->nesting_stack_ = previous_;
104     }
105 
AsBreakable()106     virtual Breakable* AsBreakable() { return NULL; }
AsIteration()107     virtual Iteration* AsIteration() { return NULL; }
AsTryCatch()108     virtual TryCatch* AsTryCatch() { return NULL; }
AsTryFinally()109     virtual TryFinally* AsTryFinally() { return NULL; }
AsFinally()110     virtual Finally* AsFinally() { return NULL; }
AsForIn()111     virtual ForIn* AsForIn() { return NULL; }
112 
IsContinueTarget(Statement * target)113     virtual bool IsContinueTarget(Statement* target) { return false; }
IsBreakTarget(Statement * target)114     virtual bool IsBreakTarget(Statement* target) { return false; }
115 
116     // Generate code to leave the nested statement. This includes
117     // cleaning up any stack elements in use and restoring the
118     // stack to the expectations of the surrounding statements.
119     // Takes a number of stack elements currently on top of the
120     // nested statement's stack, and returns a number of stack
121     // elements left on top of the surrounding statement's stack.
122     // The generated code must preserve the result register (which
123     // contains the value in case of a return).
Exit(int stack_depth)124     virtual int Exit(int stack_depth) {
125       // Default implementation for the case where there is
126       // nothing to clean up.
127       return stack_depth;
128     }
outer()129     NestedStatement* outer() { return previous_; }
130    protected:
masm()131     MacroAssembler* masm() { return codegen_->masm(); }
132    private:
133     FullCodeGenerator* codegen_;
134     NestedStatement* previous_;
135     DISALLOW_COPY_AND_ASSIGN(NestedStatement);
136   };
137 
138   class Breakable : public NestedStatement {
139    public:
Breakable(FullCodeGenerator * codegen,BreakableStatement * break_target)140     Breakable(FullCodeGenerator* codegen,
141               BreakableStatement* break_target)
142         : NestedStatement(codegen),
143           target_(break_target) {}
~Breakable()144     virtual ~Breakable() {}
AsBreakable()145     virtual Breakable* AsBreakable() { return this; }
IsBreakTarget(Statement * statement)146     virtual bool IsBreakTarget(Statement* statement) {
147       return target_ == statement;
148     }
statement()149     BreakableStatement* statement() { return target_; }
break_target()150     Label* break_target() { return &break_target_label_; }
151    private:
152     BreakableStatement* target_;
153     Label break_target_label_;
154     DISALLOW_COPY_AND_ASSIGN(Breakable);
155   };
156 
157   class Iteration : public Breakable {
158    public:
Iteration(FullCodeGenerator * codegen,IterationStatement * iteration_statement)159     Iteration(FullCodeGenerator* codegen,
160               IterationStatement* iteration_statement)
161         : Breakable(codegen, iteration_statement) {}
~Iteration()162     virtual ~Iteration() {}
AsIteration()163     virtual Iteration* AsIteration() { return this; }
IsContinueTarget(Statement * statement)164     virtual bool IsContinueTarget(Statement* statement) {
165       return this->statement() == statement;
166     }
continue_target()167     Label* continue_target() { return &continue_target_label_; }
168    private:
169     Label continue_target_label_;
170     DISALLOW_COPY_AND_ASSIGN(Iteration);
171   };
172 
173   // The environment inside the try block of a try/catch statement.
174   class TryCatch : public NestedStatement {
175    public:
TryCatch(FullCodeGenerator * codegen,Label * catch_entry)176     explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
177         : NestedStatement(codegen), catch_entry_(catch_entry) { }
~TryCatch()178     virtual ~TryCatch() {}
AsTryCatch()179     virtual TryCatch* AsTryCatch() { return this; }
catch_entry()180     Label* catch_entry() { return catch_entry_; }
181     virtual int Exit(int stack_depth);
182    private:
183     Label* catch_entry_;
184     DISALLOW_COPY_AND_ASSIGN(TryCatch);
185   };
186 
187   // The environment inside the try block of a try/finally statement.
188   class TryFinally : public NestedStatement {
189    public:
TryFinally(FullCodeGenerator * codegen,Label * finally_entry)190     explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
191         : NestedStatement(codegen), finally_entry_(finally_entry) { }
~TryFinally()192     virtual ~TryFinally() {}
AsTryFinally()193     virtual TryFinally* AsTryFinally() { return this; }
finally_entry()194     Label* finally_entry() { return finally_entry_; }
195     virtual int Exit(int stack_depth);
196    private:
197     Label* finally_entry_;
198     DISALLOW_COPY_AND_ASSIGN(TryFinally);
199   };
200 
201   // A FinallyEnvironment represents being inside a finally block.
202   // Abnormal termination of the finally block needs to clean up
203   // the block's parameters from the stack.
204   class Finally : public NestedStatement {
205    public:
Finally(FullCodeGenerator * codegen)206     explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
~Finally()207     virtual ~Finally() {}
AsFinally()208     virtual Finally* AsFinally() { return this; }
Exit(int stack_depth)209     virtual int Exit(int stack_depth) {
210       return stack_depth + kFinallyStackElementCount;
211     }
212    private:
213     // Number of extra stack slots occupied during a finally block.
214     static const int kFinallyStackElementCount = 2;
215     DISALLOW_COPY_AND_ASSIGN(Finally);
216   };
217 
218   // A ForInEnvironment represents being inside a for-in loop.
219   // Abnormal termination of the for-in block needs to clean up
220   // the block's temporary storage from the stack.
221   class ForIn : public Iteration {
222    public:
ForIn(FullCodeGenerator * codegen,ForInStatement * statement)223     ForIn(FullCodeGenerator* codegen,
224           ForInStatement* statement)
225         : Iteration(codegen, statement) { }
~ForIn()226     virtual ~ForIn() {}
AsForIn()227     virtual ForIn* AsForIn() { return this; }
Exit(int stack_depth)228     virtual int Exit(int stack_depth) {
229       return stack_depth + kForInStackElementCount;
230     }
231    private:
232     // TODO(lrn): Check that this value is correct when implementing
233     // for-in.
234     static const int kForInStackElementCount = 5;
235     DISALLOW_COPY_AND_ASSIGN(ForIn);
236   };
237 
238   enum Location {
239     kAccumulator,
240     kStack
241   };
242 
243   int SlotOffset(Slot* slot);
244 
245   // Emit code to convert a pure value (in a register, slot, as a literal,
246   // or on top of the stack) into the result expected according to an
247   // expression context.
248   void Apply(Expression::Context context, Register reg);
249 
250   // Slot cannot have type Slot::LOOKUP.
251   void Apply(Expression::Context context, Slot* slot);
252 
253   void Apply(Expression::Context context, Literal* lit);
254   void ApplyTOS(Expression::Context context);
255 
256   // Emit code to discard count elements from the top of stack, then convert
257   // a pure value into the result expected according to an expression
258   // context.
259   void DropAndApply(int count, Expression::Context context, Register reg);
260 
261   // Emit code to convert pure control flow to a pair of labels into the
262   // result expected according to an expression context.
263   void Apply(Expression::Context context,
264              Label* materialize_true,
265              Label* materialize_false);
266 
267   // Helper function to convert a pure value into a test context.  The value
268   // is expected on the stack or the accumulator, depending on the platform.
269   // See the platform-specific implementation for details.
270   void DoTest(Expression::Context context);
271 
272   void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
273   void Move(Register dst, Slot* source);
274 
275   // Return an operand used to read/write to a known (ie, non-LOOKUP) slot.
276   // May emit code to traverse the context chain, destroying the scratch
277   // register.
278   MemOperand EmitSlotSearch(Slot* slot, Register scratch);
279 
VisitForEffect(Expression * expr)280   void VisitForEffect(Expression* expr) {
281     Expression::Context saved_context = context_;
282     context_ = Expression::kEffect;
283     Visit(expr);
284     context_ = saved_context;
285   }
286 
VisitForValue(Expression * expr,Location where)287   void VisitForValue(Expression* expr, Location where) {
288     Expression::Context saved_context = context_;
289     Location saved_location = location_;
290     context_ = Expression::kValue;
291     location_ = where;
292     Visit(expr);
293     context_ = saved_context;
294     location_ = saved_location;
295   }
296 
VisitForControl(Expression * expr,Label * if_true,Label * if_false)297   void VisitForControl(Expression* expr, Label* if_true, Label* if_false) {
298     Expression::Context saved_context = context_;
299     Label* saved_true = true_label_;
300     Label* saved_false = false_label_;
301     context_ = Expression::kTest;
302     true_label_ = if_true;
303     false_label_ = if_false;
304     Visit(expr);
305     context_ = saved_context;
306     true_label_ = saved_true;
307     false_label_ = saved_false;
308   }
309 
VisitForValueControl(Expression * expr,Location where,Label * if_true,Label * if_false)310   void VisitForValueControl(Expression* expr,
311                             Location where,
312                             Label* if_true,
313                             Label* if_false) {
314     Expression::Context saved_context = context_;
315     Location saved_location = location_;
316     Label* saved_true = true_label_;
317     Label* saved_false = false_label_;
318     context_ = Expression::kValueTest;
319     location_ = where;
320     true_label_ = if_true;
321     false_label_ = if_false;
322     Visit(expr);
323     context_ = saved_context;
324     location_ = saved_location;
325     true_label_ = saved_true;
326     false_label_ = saved_false;
327   }
328 
VisitForControlValue(Expression * expr,Location where,Label * if_true,Label * if_false)329   void VisitForControlValue(Expression* expr,
330                             Location where,
331                             Label* if_true,
332                             Label* if_false) {
333     Expression::Context saved_context = context_;
334     Location saved_location = location_;
335     Label* saved_true = true_label_;
336     Label* saved_false = false_label_;
337     context_ = Expression::kTestValue;
338     location_ = where;
339     true_label_ = if_true;
340     false_label_ = if_false;
341     Visit(expr);
342     context_ = saved_context;
343     location_ = saved_location;
344     true_label_ = saved_true;
345     false_label_ = saved_false;
346   }
347 
348   void VisitDeclarations(ZoneList<Declaration*>* declarations);
349   void DeclareGlobals(Handle<FixedArray> pairs);
350 
351   // Platform-specific return sequence
352   void EmitReturnSequence(int position);
353 
354   // Platform-specific code sequences for calls
355   void EmitCallWithStub(Call* expr);
356   void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode);
357 
358   // Platform-specific code for loading variables.
359   void EmitVariableLoad(Variable* expr, Expression::Context context);
360 
361   // Platform-specific support for compiling assignments.
362 
363   // Load a value from a named property.
364   // The receiver is left on the stack by the IC.
365   void EmitNamedPropertyLoad(Property* expr);
366 
367   // Load a value from a keyed property.
368   // The receiver and the key is left on the stack by the IC.
369   void EmitKeyedPropertyLoad(Property* expr);
370 
371   // Apply the compound assignment operator. Expects the left operand on top
372   // of the stack and the right one in the accumulator.
373   void EmitBinaryOp(Token::Value op, Expression::Context context);
374 
375   // Complete a variable assignment.  The right-hand-side value is expected
376   // in the accumulator.
377   void EmitVariableAssignment(Variable* var, Expression::Context context);
378 
379   // Complete a named property assignment.  The receiver is expected on top
380   // of the stack and the right-hand-side value in the accumulator.
381   void EmitNamedPropertyAssignment(Assignment* expr);
382 
383   // Complete a keyed property assignment.  The receiver and key are
384   // expected on top of the stack and the right-hand-side value in the
385   // accumulator.
386   void EmitKeyedPropertyAssignment(Assignment* expr);
387 
388   void SetFunctionPosition(FunctionLiteral* fun);
389   void SetReturnPosition(FunctionLiteral* fun);
390   void SetStatementPosition(Statement* stmt);
391   void SetStatementPosition(int pos);
392   void SetSourcePosition(int pos);
393 
394   // Non-local control flow support.
395   void EnterFinallyBlock();
396   void ExitFinallyBlock();
397 
398   // Loop nesting counter.
loop_depth()399   int loop_depth() { return loop_depth_; }
increment_loop_depth()400   void increment_loop_depth() { loop_depth_++; }
decrement_loop_depth()401   void decrement_loop_depth() {
402     ASSERT(loop_depth_ > 0);
403     loop_depth_--;
404   }
405 
masm()406   MacroAssembler* masm() { return masm_; }
407 
script()408   Handle<Script> script() { return info_->script(); }
is_eval()409   bool is_eval() { return info_->is_eval(); }
function()410   FunctionLiteral* function() { return info_->function(); }
scope()411   Scope* scope() { return info_->scope(); }
412 
413   static Register result_register();
414   static Register context_register();
415 
416   // Set fields in the stack frame. Offsets are the frame pointer relative
417   // offsets defined in, e.g., StandardFrameConstants.
418   void StoreToFrameField(int frame_offset, Register value);
419 
420   // Load a value from the current context. Indices are defined as an enum
421   // in v8::internal::Context.
422   void LoadContextField(Register dst, int context_index);
423 
424   // AST node visit functions.
425 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
426   AST_NODE_LIST(DECLARE_VISIT)
427 #undef DECLARE_VISIT
428   // Handles the shortcutted logical binary operations in VisitBinaryOperation.
429   void EmitLogicalOperation(BinaryOperation* expr);
430 
431   MacroAssembler* masm_;
432   CompilationInfo* info_;
433 
434   Label return_label_;
435   NestedStatement* nesting_stack_;
436   int loop_depth_;
437 
438   Expression::Context context_;
439   Location location_;
440   Label* true_label_;
441   Label* false_label_;
442 
443   friend class NestedStatement;
444 
445   DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator);
446 };
447 
448 
449 } }  // namespace v8::internal
450 
451 #endif  // V8_FULL_CODEGEN_H_
452