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