 Chromium Code Reviews
 Chromium Code Reviews Issue 1131783003:
  Embedded constant pools.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1131783003:
  Embedded constant pools.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| OLD | NEW | 
|---|---|
| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 void set_predictable_code_size(bool value) { predictable_code_size_ = value; } | 72 void set_predictable_code_size(bool value) { predictable_code_size_ = value; } | 
| 73 | 73 | 
| 74 uint64_t enabled_cpu_features() const { return enabled_cpu_features_; } | 74 uint64_t enabled_cpu_features() const { return enabled_cpu_features_; } | 
| 75 void set_enabled_cpu_features(uint64_t features) { | 75 void set_enabled_cpu_features(uint64_t features) { | 
| 76 enabled_cpu_features_ = features; | 76 enabled_cpu_features_ = features; | 
| 77 } | 77 } | 
| 78 bool IsEnabled(CpuFeature f) { | 78 bool IsEnabled(CpuFeature f) { | 
| 79 return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0; | 79 return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0; | 
| 80 } | 80 } | 
| 81 | 81 | 
| 82 bool is_ool_constant_pool_available() const { | 82 bool is_constant_pool_available() const { | 
| 83 if (FLAG_enable_ool_constant_pool) { | 83 if (FLAG_enable_embedded_constant_pool) { | 
| 84 return ool_constant_pool_available_; | 84 return constant_pool_available_; | 
| 85 } else { | 85 } else { | 
| 86 // Out-of-line constant pool not supported on this architecture. | 86 // Embedded constant pool not supported on this architecture. | 
| 87 UNREACHABLE(); | 87 UNREACHABLE(); | 
| 88 return false; | 88 return false; | 
| 89 } | 89 } | 
| 90 } | 90 } | 
| 91 | 91 | 
| 92 // Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for | 92 // Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for | 
| 93 // cross-snapshotting. | 93 // cross-snapshotting. | 
| 94 static void QuietNaN(HeapObject* nan) { } | 94 static void QuietNaN(HeapObject* nan) { } | 
| 95 | 95 | 
| 96 int pc_offset() const { return static_cast<int>(pc_ - buffer_); } | 96 int pc_offset() const { return static_cast<int>(pc_ - buffer_); } | 
| 97 | 97 | 
| 98 // This function is called when code generation is aborted, so that | 98 // This function is called when code generation is aborted, so that | 
| 99 // the assembler could clean up internal data structures. | 99 // the assembler could clean up internal data structures. | 
| 100 virtual void AbortedCodeGeneration() { } | 100 virtual void AbortedCodeGeneration() { } | 
| 101 | 101 | 
| 102 static const int kMinimalBufferSize = 4*KB; | 102 static const int kMinimalBufferSize = 4*KB; | 
| 103 | 103 | 
| 104 protected: | 104 protected: | 
| 105 // The buffer into which code and relocation info are generated. It could | 105 // The buffer into which code and relocation info are generated. It could | 
| 106 // either be owned by the assembler or be provided externally. | 106 // either be owned by the assembler or be provided externally. | 
| 107 byte* buffer_; | 107 byte* buffer_; | 
| 108 int buffer_size_; | 108 int buffer_size_; | 
| 109 bool own_buffer_; | 109 bool own_buffer_; | 
| 110 | 110 | 
| 111 void set_ool_constant_pool_available(bool available) { | 111 void set_constant_pool_available(bool available) { | 
| 112 if (FLAG_enable_ool_constant_pool) { | 112 if (FLAG_enable_embedded_constant_pool) { | 
| 113 ool_constant_pool_available_ = available; | 113 constant_pool_available_ = available; | 
| 114 } else { | 114 } else { | 
| 115 // Out-of-line constant pool not supported on this architecture. | 115 // Embedded constant pool not supported on this architecture. | 
| 116 UNREACHABLE(); | 116 UNREACHABLE(); | 
| 117 } | 117 } | 
| 118 } | 118 } | 
| 119 | 119 | 
| 120 // The program counter, which points into the buffer above and moves forward. | 120 // The program counter, which points into the buffer above and moves forward. | 
| 121 byte* pc_; | 121 byte* pc_; | 
| 122 | 122 | 
| 123 private: | 123 private: | 
| 124 Isolate* isolate_; | 124 Isolate* isolate_; | 
| 125 int jit_cookie_; | 125 int jit_cookie_; | 
| 126 uint64_t enabled_cpu_features_; | 126 uint64_t enabled_cpu_features_; | 
| 127 bool emit_debug_code_; | 127 bool emit_debug_code_; | 
| 128 bool predictable_code_size_; | 128 bool predictable_code_size_; | 
| 129 bool serializer_enabled_; | 129 bool serializer_enabled_; | 
| 130 | 130 | 
| 131 // Indicates whether the constant pool can be accessed, which is only possible | 131 // Indicates whether the constant pool can be accessed, which is only possible | 
| 132 // if the pp register points to the current code object's constant pool. | 132 // if the pp register points to the current code object's constant pool. | 
| 133 bool ool_constant_pool_available_; | 133 bool constant_pool_available_; | 
| 134 | 134 | 
| 135 // Constant pool. | 135 // Constant pool. | 
| 136 friend class FrameAndConstantPoolScope; | 136 friend class FrameAndConstantPoolScope; | 
| 137 friend class ConstantPoolUnavailableScope; | 137 friend class ConstantPoolUnavailableScope; | 
| 138 }; | 138 }; | 
| 139 | 139 | 
| 140 | 140 | 
| 141 // Avoids emitting debug code during the lifetime of this scope object. | 141 // Avoids emitting debug code during the lifetime of this scope object. | 
| 142 class DontEmitDebugCodeScope BASE_EMBEDDED { | 142 class DontEmitDebugCodeScope BASE_EMBEDDED { | 
| 143 public: | 143 public: | 
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding. | 406 // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding. | 
| 407 LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID, | 407 LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID, | 
| 408 LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE_ENCODED | 408 LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE_ENCODED | 
| 409 }; | 409 }; | 
| 410 | 410 | 
| 411 RelocInfo() {} | 411 RelocInfo() {} | 
| 412 | 412 | 
| 413 RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host) | 413 RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host) | 
| 414 : pc_(pc), rmode_(rmode), data_(data), host_(host) { | 414 : pc_(pc), rmode_(rmode), data_(data), host_(host) { | 
| 415 } | 415 } | 
| 416 RelocInfo(byte* pc, double data64) | |
| 417 : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) { | |
| 418 } | |
| 419 | 416 | 
| 420 static inline bool IsRealRelocMode(Mode mode) { | 417 static inline bool IsRealRelocMode(Mode mode) { | 
| 421 return mode >= FIRST_REAL_RELOC_MODE && | 418 return mode >= FIRST_REAL_RELOC_MODE && | 
| 422 mode <= LAST_REAL_RELOC_MODE; | 419 mode <= LAST_REAL_RELOC_MODE; | 
| 423 } | 420 } | 
| 424 static inline bool IsPseudoRelocMode(Mode mode) { | 421 static inline bool IsPseudoRelocMode(Mode mode) { | 
| 425 DCHECK(!IsRealRelocMode(mode)); | 422 DCHECK(!IsRealRelocMode(mode)); | 
| 426 return mode >= FIRST_PSEUDO_RELOC_MODE && | 423 return mode >= FIRST_PSEUDO_RELOC_MODE && | 
| 427 mode <= LAST_PSEUDO_RELOC_MODE; | 424 mode <= LAST_PSEUDO_RELOC_MODE; | 
| 428 } | 425 } | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 return mode == DEBUG_BREAK; | 477 return mode == DEBUG_BREAK; | 
| 481 } | 478 } | 
| 482 static inline bool IsNone(Mode mode) { | 479 static inline bool IsNone(Mode mode) { | 
| 483 return mode == NONE32 || mode == NONE64; | 480 return mode == NONE32 || mode == NONE64; | 
| 484 } | 481 } | 
| 485 static inline bool IsCodeAgeSequence(Mode mode) { | 482 static inline bool IsCodeAgeSequence(Mode mode) { | 
| 486 return mode == CODE_AGE_SEQUENCE; | 483 return mode == CODE_AGE_SEQUENCE; | 
| 487 } | 484 } | 
| 488 static inline int ModeMask(Mode mode) { return 1 << mode; } | 485 static inline int ModeMask(Mode mode) { return 1 << mode; } | 
| 489 | 486 | 
| 490 // Returns true if the first RelocInfo has the same mode and raw data as the | |
| 491 // second one. | |
| 492 static inline bool IsEqual(RelocInfo first, RelocInfo second) { | |
| 493 return first.rmode() == second.rmode() && | |
| 494 (first.rmode() == RelocInfo::NONE64 ? | |
| 495 first.raw_data64() == second.raw_data64() : | |
| 496 first.data() == second.data()); | |
| 497 } | |
| 498 | |
| 499 // Accessors | 487 // Accessors | 
| 500 byte* pc() const { return pc_; } | 488 byte* pc() const { return pc_; } | 
| 501 void set_pc(byte* pc) { pc_ = pc; } | 489 void set_pc(byte* pc) { pc_ = pc; } | 
| 502 Mode rmode() const { return rmode_; } | 490 Mode rmode() const { return rmode_; } | 
| 503 intptr_t data() const { return data_; } | 491 intptr_t data() const { return data_; } | 
| 504 double data64() const { return data64_; } | |
| 505 uint64_t raw_data64() { return bit_cast<uint64_t>(data64_); } | |
| 506 Code* host() const { return host_; } | 492 Code* host() const { return host_; } | 
| 507 void set_host(Code* host) { host_ = host; } | 493 void set_host(Code* host) { host_ = host; } | 
| 508 | 494 | 
| 509 // Apply a relocation by delta bytes | 495 // Apply a relocation by delta bytes | 
| 510 INLINE(void apply(intptr_t delta, | 496 INLINE(void apply(intptr_t delta, | 
| 511 ICacheFlushMode icache_flush_mode = | 497 ICacheFlushMode icache_flush_mode = | 
| 512 FLUSH_ICACHE_IF_NEEDED)); | 498 FLUSH_ICACHE_IF_NEEDED)); | 
| 513 | 499 | 
| 514 // Is the pointer this relocation info refers to coded like a plain pointer | 500 // Is the pointer this relocation info refers to coded like a plain pointer | 
| 515 // or is it strange in some way (e.g. relative or patched into a series of | 501 // or is it strange in some way (e.g. relative or patched into a series of | 
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT); | 624 (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT); | 
| 639 static const int kApplyMask; // Modes affected by apply. Depends on arch. | 625 static const int kApplyMask; // Modes affected by apply. Depends on arch. | 
| 640 | 626 | 
| 641 private: | 627 private: | 
| 642 // On ARM, note that pc_ is the address of the constant pool entry | 628 // On ARM, note that pc_ is the address of the constant pool entry | 
| 643 // to be relocated and not the address of the instruction | 629 // to be relocated and not the address of the instruction | 
| 644 // referencing the constant pool entry (except when rmode_ == | 630 // referencing the constant pool entry (except when rmode_ == | 
| 645 // comment). | 631 // comment). | 
| 646 byte* pc_; | 632 byte* pc_; | 
| 647 Mode rmode_; | 633 Mode rmode_; | 
| 648 union { | 634 intptr_t data_; | 
| 649 intptr_t data_; | |
| 650 double data64_; | |
| 651 }; | |
| 652 Code* host_; | 635 Code* host_; | 
| 653 // External-reference pointers are also split across instruction-pairs | 636 // External-reference pointers are also split across instruction-pairs | 
| 654 // on some platforms, but are accessed via indirect pointers. This location | 637 // on some platforms, but are accessed via indirect pointers. This location | 
| 655 // provides a place for that pointer to exist naturally. Its address | 638 // provides a place for that pointer to exist naturally. Its address | 
| 656 // is returned by RelocInfo::target_reference_address(). | 639 // is returned by RelocInfo::target_reference_address(). | 
| 657 Address reconstructed_adr_ptr_; | 640 Address reconstructed_adr_ptr_; | 
| 658 friend class RelocIterator; | 641 friend class RelocIterator; | 
| 659 }; | 642 }; | 
| 660 | 643 | 
| 661 | 644 | 
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1160 | 1143 | 
| 1161 class NullCallWrapper : public CallWrapper { | 1144 class NullCallWrapper : public CallWrapper { | 
| 1162 public: | 1145 public: | 
| 1163 NullCallWrapper() { } | 1146 NullCallWrapper() { } | 
| 1164 virtual ~NullCallWrapper() { } | 1147 virtual ~NullCallWrapper() { } | 
| 1165 virtual void BeforeCall(int call_size) const { } | 1148 virtual void BeforeCall(int call_size) const { } | 
| 1166 virtual void AfterCall() const { } | 1149 virtual void AfterCall() const { } | 
| 1167 }; | 1150 }; | 
| 1168 | 1151 | 
| 1169 | 1152 | 
| 1153 // ----------------------------------------------------------------------------- | |
| 1154 // Embedded constant pool support | |
| 
rmcilroy
2015/06/01 09:52:08
ConstntPoolEntry is used by both embedded and inli
 
