| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 // Type of a member function that generates inline code for a native function. | 281 // Type of a member function that generates inline code for a native function. |
| 282 typedef void (FullCodeGenerator::*InlineFunctionGenerator) | 282 typedef void (FullCodeGenerator::*InlineFunctionGenerator) |
| 283 (ZoneList<Expression*>*); | 283 (ZoneList<Expression*>*); |
| 284 | 284 |
| 285 static const InlineFunctionGenerator kInlineFunctionGenerators[]; | 285 static const InlineFunctionGenerator kInlineFunctionGenerators[]; |
| 286 | 286 |
| 287 // A platform-specific utility to overwrite the accumulator register | 287 // A platform-specific utility to overwrite the accumulator register |
| 288 // with a GC-safe value. | 288 // with a GC-safe value. |
| 289 void ClearAccumulator(); | 289 void ClearAccumulator(); |
| 290 | 290 |
| 291 // Compute the frame pointer relative offset for a given local or | |
| 292 // parameter slot. | |
| 293 int SlotOffset(Slot* slot); | |
| 294 | |
| 295 // Determine whether or not to inline the smi case for the given | 291 // Determine whether or not to inline the smi case for the given |
| 296 // operation. | 292 // operation. |
| 297 bool ShouldInlineSmiCase(Token::Value op); | 293 bool ShouldInlineSmiCase(Token::Value op); |
| 298 | 294 |
| 299 // Helper function to convert a pure value into a test context. The value | 295 // Helper function to convert a pure value into a test context. The value |
| 300 // is expected on the stack or the accumulator, depending on the platform. | 296 // is expected on the stack or the accumulator, depending on the platform. |
| 301 // See the platform-specific implementation for details. | 297 // See the platform-specific implementation for details. |
| 302 void DoTest(Expression* condition, | 298 void DoTest(Expression* condition, |
| 303 Label* if_true, | 299 Label* if_true, |
| 304 Label* if_false, | 300 Label* if_false, |
| 305 Label* fall_through); | 301 Label* fall_through); |
| 306 void DoTest(const TestContext* context); | 302 void DoTest(const TestContext* context); |
| 307 | 303 |
| 308 // Helper function to split control flow and avoid a branch to the | 304 // Helper function to split control flow and avoid a branch to the |
| 309 // fall-through label if it is set up. | 305 // fall-through label if it is set up. |
| 310 #ifdef V8_TARGET_ARCH_MIPS | 306 #ifdef V8_TARGET_ARCH_MIPS |
| 311 void Split(Condition cc, | 307 void Split(Condition cc, |
| 312 Register lhs, | 308 Register lhs, |
| 313 const Operand& rhs, | 309 const Operand& rhs, |
| 314 Label* if_true, | 310 Label* if_true, |
| 315 Label* if_false, | 311 Label* if_false, |
| 316 Label* fall_through); | 312 Label* fall_through); |
| 317 #else // All non-mips arch. | 313 #else // All non-mips arch. |
| 318 void Split(Condition cc, | 314 void Split(Condition cc, |
| 319 Label* if_true, | 315 Label* if_true, |
| 320 Label* if_false, | 316 Label* if_false, |
| 321 Label* fall_through); | 317 Label* fall_through); |
| 322 #endif // V8_TARGET_ARCH_MIPS | 318 #endif // V8_TARGET_ARCH_MIPS |
| 323 | 319 |
| 324 void Move(Slot* dst, Register source, Register scratch1, Register scratch2); | 320 // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into |
| 325 void Move(Register dst, Slot* source); | 321 // a register. Emits a context chain walk if if necessary (so does |
| 322 // SetVar) so avoid calling both on the same variable. |
| 323 void GetVar(Register destination, Variable* var); |
| 326 | 324 |
| 327 // Return an operand used to read/write to a known (ie, non-LOOKUP) slot. | 325 // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable. If it's in |
| 328 // May emit code to traverse the context chain, destroying the scratch | 326 // the context, the write barrier will be emitted and source, scratch0, |
| 329 // register. | 327 // scratch1 will be clobbered. Emits a context chain walk if if necessary |
| 330 MemOperand EmitSlotSearch(Slot* slot, Register scratch); | 328 // (so does GetVar) so avoid calling both on the same variable. |
| 329 void SetVar(Variable* var, |
| 330 Register source, |
| 331 Register scratch0, |
| 332 Register scratch1); |
| 333 |
| 334 // An operand used to read/write a stack-allocated (PARAMETER or LOCAL) |
| 335 // variable. Writing does not need the write barrier. |
| 336 MemOperand StackOperand(Variable* var); |
| 337 |
| 338 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) |
| 339 // variable. May emit code to traverse the context chain, loading the |
| 340 // found context into the scratch register. Writing to this operand will |
| 341 // need the write barrier if location is CONTEXT. |
| 342 MemOperand VarOperand(Variable* var, Register scratch); |
| 331 | 343 |
| 332 // Forward the bailout responsibility for the given expression to | 344 // Forward the bailout responsibility for the given expression to |
| 333 // the next child visited (which must be in a test context). | 345 // the next child visited (which must be in a test context). |
| 334 void ForwardBailoutToChild(Expression* expr); | 346 void ForwardBailoutToChild(Expression* expr); |
| 335 | 347 |
| 336 void VisitForEffect(Expression* expr) { | 348 void VisitForEffect(Expression* expr) { |
| 337 EffectContext context(this); | 349 EffectContext context(this); |
| 338 VisitInCurrentContext(expr); | 350 VisitInCurrentContext(expr); |
| 339 } | 351 } |
| 340 | 352 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // should_normalize, the true and false labels are ignored. | 410 // should_normalize, the true and false labels are ignored. |
| 399 void PrepareForBailoutBeforeSplit(State state, | 411 void PrepareForBailoutBeforeSplit(State state, |
| 400 bool should_normalize, | 412 bool should_normalize, |
| 401 Label* if_true, | 413 Label* if_true, |
| 402 Label* if_false); | 414 Label* if_false); |
| 403 | 415 |
| 404 // Platform-specific code for a variable, constant, or function | 416 // Platform-specific code for a variable, constant, or function |
| 405 // declaration. Functions have an initial value. | 417 // declaration. Functions have an initial value. |
| 406 void EmitDeclaration(VariableProxy* proxy, | 418 void EmitDeclaration(VariableProxy* proxy, |
| 407 Variable::Mode mode, | 419 Variable::Mode mode, |
| 408 FunctionLiteral* function); | 420 FunctionLiteral* function, |
| 421 int* global_count); |
| 409 | 422 |
| 410 // Platform-specific code for checking the stack limit at the back edge of | 423 // Platform-specific code for checking the stack limit at the back edge of |
| 411 // a loop. | 424 // a loop. |
| 412 void EmitStackCheck(IterationStatement* stmt); | 425 void EmitStackCheck(IterationStatement* stmt); |
| 413 // Record the OSR AST id corresponding to a stack check in the code. | 426 // Record the OSR AST id corresponding to a stack check in the code. |
| 414 void RecordStackCheck(int osr_ast_id); | 427 void RecordStackCheck(int osr_ast_id); |
| 415 // Emit a table of stack check ids and pcs into the code stream. Return | 428 // Emit a table of stack check ids and pcs into the code stream. Return |
| 416 // the offset of the start of the table. | 429 // the offset of the start of the table. |
| 417 unsigned EmitStackCheckTable(); | 430 unsigned EmitStackCheckTable(); |
| 418 | 431 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 429 | 442 |
| 430 void EmitInlineRuntimeCall(CallRuntime* expr); | 443 void EmitInlineRuntimeCall(CallRuntime* expr); |
| 431 | 444 |
| 432 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ | 445 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ |
| 433 void Emit##name(ZoneList<Expression*>* arguments); | 446 void Emit##name(ZoneList<Expression*>* arguments); |
| 434 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 447 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
| 435 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 448 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
| 436 #undef EMIT_INLINE_RUNTIME_CALL | 449 #undef EMIT_INLINE_RUNTIME_CALL |
| 437 | 450 |
| 438 // Platform-specific code for loading variables. | 451 // Platform-specific code for loading variables. |
| 439 void EmitLoadGlobalSlotCheckExtensions(Slot* slot, | 452 void EmitLoadGlobalCheckExtensions(Variable* var, |
| 440 TypeofState typeof_state, | 453 TypeofState typeof_state, |
| 441 Label* slow); | 454 Label* slow); |
| 442 MemOperand ContextSlotOperandCheckExtensions(Slot* slot, Label* slow); | 455 MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow); |
| 443 void EmitDynamicLoadFromSlotFastCase(Slot* slot, | 456 void EmitDynamicLookupFastCase(Variable* var, |
| 444 TypeofState typeof_state, | 457 TypeofState typeof_state, |
| 445 Label* slow, | 458 Label* slow, |
| 446 Label* done); | 459 Label* done); |
| 447 void EmitVariableLoad(VariableProxy* proxy); | 460 void EmitVariableLoad(VariableProxy* proxy); |
| 448 | 461 |
| 449 enum ResolveEvalFlag { | 462 enum ResolveEvalFlag { |
| 450 SKIP_CONTEXT_LOOKUP, | 463 SKIP_CONTEXT_LOOKUP, |
| 451 PERFORM_CONTEXT_LOOKUP | 464 PERFORM_CONTEXT_LOOKUP |
| 452 }; | 465 }; |
| 453 | 466 |
| 454 // Expects the arguments and the function already pushed. | 467 // Expects the arguments and the function already pushed. |
| 455 void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count); | 468 void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count); |
| 456 | 469 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 codegen()->verify_stack_height(); | 626 codegen()->verify_stack_height(); |
| 614 } | 627 } |
| 615 } | 628 } |
| 616 | 629 |
| 617 Isolate* isolate() const { return codegen_->isolate(); } | 630 Isolate* isolate() const { return codegen_->isolate(); } |
| 618 | 631 |
| 619 // Convert constant control flow (true or false) to the result expected for | 632 // Convert constant control flow (true or false) to the result expected for |
| 620 // this expression context. | 633 // this expression context. |
| 621 virtual void Plug(bool flag) const = 0; | 634 virtual void Plug(bool flag) const = 0; |
| 622 | 635 |
| 623 // Emit code to convert a pure value (in a register, slot, as a literal, | 636 // Emit code to convert a pure value (in a register, known variable |
| 624 // or on top of the stack) into the result expected according to this | 637 // location, as a literal, or on top of the stack) into the result |
| 625 // expression context. | 638 // expected according to this expression context. |
| 626 virtual void Plug(Register reg) const = 0; | 639 virtual void Plug(Register reg) const = 0; |
| 627 virtual void Plug(Slot* slot) const = 0; | 640 virtual void Plug(Variable* var) const = 0; |
| 628 virtual void Plug(Handle<Object> lit) const = 0; | 641 virtual void Plug(Handle<Object> lit) const = 0; |
| 629 virtual void Plug(Heap::RootListIndex index) const = 0; | 642 virtual void Plug(Heap::RootListIndex index) const = 0; |
| 630 virtual void PlugTOS() const = 0; | 643 virtual void PlugTOS() const = 0; |
| 631 | 644 |
| 632 // Emit code to convert pure control flow to a pair of unbound labels into | 645 // Emit code to convert pure control flow to a pair of unbound labels into |
| 633 // the result expected according to this expression context. The | 646 // the result expected according to this expression context. The |
| 634 // implementation will bind both labels unless it's a TestContext, which | 647 // implementation will bind both labels unless it's a TestContext, which |
| 635 // won't bind them at this point. | 648 // won't bind them at this point. |
| 636 virtual void Plug(Label* materialize_true, | 649 virtual void Plug(Label* materialize_true, |
| 637 Label* materialize_false) const = 0; | 650 Label* materialize_false) const = 0; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 class AccumulatorValueContext : public ExpressionContext { | 688 class AccumulatorValueContext : public ExpressionContext { |
| 676 public: | 689 public: |
| 677 explicit AccumulatorValueContext(FullCodeGenerator* codegen) | 690 explicit AccumulatorValueContext(FullCodeGenerator* codegen) |
| 678 : ExpressionContext(codegen) { | 691 : ExpressionContext(codegen) { |
| 679 expected_stack_height_ = codegen->stack_height(); | 692 expected_stack_height_ = codegen->stack_height(); |
| 680 } | 693 } |
| 681 | 694 |
| 682 virtual void Plug(bool flag) const; | 695 virtual void Plug(bool flag) const; |
| 683 virtual void Plug(Register reg) const; | 696 virtual void Plug(Register reg) const; |
| 684 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 697 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
| 685 virtual void Plug(Slot* slot) const; | 698 virtual void Plug(Variable* var) const; |
| 686 virtual void Plug(Handle<Object> lit) const; | 699 virtual void Plug(Handle<Object> lit) const; |
| 687 virtual void Plug(Heap::RootListIndex) const; | 700 virtual void Plug(Heap::RootListIndex) const; |
| 688 virtual void PlugTOS() const; | 701 virtual void PlugTOS() const; |
| 689 virtual void DropAndPlug(int count, Register reg) const; | 702 virtual void DropAndPlug(int count, Register reg) const; |
| 690 virtual void PrepareTest(Label* materialize_true, | 703 virtual void PrepareTest(Label* materialize_true, |
| 691 Label* materialize_false, | 704 Label* materialize_false, |
| 692 Label** if_true, | 705 Label** if_true, |
| 693 Label** if_false, | 706 Label** if_false, |
| 694 Label** fall_through) const; | 707 Label** fall_through) const; |
| 695 virtual bool IsAccumulatorValue() const { return true; } | 708 virtual bool IsAccumulatorValue() const { return true; } |
| 696 }; | 709 }; |
| 697 | 710 |
| 698 class StackValueContext : public ExpressionContext { | 711 class StackValueContext : public ExpressionContext { |
| 699 public: | 712 public: |
| 700 explicit StackValueContext(FullCodeGenerator* codegen) | 713 explicit StackValueContext(FullCodeGenerator* codegen) |
| 701 : ExpressionContext(codegen) { | 714 : ExpressionContext(codegen) { |
| 702 expected_stack_height_ = codegen->stack_height() + 1; | 715 expected_stack_height_ = codegen->stack_height() + 1; |
| 703 } | 716 } |
| 704 | 717 |
| 705 virtual void Plug(bool flag) const; | 718 virtual void Plug(bool flag) const; |
| 706 virtual void Plug(Register reg) const; | 719 virtual void Plug(Register reg) const; |
| 707 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 720 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
| 708 virtual void Plug(Slot* slot) const; | 721 virtual void Plug(Variable* var) const; |
| 709 virtual void Plug(Handle<Object> lit) const; | 722 virtual void Plug(Handle<Object> lit) const; |
| 710 virtual void Plug(Heap::RootListIndex) const; | 723 virtual void Plug(Heap::RootListIndex) const; |
| 711 virtual void PlugTOS() const; | 724 virtual void PlugTOS() const; |
| 712 virtual void DropAndPlug(int count, Register reg) const; | 725 virtual void DropAndPlug(int count, Register reg) const; |
| 713 virtual void PrepareTest(Label* materialize_true, | 726 virtual void PrepareTest(Label* materialize_true, |
| 714 Label* materialize_false, | 727 Label* materialize_false, |
| 715 Label** if_true, | 728 Label** if_true, |
| 716 Label** if_false, | 729 Label** if_false, |
| 717 Label** fall_through) const; | 730 Label** fall_through) const; |
| 718 virtual bool IsStackValue() const { return true; } | 731 virtual bool IsStackValue() const { return true; } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 739 } | 752 } |
| 740 | 753 |
| 741 Expression* condition() const { return condition_; } | 754 Expression* condition() const { return condition_; } |
| 742 Label* true_label() const { return true_label_; } | 755 Label* true_label() const { return true_label_; } |
| 743 Label* false_label() const { return false_label_; } | 756 Label* false_label() const { return false_label_; } |
| 744 Label* fall_through() const { return fall_through_; } | 757 Label* fall_through() const { return fall_through_; } |
| 745 | 758 |
| 746 virtual void Plug(bool flag) const; | 759 virtual void Plug(bool flag) const; |
| 747 virtual void Plug(Register reg) const; | 760 virtual void Plug(Register reg) const; |
| 748 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 761 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
| 749 virtual void Plug(Slot* slot) const; | 762 virtual void Plug(Variable* var) const; |
| 750 virtual void Plug(Handle<Object> lit) const; | 763 virtual void Plug(Handle<Object> lit) const; |
| 751 virtual void Plug(Heap::RootListIndex) const; | 764 virtual void Plug(Heap::RootListIndex) const; |
| 752 virtual void PlugTOS() const; | 765 virtual void PlugTOS() const; |
| 753 virtual void DropAndPlug(int count, Register reg) const; | 766 virtual void DropAndPlug(int count, Register reg) const; |
| 754 virtual void PrepareTest(Label* materialize_true, | 767 virtual void PrepareTest(Label* materialize_true, |
| 755 Label* materialize_false, | 768 Label* materialize_false, |
| 756 Label** if_true, | 769 Label** if_true, |
| 757 Label** if_false, | 770 Label** if_false, |
| 758 Label** fall_through) const; | 771 Label** fall_through) const; |
| 759 virtual bool IsTest() const { return true; } | 772 virtual bool IsTest() const { return true; } |
| 760 | 773 |
| 761 private: | 774 private: |
| 762 Expression* condition_; | 775 Expression* condition_; |
| 763 Label* true_label_; | 776 Label* true_label_; |
| 764 Label* false_label_; | 777 Label* false_label_; |
| 765 Label* fall_through_; | 778 Label* fall_through_; |
| 766 }; | 779 }; |
| 767 | 780 |
| 768 class EffectContext : public ExpressionContext { | 781 class EffectContext : public ExpressionContext { |
| 769 public: | 782 public: |
| 770 explicit EffectContext(FullCodeGenerator* codegen) | 783 explicit EffectContext(FullCodeGenerator* codegen) |
| 771 : ExpressionContext(codegen) { | 784 : ExpressionContext(codegen) { |
| 772 expected_stack_height_ = codegen->stack_height(); | 785 expected_stack_height_ = codegen->stack_height(); |
| 773 } | 786 } |
| 774 | 787 |
| 775 | 788 |
| 776 virtual void Plug(bool flag) const; | 789 virtual void Plug(bool flag) const; |
| 777 virtual void Plug(Register reg) const; | 790 virtual void Plug(Register reg) const; |
| 778 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 791 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
| 779 virtual void Plug(Slot* slot) const; | 792 virtual void Plug(Variable* var) const; |
| 780 virtual void Plug(Handle<Object> lit) const; | 793 virtual void Plug(Handle<Object> lit) const; |
| 781 virtual void Plug(Heap::RootListIndex) const; | 794 virtual void Plug(Heap::RootListIndex) const; |
| 782 virtual void PlugTOS() const; | 795 virtual void PlugTOS() const; |
| 783 virtual void DropAndPlug(int count, Register reg) const; | 796 virtual void DropAndPlug(int count, Register reg) const; |
| 784 virtual void PrepareTest(Label* materialize_true, | 797 virtual void PrepareTest(Label* materialize_true, |
| 785 Label* materialize_false, | 798 Label* materialize_false, |
| 786 Label** if_true, | 799 Label** if_true, |
| 787 Label** if_false, | 800 Label** if_false, |
| 788 Label** fall_through) const; | 801 Label** fall_through) const; |
| 789 virtual bool IsEffect() const { return true; } | 802 virtual bool IsEffect() const { return true; } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 804 | 817 |
| 805 friend class NestedStatement; | 818 friend class NestedStatement; |
| 806 | 819 |
| 807 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); | 820 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); |
| 808 }; | 821 }; |
| 809 | 822 |
| 810 | 823 |
| 811 } } // namespace v8::internal | 824 } } // namespace v8::internal |
| 812 | 825 |
| 813 #endif // V8_FULL_CODEGEN_H_ | 826 #endif // V8_FULL_CODEGEN_H_ |
| OLD | NEW |