| 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 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_AST_H_ | 28 #ifndef V8_AST_H_ |
| 29 #define V8_AST_H_ | 29 #define V8_AST_H_ |
| 30 | 30 |
| 31 #include "execution.h" | 31 #include "execution.h" |
| 32 #include "factory.h" | 32 #include "factory.h" |
| 33 #include "jsregexp.h" | 33 #include "jsregexp.h" |
| 34 #include "jump-target.h" | |
| 35 #include "runtime.h" | 34 #include "runtime.h" |
| 36 #include "token.h" | 35 #include "token.h" |
| 37 #include "variables.h" | 36 #include "variables.h" |
| 38 | 37 |
| 39 namespace v8 { | 38 namespace v8 { |
| 40 namespace internal { | 39 namespace internal { |
| 41 | 40 |
| 42 // The abstract syntax tree is an intermediate, light-weight | 41 // The abstract syntax tree is an intermediate, light-weight |
| 43 // representation of the parsed JavaScript code suitable for | 42 // representation of the parsed JavaScript code suitable for |
| 44 // compilation to native code. | 43 // compilation to native code. |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 // code generation. | 212 // code generation. |
| 214 kUninitialized, | 213 kUninitialized, |
| 215 // Evaluated for its side effects. | 214 // Evaluated for its side effects. |
| 216 kEffect, | 215 kEffect, |
| 217 // Evaluated for its value (and side effects). | 216 // Evaluated for its value (and side effects). |
| 218 kValue, | 217 kValue, |
| 219 // Evaluated for control flow (and side effects). | 218 // Evaluated for control flow (and side effects). |
| 220 kTest | 219 kTest |
| 221 }; | 220 }; |
| 222 | 221 |
| 223 Expression() : bitfields_(0) {} | 222 Expression() {} |
| 224 | 223 |
| 225 virtual Expression* AsExpression() { return this; } | 224 virtual Expression* AsExpression() { return this; } |
| 226 | 225 |
| 227 virtual bool IsTrivial() { return false; } | 226 virtual bool IsTrivial() { return false; } |
| 228 virtual bool IsValidLeftHandSide() { return false; } | 227 virtual bool IsValidLeftHandSide() { return false; } |
| 229 | 228 |
| 230 // Helpers for ToBoolean conversion. | 229 // Helpers for ToBoolean conversion. |
| 231 virtual bool ToBooleanIsTrue() { return false; } | 230 virtual bool ToBooleanIsTrue() { return false; } |
| 232 virtual bool ToBooleanIsFalse() { return false; } | 231 virtual bool ToBooleanIsFalse() { return false; } |
| 233 | 232 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 259 } | 258 } |
| 260 virtual ZoneMapList* GetReceiverTypes() { | 259 virtual ZoneMapList* GetReceiverTypes() { |
| 261 UNREACHABLE(); | 260 UNREACHABLE(); |
| 262 return NULL; | 261 return NULL; |
| 263 } | 262 } |
| 264 virtual Handle<Map> GetMonomorphicReceiverType() { | 263 virtual Handle<Map> GetMonomorphicReceiverType() { |
| 265 UNREACHABLE(); | 264 UNREACHABLE(); |
| 266 return Handle<Map>(); | 265 return Handle<Map>(); |
| 267 } | 266 } |
| 268 | 267 |
| 269 // Static type information for this expression. | |
| 270 StaticType* type() { return &type_; } | |
| 271 | |
| 272 // True if the expression is a loop condition. | |
| 273 bool is_loop_condition() const { | |
| 274 return LoopConditionField::decode(bitfields_); | |
| 275 } | |
| 276 void set_is_loop_condition(bool flag) { | |
| 277 bitfields_ = (bitfields_ & ~LoopConditionField::mask()) | | |
| 278 LoopConditionField::encode(flag); | |
| 279 } | |
| 280 | |
| 281 // The value of the expression is guaranteed to be a smi, because the | 268 // The value of the expression is guaranteed to be a smi, because the |
| 282 // top operation is a bit operation with a mask, or a shift. | 269 // top operation is a bit operation with a mask, or a shift. |
| 283 bool GuaranteedSmiResult(); | 270 bool GuaranteedSmiResult(); |
| 284 | |
| 285 // AST analysis results. | |
| 286 void CopyAnalysisResultsFrom(Expression* other); | |
| 287 | |
| 288 // True if the expression rooted at this node can be compiled by the | |
| 289 // side-effect free compiler. | |
| 290 bool side_effect_free() { return SideEffectFreeField::decode(bitfields_); } | |
| 291 void set_side_effect_free(bool is_side_effect_free) { | |
| 292 bitfields_ &= ~SideEffectFreeField::mask(); | |
| 293 bitfields_ |= SideEffectFreeField::encode(is_side_effect_free); | |
| 294 } | |
| 295 | |
| 296 // Will the use of this expression treat -0 the same as 0 in all cases? | |
| 297 // If so, we can return 0 instead of -0 if we want to, to optimize code. | |
| 298 bool no_negative_zero() { return NoNegativeZeroField::decode(bitfields_); } | |
| 299 void set_no_negative_zero(bool no_negative_zero) { | |
| 300 bitfields_ &= ~NoNegativeZeroField::mask(); | |
| 301 bitfields_ |= NoNegativeZeroField::encode(no_negative_zero); | |
| 302 } | |
| 303 | |
| 304 // Will ToInt32 (ECMA 262-3 9.5) or ToUint32 (ECMA 262-3 9.6) | |
| 305 // be applied to the value of this expression? | |
| 306 // If so, we may be able to optimize the calculation of the value. | |
| 307 bool to_int32() { return ToInt32Field::decode(bitfields_); } | |
| 308 void set_to_int32(bool to_int32) { | |
| 309 bitfields_ &= ~ToInt32Field::mask(); | |
| 310 bitfields_ |= ToInt32Field::encode(to_int32); | |
| 311 } | |
| 312 | |
| 313 // How many bitwise logical or shift operators are used in this expression? | |
| 314 int num_bit_ops() { return NumBitOpsField::decode(bitfields_); } | |
| 315 void set_num_bit_ops(int num_bit_ops) { | |
| 316 bitfields_ &= ~NumBitOpsField::mask(); | |
| 317 num_bit_ops = Min(num_bit_ops, kMaxNumBitOps); | |
| 318 bitfields_ |= NumBitOpsField::encode(num_bit_ops); | |
| 319 } | |
| 320 | |
| 321 private: | |
| 322 static const int kMaxNumBitOps = (1 << 5) - 1; | |
| 323 | |
| 324 uint32_t bitfields_; | |
| 325 StaticType type_; | |
| 326 | |
| 327 // Using template BitField<type, start, size>. | |
| 328 class SideEffectFreeField : public BitField<bool, 0, 1> {}; | |
| 329 class NoNegativeZeroField : public BitField<bool, 1, 1> {}; | |
| 330 class ToInt32Field : public BitField<bool, 2, 1> {}; | |
| 331 class NumBitOpsField : public BitField<int, 3, 5> {}; | |
| 332 class LoopConditionField: public BitField<bool, 8, 1> {}; | |
| 333 }; | 271 }; |
| 334 | 272 |
| 335 | 273 |
| 336 /** | 274 /** |
| 337 * A sentinel used during pre parsing that represents some expression | 275 * A sentinel used during pre parsing that represents some expression |
| 338 * that is a valid left hand side without having to actually build | 276 * that is a valid left hand side without having to actually build |
| 339 * the expression. | 277 * the expression. |
| 340 */ | 278 */ |
| 341 class ValidLeftHandSideSentinel: public Expression { | 279 class ValidLeftHandSideSentinel: public Expression { |
| 342 public: | 280 public: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 353 }; | 291 }; |
| 354 | 292 |
| 355 // The labels associated with this statement. May be NULL; | 293 // The labels associated with this statement. May be NULL; |
| 356 // if it is != NULL, guaranteed to contain at least one entry. | 294 // if it is != NULL, guaranteed to contain at least one entry. |
| 357 ZoneStringList* labels() const { return labels_; } | 295 ZoneStringList* labels() const { return labels_; } |
| 358 | 296 |
| 359 // Type testing & conversion. | 297 // Type testing & conversion. |
| 360 virtual BreakableStatement* AsBreakableStatement() { return this; } | 298 virtual BreakableStatement* AsBreakableStatement() { return this; } |
| 361 | 299 |
| 362 // Code generation | 300 // Code generation |
| 363 BreakTarget* break_target() { return &break_target_; } | 301 Label* break_target() { return &break_target_; } |
| 364 | 302 |
| 365 // Testers. | 303 // Testers. |
| 366 bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; } | 304 bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; } |
| 367 | 305 |
| 368 // Bailout support. | 306 // Bailout support. |
| 369 int EntryId() const { return entry_id_; } | 307 int EntryId() const { return entry_id_; } |
| 370 int ExitId() const { return exit_id_; } | 308 int ExitId() const { return exit_id_; } |
| 371 | 309 |
| 372 protected: | 310 protected: |
| 373 inline BreakableStatement(ZoneStringList* labels, Type type); | 311 inline BreakableStatement(ZoneStringList* labels, Type type); |
| 374 | 312 |
| 375 private: | 313 private: |
| 376 ZoneStringList* labels_; | 314 ZoneStringList* labels_; |
| 377 Type type_; | 315 Type type_; |
| 378 BreakTarget break_target_; | 316 Label break_target_; |
| 379 int entry_id_; | 317 int entry_id_; |
| 380 int exit_id_; | 318 int exit_id_; |
| 381 }; | 319 }; |
| 382 | 320 |
| 383 | 321 |
| 384 class Block: public BreakableStatement { | 322 class Block: public BreakableStatement { |
| 385 public: | 323 public: |
| 386 inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block); | 324 inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block); |
| 387 | 325 |
| 388 DECLARE_NODE_TYPE(Block) | 326 DECLARE_NODE_TYPE(Block) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 // Type testing & conversion. | 377 // Type testing & conversion. |
| 440 virtual IterationStatement* AsIterationStatement() { return this; } | 378 virtual IterationStatement* AsIterationStatement() { return this; } |
| 441 | 379 |
| 442 Statement* body() const { return body_; } | 380 Statement* body() const { return body_; } |
| 443 | 381 |
| 444 // Bailout support. | 382 // Bailout support. |
| 445 int OsrEntryId() const { return osr_entry_id_; } | 383 int OsrEntryId() const { return osr_entry_id_; } |
| 446 virtual int ContinueId() const = 0; | 384 virtual int ContinueId() const = 0; |
| 447 | 385 |
| 448 // Code generation | 386 // Code generation |
| 449 BreakTarget* continue_target() { return &continue_target_; } | 387 Label* continue_target() { return &continue_target_; } |
| 450 | 388 |
| 451 protected: | 389 protected: |
| 452 explicit inline IterationStatement(ZoneStringList* labels); | 390 explicit inline IterationStatement(ZoneStringList* labels); |
| 453 | 391 |
| 454 void Initialize(Statement* body) { | 392 void Initialize(Statement* body) { |
| 455 body_ = body; | 393 body_ = body; |
| 456 } | 394 } |
| 457 | 395 |
| 458 private: | 396 private: |
| 459 Statement* body_; | 397 Statement* body_; |
| 460 BreakTarget continue_target_; | 398 Label continue_target_; |
| 461 int osr_entry_id_; | 399 int osr_entry_id_; |
| 462 }; | 400 }; |
| 463 | 401 |
| 464 | 402 |
| 465 class DoWhileStatement: public IterationStatement { | 403 class DoWhileStatement: public IterationStatement { |
| 466 public: | 404 public: |
| 467 explicit inline DoWhileStatement(ZoneStringList* labels); | 405 explicit inline DoWhileStatement(ZoneStringList* labels); |
| 468 | 406 |
| 469 DECLARE_NODE_TYPE(DoWhileStatement) | 407 DECLARE_NODE_TYPE(DoWhileStatement) |
| 470 | 408 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 | 624 |
| 687 class CaseClause: public ZoneObject { | 625 class CaseClause: public ZoneObject { |
| 688 public: | 626 public: |
| 689 CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos); | 627 CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos); |
| 690 | 628 |
| 691 bool is_default() const { return label_ == NULL; } | 629 bool is_default() const { return label_ == NULL; } |
| 692 Expression* label() const { | 630 Expression* label() const { |
| 693 CHECK(!is_default()); | 631 CHECK(!is_default()); |
| 694 return label_; | 632 return label_; |
| 695 } | 633 } |
| 696 JumpTarget* body_target() { return &body_target_; } | 634 Label* body_target() { return &body_target_; } |
| 697 ZoneList<Statement*>* statements() const { return statements_; } | 635 ZoneList<Statement*>* statements() const { return statements_; } |
| 698 | 636 |
| 699 int position() { return position_; } | 637 int position() { return position_; } |
| 700 void set_position(int pos) { position_ = pos; } | 638 void set_position(int pos) { position_ = pos; } |
| 701 | 639 |
| 702 int EntryId() { return entry_id_; } | 640 int EntryId() { return entry_id_; } |
| 703 | 641 |
| 704 // Type feedback information. | 642 // Type feedback information. |
| 705 void RecordTypeFeedback(TypeFeedbackOracle* oracle); | 643 void RecordTypeFeedback(TypeFeedbackOracle* oracle); |
| 706 bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } | 644 bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } |
| 707 bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } | 645 bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } |
| 708 | 646 |
| 709 private: | 647 private: |
| 710 Expression* label_; | 648 Expression* label_; |
| 711 JumpTarget body_target_; | 649 Label body_target_; |
| 712 ZoneList<Statement*>* statements_; | 650 ZoneList<Statement*>* statements_; |
| 713 int position_; | 651 int position_; |
| 714 enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY }; | 652 enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY }; |
| 715 CompareTypeFeedback compare_type_; | 653 CompareTypeFeedback compare_type_; |
| 716 int entry_id_; | 654 int entry_id_; |
| 717 }; | 655 }; |
| 718 | 656 |
| 719 | 657 |
| 720 class SwitchStatement: public BreakableStatement { | 658 class SwitchStatement: public BreakableStatement { |
| 721 public: | 659 public: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 Statement* else_statement_; | 712 Statement* else_statement_; |
| 775 int then_id_; | 713 int then_id_; |
| 776 int else_id_; | 714 int else_id_; |
| 777 }; | 715 }; |
| 778 | 716 |
| 779 | 717 |
| 780 // NOTE: TargetCollectors are represented as nodes to fit in the target | 718 // NOTE: TargetCollectors are represented as nodes to fit in the target |
| 781 // stack in the compiler; this should probably be reworked. | 719 // stack in the compiler; this should probably be reworked. |
| 782 class TargetCollector: public AstNode { | 720 class TargetCollector: public AstNode { |
| 783 public: | 721 public: |
| 784 explicit TargetCollector(ZoneList<BreakTarget*>* targets) | 722 explicit TargetCollector(ZoneList<Label*>* targets) |
| 785 : targets_(targets) { | 723 : targets_(targets) { |
| 786 } | 724 } |
| 787 | 725 |
| 788 // Adds a jump target to the collector. The collector stores a pointer not | 726 // Adds a jump target to the collector. The collector stores a pointer not |
| 789 // a copy of the target to make binding work, so make sure not to pass in | 727 // a copy of the target to make binding work, so make sure not to pass in |
| 790 // references to something on the stack. | 728 // references to something on the stack. |
| 791 void AddTarget(BreakTarget* target); | 729 void AddTarget(Label* target); |
| 792 | 730 |
| 793 // Virtual behaviour. TargetCollectors are never part of the AST. | 731 // Virtual behaviour. TargetCollectors are never part of the AST. |
| 794 virtual void Accept(AstVisitor* v) { UNREACHABLE(); } | 732 virtual void Accept(AstVisitor* v) { UNREACHABLE(); } |
| 795 virtual TargetCollector* AsTargetCollector() { return this; } | 733 virtual TargetCollector* AsTargetCollector() { return this; } |
| 796 | 734 |
| 797 ZoneList<BreakTarget*>* targets() { return targets_; } | 735 ZoneList<Label*>* targets() { return targets_; } |
| 798 | 736 |
| 799 private: | 737 private: |
| 800 ZoneList<BreakTarget*>* targets_; | 738 ZoneList<Label*>* targets_; |
| 801 }; | 739 }; |
| 802 | 740 |
| 803 | 741 |
| 804 class TryStatement: public Statement { | 742 class TryStatement: public Statement { |
| 805 public: | 743 public: |
| 806 explicit TryStatement(Block* try_block) | 744 explicit TryStatement(Block* try_block) |
| 807 : try_block_(try_block), escaping_targets_(NULL) { } | 745 : try_block_(try_block), escaping_targets_(NULL) { } |
| 808 | 746 |
| 809 void set_escaping_targets(ZoneList<BreakTarget*>* targets) { | 747 void set_escaping_targets(ZoneList<Label*>* targets) { |
| 810 escaping_targets_ = targets; | 748 escaping_targets_ = targets; |
| 811 } | 749 } |
| 812 | 750 |
| 813 Block* try_block() const { return try_block_; } | 751 Block* try_block() const { return try_block_; } |
| 814 ZoneList<BreakTarget*>* escaping_targets() const { return escaping_targets_; } | 752 ZoneList<Label*>* escaping_targets() const { return escaping_targets_; } |
| 815 | 753 |
| 816 private: | 754 private: |
| 817 Block* try_block_; | 755 Block* try_block_; |
| 818 ZoneList<BreakTarget*>* escaping_targets_; | 756 ZoneList<Label*>* escaping_targets_; |
| 819 }; | 757 }; |
| 820 | 758 |
| 821 | 759 |
| 822 class TryCatchStatement: public TryStatement { | 760 class TryCatchStatement: public TryStatement { |
| 823 public: | 761 public: |
| 824 TryCatchStatement(Block* try_block, | 762 TryCatchStatement(Block* try_block, |
| 825 VariableProxy* catch_var, | 763 VariableProxy* catch_var, |
| 826 Block* catch_block) | 764 Block* catch_block) |
| 827 : TryStatement(try_block), | 765 : TryStatement(try_block), |
| 828 catch_var_(catch_var), | 766 catch_var_(catch_var), |
| (...skipping 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2225 | 2163 |
| 2226 private: | 2164 private: |
| 2227 Isolate* isolate_; | 2165 Isolate* isolate_; |
| 2228 bool stack_overflow_; | 2166 bool stack_overflow_; |
| 2229 }; | 2167 }; |
| 2230 | 2168 |
| 2231 | 2169 |
| 2232 } } // namespace v8::internal | 2170 } } // namespace v8::internal |
| 2233 | 2171 |
| 2234 #endif // V8_AST_H_ | 2172 #endif // V8_AST_H_ |
| OLD | NEW |