v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
simulator-mips.h
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 
29 // Declares a Simulator for MIPS instructions if we are not generating a native
30 // MIPS binary. This Simulator allows us to run and debug MIPS code generation
31 // on regular desktop machines.
32 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro,
33 // which will start execution in the Simulator or forwards to the real entry
34 // on a MIPS HW platform.
35 
36 #ifndef V8_MIPS_SIMULATOR_MIPS_H_
37 #define V8_MIPS_SIMULATOR_MIPS_H_
38 
39 #include "allocation.h"
40 #include "constants-mips.h"
41 
42 #if !defined(USE_SIMULATOR)
43 // Running without a simulator on a native mips platform.
44 
45 namespace v8 {
46 namespace internal {
47 
48 // When running without a simulator we call the entry directly.
49 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
50  entry(p0, p1, p2, p3, p4)
51 
52 typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
53  void*, int*, int, Address, int, Isolate*);
54 
55 
56 // Call the generated regexp code directly. The code at the entry address
57 // should act as a function matching the type arm_regexp_matcher.
58 // The fifth argument is a dummy that reserves the space used for
59 // the return address added by the ExitFrame in native calls.
60 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
61  (FUNCTION_CAST<mips_regexp_matcher>(entry)( \
62  p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
63 
64 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
65  reinterpret_cast<TryCatch*>(try_catch_address)
66 
67 // The stack limit beyond which we will throw stack overflow errors in
68 // generated code. Because generated code on mips uses the C stack, we
69 // just use the C stack limit.
70 class SimulatorStack : public v8::internal::AllStatic {
71  public:
72  static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
73  uintptr_t c_limit) {
74  return c_limit;
75  }
76 
77  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
78  return try_catch_address;
79  }
80 
81  static inline void UnregisterCTryCatch() { }
82 };
83 
84 } } // namespace v8::internal
85 
86 // Calculated the stack limit beyond which we will throw stack overflow errors.
87 // This macro must be called from a C++ method. It relies on being able to take
88 // the address of "this" to get a value on the current execution stack and then
89 // calculates the stack limit based on that value.
90 // NOTE: The check for overflow is not safe as there is no guarantee that the
91 // running thread has its stack in all memory up to address 0x00000000.
92 #define GENERATED_CODE_STACK_LIMIT(limit) \
93  (reinterpret_cast<uintptr_t>(this) >= limit ? \
94  reinterpret_cast<uintptr_t>(this) - limit : 0)
95 
96 #else // !defined(USE_SIMULATOR)
97 // Running with a simulator.
98 
99 #include "hashmap.h"
100 #include "assembler.h"
101 
102 namespace v8 {
103 namespace internal {
104 
105 // -----------------------------------------------------------------------------
106 // Utility functions
107 
108 class CachePage {
109  public:
110  static const int LINE_VALID = 0;
111  static const int LINE_INVALID = 1;
112 
113  static const int kPageShift = 12;
114  static const int kPageSize = 1 << kPageShift;
115  static const int kPageMask = kPageSize - 1;
116  static const int kLineShift = 2; // The cache line is only 4 bytes right now.
117  static const int kLineLength = 1 << kLineShift;
118  static const int kLineMask = kLineLength - 1;
119 
120  CachePage() {
121  memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
122  }
123 
124  char* ValidityByte(int offset) {
125  return &validity_map_[offset >> kLineShift];
126  }
127 
128  char* CachedData(int offset) {
129  return &data_[offset];
130  }
131 
132  private:
133  char data_[kPageSize]; // The cached data.
134  static const int kValidityMapSize = kPageSize >> kLineShift;
135  char validity_map_[kValidityMapSize]; // One byte per line.
136 };
137 
138 class Simulator {
139  public:
140  friend class MipsDebugger;
141 
142  // Registers are declared in order. See SMRL chapter 2.
143  enum Register {
144  no_reg = -1,
145  zero_reg = 0,
146  at,
147  v0, v1,
148  a0, a1, a2, a3,
149  t0, t1, t2, t3, t4, t5, t6, t7,
150  s0, s1, s2, s3, s4, s5, s6, s7,
151  t8, t9,
152  k0, k1,
153  gp,
154  sp,
155  s8,
156  ra,
157  // LO, HI, and pc.
158  LO,
159  HI,
160  pc, // pc must be the last register.
162  // aliases
163  fp = s8
164  };
165 
166  // Coprocessor registers.
167  // Generated code will always use doubles. So we will only use even registers.
168  enum FPURegister {
169  f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11,
170  f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters.
171  f16, f17, f18, f19, f20, f21, f22, f23, f24, f25,
172  f26, f27, f28, f29, f30, f31,
174  };
175 
176  explicit Simulator(Isolate* isolate);
177  ~Simulator();
178 
179  // The currently executing Simulator instance. Potentially there can be one
180  // for each native thread.
181  static Simulator* current(v8::internal::Isolate* isolate);
182 
183  // Accessors for register state. Reading the pc value adheres to the MIPS
184  // architecture specification and is off by a 8 from the currently executing
185  // instruction.
186  void set_register(int reg, int32_t value);
187  void set_dw_register(int dreg, const int* dbl);
188  int32_t get_register(int reg) const;
189  double get_double_from_register_pair(int reg);
190  // Same for FPURegisters.
191  void set_fpu_register(int fpureg, int32_t value);
192  void set_fpu_register_float(int fpureg, float value);
193  void set_fpu_register_double(int fpureg, double value);
194  int32_t get_fpu_register(int fpureg) const;
195  int64_t get_fpu_register_long(int fpureg) const;
196  float get_fpu_register_float(int fpureg) const;
197  double get_fpu_register_double(int fpureg) const;
198  void set_fcsr_bit(uint32_t cc, bool value);
199  bool test_fcsr_bit(uint32_t cc);
200  bool set_fcsr_round_error(double original, double rounded);
201 
202  // Special case of set_register and get_register to access the raw PC value.
203  void set_pc(int32_t value);
204  int32_t get_pc() const;
205 
206  Address get_sp() {
207  return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp)));
208  }
209 
210  // Accessor to the internal simulator stack area.
211  uintptr_t StackLimit() const;
212 
213  // Executes MIPS instructions until the PC reaches end_sim_pc.
214  void Execute();
215 
216  // Call on program start.
217  static void Initialize(Isolate* isolate);
218 
219  // V8 generally calls into generated JS code with 5 parameters and into
220  // generated RegExp code with 7 parameters. This is a convenience function,
221  // which sets up the simulator state and grabs the result on return.
222  int32_t Call(byte* entry, int argument_count, ...);
223  // Alternative: call a 2-argument double function.
224  double CallFP(byte* entry, double d0, double d1);
225 
226  // Push an address onto the JS stack.
227  uintptr_t PushAddress(uintptr_t address);
228 
229  // Pop an address from the JS stack.
230  uintptr_t PopAddress();
231 
232  // Debugger input.
233  void set_last_debugger_input(char* input);
234  char* last_debugger_input() { return last_debugger_input_; }
235 
236  // ICache checking.
237  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
238  size_t size);
239 
240  // Returns true if pc register contains one of the 'special_values' defined
241  // below (bad_ra, end_sim_pc).
242  bool has_bad_pc() const;
243 
244  private:
245  enum special_values {
246  // Known bad pc value to ensure that the simulator does not execute
247  // without being properly setup.
248  bad_ra = -1,
249  // A pc value used to signal the simulator to stop execution. Generally
250  // the ra is set to this value on transition from native C code to
251  // simulated execution, so that the simulator can "return" to the native
252  // C code.
253  end_sim_pc = -2,
254  // Unpredictable value.
255  Unpredictable = 0xbadbeaf
256  };
257 
258  // Unsupported instructions use Format to print an error and stop execution.
259  void Format(Instruction* instr, const char* format);
260 
261  // Read and write memory.
262  inline uint32_t ReadBU(int32_t addr);
263  inline int32_t ReadB(int32_t addr);
264  inline void WriteB(int32_t addr, uint8_t value);
265  inline void WriteB(int32_t addr, int8_t value);
266 
267  inline uint16_t ReadHU(int32_t addr, Instruction* instr);
268  inline int16_t ReadH(int32_t addr, Instruction* instr);
269  // Note: Overloaded on the sign of the value.
270  inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
271  inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
272 
273  inline int ReadW(int32_t addr, Instruction* instr);
274  inline void WriteW(int32_t addr, int value, Instruction* instr);
275 
276  inline double ReadD(int32_t addr, Instruction* instr);
277  inline void WriteD(int32_t addr, double value, Instruction* instr);
278 
279  // Operations depending on endianness.
280  // Get Double Higher / Lower word.
281  inline int32_t GetDoubleHIW(double* addr);
282  inline int32_t GetDoubleLOW(double* addr);
283  // Set Double Higher / Lower word.
284  inline int32_t SetDoubleHIW(double* addr);
285  inline int32_t SetDoubleLOW(double* addr);
286 
287  // Executing is handled based on the instruction type.
288  void DecodeTypeRegister(Instruction* instr);
289 
290  // Helper function for DecodeTypeRegister.
291  void ConfigureTypeRegister(Instruction* instr,
292  int32_t& alu_out,
293  int64_t& i64hilo,
294  uint64_t& u64hilo,
295  int32_t& next_pc,
296  int32_t& return_addr_reg,
297  bool& do_interrupt);
298 
299  void DecodeTypeImmediate(Instruction* instr);
300  void DecodeTypeJump(Instruction* instr);
301 
302  // Used for breakpoints and traps.
303  void SoftwareInterrupt(Instruction* instr);
304 
305  // Stop helper functions.
306  bool IsWatchpoint(uint32_t code);
307  void PrintWatchpoint(uint32_t code);
308  void HandleStop(uint32_t code, Instruction* instr);
309  bool IsStopInstruction(Instruction* instr);
310  bool IsEnabledStop(uint32_t code);
311  void EnableStop(uint32_t code);
312  void DisableStop(uint32_t code);
313  void IncreaseStopCounter(uint32_t code);
314  void PrintStopInfo(uint32_t code);
315 
316 
317  // Executes one instruction.
318  void InstructionDecode(Instruction* instr);
319  // Execute one instruction placed in a branch delay slot.
320  void BranchDelayInstructionDecode(Instruction* instr) {
321  if (instr->InstructionBits() == nopInstr) {
322  // Short-cut generic nop instructions. They are always valid and they
323  // never change the simulator state.
324  return;
325  }
326 
327  if (instr->IsForbiddenInBranchDelay()) {
328  V8_Fatal(__FILE__, __LINE__,
329  "Eror:Unexpected %i opcode in a branch delay slot.",
330  instr->OpcodeValue());
331  }
332  InstructionDecode(instr);
333  }
334 
335  // ICache.
336  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
337  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
338  int size);
339  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
340 
341  enum Exception {
342  none,
343  kIntegerOverflow,
344  kIntegerUnderflow,
345  kDivideByZero,
346  kNumExceptions
347  };
348  int16_t exceptions[kNumExceptions];
349 
350  // Exceptions.
351  void SignalExceptions();
352 
353  // Runtime call support.
354  static void* RedirectExternalReference(void* external_function,
356 
357  // Handle arguments and return value for runtime FP functions.
358  void GetFpArgs(double* x, double* y, int32_t* z);
359  void SetFpResult(const double& result);
360 
361  void CallInternal(byte* entry);
362 
363  // Architecture state.
364  // Registers.
365  int32_t registers_[kNumSimuRegisters];
366  // Coprocessor Registers.
367  int32_t FPUregisters_[kNumFPURegisters];
368  // FPU control register.
369  uint32_t FCSR_;
370 
371  // Simulator support.
372  // Allocate 1MB for stack.
373  static const size_t stack_size_ = 1 * 1024*1024;
374  char* stack_;
375  bool pc_modified_;
376  int icount_;
377  int break_count_;
378 
379  // Debugger input.
380  char* last_debugger_input_;
381 
382  // Icache simulation.
383  v8::internal::HashMap* i_cache_;
384 
385  v8::internal::Isolate* isolate_;
386 
387  // Registered breakpoints.
388  Instruction* break_pc_;
389  Instr break_instr_;
390 
391  // Stop is disabled if bit 31 is set.
392  static const uint32_t kStopDisabledBit = 1 << 31;
393 
394  // A stop is enabled, meaning the simulator will stop when meeting the
395  // instruction, if bit 31 of watched_stops_[code].count is unset.
396  // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
397  // the breakpoint was hit or gone through.
398  struct StopCountAndDesc {
399  uint32_t count;
400  char* desc;
401  };
402  StopCountAndDesc watched_stops_[kMaxStopCode + 1];
403 };
404 
405 
406 // When running with the simulator transition into simulated execution at this
407 // point.
408 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
409  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
410  FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
411 
412 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
413  Simulator::current(Isolate::Current())->Call( \
414  entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
415 
416 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
417  try_catch_address == NULL ? \
418  NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
419 
420 
421 // The simulator has its own stack. Thus it has a different stack limit from
422 // the C-based native code. Setting the c_limit to indicate a very small
423 // stack cause stack overflow errors, since the simulator ignores the input.
424 // This is unlikely to be an issue in practice, though it might cause testing
425 // trouble down the line.
426 class SimulatorStack : public v8::internal::AllStatic {
427  public:
428  static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
429  uintptr_t c_limit) {
430  return Simulator::current(isolate)->StackLimit();
431  }
432 
433  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
434  Simulator* sim = Simulator::current(Isolate::Current());
435  return sim->PushAddress(try_catch_address);
436  }
437 
438  static inline void UnregisterCTryCatch() {
439  Simulator::current(Isolate::Current())->PopAddress();
440  }
441 };
442 
443 } } // namespace v8::internal
444 
445 #endif // !defined(USE_SIMULATOR)
446 #endif // V8_MIPS_SIMULATOR_MIPS_H_
byte * Address
Definition: globals.h:186
const FPURegister f4
const SwVfpRegister s2
const FPURegister f20
const FPURegister f21
const FPURegister f28
const FPURegister f5
const FPURegister f15
const FPURegister f11
const SwVfpRegister s7
const LowDwVfpRegister d0
const SwVfpRegister s8
const FPURegister f0
static uintptr_t JsLimitFromCLimit(Isolate *isolate, uintptr_t c_limit)
const FPURegister f24
const FPURegister f22
const FPURegister f10
const int kNumSimuRegisters
const FPURegister f18
int(* mips_regexp_matcher)(String *, int, const byte *, const byte *, void *, int *, int, Address, int, Isolate *)
TypeImpl< ZoneTypeConfig > Type
int int32_t
Definition: unicode.cc:47
const uint32_t kMaxStopCode
unsigned short uint16_t
Definition: unicode.cc:46
const FPURegister f3
const Instr nopInstr
const SwVfpRegister s6
const int kNumFPURegisters
uint8_t byte
Definition: globals.h:185
const Register sp
const SwVfpRegister s3
void V8_Fatal(const char *file, int line, const char *format,...)
Definition: checks.cc:100
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
const FPURegister f16
const FPURegister f9
const FPURegister f29
static uintptr_t JsLimitFromCLimit(v8::internal::Isolate *isolate, uintptr_t c_limit)
Definition: simulator-arm.h:71
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const FPURegister f17
const FPURegister f23
const Register pc
const SwVfpRegister s0
const FPURegister f2
const SwVfpRegister s5
const SwVfpRegister s1
const FPURegister f19
const FPURegister f30
const FPURegister f27
const FPURegister f1
const FPURegister f7
const SwVfpRegister s4
const FPURegister f12
const FPURegister f6
const Register no_reg
const LowDwVfpRegister d1
static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address)
const Register fp
signed short int16_t
Definition: unicode.cc:45
const FPURegister f14
const FPURegister f31
const FPURegister f25
const FPURegister f26
const FPURegister f13
const FPURegister f8