Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: src/mips/assembler-mips.h

Issue 7239020: MIPS: Long branch implementation and trampoline improvement. (Closed)
Patch Set: Update per comments, refactor buffer-growth-blocking for internal refs. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/mips/assembler-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 // 474 //
475 // Label L; // unbound label 475 // Label L; // unbound label
476 // j(cc, &L); // forward branch to unbound label 476 // j(cc, &L); // forward branch to unbound label
477 // bind(&L); // bind label to the current pc 477 // bind(&L); // bind label to the current pc
478 // j(cc, &L); // backward branch to bound label 478 // j(cc, &L); // backward branch to bound label
479 // bind(&L); // illegal: a label may be bound only once 479 // bind(&L); // illegal: a label may be bound only once
480 // 480 //
481 // Note: The same Label can be used for forward and backward branches 481 // Note: The same Label can be used for forward and backward branches
482 // but it may be bound only once. 482 // but it may be bound only once.
483 void bind(Label* L); // Binds an unbound label L to current code position. 483 void bind(Label* L); // Binds an unbound label L to current code position.
484 // Determines if Label is bound and near enough so that branch instruction
485 // can be used to reach it, instead of jump instruction.
486 bool is_near(Label* L);
484 487
485 // Returns the branch offset to the given label from the current code 488 // Returns the branch offset to the given label from the current code
486 // position. Links the label to the current position if it is still unbound. 489 // position. Links the label to the current position if it is still unbound.
487 // Manages the jump elimination optimization if the second parameter is true. 490 // Manages the jump elimination optimization if the second parameter is true.
488 int32_t branch_offset(Label* L, bool jump_elimination_allowed); 491 int32_t branch_offset(Label* L, bool jump_elimination_allowed);
489 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { 492 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) {
490 int32_t o = branch_offset(L, jump_elimination_allowed); 493 int32_t o = branch_offset(L, jump_elimination_allowed);
491 ASSERT((o & 3) == 0); // Assert the offset is aligned. 494 ASSERT((o & 3) == 0); // Assert the offset is aligned.
492 return o >> 2; 495 return o >> 2;
493 } 496 }
497 uint32_t jump_address(Label* L);
494 498
495 // Puts a labels target address at the given position. 499 // Puts a labels target address at the given position.
496 // The high 8 bits are set to zero. 500 // The high 8 bits are set to zero.
497 void label_at_put(Label* L, int at_offset); 501 void label_at_put(Label* L, int at_offset);
498 502
499 // Read/Modify the code target address in the branch/call instruction at pc. 503 // Read/Modify the code target address in the branch/call instruction at pc.
500 static Address target_address_at(Address pc); 504 static Address target_address_at(Address pc);
501 static void set_target_address_at(Address pc, Address target); 505 static void set_target_address_at(Address pc, Address target);
502 506
503 // This sets the branch destination (which gets loaded at the call address). 507 // This sets the branch destination (which gets loaded at the call address).
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 ~BlockTrampolinePoolScope() { 792 ~BlockTrampolinePoolScope() {
789 assem_->EndBlockTrampolinePool(); 793 assem_->EndBlockTrampolinePool();
790 } 794 }
791 795
792 private: 796 private:
793 Assembler* assem_; 797 Assembler* assem_;
794 798
795 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 799 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
796 }; 800 };
797 801
802 // Class for postponing the assembly buffer growth. Typically used for
803 // sequences of instructions that must be emitted as a unit, before
804 // buffer growth (and relocation) can occur.
805 // This blocking scope is not nestable.
806 class BlockGrowBufferScope {
807 public:
808 explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
809 assem_->StartBlockGrowBuffer();
810 }
811 ~BlockGrowBufferScope() {
812 assem_->EndBlockGrowBuffer();
813 }
814
815 private:
816 Assembler* assem_;
817
818 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
819 };
820
798 // Debugging. 821 // Debugging.
799 822
800 // Mark address of the ExitJSFrame code. 823 // Mark address of the ExitJSFrame code.
801 void RecordJSReturn(); 824 void RecordJSReturn();
802 825
803 // Mark address of a debug break slot. 826 // Mark address of a debug break slot.
804 void RecordDebugBreakSlot(); 827 void RecordDebugBreakSlot();
805 828
806 // Record the AST id of the CallIC being compiled, so that it can be placed 829 // Record the AST id of the CallIC being compiled, so that it can be placed
807 // in the relocation information. 830 // in the relocation information.
808 void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; } 831 void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
809 832
810 // Record a comment relocation entry that can be used by a disassembler. 833 // Record a comment relocation entry that can be used by a disassembler.
811 // Use --code-comments to enable. 834 // Use --code-comments to enable.
812 void RecordComment(const char* msg); 835 void RecordComment(const char* msg);
813 836
837 static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
838
814 // Writes a single byte or word of data in the code stream. Used for 839 // Writes a single byte or word of data in the code stream. Used for
815 // inline tables, e.g., jump-tables. 840 // inline tables, e.g., jump-tables.
816 void db(uint8_t data); 841 void db(uint8_t data);
817 void dd(uint32_t data); 842 void dd(uint32_t data);
818 843
819 int32_t pc_offset() const { return pc_ - buffer_; } 844 int32_t pc_offset() const { return pc_ - buffer_; }
820 845
821 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 846 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
822 847
823 // Postpone the generation of the trampoline pool for the specified number of 848 // Postpone the generation of the trampoline pool for the specified number of
(...skipping 16 matching lines...) Expand all
840 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 865 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
841 void instr_at_put(int pos, Instr instr) { 866 void instr_at_put(int pos, Instr instr) {
842 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 867 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
843 } 868 }
844 869
845 // Check if an instruction is a branch of some kind. 870 // Check if an instruction is a branch of some kind.
846 static bool IsBranch(Instr instr); 871 static bool IsBranch(Instr instr);
847 static bool IsBeq(Instr instr); 872 static bool IsBeq(Instr instr);
848 static bool IsBne(Instr instr); 873 static bool IsBne(Instr instr);
849 874
875 static bool IsJump(Instr instr);
876 static bool IsJ(Instr instr);
877 static bool IsLui(Instr instr);
878 static bool IsOri(Instr instr);
879
850 static bool IsNop(Instr instr, unsigned int type); 880 static bool IsNop(Instr instr, unsigned int type);
851 static bool IsPop(Instr instr); 881 static bool IsPop(Instr instr);
852 static bool IsPush(Instr instr); 882 static bool IsPush(Instr instr);
853 static bool IsLwRegFpOffset(Instr instr); 883 static bool IsLwRegFpOffset(Instr instr);
854 static bool IsSwRegFpOffset(Instr instr); 884 static bool IsSwRegFpOffset(Instr instr);
855 static bool IsLwRegFpNegOffset(Instr instr); 885 static bool IsLwRegFpNegOffset(Instr instr);
856 static bool IsSwRegFpNegOffset(Instr instr); 886 static bool IsSwRegFpNegOffset(Instr instr);
857 887
858 static Register GetRtReg(Instr instr); 888 static Register GetRtReg(Instr instr);
859 static Register GetRsReg(Instr instr); 889 static Register GetRsReg(Instr instr);
860 static Register GetRdReg(Instr instr); 890 static Register GetRdReg(Instr instr);
861 891
862 static uint32_t GetRt(Instr instr); 892 static uint32_t GetRt(Instr instr);
863 static uint32_t GetRtField(Instr instr); 893 static uint32_t GetRtField(Instr instr);
864 static uint32_t GetRs(Instr instr); 894 static uint32_t GetRs(Instr instr);
865 static uint32_t GetRsField(Instr instr); 895 static uint32_t GetRsField(Instr instr);
866 static uint32_t GetRd(Instr instr); 896 static uint32_t GetRd(Instr instr);
867 static uint32_t GetRdField(Instr instr); 897 static uint32_t GetRdField(Instr instr);
868 static uint32_t GetSa(Instr instr); 898 static uint32_t GetSa(Instr instr);
869 static uint32_t GetSaField(Instr instr); 899 static uint32_t GetSaField(Instr instr);
870 static uint32_t GetOpcodeField(Instr instr); 900 static uint32_t GetOpcodeField(Instr instr);
901 static uint32_t GetFunction(Instr instr);
902 static uint32_t GetFunctionField(Instr instr);
871 static uint32_t GetImmediate16(Instr instr); 903 static uint32_t GetImmediate16(Instr instr);
872 static uint32_t GetLabelConst(Instr instr); 904 static uint32_t GetLabelConst(Instr instr);
873 905
874 static int32_t GetBranchOffset(Instr instr); 906 static int32_t GetBranchOffset(Instr instr);
875 static bool IsLw(Instr instr); 907 static bool IsLw(Instr instr);
876 static int16_t GetLwOffset(Instr instr); 908 static int16_t GetLwOffset(Instr instr);
877 static Instr SetLwOffset(Instr instr, int16_t offset); 909 static Instr SetLwOffset(Instr instr, int16_t offset);
878 910
879 static bool IsSw(Instr instr); 911 static bool IsSw(Instr instr);
880 static Instr SetSwOffset(Instr instr, int16_t offset); 912 static Instr SetSwOffset(Instr instr, int16_t offset);
881 static bool IsAddImmediate(Instr instr); 913 static bool IsAddImmediate(Instr instr);
882 static Instr SetAddImmediateOffset(Instr instr, int16_t offset); 914 static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
883 915
884 static bool IsAndImmediate(Instr instr); 916 static bool IsAndImmediate(Instr instr);
885 917
886 void CheckTrampolinePool(bool force_emit = false); 918 void CheckTrampolinePool();
887 919
888 protected: 920 protected:
889 // Relocation for a type-recording IC has the AST id added to it. This 921 // Relocation for a type-recording IC has the AST id added to it. This
890 // member variable is a way to pass the information from the call site to 922 // member variable is a way to pass the information from the call site to
891 // the relocation info. 923 // the relocation info.
892 unsigned ast_id_for_reloc_info_; 924 unsigned ast_id_for_reloc_info_;
893 925
894 bool emit_debug_code() const { return emit_debug_code_; } 926 bool emit_debug_code() const { return emit_debug_code_; }
895 927
896 int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } 928 int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
(...skipping 12 matching lines...) Expand all
909 941
910 // Block the emission of the trampoline pool before pc_offset. 942 // Block the emission of the trampoline pool before pc_offset.
911 void BlockTrampolinePoolBefore(int pc_offset) { 943 void BlockTrampolinePoolBefore(int pc_offset) {
912 if (no_trampoline_pool_before_ < pc_offset) 944 if (no_trampoline_pool_before_ < pc_offset)
913 no_trampoline_pool_before_ = pc_offset; 945 no_trampoline_pool_before_ = pc_offset;
914 } 946 }
915 947
916 void StartBlockTrampolinePool() { 948 void StartBlockTrampolinePool() {
917 trampoline_pool_blocked_nesting_++; 949 trampoline_pool_blocked_nesting_++;
918 } 950 }
951
919 void EndBlockTrampolinePool() { 952 void EndBlockTrampolinePool() {
920 trampoline_pool_blocked_nesting_--; 953 trampoline_pool_blocked_nesting_--;
921 } 954 }
922 955
923 bool is_trampoline_pool_blocked() const { 956 bool is_trampoline_pool_blocked() const {
924 return trampoline_pool_blocked_nesting_ > 0; 957 return trampoline_pool_blocked_nesting_ > 0;
925 } 958 }
926 959
927 bool has_exception() const { 960 bool has_exception() const {
928 return internal_trampoline_exception_; 961 return internal_trampoline_exception_;
929 } 962 }
930 963
964 bool is_trampoline_emitted() const {
965 return trampoline_emitted_;
966 }
967
968 // Temporarily block automatic assembly buffer growth.
969 void StartBlockGrowBuffer() {
970 ASSERT(!block_buffer_growth_);
971 block_buffer_growth_ = true;
972 }
973
974 void EndBlockGrowBuffer() {
975 ASSERT(block_buffer_growth_);
976 block_buffer_growth_ = false;
977 }
978
979 bool is_buffer_growth_blocked() const {
980 return block_buffer_growth_;
981 }
982
931 private: 983 private:
932 // Code buffer: 984 // Code buffer:
933 // The buffer into which code and relocation info are generated. 985 // The buffer into which code and relocation info are generated.
934 byte* buffer_; 986 byte* buffer_;
935 int buffer_size_; 987 int buffer_size_;
936 // True if the assembler owns the buffer, false if buffer is external. 988 // True if the assembler owns the buffer, false if buffer is external.
937 bool own_buffer_; 989 bool own_buffer_;
938 990
939 // Buffer size and constant pool distance are checked together at regular 991 // Buffer size and constant pool distance are checked together at regular
940 // intervals of kBufferCheckInterval emitted bytes. 992 // intervals of kBufferCheckInterval emitted bytes.
(...skipping 16 matching lines...) Expand all
957 1009
958 int next_buffer_check_; // pc offset of next buffer check. 1010 int next_buffer_check_; // pc offset of next buffer check.
959 1011
960 // Emission of the trampoline pool may be blocked in some code sequences. 1012 // Emission of the trampoline pool may be blocked in some code sequences.
961 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 1013 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
962 int no_trampoline_pool_before_; // Block emission before this pc offset. 1014 int no_trampoline_pool_before_; // Block emission before this pc offset.
963 1015
964 // Keep track of the last emitted pool to guarantee a maximal distance. 1016 // Keep track of the last emitted pool to guarantee a maximal distance.
965 int last_trampoline_pool_end_; // pc offset of the end of the last pool. 1017 int last_trampoline_pool_end_; // pc offset of the end of the last pool.
966 1018
1019 // Automatic growth of the assembly buffer may be blocked for some sequences.
1020 bool block_buffer_growth_; // Block growth when true.
1021
967 // Relocation information generation. 1022 // Relocation information generation.
968 // Each relocation is encoded as a variable size value. 1023 // Each relocation is encoded as a variable size value.
969 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1024 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
970 RelocInfoWriter reloc_info_writer; 1025 RelocInfoWriter reloc_info_writer;
971 1026
972 // The bound position, before this we cannot do instruction elimination. 1027 // The bound position, before this we cannot do instruction elimination.
973 int last_bound_pos_; 1028 int last_bound_pos_;
974 1029
975 // Code emission. 1030 // Code emission.
976 inline void CheckBuffer(); 1031 inline void CheckBuffer();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 1092
1038 void GenInstrJump(Opcode opcode, 1093 void GenInstrJump(Opcode opcode,
1039 uint32_t address); 1094 uint32_t address);
1040 1095
1041 // Helpers. 1096 // Helpers.
1042 void LoadRegPlusOffsetToAt(const MemOperand& src); 1097 void LoadRegPlusOffsetToAt(const MemOperand& src);
1043 1098
1044 // Labels. 1099 // Labels.
1045 void print(Label* L); 1100 void print(Label* L);
1046 void bind_to(Label* L, int pos); 1101 void bind_to(Label* L, int pos);
1047 void link_to(Label* L, Label* appendix);
1048 void next(Label* L); 1102 void next(Label* L);
1049 1103
1050 // One trampoline consists of: 1104 // One trampoline consists of:
1051 // - space for trampoline slots, 1105 // - space for trampoline slots,
1052 // - space for labels. 1106 // - space for labels.
1053 // 1107 //
1054 // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. 1108 // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
1055 // Space for trampoline slots preceeds space for labels. Each label is of one 1109 // Space for trampoline slots preceeds space for labels. Each label is of one
1056 // instruction size, so total amount for labels is equal to 1110 // instruction size, so total amount for labels is equal to
1057 // label_count * kInstrSize. 1111 // label_count * kInstrSize.
1058 class Trampoline { 1112 class Trampoline {
1059 public: 1113 public:
1060 Trampoline(int start, int slot_count, int label_count) { 1114 Trampoline() {
1115 start_ = 0;
1116 next_slot_ = 0;
1117 free_slot_count_ = 0;
1118 end_ = 0;
1119 }
1120 Trampoline(int start, int slot_count) {
1061 start_ = start; 1121 start_ = start;
1062 next_slot_ = start; 1122 next_slot_ = start;
1063 free_slot_count_ = slot_count; 1123 free_slot_count_ = slot_count;
1064 next_label_ = start + slot_count * 2 * kInstrSize; 1124 end_ = start + slot_count * kTrampolineSlotsSize;
1065 free_label_count_ = label_count;
1066 end_ = next_label_ + (label_count - 1) * kInstrSize;
1067 } 1125 }
1068 int start() { 1126 int start() {
1069 return start_; 1127 return start_;
1070 } 1128 }
1071 int end() { 1129 int end() {
1072 return end_; 1130 return end_;
1073 } 1131 }
1074 int take_slot() { 1132 int take_slot() {
1075 int trampoline_slot = kInvalidSlotPos; 1133 int trampoline_slot = kInvalidSlotPos;
1076 if (free_slot_count_ <= 0) { 1134 if (free_slot_count_ <= 0) {
1077 // We have run out of space on trampolines. 1135 // We have run out of space on trampolines.
1078 // Make sure we fail in debug mode, so we become aware of each case 1136 // Make sure we fail in debug mode, so we become aware of each case
1079 // when this happens. 1137 // when this happens.
1080 ASSERT(0); 1138 ASSERT(0);
1081 // Internal exception will be caught. 1139 // Internal exception will be caught.
1082 } else { 1140 } else {
1083 trampoline_slot = next_slot_; 1141 trampoline_slot = next_slot_;
1084 free_slot_count_--; 1142 free_slot_count_--;
1085 next_slot_ += 2*kInstrSize; 1143 next_slot_ += kTrampolineSlotsSize;
1086 } 1144 }
1087 return trampoline_slot; 1145 return trampoline_slot;
1088 } 1146 }
1089 int take_label() {
1090 int label_pos = next_label_;
1091 ASSERT(free_label_count_ > 0);
1092 free_label_count_--;
1093 next_label_ += kInstrSize;
1094 return label_pos;
1095 }
1096
1097 private: 1147 private:
1098 int start_; 1148 int start_;
1099 int end_; 1149 int end_;
1100 int next_slot_; 1150 int next_slot_;
1101 int free_slot_count_; 1151 int free_slot_count_;
1102 int next_label_;
1103 int free_label_count_;
1104 }; 1152 };
1105 1153
1106 int32_t get_label_entry(int32_t pos, bool next_pool = true); 1154 int32_t get_trampoline_entry(int32_t pos);
1107 int32_t get_trampoline_entry(int32_t pos, bool next_pool = true); 1155 int unbound_labels_count_;
1108 1156 // If trampoline is emitted, generated code is becoming large. As this is
1109 static const int kSlotsPerTrampoline = 2304; 1157 // already a slow case which can possibly break our code generation for the
1110 static const int kLabelsPerTrampoline = 8; 1158 // extreme case, we use this information to trigger different mode of
1111 static const int kTrampolineInst = 1159 // branch instruction generation, where we use jump instructions rather
1112 2 * kSlotsPerTrampoline + kLabelsPerTrampoline; 1160 // than regular branch instructions.
1113 static const int kTrampolineSize = kTrampolineInst * kInstrSize; 1161 bool trampoline_emitted_;
1162 static const int kTrampolineSlotsSize = 4 * kInstrSize;
1114 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 1163 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
1115 static const int kMaxDistBetweenPools =
1116 kMaxBranchOffset - 2 * kTrampolineSize;
1117 static const int kInvalidSlotPos = -1; 1164 static const int kInvalidSlotPos = -1;
1118 1165
1119 List<Trampoline> trampolines_; 1166 Trampoline trampoline_;
1120 bool internal_trampoline_exception_; 1167 bool internal_trampoline_exception_;
1121 1168
1122 friend class RegExpMacroAssemblerMIPS; 1169 friend class RegExpMacroAssemblerMIPS;
1123 friend class RelocInfo; 1170 friend class RelocInfo;
1124 friend class CodePatcher; 1171 friend class CodePatcher;
1125 friend class BlockTrampolinePoolScope; 1172 friend class BlockTrampolinePoolScope;
1126 1173
1127 PositionsRecorder positions_recorder_; 1174 PositionsRecorder positions_recorder_;
1128 bool emit_debug_code_; 1175 bool emit_debug_code_;
1129 friend class PositionsRecorder; 1176 friend class PositionsRecorder;
1130 friend class EnsureSpace; 1177 friend class EnsureSpace;
1131 }; 1178 };
1132 1179
1133 1180
1134 class EnsureSpace BASE_EMBEDDED { 1181 class EnsureSpace BASE_EMBEDDED {
1135 public: 1182 public:
1136 explicit EnsureSpace(Assembler* assembler) { 1183 explicit EnsureSpace(Assembler* assembler) {
1137 assembler->CheckBuffer(); 1184 assembler->CheckBuffer();
1138 } 1185 }
1139 }; 1186 };
1140 1187
1141 } } // namespace v8::internal 1188 } } // namespace v8::internal
1142 1189
1143 #endif // V8_ARM_ASSEMBLER_MIPS_H_ 1190 #endif // V8_ARM_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « no previous file | src/mips/assembler-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698