| 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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 | 184 |
| 185 // BinaryOpStub needs to override this. | 185 // BinaryOpStub needs to override this. |
| 186 virtual int GetCodeKind(); | 186 virtual int GetCodeKind(); |
| 187 | 187 |
| 188 // BinaryOpStub needs to override this. | 188 // BinaryOpStub needs to override this. |
| 189 virtual InlineCacheState GetICState() { | 189 virtual InlineCacheState GetICState() { |
| 190 return UNINITIALIZED; | 190 return UNINITIALIZED; |
| 191 } | 191 } |
| 192 | 192 |
| 193 // Returns a name for logging/debugging purposes. | 193 // Returns a name for logging/debugging purposes. |
| 194 virtual const char* GetName() { return MajorName(MajorKey(), false); } | 194 SmartPointer<const char> GetName(); |
| 195 virtual void PrintName(StringStream* stream) { |
| 196 stream->Add("%s", MajorName(MajorKey(), false)); |
| 197 } |
| 195 | 198 |
| 196 // Returns whether the code generated for this stub needs to be allocated as | 199 // Returns whether the code generated for this stub needs to be allocated as |
| 197 // a fixed (non-moveable) code object. | 200 // a fixed (non-moveable) code object. |
| 198 virtual bool NeedsImmovableCode() { return false; } | 201 virtual bool NeedsImmovableCode() { return false; } |
| 199 | 202 |
| 200 #ifdef DEBUG | |
| 201 virtual void Print() { PrintF("%s\n", GetName()); } | |
| 202 #endif | |
| 203 | |
| 204 // Computes the key based on major and minor. | 203 // Computes the key based on major and minor. |
| 205 uint32_t GetKey() { | 204 uint32_t GetKey() { |
| 206 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); | 205 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); |
| 207 return MinorKeyBits::encode(MinorKey()) | | 206 return MinorKeyBits::encode(MinorKey()) | |
| 208 MajorKeyBits::encode(MajorKey()); | 207 MajorKeyBits::encode(MajorKey()); |
| 209 } | 208 } |
| 210 | 209 |
| 211 // See comment above, where Instanceof is defined. | 210 // See comment above, where Instanceof is defined. |
| 212 bool AllowsStubCalls() { return MajorKey() <= Instanceof; } | 211 bool AllowsStubCalls() { return MajorKey() <= Instanceof; } |
| 213 | 212 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 | 364 |
| 366 class InstanceofStub: public CodeStub { | 365 class InstanceofStub: public CodeStub { |
| 367 public: | 366 public: |
| 368 enum Flags { | 367 enum Flags { |
| 369 kNoFlags = 0, | 368 kNoFlags = 0, |
| 370 kArgsInRegisters = 1 << 0, | 369 kArgsInRegisters = 1 << 0, |
| 371 kCallSiteInlineCheck = 1 << 1, | 370 kCallSiteInlineCheck = 1 << 1, |
| 372 kReturnTrueFalseObject = 1 << 2 | 371 kReturnTrueFalseObject = 1 << 2 |
| 373 }; | 372 }; |
| 374 | 373 |
| 375 explicit InstanceofStub(Flags flags) : flags_(flags), name_(NULL) { } | 374 explicit InstanceofStub(Flags flags) : flags_(flags) { } |
| 376 | 375 |
| 377 static Register left(); | 376 static Register left(); |
| 378 static Register right(); | 377 static Register right(); |
| 379 | 378 |
| 380 void Generate(MacroAssembler* masm); | 379 void Generate(MacroAssembler* masm); |
| 381 | 380 |
| 382 private: | 381 private: |
| 383 Major MajorKey() { return Instanceof; } | 382 Major MajorKey() { return Instanceof; } |
| 384 int MinorKey() { return static_cast<int>(flags_); } | 383 int MinorKey() { return static_cast<int>(flags_); } |
| 385 | 384 |
| 386 bool HasArgsInRegisters() const { | 385 bool HasArgsInRegisters() const { |
| 387 return (flags_ & kArgsInRegisters) != 0; | 386 return (flags_ & kArgsInRegisters) != 0; |
| 388 } | 387 } |
| 389 | 388 |
| 390 bool HasCallSiteInlineCheck() const { | 389 bool HasCallSiteInlineCheck() const { |
| 391 return (flags_ & kCallSiteInlineCheck) != 0; | 390 return (flags_ & kCallSiteInlineCheck) != 0; |
| 392 } | 391 } |
| 393 | 392 |
| 394 bool ReturnTrueFalseObject() const { | 393 bool ReturnTrueFalseObject() const { |
| 395 return (flags_ & kReturnTrueFalseObject) != 0; | 394 return (flags_ & kReturnTrueFalseObject) != 0; |
| 396 } | 395 } |
| 397 | 396 |
| 398 virtual const char* GetName(); | 397 virtual void PrintName(StringStream* stream); |
| 399 | 398 |
| 400 Flags flags_; | 399 Flags flags_; |
| 401 char* name_; | |
| 402 }; | 400 }; |
| 403 | 401 |
| 404 | 402 |
| 405 class MathPowStub: public CodeStub { | 403 class MathPowStub: public CodeStub { |
| 406 public: | 404 public: |
| 407 MathPowStub() {} | 405 MathPowStub() {} |
| 408 virtual void Generate(MacroAssembler* masm); | 406 virtual void Generate(MacroAssembler* masm); |
| 409 | 407 |
| 410 private: | 408 private: |
| 411 virtual CodeStub::Major MajorKey() { return MathPow; } | 409 virtual CodeStub::Major MajorKey() { return MathPow; } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 bool strict, | 467 bool strict, |
| 470 CompareFlags flags, | 468 CompareFlags flags, |
| 471 Register lhs, | 469 Register lhs, |
| 472 Register rhs) : | 470 Register rhs) : |
| 473 cc_(cc), | 471 cc_(cc), |
| 474 strict_(strict), | 472 strict_(strict), |
| 475 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), | 473 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), |
| 476 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), | 474 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), |
| 477 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), | 475 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), |
| 478 lhs_(lhs), | 476 lhs_(lhs), |
| 479 rhs_(rhs), | 477 rhs_(rhs) { } |
| 480 name_(NULL) { } | |
| 481 | 478 |
| 482 CompareStub(Condition cc, | 479 CompareStub(Condition cc, |
| 483 bool strict, | 480 bool strict, |
| 484 CompareFlags flags) : | 481 CompareFlags flags) : |
| 485 cc_(cc), | 482 cc_(cc), |
| 486 strict_(strict), | 483 strict_(strict), |
| 487 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), | 484 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), |
| 488 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), | 485 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), |
| 489 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), | 486 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), |
| 490 lhs_(no_reg), | 487 lhs_(no_reg), |
| 491 rhs_(no_reg), | 488 rhs_(no_reg) { } |
| 492 name_(NULL) { } | |
| 493 | 489 |
| 494 void Generate(MacroAssembler* masm); | 490 void Generate(MacroAssembler* masm); |
| 495 | 491 |
| 496 private: | 492 private: |
| 497 Condition cc_; | 493 Condition cc_; |
| 498 bool strict_; | 494 bool strict_; |
| 499 // Only used for 'equal' comparisons. Tells the stub that we already know | 495 // Only used for 'equal' comparisons. Tells the stub that we already know |
| 500 // that at least one side of the comparison is not NaN. This allows the | 496 // that at least one side of the comparison is not NaN. This allows the |
| 501 // stub to use object identity in the positive case. We ignore it when | 497 // stub to use object identity in the positive case. We ignore it when |
| 502 // generating the minor key for other comparisons to avoid creating more | 498 // generating the minor key for other comparisons to avoid creating more |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 } | 532 } |
| 537 | 533 |
| 538 // Branch to the label if the given object isn't a symbol. | 534 // Branch to the label if the given object isn't a symbol. |
| 539 void BranchIfNonSymbol(MacroAssembler* masm, | 535 void BranchIfNonSymbol(MacroAssembler* masm, |
| 540 Label* label, | 536 Label* label, |
| 541 Register object, | 537 Register object, |
| 542 Register scratch); | 538 Register scratch); |
| 543 | 539 |
| 544 // Unfortunately you have to run without snapshots to see most of these | 540 // Unfortunately you have to run without snapshots to see most of these |
| 545 // names in the profile since most compare stubs end up in the snapshot. | 541 // names in the profile since most compare stubs end up in the snapshot. |
| 546 char* name_; | 542 virtual void PrintName(StringStream* stream); |
| 547 virtual const char* GetName(); | |
| 548 #ifdef DEBUG | |
| 549 void Print() { | |
| 550 PrintF("CompareStub (minor %d) (cc %d), (strict %s), " | |
| 551 "(never_nan_nan %s), (smi_compare %s) (number_compare %s) ", | |
| 552 MinorKey(), | |
| 553 static_cast<int>(cc_), | |
| 554 strict_ ? "true" : "false", | |
| 555 never_nan_nan_ ? "true" : "false", | |
| 556 include_smi_compare_ ? "inluded" : "not included", | |
| 557 include_number_compare_ ? "included" : "not included"); | |
| 558 | |
| 559 if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) { | |
| 560 PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code()); | |
| 561 } else { | |
| 562 PrintF("\n"); | |
| 563 } | |
| 564 } | |
| 565 #endif | |
| 566 }; | 543 }; |
| 567 | 544 |
| 568 | 545 |
| 569 class CEntryStub : public CodeStub { | 546 class CEntryStub : public CodeStub { |
| 570 public: | 547 public: |
| 571 explicit CEntryStub(int result_size, | 548 explicit CEntryStub(int result_size, |
| 572 SaveFPRegsMode save_doubles = kDontSaveFPRegs) | 549 SaveFPRegsMode save_doubles = kDontSaveFPRegs) |
| 573 : result_size_(result_size), save_doubles_(save_doubles) { } | 550 : result_size_(result_size), save_doubles_(save_doubles) { } |
| 574 | 551 |
| 575 void Generate(MacroAssembler* masm); | 552 void Generate(MacroAssembler* masm); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 | 590 |
| 614 class JSConstructEntryStub : public JSEntryStub { | 591 class JSConstructEntryStub : public JSEntryStub { |
| 615 public: | 592 public: |
| 616 JSConstructEntryStub() { } | 593 JSConstructEntryStub() { } |
| 617 | 594 |
| 618 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } | 595 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } |
| 619 | 596 |
| 620 private: | 597 private: |
| 621 int MinorKey() { return 1; } | 598 int MinorKey() { return 1; } |
| 622 | 599 |
| 623 virtual const char* GetName() { return "JSConstructEntryStub"; } | 600 virtual void PrintName(StringStream* stream) { |
| 601 stream->Add("JSConstructEntryStub"); |
| 602 } |
| 624 }; | 603 }; |
| 625 | 604 |
| 626 | 605 |
| 627 class ArgumentsAccessStub: public CodeStub { | 606 class ArgumentsAccessStub: public CodeStub { |
| 628 public: | 607 public: |
| 629 enum Type { | 608 enum Type { |
| 630 READ_ELEMENT, | 609 READ_ELEMENT, |
| 631 NEW_NON_STRICT_FAST, | 610 NEW_NON_STRICT_FAST, |
| 632 NEW_NON_STRICT_SLOW, | 611 NEW_NON_STRICT_SLOW, |
| 633 NEW_STRICT | 612 NEW_STRICT |
| 634 }; | 613 }; |
| 635 | 614 |
| 636 explicit ArgumentsAccessStub(Type type) : type_(type) { } | 615 explicit ArgumentsAccessStub(Type type) : type_(type) { } |
| 637 | 616 |
| 638 private: | 617 private: |
| 639 Type type_; | 618 Type type_; |
| 640 | 619 |
| 641 Major MajorKey() { return ArgumentsAccess; } | 620 Major MajorKey() { return ArgumentsAccess; } |
| 642 int MinorKey() { return type_; } | 621 int MinorKey() { return type_; } |
| 643 | 622 |
| 644 void Generate(MacroAssembler* masm); | 623 void Generate(MacroAssembler* masm); |
| 645 void GenerateReadElement(MacroAssembler* masm); | 624 void GenerateReadElement(MacroAssembler* masm); |
| 646 void GenerateNewStrict(MacroAssembler* masm); | 625 void GenerateNewStrict(MacroAssembler* masm); |
| 647 void GenerateNewNonStrictFast(MacroAssembler* masm); | 626 void GenerateNewNonStrictFast(MacroAssembler* masm); |
| 648 void GenerateNewNonStrictSlow(MacroAssembler* masm); | 627 void GenerateNewNonStrictSlow(MacroAssembler* masm); |
| 649 | 628 |
| 650 #ifdef DEBUG | 629 virtual void PrintName(StringStream* stream); |
| 651 void Print() { | |
| 652 PrintF("ArgumentsAccessStub (type %d)\n", type_); | |
| 653 } | |
| 654 #endif | |
| 655 }; | 630 }; |
| 656 | 631 |
| 657 | 632 |
| 658 class RegExpExecStub: public CodeStub { | 633 class RegExpExecStub: public CodeStub { |
| 659 public: | 634 public: |
| 660 RegExpExecStub() { } | 635 RegExpExecStub() { } |
| 661 | 636 |
| 662 private: | 637 private: |
| 663 Major MajorKey() { return RegExpExec; } | 638 Major MajorKey() { return RegExpExec; } |
| 664 int MinorKey() { return 0; } | 639 int MinorKey() { return 0; } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 688 | 663 |
| 689 static int ExtractArgcFromMinorKey(int minor_key) { | 664 static int ExtractArgcFromMinorKey(int minor_key) { |
| 690 return ArgcBits::decode(minor_key); | 665 return ArgcBits::decode(minor_key); |
| 691 } | 666 } |
| 692 | 667 |
| 693 private: | 668 private: |
| 694 int argc_; | 669 int argc_; |
| 695 InLoopFlag in_loop_; | 670 InLoopFlag in_loop_; |
| 696 CallFunctionFlags flags_; | 671 CallFunctionFlags flags_; |
| 697 | 672 |
| 698 #ifdef DEBUG | 673 virtual void PrintName(StringStream* stream); |
| 699 void Print() { | |
| 700 PrintF("CallFunctionStub (args %d, in_loop %d, flags %d)\n", | |
| 701 argc_, | |
| 702 static_cast<int>(in_loop_), | |
| 703 static_cast<int>(flags_)); | |
| 704 } | |
| 705 #endif | |
| 706 | 674 |
| 707 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. | 675 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. |
| 708 class InLoopBits: public BitField<InLoopFlag, 0, 1> {}; | 676 class InLoopBits: public BitField<InLoopFlag, 0, 1> {}; |
| 709 class FlagBits: public BitField<CallFunctionFlags, 1, 1> {}; | 677 class FlagBits: public BitField<CallFunctionFlags, 1, 1> {}; |
| 710 class ArgcBits: public BitField<int, 2, 32 - 2> {}; | 678 class ArgcBits: public BitField<int, 2, 32 - 2> {}; |
| 711 | 679 |
| 712 Major MajorKey() { return CallFunction; } | 680 Major MajorKey() { return CallFunction; } |
| 713 int MinorKey() { | 681 int MinorKey() { |
| 714 // Encode the parameters in a unique 32 bit value. | 682 // Encode the parameters in a unique 32 bit value. |
| 715 return InLoopBits::encode(in_loop_) | 683 return InLoopBits::encode(in_loop_) |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 private: | 903 private: |
| 936 bool is_js_array_; | 904 bool is_js_array_; |
| 937 JSObject::ElementsKind elements_kind_; | 905 JSObject::ElementsKind elements_kind_; |
| 938 | 906 |
| 939 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub); | 907 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub); |
| 940 }; | 908 }; |
| 941 | 909 |
| 942 | 910 |
| 943 class ToBooleanStub: public CodeStub { | 911 class ToBooleanStub: public CodeStub { |
| 944 public: | 912 public: |
| 945 explicit ToBooleanStub(Register tos) : tos_(tos) { } | 913 enum Type { |
| 914 UNDEFINED, |
| 915 BOOLEAN, |
| 916 NULL_TYPE, |
| 917 SMI, |
| 918 SPEC_OBJECT, |
| 919 STRING, |
| 920 HEAP_NUMBER, |
| 921 INTERNAL_OBJECT, |
| 922 NUMBER_OF_TYPES |
| 923 }; |
| 924 |
| 925 // At most 8 different types can be distinguished, because the Code object |
| 926 // only has room for a single byte to hold a set of these types. :-P |
| 927 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); |
| 928 |
| 929 class Types { |
| 930 public: |
| 931 Types() {} |
| 932 explicit Types(byte bits) : set_(bits) {} |
| 933 |
| 934 bool IsEmpty() const { return set_.IsEmpty(); } |
| 935 bool IsAll() const { return ToByte() == ((1 << NUMBER_OF_TYPES) - 1); } |
| 936 bool Contains(Type type) const { return set_.Contains(type); } |
| 937 void Add(Type type) { set_.Add(type); } |
| 938 byte ToByte() const { return set_.ToIntegral(); } |
| 939 void Print(StringStream* stream) const; |
| 940 void TraceTransition(Types to) const; |
| 941 bool Record(Handle<Object> object); |
| 942 bool NeedsMap() const; |
| 943 |
| 944 private: |
| 945 EnumSet<Type, byte> set_; |
| 946 }; |
| 947 |
| 948 static Types no_types() { return Types(); } |
| 949 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); } |
| 950 |
| 951 explicit ToBooleanStub(Register tos, Types types = Types()) |
| 952 : tos_(tos), types_(types) { } |
| 946 | 953 |
| 947 void Generate(MacroAssembler* masm); | 954 void Generate(MacroAssembler* masm); |
| 955 virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; } |
| 956 virtual void PrintName(StringStream* stream); |
| 948 | 957 |
| 949 private: | 958 private: |
| 959 Major MajorKey() { return ToBoolean; } |
| 960 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); } |
| 961 |
| 962 virtual void FinishCode(Code* code) { |
| 963 code->set_to_boolean_state(types_.ToByte()); |
| 964 } |
| 965 |
| 966 void CheckOddball(MacroAssembler* masm, |
| 967 Type type, |
| 968 Heap::RootListIndex value, |
| 969 bool result, |
| 970 Label* patch); |
| 971 void GenerateTypeTransition(MacroAssembler* masm); |
| 972 |
| 950 Register tos_; | 973 Register tos_; |
| 951 Major MajorKey() { return ToBoolean; } | 974 Types types_; |
| 952 int MinorKey() { return tos_.code(); } | |
| 953 }; | 975 }; |
| 954 | 976 |
| 955 } } // namespace v8::internal | 977 } } // namespace v8::internal |
| 956 | 978 |
| 957 #endif // V8_CODE_STUBS_H_ | 979 #endif // V8_CODE_STUBS_H_ |
| OLD | NEW |