1 // Copyright 2010 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 #include "code-stubs.h" 35 #include "codegen.h" 36 #include "compiler.h" 37 38 namespace v8 { 39 namespace internal { 40 41 // Forward declarations. 42 class JumpPatchSite; 43 44 // AST node visitor which can tell whether a given statement will be breakable 45 // when the code is compiled by the full compiler in the debugger. This means 46 // that there will be an IC (load/store/call) in the code generated for the 47 // debugger to piggybag on. 48 class BreakableStatementChecker: public AstVisitor { 49 public: 50 BreakableStatementChecker() : is_breakable_(false) {} 51 52 void Check(Statement* stmt); 53 void Check(Expression* stmt); 54 55 bool is_breakable() { return is_breakable_; } 56 57 private: 58 // AST node visit functions. 59 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); 60 AST_NODE_LIST(DECLARE_VISIT) 61 #undef DECLARE_VISIT 62 63 bool is_breakable_; 64 65 DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker); 66 }; 67 68 69 // ----------------------------------------------------------------------------- 70 // Full code generator. 71 72 class FullCodeGenerator: public AstVisitor { 73 public: 74 enum State { 75 NO_REGISTERS, 76 TOS_REG 77 }; 78 79 explicit FullCodeGenerator(MacroAssembler* masm) 80 : masm_(masm), 81 info_(NULL), 82 nesting_stack_(NULL), 83 loop_depth_(0), 84 context_(NULL), 85 bailout_entries_(0), 86 stack_checks_(2), // There's always at least one. 87 forward_bailout_stack_(NULL), 88 forward_bailout_pending_(NULL) { 89 } 90 91 static bool MakeCode(CompilationInfo* info); 92 93 void Generate(CompilationInfo* info); 94 void PopulateDeoptimizationData(Handle<Code> code); 95 96 class StateField : public BitField<State, 0, 8> { }; 97 class PcField : public BitField<unsigned, 8, 32-8> { }; 98 99 static const char* State2String(State state) { 100 switch (state) { 101 case NO_REGISTERS: return "NO_REGISTERS"; 102 case TOS_REG: return "TOS_REG"; 103 } 104 UNREACHABLE(); 105 return NULL; 106 } 107 108 private: 109 class Breakable; 110 class Iteration; 111 class TryCatch; 112 class TryFinally; 113 class Finally; 114 class ForIn; 115 116 class NestedStatement BASE_EMBEDDED { 117 public: 118 explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) { 119 // Link into codegen's nesting stack. 120 previous_ = codegen->nesting_stack_; 121 codegen->nesting_stack_ = this; 122 } 123 virtual ~NestedStatement() { 124 // Unlink from codegen's nesting stack. 125 ASSERT_EQ(this, codegen_->nesting_stack_); 126 codegen_->nesting_stack_ = previous_; 127 } 128 129 virtual Breakable* AsBreakable() { return NULL; } 130 virtual Iteration* AsIteration() { return NULL; } 131 virtual TryCatch* AsTryCatch() { return NULL; } 132 virtual TryFinally* AsTryFinally() { return NULL; } 133 virtual Finally* AsFinally() { return NULL; } 134 virtual ForIn* AsForIn() { return NULL; } 135 136 virtual bool IsContinueTarget(Statement* target) { return false; } 137 virtual bool IsBreakTarget(Statement* target) { return false; } 138 139 // Generate code to leave the nested statement. This includes 140 // cleaning up any stack elements in use and restoring the 141 // stack to the expectations of the surrounding statements. 142 // Takes a number of stack elements currently on top of the 143 // nested statement's stack, and returns a number of stack 144 // elements left on top of the surrounding statement's stack. 145 // The generated code must preserve the result register (which 146 // contains the value in case of a return). 147 virtual int Exit(int stack_depth) { 148 // Default implementation for the case where there is 149 // nothing to clean up. 150 return stack_depth; 151 } 152 NestedStatement* outer() { return previous_; } 153 protected: 154 MacroAssembler* masm() { return codegen_->masm(); } 155 private: 156 FullCodeGenerator* codegen_; 157 NestedStatement* previous_; 158 DISALLOW_COPY_AND_ASSIGN(NestedStatement); 159 }; 160 161 class Breakable : public NestedStatement { 162 public: 163 Breakable(FullCodeGenerator* codegen, 164 BreakableStatement* break_target) 165 : NestedStatement(codegen), 166 target_(break_target) {} 167 virtual ~Breakable() {} 168 virtual Breakable* AsBreakable() { return this; } 169 virtual bool IsBreakTarget(Statement* statement) { 170 return target_ == statement; 171 } 172 BreakableStatement* statement() { return target_; } 173 Label* break_target() { return &break_target_label_; } 174 private: 175 BreakableStatement* target_; 176 Label break_target_label_; 177 DISALLOW_COPY_AND_ASSIGN(Breakable); 178 }; 179 180 class Iteration : public Breakable { 181 public: 182 Iteration(FullCodeGenerator* codegen, 183 IterationStatement* iteration_statement) 184 : Breakable(codegen, iteration_statement) {} 185 virtual ~Iteration() {} 186 virtual Iteration* AsIteration() { return this; } 187 virtual bool IsContinueTarget(Statement* statement) { 188 return this->statement() == statement; 189 } 190 Label* continue_target() { return &continue_target_label_; } 191 private: 192 Label continue_target_label_; 193 DISALLOW_COPY_AND_ASSIGN(Iteration); 194 }; 195 196 // The environment inside the try block of a try/catch statement. 197 class TryCatch : public NestedStatement { 198 public: 199 explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry) 200 : NestedStatement(codegen), catch_entry_(catch_entry) { } 201 virtual ~TryCatch() {} 202 virtual TryCatch* AsTryCatch() { return this; } 203 Label* catch_entry() { return catch_entry_; } 204 virtual int Exit(int stack_depth); 205 private: 206 Label* catch_entry_; 207 DISALLOW_COPY_AND_ASSIGN(TryCatch); 208 }; 209 210 // The environment inside the try block of a try/finally statement. 211 class TryFinally : public NestedStatement { 212 public: 213 explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry) 214 : NestedStatement(codegen), finally_entry_(finally_entry) { } 215 virtual ~TryFinally() {} 216 virtual TryFinally* AsTryFinally() { return this; } 217 Label* finally_entry() { return finally_entry_; } 218 virtual int Exit(int stack_depth); 219 private: 220 Label* finally_entry_; 221 DISALLOW_COPY_AND_ASSIGN(TryFinally); 222 }; 223 224 // A FinallyEnvironment represents being inside a finally block. 225 // Abnormal termination of the finally block needs to clean up 226 // the block's parameters from the stack. 227 class Finally : public NestedStatement { 228 public: 229 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { } 230 virtual ~Finally() {} 231 virtual Finally* AsFinally() { return this; } 232 virtual int Exit(int stack_depth) { 233 return stack_depth + kFinallyStackElementCount; 234 } 235 private: 236 // Number of extra stack slots occupied during a finally block. 237 static const int kFinallyStackElementCount = 2; 238 DISALLOW_COPY_AND_ASSIGN(Finally); 239 }; 240 241 // A ForInEnvironment represents being inside a for-in loop. 242 // Abnormal termination of the for-in block needs to clean up 243 // the block's temporary storage from the stack. 244 class ForIn : public Iteration { 245 public: 246 ForIn(FullCodeGenerator* codegen, 247 ForInStatement* statement) 248 : Iteration(codegen, statement) { } 249 virtual ~ForIn() {} 250 virtual ForIn* AsForIn() { return this; } 251 virtual int Exit(int stack_depth) { 252 return stack_depth + kForInStackElementCount; 253 } 254 private: 255 static const int kForInStackElementCount = 5; 256 DISALLOW_COPY_AND_ASSIGN(ForIn); 257 }; 258 259 // The forward bailout stack keeps track of the expressions that can 260 // bail out to just before the control flow is split in a child 261 // node. The stack elements are linked together through the parent 262 // link when visiting expressions in test contexts after requesting 263 // bailout in child forwarding. 264 class ForwardBailoutStack BASE_EMBEDDED { 265 public: 266 ForwardBailoutStack(Expression* expr, ForwardBailoutStack* parent) 267 : expr_(expr), parent_(parent) { } 268 269 Expression* expr() const { return expr_; } 270 ForwardBailoutStack* parent() const { return parent_; } 271 272 private: 273 Expression* const expr_; 274 ForwardBailoutStack* const parent_; 275 }; 276 277 // Type of a member function that generates inline code for a native function. 278 typedef void (FullCodeGenerator::*InlineFunctionGenerator) 279 (ZoneList<Expression*>*); 280 281 static const InlineFunctionGenerator kInlineFunctionGenerators[]; 282 283 // A platform-specific utility to overwrite the accumulator register 284 // with a GC-safe value. 285 void ClearAccumulator(); 286 287 // Compute the frame pointer relative offset for a given local or 288 // parameter slot. 289 int SlotOffset(Slot* slot); 290 291 // Determine whether or not to inline the smi case for the given 292 // operation. 293 bool ShouldInlineSmiCase(Token::Value op); 294 295 // Helper function to convert a pure value into a test context. The value 296 // is expected on the stack or the accumulator, depending on the platform. 297 // See the platform-specific implementation for details. 298 void DoTest(Label* if_true, Label* if_false, Label* fall_through); 299 300 // Helper function to split control flow and avoid a branch to the 301 // fall-through label if it is set up. 302 void Split(Condition cc, 303 Label* if_true, 304 Label* if_false, 305 Label* fall_through); 306 307 void Move(Slot* dst, Register source, Register scratch1, Register scratch2); 308 void Move(Register dst, Slot* source); 309 310 // Return an operand used to read/write to a known (ie, non-LOOKUP) slot. 311 // May emit code to traverse the context chain, destroying the scratch 312 // register. 313 MemOperand EmitSlotSearch(Slot* slot, Register scratch); 314 315 // Forward the bailout responsibility for the given expression to 316 // the next child visited (which must be in a test context). 317 void ForwardBailoutToChild(Expression* expr); 318 319 void VisitForEffect(Expression* expr) { 320 EffectContext context(this); 321 HandleInNonTestContext(expr, NO_REGISTERS); 322 } 323 324 void VisitForAccumulatorValue(Expression* expr) { 325 AccumulatorValueContext context(this); 326 HandleInNonTestContext(expr, TOS_REG); 327 } 328 329 void VisitForStackValue(Expression* expr) { 330 StackValueContext context(this); 331 HandleInNonTestContext(expr, NO_REGISTERS); 332 } 333 334 void VisitForControl(Expression* expr, 335 Label* if_true, 336 Label* if_false, 337 Label* fall_through) { 338 TestContext context(this, if_true, if_false, fall_through); 339 VisitInTestContext(expr); 340 // Forwarding bailouts to children is a one shot operation. It 341 // should have been processed at this point. 342 ASSERT(forward_bailout_pending_ == NULL); 343 } 344 345 void HandleInNonTestContext(Expression* expr, State state); 346 void VisitInTestContext(Expression* expr); 347 348 void VisitDeclarations(ZoneList<Declaration*>* declarations); 349 void DeclareGlobals(Handle<FixedArray> pairs); 350 351 // Try to perform a comparison as a fast inlined literal compare if 352 // the operands allow it. Returns true if the compare operations 353 // has been matched and all code generated; false otherwise. 354 bool TryLiteralCompare(Token::Value op, 355 Expression* left, 356 Expression* right, 357 Label* if_true, 358 Label* if_false, 359 Label* fall_through); 360 361 // Bailout support. 362 void PrepareForBailout(AstNode* node, State state); 363 void PrepareForBailoutForId(int id, State state); 364 365 // Record a call's return site offset, used to rebuild the frame if the 366 // called function was inlined at the site. 367 void RecordJSReturnSite(Call* call); 368 369 // Prepare for bailout before a test (or compare) and branch. If 370 // should_normalize, then the following comparison will not handle the 371 // canonical JS true value so we will insert a (dead) test against true at 372 // the actual bailout target from the optimized code. If not 373 // should_normalize, the true and false labels are ignored. 374 void PrepareForBailoutBeforeSplit(State state, 375 bool should_normalize, 376 Label* if_true, 377 Label* if_false); 378 379 // Platform-specific code for a variable, constant, or function 380 // declaration. Functions have an initial value. 381 void EmitDeclaration(Variable* variable, 382 Variable::Mode mode, 383 FunctionLiteral* function); 384 385 // Platform-specific code for checking the stack limit at the back edge of 386 // a loop. 387 void EmitStackCheck(IterationStatement* stmt); 388 // Record the OSR AST id corresponding to a stack check in the code. 389 void RecordStackCheck(int osr_ast_id); 390 // Emit a table of stack check ids and pcs into the code stream. Return 391 // the offset of the start of the table. 392 unsigned EmitStackCheckTable(); 393 394 // Platform-specific return sequence 395 void EmitReturnSequence(); 396 397 // Platform-specific code sequences for calls 398 void EmitCallWithStub(Call* expr); 399 void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode mode); 400 void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode); 401 402 // Platform-specific code for inline runtime calls. 403 InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id); 404 405 void EmitInlineRuntimeCall(CallRuntime* expr); 406 407 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ 408 void Emit##name(ZoneList<Expression*>* arguments); 409 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) 410 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) 411 #undef EMIT_INLINE_RUNTIME_CALL 412 413 // Platform-specific code for loading variables. 414 void EmitLoadGlobalSlotCheckExtensions(Slot* slot, 415 TypeofState typeof_state, 416 Label* slow); 417 MemOperand ContextSlotOperandCheckExtensions(Slot* slot, Label* slow); 418 void EmitDynamicLoadFromSlotFastCase(Slot* slot, 419 TypeofState typeof_state, 420 Label* slow, 421 Label* done); 422 void EmitVariableLoad(Variable* expr); 423 424 enum ResolveEvalFlag { 425 SKIP_CONTEXT_LOOKUP, 426 PERFORM_CONTEXT_LOOKUP 427 }; 428 429 // Expects the arguments and the function already pushed. 430 void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count); 431 432 // Platform-specific support for allocating a new closure based on 433 // the given function info. 434 void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure); 435 436 // Platform-specific support for compiling assignments. 437 438 // Load a value from a named property. 439 // The receiver is left on the stack by the IC. 440 void EmitNamedPropertyLoad(Property* expr); 441 442 // Load a value from a keyed property. 443 // The receiver and the key is left on the stack by the IC. 444 void EmitKeyedPropertyLoad(Property* expr); 445 446 // Apply the compound assignment operator. Expects the left operand on top 447 // of the stack and the right one in the accumulator. 448 void EmitBinaryOp(Token::Value op, 449 OverwriteMode mode); 450 451 // Helper functions for generating inlined smi code for certain 452 // binary operations. 453 void EmitInlineSmiBinaryOp(Expression* expr, 454 Token::Value op, 455 OverwriteMode mode, 456 Expression* left, 457 Expression* right); 458 459 // Assign to the given expression as if via '='. The right-hand-side value 460 // is expected in the accumulator. 461 void EmitAssignment(Expression* expr, int bailout_ast_id); 462 463 // Complete a variable assignment. The right-hand-side value is expected 464 // in the accumulator. 465 void EmitVariableAssignment(Variable* var, 466 Token::Value op); 467 468 // Complete a named property assignment. The receiver is expected on top 469 // of the stack and the right-hand-side value in the accumulator. 470 void EmitNamedPropertyAssignment(Assignment* expr); 471 472 // Complete a keyed property assignment. The receiver and key are 473 // expected on top of the stack and the right-hand-side value in the 474 // accumulator. 475 void EmitKeyedPropertyAssignment(Assignment* expr); 476 477 void SetFunctionPosition(FunctionLiteral* fun); 478 void SetReturnPosition(FunctionLiteral* fun); 479 void SetStatementPosition(Statement* stmt); 480 void SetExpressionPosition(Expression* expr, int pos); 481 void SetStatementPosition(int pos); 482 void SetSourcePosition(int pos); 483 484 // Non-local control flow support. 485 void EnterFinallyBlock(); 486 void ExitFinallyBlock(); 487 488 // Loop nesting counter. 489 int loop_depth() { return loop_depth_; } 490 void increment_loop_depth() { loop_depth_++; } 491 void decrement_loop_depth() { 492 ASSERT(loop_depth_ > 0); 493 loop_depth_--; 494 } 495 496 MacroAssembler* masm() { return masm_; } 497 498 class ExpressionContext; 499 const ExpressionContext* context() { return context_; } 500 void set_new_context(const ExpressionContext* context) { context_ = context; } 501 502 Handle<Script> script() { return info_->script(); } 503 bool is_eval() { return info_->is_eval(); } 504 bool is_strict_mode() { return function()->strict_mode(); } 505 StrictModeFlag strict_mode_flag() { 506 return is_strict_mode() ? kStrictMode : kNonStrictMode; 507 } 508 FunctionLiteral* function() { return info_->function(); } 509 Scope* scope() { return info_->scope(); } 510 511 static Register result_register(); 512 static Register context_register(); 513 514 // Helper for calling an IC stub. 515 void EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode); 516 517 // Calling an IC stub with a patch site. Passing NULL for patch_site 518 // or non NULL patch_site which is not activated indicates no inlined smi code 519 // and emits a nop after the IC call. 520 void EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site); 521 522 // Set fields in the stack frame. Offsets are the frame pointer relative 523 // offsets defined in, e.g., StandardFrameConstants. 524 void StoreToFrameField(int frame_offset, Register value); 525 526 // Load a value from the current context. Indices are defined as an enum 527 // in v8::internal::Context. 528 void LoadContextField(Register dst, int context_index); 529 530 // AST node visit functions. 531 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); 532 AST_NODE_LIST(DECLARE_VISIT) 533 #undef DECLARE_VISIT 534 // Handles the shortcutted logical binary operations in VisitBinaryOperation. 535 void EmitLogicalOperation(BinaryOperation* expr); 536 537 void VisitForTypeofValue(Expression* expr); 538 539 struct BailoutEntry { 540 unsigned id; 541 unsigned pc_and_state; 542 }; 543 544 545 class ExpressionContext BASE_EMBEDDED { 546 public: 547 explicit ExpressionContext(FullCodeGenerator* codegen) 548 : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) { 549 codegen->set_new_context(this); 550 } 551 552 virtual ~ExpressionContext() { 553 codegen_->set_new_context(old_); 554 } 555 556 Isolate* isolate() const { return codegen_->isolate(); } 557 558 // Convert constant control flow (true or false) to the result expected for 559 // this expression context. 560 virtual void Plug(bool flag) const = 0; 561 562 // Emit code to convert a pure value (in a register, slot, as a literal, 563 // or on top of the stack) into the result expected according to this 564 // expression context. 565 virtual void Plug(Register reg) const = 0; 566 virtual void Plug(Slot* slot) const = 0; 567 virtual void Plug(Handle<Object> lit) const = 0; 568 virtual void Plug(Heap::RootListIndex index) const = 0; 569 virtual void PlugTOS() const = 0; 570 571 // Emit code to convert pure control flow to a pair of unbound labels into 572 // the result expected according to this expression context. The 573 // implementation will bind both labels unless it's a TestContext, which 574 // won't bind them at this point. 575 virtual void Plug(Label* materialize_true, 576 Label* materialize_false) const = 0; 577 578 // Emit code to discard count elements from the top of stack, then convert 579 // a pure value into the result expected according to this expression 580 // context. 581 virtual void DropAndPlug(int count, Register reg) const = 0; 582 583 // For shortcutting operations || and &&. 584 virtual void EmitLogicalLeft(BinaryOperation* expr, 585 Label* eval_right, 586 Label* done) const = 0; 587 588 // Set up branch labels for a test expression. The three Label** parameters 589 // are output parameters. 590 virtual void PrepareTest(Label* materialize_true, 591 Label* materialize_false, 592 Label** if_true, 593 Label** if_false, 594 Label** fall_through) const = 0; 595 596 virtual void HandleExpression(Expression* expr) const = 0; 597 598 // Returns true if we are evaluating only for side effects (ie if the result 599 // will be discarded). 600 virtual bool IsEffect() const { return false; } 601 602 // Returns true if we are branching on the value rather than materializing 603 // it. Only used for asserts. 604 virtual bool IsTest() const { return false; } 605 606 protected: 607 FullCodeGenerator* codegen() const { return codegen_; } 608 MacroAssembler* masm() const { return masm_; } 609 MacroAssembler* masm_; 610 611 private: 612 const ExpressionContext* old_; 613 FullCodeGenerator* codegen_; 614 }; 615 616 class AccumulatorValueContext : public ExpressionContext { 617 public: 618 explicit AccumulatorValueContext(FullCodeGenerator* codegen) 619 : ExpressionContext(codegen) { } 620 621 virtual void Plug(bool flag) const; 622 virtual void Plug(Register reg) const; 623 virtual void Plug(Label* materialize_true, Label* materialize_false) const; 624 virtual void Plug(Slot* slot) const; 625 virtual void Plug(Handle<Object> lit) const; 626 virtual void Plug(Heap::RootListIndex) const; 627 virtual void PlugTOS() const; 628 virtual void DropAndPlug(int count, Register reg) const; 629 virtual void EmitLogicalLeft(BinaryOperation* expr, 630 Label* eval_right, 631 Label* done) const; 632 virtual void PrepareTest(Label* materialize_true, 633 Label* materialize_false, 634 Label** if_true, 635 Label** if_false, 636 Label** fall_through) const; 637 virtual void HandleExpression(Expression* expr) const; 638 }; 639 640 class StackValueContext : public ExpressionContext { 641 public: 642 explicit StackValueContext(FullCodeGenerator* codegen) 643 : ExpressionContext(codegen) { } 644 645 virtual void Plug(bool flag) const; 646 virtual void Plug(Register reg) const; 647 virtual void Plug(Label* materialize_true, Label* materialize_false) const; 648 virtual void Plug(Slot* slot) const; 649 virtual void Plug(Handle<Object> lit) const; 650 virtual void Plug(Heap::RootListIndex) const; 651 virtual void PlugTOS() const; 652 virtual void DropAndPlug(int count, Register reg) const; 653 virtual void EmitLogicalLeft(BinaryOperation* expr, 654 Label* eval_right, 655 Label* done) const; 656 virtual void PrepareTest(Label* materialize_true, 657 Label* materialize_false, 658 Label** if_true, 659 Label** if_false, 660 Label** fall_through) const; 661 virtual void HandleExpression(Expression* expr) const; 662 }; 663 664 class TestContext : public ExpressionContext { 665 public: 666 explicit TestContext(FullCodeGenerator* codegen, 667 Label* true_label, 668 Label* false_label, 669 Label* fall_through) 670 : ExpressionContext(codegen), 671 true_label_(true_label), 672 false_label_(false_label), 673 fall_through_(fall_through) { } 674 675 static const TestContext* cast(const ExpressionContext* context) { 676 ASSERT(context->IsTest()); 677 return reinterpret_cast<const TestContext*>(context); 678 } 679 680 Label* true_label() const { return true_label_; } 681 Label* false_label() const { return false_label_; } 682 Label* fall_through() const { return fall_through_; } 683 684 virtual void Plug(bool flag) const; 685 virtual void Plug(Register reg) const; 686 virtual void Plug(Label* materialize_true, Label* materialize_false) const; 687 virtual void Plug(Slot* slot) const; 688 virtual void Plug(Handle<Object> lit) const; 689 virtual void Plug(Heap::RootListIndex) const; 690 virtual void PlugTOS() const; 691 virtual void DropAndPlug(int count, Register reg) const; 692 virtual void EmitLogicalLeft(BinaryOperation* expr, 693 Label* eval_right, 694 Label* done) const; 695 virtual void PrepareTest(Label* materialize_true, 696 Label* materialize_false, 697 Label** if_true, 698 Label** if_false, 699 Label** fall_through) const; 700 virtual void HandleExpression(Expression* expr) const; 701 virtual bool IsTest() const { return true; } 702 703 private: 704 Label* true_label_; 705 Label* false_label_; 706 Label* fall_through_; 707 }; 708 709 class EffectContext : public ExpressionContext { 710 public: 711 explicit EffectContext(FullCodeGenerator* codegen) 712 : ExpressionContext(codegen) { } 713 714 virtual void Plug(bool flag) const; 715 virtual void Plug(Register reg) const; 716 virtual void Plug(Label* materialize_true, Label* materialize_false) const; 717 virtual void Plug(Slot* slot) const; 718 virtual void Plug(Handle<Object> lit) const; 719 virtual void Plug(Heap::RootListIndex) const; 720 virtual void PlugTOS() const; 721 virtual void DropAndPlug(int count, Register reg) const; 722 virtual void EmitLogicalLeft(BinaryOperation* expr, 723 Label* eval_right, 724 Label* done) const; 725 virtual void PrepareTest(Label* materialize_true, 726 Label* materialize_false, 727 Label** if_true, 728 Label** if_false, 729 Label** fall_through) const; 730 virtual void HandleExpression(Expression* expr) const; 731 virtual bool IsEffect() const { return true; } 732 }; 733 734 MacroAssembler* masm_; 735 CompilationInfo* info_; 736 Label return_label_; 737 NestedStatement* nesting_stack_; 738 int loop_depth_; 739 const ExpressionContext* context_; 740 ZoneList<BailoutEntry> bailout_entries_; 741 ZoneList<BailoutEntry> stack_checks_; 742 ForwardBailoutStack* forward_bailout_stack_; 743 ForwardBailoutStack* forward_bailout_pending_; 744 745 friend class NestedStatement; 746 747 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); 748 }; 749 750 751 } } // namespace v8::internal 752 753 #endif // V8_FULL_CODEGEN_H_ 754