OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 virtual void Generate(MacroAssembler* masm); | 475 virtual void Generate(MacroAssembler* masm); |
476 | 476 |
477 private: | 477 private: |
478 virtual CodeStub::Major MajorKey() { return MathPow; } | 478 virtual CodeStub::Major MajorKey() { return MathPow; } |
479 virtual int MinorKey() { return exponent_type_; } | 479 virtual int MinorKey() { return exponent_type_; } |
480 | 480 |
481 ExponentType exponent_type_; | 481 ExponentType exponent_type_; |
482 }; | 482 }; |
483 | 483 |
484 | 484 |
| 485 class BinaryOpStub: public CodeStub { |
| 486 public: |
| 487 BinaryOpStub(Token::Value op, OverwriteMode mode) |
| 488 : op_(op), |
| 489 mode_(mode), |
| 490 platform_specific_bit_(false), |
| 491 left_type_(BinaryOpIC::UNINITIALIZED), |
| 492 right_type_(BinaryOpIC::UNINITIALIZED), |
| 493 result_type_(BinaryOpIC::UNINITIALIZED) { |
| 494 Initialize(); |
| 495 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); |
| 496 } |
| 497 |
| 498 BinaryOpStub( |
| 499 int key, |
| 500 BinaryOpIC::TypeInfo left_type, |
| 501 BinaryOpIC::TypeInfo right_type, |
| 502 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED) |
| 503 : op_(OpBits::decode(key)), |
| 504 mode_(ModeBits::decode(key)), |
| 505 platform_specific_bit_(PlatformSpecificBits::decode(key)), |
| 506 left_type_(left_type), |
| 507 right_type_(right_type), |
| 508 result_type_(result_type) { } |
| 509 |
| 510 static void decode_types_from_minor_key(int minor_key, |
| 511 BinaryOpIC::TypeInfo* left_type, |
| 512 BinaryOpIC::TypeInfo* right_type, |
| 513 BinaryOpIC::TypeInfo* result_type) { |
| 514 *left_type = |
| 515 static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key)); |
| 516 *right_type = |
| 517 static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key)); |
| 518 *result_type = |
| 519 static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key)); |
| 520 } |
| 521 |
| 522 static Token::Value decode_op_from_minor_key(int minor_key) { |
| 523 return static_cast<Token::Value>(OpBits::decode(minor_key)); |
| 524 } |
| 525 |
| 526 enum SmiCodeGenerateHeapNumberResults { |
| 527 ALLOW_HEAPNUMBER_RESULTS, |
| 528 NO_HEAPNUMBER_RESULTS |
| 529 }; |
| 530 |
| 531 private: |
| 532 Token::Value op_; |
| 533 OverwriteMode mode_; |
| 534 bool platform_specific_bit_; // Indicates SSE3 on IA32, VFP2 on ARM. |
| 535 |
| 536 // Operand type information determined at runtime. |
| 537 BinaryOpIC::TypeInfo left_type_; |
| 538 BinaryOpIC::TypeInfo right_type_; |
| 539 BinaryOpIC::TypeInfo result_type_; |
| 540 |
| 541 virtual void PrintName(StringStream* stream); |
| 542 |
| 543 // Minor key encoding in 19 bits TTTRRRLLLSOOOOOOOMM. |
| 544 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; |
| 545 class OpBits: public BitField<Token::Value, 2, 7> {}; |
| 546 class PlatformSpecificBits: public BitField<bool, 9, 1> {}; |
| 547 class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {}; |
| 548 class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {}; |
| 549 class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {}; |
| 550 |
| 551 Major MajorKey() { return BinaryOp; } |
| 552 int MinorKey() { |
| 553 return OpBits::encode(op_) |
| 554 | ModeBits::encode(mode_) |
| 555 | PlatformSpecificBits::encode(platform_specific_bit_) |
| 556 | LeftTypeBits::encode(left_type_) |
| 557 | RightTypeBits::encode(right_type_) |
| 558 | ResultTypeBits::encode(result_type_); |
| 559 } |
| 560 |
| 561 |
| 562 // Platform-independent implementation. |
| 563 void Generate(MacroAssembler* masm); |
| 564 void GenerateCallRuntime(MacroAssembler* masm); |
| 565 |
| 566 // Platform-independent signature, platform-specific implementation. |
| 567 void Initialize(); |
| 568 void GenerateAddStrings(MacroAssembler* masm); |
| 569 void GenerateBothStringStub(MacroAssembler* masm); |
| 570 void GenerateGeneric(MacroAssembler* masm); |
| 571 void GenerateGenericStub(MacroAssembler* masm); |
| 572 void GenerateHeapNumberStub(MacroAssembler* masm); |
| 573 void GenerateInt32Stub(MacroAssembler* masm); |
| 574 void GenerateLoadArguments(MacroAssembler* masm); |
| 575 void GenerateOddballStub(MacroAssembler* masm); |
| 576 void GenerateRegisterArgsPush(MacroAssembler* masm); |
| 577 void GenerateReturn(MacroAssembler* masm); |
| 578 void GenerateSmiStub(MacroAssembler* masm); |
| 579 void GenerateStringStub(MacroAssembler* masm); |
| 580 void GenerateTypeTransition(MacroAssembler* masm); |
| 581 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm); |
| 582 void GenerateUninitializedStub(MacroAssembler* masm); |
| 583 |
| 584 // Entirely platform-specific methods are defined as static helper |
| 585 // functions in the <arch>/code-stubs-<arch>.cc files. |
| 586 |
| 587 virtual int GetCodeKind() { return Code::BINARY_OP_IC; } |
| 588 |
| 589 virtual InlineCacheState GetICState() { |
| 590 return BinaryOpIC::ToState(Max(left_type_, right_type_)); |
| 591 } |
| 592 |
| 593 virtual void FinishCode(Handle<Code> code) { |
| 594 code->set_stub_info(MinorKey()); |
| 595 } |
| 596 |
| 597 friend class CodeGenerator; |
| 598 }; |
| 599 |
| 600 |
485 class ICCompareStub: public CodeStub { | 601 class ICCompareStub: public CodeStub { |
486 public: | 602 public: |
487 ICCompareStub(Token::Value op, CompareIC::State state) | 603 ICCompareStub(Token::Value op, |
488 : op_(op), state_(state) { | 604 CompareIC::State left, |
| 605 CompareIC::State right, |
| 606 CompareIC::State handler) |
| 607 : op_(op), |
| 608 left_(left), |
| 609 right_(right), |
| 610 state_(handler) { |
489 ASSERT(Token::IsCompareOp(op)); | 611 ASSERT(Token::IsCompareOp(op)); |
490 } | 612 } |
491 | 613 |
492 virtual void Generate(MacroAssembler* masm); | 614 virtual void Generate(MacroAssembler* masm); |
493 | 615 |
494 void set_known_map(Handle<Map> map) { known_map_ = map; } | 616 void set_known_map(Handle<Map> map) { known_map_ = map; } |
495 | 617 |
| 618 static void DecodeMinorKey(int minor_key, |
| 619 CompareIC::State* left_state, |
| 620 CompareIC::State* right_state, |
| 621 CompareIC::State* handler_state, |
| 622 Token::Value* op); |
| 623 |
| 624 static CompareIC::State CompareState(int minor_key) { |
| 625 return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key)); |
| 626 } |
| 627 |
496 private: | 628 private: |
497 class OpField: public BitField<int, 0, 3> { }; | 629 class OpField: public BitField<int, 0, 3> { }; |
498 class StateField: public BitField<int, 3, 5> { }; | 630 class LeftStateField: public BitField<int, 3, 3> { }; |
| 631 class RightStateField: public BitField<int, 6, 3> { }; |
| 632 class HandlerStateField: public BitField<int, 9, 3> { }; |
499 | 633 |
500 virtual void FinishCode(Handle<Code> code) { | 634 virtual void FinishCode(Handle<Code> code) { |
501 code->set_compare_state(state_); | 635 code->set_stub_info(MinorKey()); |
502 code->set_compare_operation(op_ - Token::EQ); | |
503 } | 636 } |
504 | 637 |
505 virtual CodeStub::Major MajorKey() { return CompareIC; } | 638 virtual CodeStub::Major MajorKey() { return CompareIC; } |
506 virtual int MinorKey(); | 639 virtual int MinorKey(); |
507 | 640 |
508 virtual int GetCodeKind() { return Code::COMPARE_IC; } | 641 virtual int GetCodeKind() { return Code::COMPARE_IC; } |
509 | 642 |
510 void GenerateSmis(MacroAssembler* masm); | 643 void GenerateSmis(MacroAssembler* masm); |
511 void GenerateHeapNumbers(MacroAssembler* masm); | 644 void GenerateHeapNumbers(MacroAssembler* masm); |
512 void GenerateSymbols(MacroAssembler* masm); | 645 void GenerateSymbols(MacroAssembler* masm); |
513 void GenerateStrings(MacroAssembler* masm); | 646 void GenerateStrings(MacroAssembler* masm); |
514 void GenerateObjects(MacroAssembler* masm); | 647 void GenerateObjects(MacroAssembler* masm); |
515 void GenerateMiss(MacroAssembler* masm); | 648 void GenerateMiss(MacroAssembler* masm); |
516 void GenerateKnownObjects(MacroAssembler* masm); | 649 void GenerateKnownObjects(MacroAssembler* masm); |
| 650 void GenerateGeneric(MacroAssembler* masm); |
517 | 651 |
518 bool strict() const { return op_ == Token::EQ_STRICT; } | 652 bool strict() const { return op_ == Token::EQ_STRICT; } |
519 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); } | 653 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); } |
520 | 654 |
521 virtual void AddToSpecialCache(Handle<Code> new_object); | 655 virtual void AddToSpecialCache(Handle<Code> new_object); |
522 virtual bool FindCodeInSpecialCache(Code** code_out); | 656 virtual bool FindCodeInSpecialCache(Code** code_out); |
523 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; } | 657 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; } |
524 | 658 |
525 Token::Value op_; | 659 Token::Value op_; |
| 660 CompareIC::State left_; |
| 661 CompareIC::State right_; |
526 CompareIC::State state_; | 662 CompareIC::State state_; |
527 Handle<Map> known_map_; | 663 Handle<Map> known_map_; |
528 }; | 664 }; |
529 | 665 |
530 | 666 |
531 // Flags that control the compare stub code generation. | |
532 enum CompareFlags { | |
533 NO_COMPARE_FLAGS = 0, | |
534 NO_SMI_COMPARE_IN_STUB = 1 << 0, | |
535 NO_NUMBER_COMPARE_IN_STUB = 1 << 1, | |
536 CANT_BOTH_BE_NAN = 1 << 2 | |
537 }; | |
538 | |
539 | |
540 enum NaNInformation { | |
541 kBothCouldBeNaN, | |
542 kCantBothBeNaN | |
543 }; | |
544 | |
545 | |
546 class CompareStub: public CodeStub { | |
547 public: | |
548 CompareStub(Condition cc, | |
549 bool strict, | |
550 CompareFlags flags, | |
551 Register lhs, | |
552 Register rhs) : | |
553 cc_(cc), | |
554 strict_(strict), | |
555 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), | |
556 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), | |
557 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), | |
558 lhs_(lhs), | |
559 rhs_(rhs) { } | |
560 | |
561 CompareStub(Condition cc, | |
562 bool strict, | |
563 CompareFlags flags) : | |
564 cc_(cc), | |
565 strict_(strict), | |
566 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0), | |
567 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0), | |
568 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0), | |
569 lhs_(no_reg), | |
570 rhs_(no_reg) { } | |
571 | |
572 void Generate(MacroAssembler* masm); | |
573 | |
574 private: | |
575 Condition cc_; | |
576 bool strict_; | |
577 // Only used for 'equal' comparisons. Tells the stub that we already know | |
578 // that at least one side of the comparison is not NaN. This allows the | |
579 // stub to use object identity in the positive case. We ignore it when | |
580 // generating the minor key for other comparisons to avoid creating more | |
581 // stubs. | |
582 bool never_nan_nan_; | |
583 // Do generate the number comparison code in the stub. Stubs without number | |
584 // comparison code is used when the number comparison has been inlined, and | |
585 // the stub will be called if one of the operands is not a number. | |
586 bool include_number_compare_; | |
587 | |
588 // Generate the comparison code for two smi operands in the stub. | |
589 bool include_smi_compare_; | |
590 | |
591 // Register holding the left hand side of the comparison if the stub gives | |
592 // a choice, no_reg otherwise. | |
593 | |
594 Register lhs_; | |
595 // Register holding the right hand side of the comparison if the stub gives | |
596 // a choice, no_reg otherwise. | |
597 Register rhs_; | |
598 | |
599 // Encoding of the minor key in 16 bits. | |
600 class StrictField: public BitField<bool, 0, 1> {}; | |
601 class NeverNanNanField: public BitField<bool, 1, 1> {}; | |
602 class IncludeNumberCompareField: public BitField<bool, 2, 1> {}; | |
603 class IncludeSmiCompareField: public BitField<bool, 3, 1> {}; | |
604 class RegisterField: public BitField<bool, 4, 1> {}; | |
605 class ConditionField: public BitField<int, 5, 11> {}; | |
606 | |
607 Major MajorKey() { return Compare; } | |
608 | |
609 int MinorKey(); | |
610 | |
611 virtual int GetCodeKind() { return Code::COMPARE_IC; } | |
612 virtual void FinishCode(Handle<Code> code) { | |
613 code->set_compare_state(CompareIC::GENERIC); | |
614 } | |
615 | |
616 // Branch to the label if the given object isn't a symbol. | |
617 void BranchIfNonSymbol(MacroAssembler* masm, | |
618 Label* label, | |
619 Register object, | |
620 Register scratch); | |
621 | |
622 // Unfortunately you have to run without snapshots to see most of these | |
623 // names in the profile since most compare stubs end up in the snapshot. | |
624 virtual void PrintName(StringStream* stream); | |
625 }; | |
626 | |
627 | |
628 class CEntryStub : public CodeStub { | 667 class CEntryStub : public CodeStub { |
629 public: | 668 public: |
630 explicit CEntryStub(int result_size, | 669 explicit CEntryStub(int result_size, |
631 SaveFPRegsMode save_doubles = kDontSaveFPRegs) | 670 SaveFPRegsMode save_doubles = kDontSaveFPRegs) |
632 : result_size_(result_size), save_doubles_(save_doubles) { } | 671 : result_size_(result_size), save_doubles_(save_doubles) { } |
633 | 672 |
634 void Generate(MacroAssembler* masm); | 673 void Generate(MacroAssembler* masm); |
635 | 674 |
636 // The version of this stub that doesn't save doubles is generated ahead of | 675 // The version of this stub that doesn't save doubles is generated ahead of |
637 // time, so it's OK to call it from other stubs that can't cope with GC during | 676 // time, so it's OK to call it from other stubs that can't cope with GC during |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 // only has room for a single byte to hold a set of these types. :-P | 1085 // only has room for a single byte to hold a set of these types. :-P |
1047 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); | 1086 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); |
1048 | 1087 |
1049 class Types { | 1088 class Types { |
1050 public: | 1089 public: |
1051 Types() {} | 1090 Types() {} |
1052 explicit Types(byte bits) : set_(bits) {} | 1091 explicit Types(byte bits) : set_(bits) {} |
1053 | 1092 |
1054 bool IsEmpty() const { return set_.IsEmpty(); } | 1093 bool IsEmpty() const { return set_.IsEmpty(); } |
1055 bool Contains(Type type) const { return set_.Contains(type); } | 1094 bool Contains(Type type) const { return set_.Contains(type); } |
| 1095 bool ContainsAnyOf(Types types) const { |
| 1096 return set_.ContainsAnyOf(types.set_); |
| 1097 } |
1056 void Add(Type type) { set_.Add(type); } | 1098 void Add(Type type) { set_.Add(type); } |
1057 byte ToByte() const { return set_.ToIntegral(); } | 1099 byte ToByte() const { return set_.ToIntegral(); } |
1058 void Print(StringStream* stream) const; | 1100 void Print(StringStream* stream) const; |
1059 void TraceTransition(Types to) const; | 1101 void TraceTransition(Types to) const; |
1060 bool Record(Handle<Object> object); | 1102 bool Record(Handle<Object> object); |
1061 bool NeedsMap() const; | 1103 bool NeedsMap() const; |
1062 bool CanBeUndetectable() const; | 1104 bool CanBeUndetectable() const; |
1063 | 1105 |
1064 private: | 1106 private: |
1065 EnumSet<Type, byte> set_; | 1107 EnumSet<Type, byte> set_; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 | 1226 |
1185 // The current function entry hook. | 1227 // The current function entry hook. |
1186 static FunctionEntryHook entry_hook_; | 1228 static FunctionEntryHook entry_hook_; |
1187 | 1229 |
1188 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); | 1230 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); |
1189 }; | 1231 }; |
1190 | 1232 |
1191 } } // namespace v8::internal | 1233 } } // namespace v8::internal |
1192 | 1234 |
1193 #endif // V8_CODE_STUBS_H_ | 1235 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |