5#ifndef V8_EXECUTION_ARM_SIMULATOR_ARM_H_
6#define V8_EXECUTION_ARM_SIMULATOR_ARM_H_
18#if defined(USE_SIMULATOR)
38 static const int LINE_VALID = 0;
39 static const int LINE_INVALID = 1;
41 static const int kPageShift = 12;
42 static const int kPageSize = 1 << kPageShift;
43 static const int kPageMask =
kPageSize - 1;
44 static const int kLineShift = 2;
45 static const int kLineLength = 1 << kLineShift;
46 static const int kLineMask = kLineLength - 1;
48 CachePage() { memset(&validity_map_, LINE_INVALID,
sizeof(validity_map_)); }
50 char* ValidityByte(
int offset) {
51 return &validity_map_[
offset >> kLineShift];
58 static const int kValidityMapSize =
kPageSize >> kLineShift;
59 char validity_map_[kValidityMapSize];
62class Simulator :
public SimulatorBase {
64 friend class ArmDebugger;
121 num_s_registers = 32,
154 num_d_registers = 32,
174 explicit Simulator(Isolate* isolate);
184 void set_register(
int reg, int32_t value);
186 double get_double_from_register_pair(
int reg);
187 void set_register_pair_from_double(
int reg,
double* value);
188 void set_dw_register(
int dreg,
const int* dbl);
191 void get_d_register(
int dreg, uint64_t* value);
192 void set_d_register(
int dreg,
const uint64_t* value);
193 void get_d_register(
int dreg, uint32_t* value);
194 void set_d_register(
int dreg,
const uint32_t* value);
196 template <
typename T,
int SIZE = kSimd128Size>
197 void get_neon_register(
int reg, T (&value)[
SIZE /
sizeof(T)]);
198 template <
typename T,
int SIZE = kSimd128Size>
199 void set_neon_register(
int reg,
const T (&value)[
SIZE /
sizeof(T)]);
201 void set_s_register(
int reg,
unsigned int value);
202 unsigned int get_s_register(
int reg)
const;
204 void set_d_register_from_double(
int dreg,
const Float64 dbl) {
205 SetVFPRegister<Float64, 2>(dreg, dbl);
207 void set_d_register_from_double(
int dreg,
const double dbl) {
208 SetVFPRegister<double, 2>(dreg, dbl);
211 Float64 get_double_from_d_register(
int dreg) {
212 return GetFromVFPRegister<Float64, 2>(dreg);
215 void set_s_register_from_float(
int sreg,
const Float32 flt) {
216 SetVFPRegister<Float32, 1>(sreg, flt);
218 void set_s_register_from_float(
int sreg,
const float flt) {
219 SetVFPRegister<float, 1>(sreg, flt);
222 Float32 get_float_from_s_register(
int sreg) {
223 return GetFromVFPRegister<Float32, 1>(sreg);
226 void set_s_register_from_sinteger(
int sreg,
const int sint) {
227 SetVFPRegister<int, 1>(sreg, sint);
230 int get_sinteger_from_s_register(
int sreg) {
231 return GetFromVFPRegister<int, 1>(sreg);
235 void set_pc(int32_t value);
238 Address get_sp()
const {
return static_cast<Address>(get_register(sp)); }
242 uintptr_t StackLimit(uintptr_t c_limit)
const;
244 uintptr_t StackBase()
const;
248 base::Vector<uint8_t> GetCentralStackView()
const;
249 static constexpr int JSStackLimitMargin() {
return kAdditionalStackMargin; }
256 template <
typename Return,
typename... Args>
257 Return Call(Address entry, Args...
args) {
258 return VariadicCall<Return>(
this, &Simulator::CallImpl, entry,
args...);
262 template <
typename Return>
263 Return CallFP(Address entry,
double d0,
double d1) {
264 return ConvertReturn<Return>(CallFPImpl(entry, d0, d1));
274 void set_last_debugger_input(ArrayUniquePtr<char> input) {
275 last_debugger_input_ = std::move(input);
277 const char* last_debugger_input() {
return last_debugger_input_.get(); }
280 static void SetRedirectInstruction(Instruction* instruction);
283 static bool ICacheMatch(
void*
one,
void* two);
284 static void FlushICache(base::CustomMatcherHashMap* i_cache,
void*
start,
289 bool has_bad_pc()
const;
292 bool use_eabi_hardfloat() {
293#if USE_EABI_HARDFLOAT
301 bool InstructionTracingEnabled();
303 void ToggleInstructionTracing();
306 enum special_values {
318 const intptr_t* arguments);
319 intptr_t CallFPImpl(Address entry,
double d0,
double d1);
322 void Format(Instruction*
instr,
const char* format);
326 inline bool ConditionallyExecute(Instruction*
instr);
329 void SetNZFlags(int32_t val);
330 void SetCFlag(
bool val);
331 void SetVFlag(
bool val);
332 bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
333 bool BorrowFrom(int32_t left, int32_t right, int32_t carry = 1);
334 bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
337 inline int GetCarry() {
return c_flag_ ? 1 : 0; }
340 void Compute_FPSCR_Flags(
float val1,
float val2);
341 void Compute_FPSCR_Flags(
double val1,
double val2);
342 void Copy_FPSCR_to_APSR();
343 inline float canonicalizeNaN(
float value);
344 inline double canonicalizeNaN(
double value);
345 inline Float32 canonicalizeNaN(Float32 value);
346 inline Float64 canonicalizeNaN(Float64 value);
349 int32_t GetShiftRm(Instruction*
instr,
bool* carry_out);
351 int32_t ProcessPU(Instruction*
instr,
int num_regs,
int operand_size,
352 intptr_t* start_address, intptr_t* end_address);
353 void HandleRList(Instruction*
instr,
bool load);
354 void HandleVList(Instruction* inst);
355 void SoftwareInterrupt(Instruction*
instr);
356 void DebugAtNextPC();
360 bool instruction_tracing_ =
v8_flags.trace_sim;
363 void AdvancedSIMDElementOrStructureLoadStoreWriteback(
int Rn,
int Rm,
367 inline bool isWatchedStop(uint32_t bkpt_code);
368 inline bool isEnabledStop(uint32_t bkpt_code);
369 inline void EnableStop(uint32_t bkpt_code);
370 inline void DisableStop(uint32_t bkpt_code);
371 inline void IncreaseStopCounter(uint32_t bkpt_code);
372 void PrintStopInfo(uint32_t code);
377 inline uint8_t ReadBU(int32_t addr);
378 inline int8_t ReadB(int32_t addr);
379 uint8_t ReadExBU(int32_t addr);
380 inline void WriteB(int32_t addr, uint8_t value);
381 inline void WriteB(int32_t addr, int8_t value);
382 int WriteExB(int32_t addr, uint8_t value);
384 inline uint16_t ReadHU(int32_t addr);
385 inline int16_t ReadH(int32_t addr);
388 inline void WriteH(int32_t addr, uint16_t value);
389 inline void WriteH(int32_t addr, int16_t value);
390 int WriteExH(int32_t addr, uint16_t value);
392 inline int ReadW(int32_t addr);
393 int ReadExW(int32_t addr);
394 inline void WriteW(int32_t addr,
int value);
395 int WriteExW(int32_t addr,
int value);
398 void WriteDW(int32_t addr, int32_t value1, int32_t value2);
399 int32_t* ReadExDW(int32_t addr);
400 int WriteExDW(int32_t addr, int32_t value1, int32_t value2);
404 void DecodeType01(Instruction*
instr);
405 void DecodeType2(Instruction*
instr);
406 void DecodeType3(Instruction*
instr);
407 void DecodeType4(Instruction*
instr);
408 void DecodeType5(Instruction*
instr);
409 void DecodeType6(Instruction*
instr);
410 void DecodeType7(Instruction*
instr);
413 void DecodeTypeCP15(Instruction*
instr);
416 void DecodeTypeVFP(Instruction*
instr);
417 void DecodeType6CoprocessorIns(Instruction*
instr);
418 void DecodeSpecialCondition(Instruction*
instr);
420 void DecodeFloatingPointDataProcessing(Instruction*
instr);
421 void DecodeUnconditional(Instruction*
instr);
422 void DecodeAdvancedSIMDDataProcessing(Instruction*
instr);
423 void DecodeMemoryHintsAndBarriers(Instruction*
instr);
424 void DecodeAdvancedSIMDElementOrStructureLoadStore(Instruction*
instr);
425 void DecodeAdvancedSIMDLoadStoreMultipleStructures(Instruction*
instr);
426 void DecodeAdvancedSIMDLoadSingleStructureToAllLanes(Instruction*
instr);
427 void DecodeAdvancedSIMDLoadStoreSingleStructureToOneLane(Instruction*
instr);
428 void DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction*
instr);
430 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction*
instr);
431 void DecodeVCMP(Instruction*
instr);
432 void DecodeVCVTBetweenDoubleAndSingle(Instruction*
instr);
433 int32_t ConvertDoubleToInt(
double val,
bool unsigned_integer,
434 VFPRoundingMode mode);
435 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction*
instr);
438 void InstructionDecode(Instruction*
instr);
441 static void CheckICache(base::CustomMatcherHashMap* i_cache,
443 static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t
start,
445 static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
449 void GetFpArgs(
double*
x,
double*
y, int32_t*
z);
450 void SetFpResult(
const double&
result);
451 void TrashCallerSaveRegisters();
453 template <
class ReturnType,
int register_size>
454 ReturnType GetFromVFPRegister(
int reg_index);
456 template <
class InputType,
int register_size>
457 void SetVFPRegister(
int reg_index,
const InputType& value);
459 void SetSpecialRegister(SRegisterFieldMask reg_and_mask, uint32_t value);
460 uint32_t GetFromSpecialRegister(SRegister
reg);
462 void CallInternal(Address entry);
475 unsigned int vfp_registers_[num_d_registers * 2];
483 bool FPSCR_default_NaN_mode_;
486 bool inv_op_vfp_flag_;
487 bool div_zero_vfp_flag_;
488 bool overflow_vfp_flag_;
489 bool underflow_vfp_flag_;
490 bool inexact_vfp_flag_;
494 static const size_t kAllocatedStackSize = 1 *
MB;
497 static const int kStackMargin = 64;
499 static const int kAdditionalStackMargin = 4 *
KB;
500 static const size_t kUsableStackSize = kAllocatedStackSize - kStackMargin;
505 ArrayUniquePtr<char> last_debugger_input_;
508 Instruction* break_pc_;
515 static const uint32_t kNumOfWatchedStops = 256;
518 static const uint32_t kStopDisabledBit = 1 << 31;
524 struct StopCountAndDesc {
528 StopCountAndDesc watched_stops_[kNumOfWatchedStops];
531 enum class MonitorAccess {
536 enum class TransactionSize {
546 static const int32_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1);
556 void NotifyLoad(int32_t addr);
557 void NotifyLoadExcl(int32_t addr, TransactionSize size);
558 void NotifyStore(int32_t addr);
559 bool NotifyStoreExcl(int32_t addr, TransactionSize size);
564 MonitorAccess access_state_;
566 TransactionSize
size_;
569 class GlobalMonitor {
571 class SimulatorMutex final {
573 explicit SimulatorMutex(GlobalMonitor* global_monitor) {
574 if (!global_monitor->IsSingleThreaded()) {
575 guard.emplace(global_monitor->mutex_);
580 std::optional<base::MutexGuard> guard;
588 friend class GlobalMonitor;
592 void NotifyLoadExcl_Locked(int32_t addr);
593 void NotifyStore_Locked(int32_t addr,
bool is_requesting_processor);
594 bool NotifyStoreExcl_Locked(int32_t addr,
bool is_requesting_processor);
596 MonitorAccess access_state_;
604 static const int kMaxFailureCounter = 5;
605 int failure_counter_;
608 void NotifyLoadExcl_Locked(int32_t addr, Processor* processor);
609 void NotifyStore_Locked(int32_t addr, Processor* processor);
610 bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor);
613 void PrependProcessor(Processor* processor);
615 void RemoveProcessor(Processor* processor);
617 static GlobalMonitor*
Get();
620 bool IsSingleThreaded()
const {
return num_processors_ == 1; }
623 GlobalMonitor() =
default;
624 friend class base::LeakyObject<GlobalMonitor>;
626 Processor* head_ =
nullptr;
627 std::atomic<uint32_t> num_processors_ = 0;
631 LocalMonitor local_monitor_;
632 GlobalMonitor::Processor global_monitor_processor_;
633 GlobalMonitor* global_monitor_;
uint8_t data_[MAX_STACK_LENGTH]
#define SIZE(Type, type, TYPE, ctype)
base::Vector< const DirectHandle< Object > > args
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage * MB
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
ZoneVector< RpoNumber > & result
constexpr size_t kPageSize
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
FloatWithBits< 32 > Float32
UntaggedUnion< Word32, Word64 > Word
FloatWithBits< 64 > Float64
uint32_t WasmInterpreterRuntime int64_t r0
constexpr Register no_reg
V8_EXPORT_PRIVATE FlagValues v8_flags
base::SmallVector< RegisterT, kStaticCapacity > registers_
#define V8_EXPORT_PRIVATE