MTBrandyberry
2015/06/01 21:01:30
Done.
 | |
| 1155 | |
| 1156 class ConstantPoolEntry { | |
| 1157 public: | |
| 1158 ConstantPoolEntry() {} | |
| 1159 ConstantPoolEntry(int position, intptr_t value, bool sharing_ok) | |
| 1160 : position_(position), | |
| 1161 merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED), | |
| 1162 value_(value) {} | |
| 1163 ConstantPoolEntry(int position, double value) | |
| 1164 : position_(position), merged_index_(SHARING_ALLOWED), value64_(value) {} | |
| 1165 | |
| 1166 int position() const { return position_; } | |
| 1167 bool sharing_ok() const { return merged_index_ != SHARING_PROHIBITED; } | |
| 1168 bool is_merged() const { return merged_index_ >= 0; } | |
| 1169 intptr_t value() const { return value_; } | |
| 1170 uint64_t value64() const { return bit_cast<uint64_t>(value64_); } | |
| 1171 | |
| 1172 enum Type { INTPTR, DOUBLE, NUMBER_OF_TYPES }; | |
| 1173 | |
| 1174 static int size(Type type) { | |
| 1175 return (type == INTPTR) ? kPointerSize : kDoubleSize; | |
| 1176 } | |
| 1177 | |
| 1178 enum Access { REGULAR, OVERFLOWED }; | |
| 1179 | |
| 1180 private: | |
| 1181 int position_; | |
| 1182 int merged_index_; | |
| 1183 union { | |
| 1184 intptr_t value_; | |
| 1185 double value64_; | |
| 1186 }; | |
| 1187 enum { SHARING_PROHIBITED = -2, SHARING_ALLOWED = -1 }; | |
| 1188 | |
| 1189 friend class ConstantPoolBuilder; | |
| 
rmcilroy
2015/06/01 09:52:09
is this only for setting merged_index_? If so, I w
 
