OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 (entry(p0, p1, p2, p3, p4)) | 49 (entry(p0, p1, p2, p3, p4)) |
50 | 50 |
51 typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, | 51 typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, |
52 void*, int*, Address, int); | 52 void*, int*, Address, int); |
53 | 53 |
54 | 54 |
55 // Call the generated regexp code directly. The code at the entry address | 55 // Call the generated regexp code directly. The code at the entry address |
56 // should act as a function matching the type arm_regexp_matcher. | 56 // should act as a function matching the type arm_regexp_matcher. |
57 // The fifth argument is a dummy that reserves the space used for | 57 // The fifth argument is a dummy that reserves the space used for |
58 // the return address added by the ExitFrame in native calls. | 58 // the return address added by the ExitFrame in native calls. |
59 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ | 59 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \ |
60 (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6)) | 60 (FUNCTION_CAST<arm_regexp_matcher>(entry)( \ |
| 61 p0, p1, p2, p3, NULL, p4, p5, p6, p7)) |
61 | 62 |
62 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ | 63 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ |
63 (reinterpret_cast<TryCatch*>(try_catch_address)) | 64 reinterpret_cast<TryCatch*>(try_catch_address) |
64 | 65 |
65 // The stack limit beyond which we will throw stack overflow errors in | 66 // The stack limit beyond which we will throw stack overflow errors in |
66 // generated code. Because generated code on arm uses the C stack, we | 67 // generated code. Because generated code on arm uses the C stack, we |
67 // just use the C stack limit. | 68 // just use the C stack limit. |
68 class SimulatorStack : public v8::internal::AllStatic { | 69 class SimulatorStack : public v8::internal::AllStatic { |
69 public: | 70 public: |
70 static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { | 71 static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { |
71 return c_limit; | 72 return c_limit; |
72 } | 73 } |
73 | 74 |
74 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { | 75 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { |
75 return try_catch_address; | 76 return try_catch_address; |
76 } | 77 } |
77 | 78 |
78 static inline void UnregisterCTryCatch() { } | 79 static inline void UnregisterCTryCatch() { } |
79 }; | 80 }; |
80 | 81 |
81 } } // namespace v8::internal | |
82 | |
83 #else // !defined(USE_SIMULATOR) | 82 #else // !defined(USE_SIMULATOR) |
84 // Running with a simulator. | 83 // Running with a simulator. |
85 | 84 |
86 #include "constants-arm.h" | 85 #include "constants-arm.h" |
87 #include "hashmap.h" | 86 #include "hashmap.h" |
88 #include "assembler.h" | 87 #include "assembler.h" |
89 | 88 |
90 namespace v8 { | 89 namespace v8 { |
91 namespace internal { | 90 namespace internal { |
92 | 91 |
(...skipping 23 matching lines...) Expand all Loading... |
116 | 115 |
117 private: | 116 private: |
118 char data_[kPageSize]; // The cached data. | 117 char data_[kPageSize]; // The cached data. |
119 static const int kValidityMapSize = kPageSize >> kLineShift; | 118 static const int kValidityMapSize = kPageSize >> kLineShift; |
120 char validity_map_[kValidityMapSize]; // One byte per line. | 119 char validity_map_[kValidityMapSize]; // One byte per line. |
121 }; | 120 }; |
122 | 121 |
123 | 122 |
124 class Simulator { | 123 class Simulator { |
125 public: | 124 public: |
126 friend class Debugger; | 125 friend class ArmDebugger; |
127 enum Register { | 126 enum Register { |
128 no_reg = -1, | 127 no_reg = -1, |
129 r0 = 0, r1, r2, r3, r4, r5, r6, r7, | 128 r0 = 0, r1, r2, r3, r4, r5, r6, r7, |
130 r8, r9, r10, r11, r12, r13, r14, r15, | 129 r8, r9, r10, r11, r12, r13, r14, r15, |
131 num_registers, | 130 num_registers, |
132 sp = 13, | 131 sp = 13, |
133 lr = 14, | 132 lr = 14, |
134 pc = 15, | 133 pc = 15, |
135 s0 = 0, s1, s2, s3, s4, s5, s6, s7, | 134 s0 = 0, s1, s2, s3, s4, s5, s6, s7, |
136 s8, s9, s10, s11, s12, s13, s14, s15, | 135 s8, s9, s10, s11, s12, s13, s14, s15, |
137 s16, s17, s18, s19, s20, s21, s22, s23, | 136 s16, s17, s18, s19, s20, s21, s22, s23, |
138 s24, s25, s26, s27, s28, s29, s30, s31, | 137 s24, s25, s26, s27, s28, s29, s30, s31, |
139 num_s_registers = 32, | 138 num_s_registers = 32, |
140 d0 = 0, d1, d2, d3, d4, d5, d6, d7, | 139 d0 = 0, d1, d2, d3, d4, d5, d6, d7, |
141 d8, d9, d10, d11, d12, d13, d14, d15, | 140 d8, d9, d10, d11, d12, d13, d14, d15, |
142 num_d_registers = 16 | 141 num_d_registers = 16 |
143 }; | 142 }; |
144 | 143 |
145 Simulator(); | 144 Simulator(); |
146 ~Simulator(); | 145 ~Simulator(); |
147 | 146 |
148 // The currently executing Simulator instance. Potentially there can be one | 147 // The currently executing Simulator instance. Potentially there can be one |
149 // for each native thread. | 148 // for each native thread. |
150 static Simulator* current(); | 149 static Simulator* current(v8::internal::Isolate* isolate); |
151 | 150 |
152 // Accessors for register state. Reading the pc value adheres to the ARM | 151 // Accessors for register state. Reading the pc value adheres to the ARM |
153 // architecture specification and is off by a 8 from the currently executing | 152 // architecture specification and is off by a 8 from the currently executing |
154 // instruction. | 153 // instruction. |
155 void set_register(int reg, int32_t value); | 154 void set_register(int reg, int32_t value); |
156 int32_t get_register(int reg) const; | 155 int32_t get_register(int reg) const; |
157 void set_dw_register(int dreg, const int* dbl); | 156 void set_dw_register(int dreg, const int* dbl); |
158 | 157 |
159 // Support for VFP. | 158 // Support for VFP. |
160 void set_s_register(int reg, unsigned int value); | 159 void set_s_register(int reg, unsigned int value); |
(...skipping 23 matching lines...) Expand all Loading... |
184 // which sets up the simulator state and grabs the result on return. | 183 // which sets up the simulator state and grabs the result on return. |
185 int32_t Call(byte* entry, int argument_count, ...); | 184 int32_t Call(byte* entry, int argument_count, ...); |
186 | 185 |
187 // Push an address onto the JS stack. | 186 // Push an address onto the JS stack. |
188 uintptr_t PushAddress(uintptr_t address); | 187 uintptr_t PushAddress(uintptr_t address); |
189 | 188 |
190 // Pop an address from the JS stack. | 189 // Pop an address from the JS stack. |
191 uintptr_t PopAddress(); | 190 uintptr_t PopAddress(); |
192 | 191 |
193 // ICache checking. | 192 // ICache checking. |
194 static void FlushICache(void* start, size_t size); | 193 static void FlushICache(v8::internal::HashMap* i_cache, void* start, |
| 194 size_t size); |
195 | 195 |
196 // Returns true if pc register contains one of the 'special_values' defined | 196 // Returns true if pc register contains one of the 'special_values' defined |
197 // below (bad_lr, end_sim_pc). | 197 // below (bad_lr, end_sim_pc). |
198 bool has_bad_pc() const; | 198 bool has_bad_pc() const; |
199 | 199 |
200 private: | 200 private: |
201 enum special_values { | 201 enum special_values { |
202 // Known bad pc value to ensure that the simulator does not execute | 202 // Known bad pc value to ensure that the simulator does not execute |
203 // without being properly setup. | 203 // without being properly setup. |
204 bad_lr = -1, | 204 bad_lr = -1, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 280 |
281 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); | 281 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); |
282 void DecodeVCMP(Instruction* instr); | 282 void DecodeVCMP(Instruction* instr); |
283 void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); | 283 void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); |
284 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); | 284 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); |
285 | 285 |
286 // Executes one instruction. | 286 // Executes one instruction. |
287 void InstructionDecode(Instruction* instr); | 287 void InstructionDecode(Instruction* instr); |
288 | 288 |
289 // ICache. | 289 // ICache. |
290 static void CheckICache(Instruction* instr); | 290 static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); |
291 static void FlushOnePage(intptr_t start, int size); | 291 static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, |
292 static CachePage* GetCachePage(void* page); | 292 int size); |
| 293 static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); |
293 | 294 |
294 // Runtime call support. | 295 // Runtime call support. |
295 static void* RedirectExternalReference( | 296 static void* RedirectExternalReference( |
296 void* external_function, | 297 void* external_function, |
297 v8::internal::ExternalReference::Type type); | 298 v8::internal::ExternalReference::Type type); |
298 | 299 |
299 // For use in calls that take two double values, constructed from r0, r1, r2 | 300 // For use in calls that take two double values, constructed from r0, r1, r2 |
300 // and r3. | 301 // and r3. |
301 void GetFpArgs(double* x, double* y); | 302 void GetFpArgs(double* x, double* y); |
302 void SetFpResult(const double& result); | 303 void SetFpResult(const double& result); |
(...skipping 23 matching lines...) Expand all Loading... |
326 bool inv_op_vfp_flag_; | 327 bool inv_op_vfp_flag_; |
327 bool div_zero_vfp_flag_; | 328 bool div_zero_vfp_flag_; |
328 bool overflow_vfp_flag_; | 329 bool overflow_vfp_flag_; |
329 bool underflow_vfp_flag_; | 330 bool underflow_vfp_flag_; |
330 bool inexact_vfp_flag_; | 331 bool inexact_vfp_flag_; |
331 | 332 |
332 // Simulator support. | 333 // Simulator support. |
333 char* stack_; | 334 char* stack_; |
334 bool pc_modified_; | 335 bool pc_modified_; |
335 int icount_; | 336 int icount_; |
336 static bool initialized_; | |
337 | 337 |
338 // Icache simulation | 338 // Icache simulation |
339 static v8::internal::HashMap* i_cache_; | 339 v8::internal::HashMap* i_cache_; |
340 | 340 |
341 // Registered breakpoints. | 341 // Registered breakpoints. |
342 Instruction* break_pc_; | 342 Instruction* break_pc_; |
343 Instr break_instr_; | 343 Instr break_instr_; |
344 | 344 |
| 345 v8::internal::Isolate* isolate_; |
| 346 |
345 // A stop is watched if its code is less than kNumOfWatchedStops. | 347 // A stop is watched if its code is less than kNumOfWatchedStops. |
346 // Only watched stops support enabling/disabling and the counter feature. | 348 // Only watched stops support enabling/disabling and the counter feature. |
347 static const uint32_t kNumOfWatchedStops = 256; | 349 static const uint32_t kNumOfWatchedStops = 256; |
348 | 350 |
349 // Breakpoint is disabled if bit 31 is set. | 351 // Breakpoint is disabled if bit 31 is set. |
350 static const uint32_t kStopDisabledBit = 1 << 31; | 352 static const uint32_t kStopDisabledBit = 1 << 31; |
351 | 353 |
352 // A stop is enabled, meaning the simulator will stop when meeting the | 354 // A stop is enabled, meaning the simulator will stop when meeting the |
353 // instruction, if bit 31 of watched_stops[code].count is unset. | 355 // instruction, if bit 31 of watched_stops[code].count is unset. |
354 // The value watched_stops[code].count & ~(1 << 31) indicates how many times | 356 // The value watched_stops[code].count & ~(1 << 31) indicates how many times |
355 // the breakpoint was hit or gone through. | 357 // the breakpoint was hit or gone through. |
356 struct StopCountAndDesc { | 358 struct StopCountAndDesc { |
357 uint32_t count; | 359 uint32_t count; |
358 char* desc; | 360 char* desc; |
359 }; | 361 }; |
360 StopCountAndDesc watched_stops[kNumOfWatchedStops]; | 362 StopCountAndDesc watched_stops[kNumOfWatchedStops]; |
361 }; | 363 }; |
362 | 364 |
363 | 365 |
364 // When running with the simulator transition into simulated execution at this | 366 // When running with the simulator transition into simulated execution at this |
365 // point. | 367 // point. |
366 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ | 368 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ |
367 reinterpret_cast<Object*>(Simulator::current()->Call( \ | 369 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \ |
368 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) | 370 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) |
369 | 371 |
370 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ | 372 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \ |
371 Simulator::current()->Call(entry, 8, p0, p1, p2, p3, NULL, p4, p5, p6) | 373 Simulator::current(Isolate::Current())->Call( \ |
| 374 entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7) |
372 | 375 |
373 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ | 376 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ |
374 try_catch_address == \ | 377 try_catch_address == NULL ? \ |
375 NULL ? NULL : *(reinterpret_cast<TryCatch**>(try_catch_address)) | 378 NULL : *(reinterpret_cast<TryCatch**>(try_catch_address)) |
376 | 379 |
377 | 380 |
378 // The simulator has its own stack. Thus it has a different stack limit from | 381 // The simulator has its own stack. Thus it has a different stack limit from |
379 // the C-based native code. Setting the c_limit to indicate a very small | 382 // the C-based native code. Setting the c_limit to indicate a very small |
380 // stack cause stack overflow errors, since the simulator ignores the input. | 383 // stack cause stack overflow errors, since the simulator ignores the input. |
381 // This is unlikely to be an issue in practice, though it might cause testing | 384 // This is unlikely to be an issue in practice, though it might cause testing |
382 // trouble down the line. | 385 // trouble down the line. |
383 class SimulatorStack : public v8::internal::AllStatic { | 386 class SimulatorStack : public v8::internal::AllStatic { |
384 public: | 387 public: |
385 static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { | 388 static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { |
386 return Simulator::current()->StackLimit(); | 389 return Simulator::current(Isolate::Current())->StackLimit(); |
387 } | 390 } |
388 | 391 |
389 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { | 392 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { |
390 Simulator* sim = Simulator::current(); | 393 Simulator* sim = Simulator::current(Isolate::Current()); |
391 return sim->PushAddress(try_catch_address); | 394 return sim->PushAddress(try_catch_address); |
392 } | 395 } |
393 | 396 |
394 static inline void UnregisterCTryCatch() { | 397 static inline void UnregisterCTryCatch() { |
395 Simulator::current()->PopAddress(); | 398 Simulator::current(Isolate::Current())->PopAddress(); |
396 } | 399 } |
397 }; | 400 }; |
398 | 401 |
399 } } // namespace v8::internal | 402 } } // namespace v8::internal |
400 | 403 |
401 #endif // !defined(USE_SIMULATOR) | 404 #endif // !defined(USE_SIMULATOR) |
402 #endif // V8_ARM_SIMULATOR_ARM_H_ | 405 #endif // V8_ARM_SIMULATOR_ARM_H_ |
OLD | NEW |