35 #ifndef V8_ASSEMBLER_H_ 36 #define V8_ASSEMBLER_H_ 38 #include <forward_list> 40 #include "src/deoptimize-reason.h" 41 #include "src/external-reference.h" 42 #include "src/flags.h" 43 #include "src/globals.h" 44 #include "src/handles.h" 45 #include "src/objects.h" 46 #include "src/reglist.h" 47 #include "src/reloc-info.h" 58 class InstructionStream;
60 class SCTableReference;
63 class StringConstantBase;
70 bool is_collecting()
const {
return stage_ == kCollection; }
71 bool is_optimizing()
const {
return stage_ == kOptimization; }
72 void set_optimizing() { stage_ = kOptimization; }
74 bool is_optimizable()
const {
return optimizable_; }
75 void set_optimizable() { optimizable_ =
true; }
78 size_t hash_code()
const {
return hash_code_; }
79 void set_hash_code(
size_t hash_code) { hash_code_ = hash_code; }
81 std::vector<uint32_t>& farjmp_bitmap() {
return farjmp_bitmap_; }
84 enum { kCollection, kOptimization } stage_ = kCollection;
85 bool optimizable_ =
false;
86 std::vector<uint32_t> farjmp_bitmap_;
87 size_t hash_code_ = 0u;
96 enum Kind { kHeapNumber, kCodeStub, kStringConstant };
97 Kind kind()
const {
return kind_; }
99 double heap_number()
const {
100 DCHECK_EQ(kind(), kHeapNumber);
101 return value_.heap_number;
105 DCHECK_EQ(kind(), kCodeStub);
106 return value_.code_stub;
110 DCHECK_EQ(kind(), kStringConstant);
111 return value_.string;
116 DCHECK_GE(offset_, 0);
119 void set_offset(
int offset) {
120 DCHECK_LT(offset_, 0);
122 DCHECK_GE(offset_, 0);
140 enum class CodeObjectRequired { kNo, kYes };
145 bool v8_agnostic_code =
false;
150 bool record_reloc_info_for_serialization =
true;
154 bool disable_reloc_info_for_patching =
false;
157 bool enable_root_array_delta_access =
false;
159 bool enable_simulator_code =
false;
163 bool isolate_independent_code =
false;
166 bool inline_offheap_trampolines =
false;
173 bool use_pc_relative_calls_and_jumps =
false;
179 Isolate* isolate,
bool explicitly_support_serialization =
false);
189 bool emit_debug_code()
const {
return emit_debug_code_; }
190 void set_emit_debug_code(
bool value) { emit_debug_code_ = value; }
192 bool predictable_code_size()
const {
return predictable_code_size_; }
193 void set_predictable_code_size(
bool value) { predictable_code_size_ = value; }
195 uint64_t enabled_cpu_features()
const {
return enabled_cpu_features_; }
196 void set_enabled_cpu_features(uint64_t features) {
197 enabled_cpu_features_ = features;
201 bool IsEnabled(CpuFeature f) {
202 return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
204 void EnableCpuFeature(CpuFeature f) {
205 enabled_cpu_features_ |= (
static_cast<uint64_t
>(1) << f);
208 bool is_constant_pool_available()
const {
209 if (FLAG_enable_embedded_constant_pool) {
210 return constant_pool_available_;
218 return jump_optimization_info_;
221 jump_optimization_info_ = jump_opt;
228 int pc_offset()
const {
return static_cast<int>(pc_ - buffer_); }
232 virtual void AbortedCodeGeneration() { }
237 static const int kMinimalBufferSize = 4*KB;
239 static void FlushICache(
void* start,
size_t size);
240 static void FlushICache(
Address start,
size_t size) {
241 return FlushICache(reinterpret_cast<void*>(start), size);
245 static const char* GetSpecialRegisterName(
int code) {
return "UNKNOWN"; }
251 Handle<Code> GetCodeTarget(intptr_t code_target_index)
const;
253 void UpdateCodeTarget(intptr_t code_target_index,
Handle<Code> target);
255 void ReserveCodeTargetSpace(
size_t num_of_code_targets);
262 std::forward_list<HeapObjectRequest> heap_object_requests_;
267 void set_constant_pool_available(
bool available) {
268 if (FLAG_enable_embedded_constant_pool) {
269 constant_pool_available_ = available;
283 bool ShouldRecordRelocInfo(RelocInfo::Mode rmode)
const {
284 DCHECK(!RelocInfo::IsNone(rmode));
285 if (options().disable_reloc_info_for_patching)
return false;
286 if (RelocInfo::IsOnlyForSerializer(rmode) &&
287 !options().record_reloc_info_for_serialization && !emit_debug_code()) {
300 std::vector<Handle<Code>> code_targets_;
303 uint64_t enabled_cpu_features_;
304 bool emit_debug_code_;
305 bool predictable_code_size_;
309 bool constant_pool_available_;
322 : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
323 assembler_->set_emit_debug_code(
false);
326 assembler_->set_emit_debug_code(old_value_);
343 int const expected_size_;
344 int const start_offset_;
345 bool const old_value_;
359 CheckPolicy check = kCheckSupported);
364 uint64_t old_enabled_;
367 CheckPolicy check = kCheckSupported) {}
385 static void Probe(
bool cross_compile) {
386 STATIC_ASSERT(NUMBER_OF_CPU_FEATURES <= kBitsPerInt);
387 if (initialized_)
return;
389 ProbeImpl(cross_compile);
392 static unsigned SupportedFeatures() {
397 static bool IsSupported(CpuFeature f) {
398 return (supported_ & (1u << f)) != 0;
401 static inline bool SupportsOptimizer();
403 static inline bool SupportsWasmSimd128();
405 static inline unsigned icache_line_size() {
406 DCHECK_NE(icache_line_size_, 0);
407 return icache_line_size_;
410 static inline unsigned dcache_line_size() {
411 DCHECK_NE(dcache_line_size_, 0);
412 return dcache_line_size_;
415 static void PrintTarget();
416 static void PrintFeatures();
422 static void FlushICache(
void* start,
size_t size);
425 static void ProbeImpl(
bool cross_compile);
427 static unsigned supported_;
428 static unsigned icache_line_size_;
429 static unsigned dcache_line_size_;
430 static bool initialized_;
438 double power_helper(
double x,
double y);
439 double power_double_int(
double x,
int y);
440 double power_double_double(
double x,
double y);
455 template <
typename SubType,
int kAfterLastRegister>
459 enum class RegisterCode :
int { kFirst = 0, kAfterLast = kAfterLastRegister };
462 static constexpr
int kCode_no_reg = -1;
463 static constexpr
int kNumRegisters = kAfterLastRegister;
465 static constexpr SubType no_reg() {
return SubType{kCode_no_reg}; }
468 static constexpr SubType from_code() {
469 static_assert(code >= 0 && code < kNumRegisters,
"must be valid reg code");
470 return SubType{code};
473 constexpr
operator RegisterCode()
const {
474 return static_cast<RegisterCode
>(reg_code_);
477 template <RegisterCode reg_code>
478 static constexpr
int code() {
480 reg_code >= RegisterCode::kFirst && reg_code < RegisterCode::kAfterLast,
481 "must be valid reg");
482 return static_cast<int>(reg_code);
485 template <RegisterCode reg_code>
486 static constexpr
RegList bit() {
487 return RegList{1} << code<reg_code>();
490 static SubType from_code(
int code) {
492 DCHECK_GT(kNumRegisters, code);
493 return SubType{code};
497 template <RegisterCode... reg_codes>
498 static constexpr
RegList ListOf() {
499 return CombineRegLists(RegisterBase::bit<reg_codes>()...);
505 return CombineRegLists(regs.bit()...);
508 bool is_valid()
const {
return reg_code_ != kCode_no_reg; }
517 inline constexpr
bool operator==(SubType other)
const {
518 return reg_code_ == other.reg_code_;
520 inline constexpr
bool operator!=(SubType other)
const {
521 return reg_code_ != other.reg_code_;
525 explicit constexpr
RegisterBase(
int code) : reg_code_(code) {}
531 #define DEFINE_REGISTER_NAMES_NAME(name) #name, 532 #define DEFINE_REGISTER_NAMES(RegType, LIST) \ 533 inline const char* RegisterName(RegType reg) { \ 534 static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \ 535 STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \ 536 return reg.is_valid() ? Names[reg.code()] : "invalid"; \ 539 template <
typename RegType,
540 typename = decltype(RegisterName(std::declval<RegType>()))>
541 inline std::ostream& operator<<(std::ostream& os, RegType reg) {
542 return os << RegisterName(reg);
547 #endif // V8_ASSEMBLER_H_