MTBrandyberry
2015/06/01 21:01:30
Done.
 | |
| 1190 }; | |
| 1191 | |
| 1192 | |
| 1193 class ConstantPoolBuilder BASE_EMBEDDED { | |
| 1194 public: | |
| 1195 ConstantPoolBuilder(int ptr_reach_bits, int double_reach_bits); | |
| 1196 | |
| 1197 // Add pointer-sized constant to the embedded constant pool | |
| 1198 ConstantPoolEntry::Access AddEntry(int position, intptr_t value, | |
| 1199 bool sharing_ok) { | |
| 1200 ConstantPoolEntry entry(position, value, sharing_ok); | |
| 1201 return AddEntry(entry, ConstantPoolEntry::INTPTR); | |
| 1202 } | |
| 1203 | |
| 1204 // Add double constant to the embedded constant pool | |
| 1205 ConstantPoolEntry::Access AddEntry(int position, double value) { | |
| 1206 ConstantPoolEntry entry(position, value); | |
| 1207 return AddEntry(entry, ConstantPoolEntry::DOUBLE); | |
| 1208 } | |
| 1209 | |
| 1210 // Previews the access type required for the next new entry to be added. | |
| 1211 ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const; | |
| 1212 | |
| 1213 bool IsEmpty() { | |
| 1214 return info_[ConstantPoolEntry::INTPTR].entries.empty() && | |
| 1215 info_[ConstantPoolEntry::INTPTR].shared_entries.empty() && | |
| 1216 info_[ConstantPoolEntry::DOUBLE].entries.empty() && | |
| 1217 info_[ConstantPoolEntry::DOUBLE].shared_entries.empty(); | |
| 1218 } | |
| 1219 | |
| 1220 // Emit the constant pool. Invoke only after all entries have been | |
| 1221 // added and all instructions have been emitted. | |
| 1222 // Returns position of the emitted pool (zero implies no constant pool). | |
| 1223 int Emit(Assembler* assm); | |
| 1224 | |
| 1225 // Returns the label associated with the start of the constant pool. | |
| 1226 // Linking to this label in the function prologue may provide an | |
| 1227 // efficient means of constant pool pointer register initialization | |
| 1228 // on some architectures. | |
| 1229 inline Label* EmittedPosition() { return &emitted_label_; } | |
| 1230 | |
| 1231 private: | |
| 1232 ConstantPoolEntry::Access AddEntry(ConstantPoolEntry& entry, | |
| 1233 ConstantPoolEntry::Type type); | |
| 1234 void EmitSharedEntries(Assembler* assm, ConstantPoolEntry::Type type); | |
| 1235 void EmitGroup(Assembler* assm, ConstantPoolEntry::Access access, | |
| 1236 ConstantPoolEntry::Type type); | |
| 1237 | |
| 1238 struct PerTypeEntryInfo { | |
| 1239 PerTypeEntryInfo() : regular_count(0), overflow_start(-1) {} | |
| 1240 bool overflow() const { | |
| 1241 return (overflow_start >= 0 && | |
| 1242 overflow_start < static_cast<int>(entries.size())); | |
| 1243 } | |
| 1244 int regular_reach_bits; | |
| 1245 int regular_count; | |
| 1246 int overflow_start; | |
| 1247 std::vector<ConstantPoolEntry> entries; | |
| 1248 std::vector<ConstantPoolEntry> shared_entries; | |
| 1249 }; | |
| 1250 | |
| 1251 Label emitted_label_; // Records pc_offset of emitted pool | |
| 1252 PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES]; | |
| 1253 }; | |
| 1254 | |
| 1255 | |
| 1170 } } // namespace v8::internal | 1256 } } // namespace v8::internal | 
| 1171 | 1257 | 
| 1172 #endif // V8_ASSEMBLER_H_ | 1258 #endif // V8_ASSEMBLER_H_ | 
| OLD | NEW |