OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #include <setjmp.h> // NOLINT | |
6 #include <stdlib.h> | |
7 | |
8 #include "vm/globals.h" | |
9 #if defined(TARGET_ARCH_DBC) | |
10 | |
11 #if !defined(USING_SIMULATOR) | |
12 #error "DBC is a simulated architecture" | |
13 #endif | |
14 | |
15 #include "vm/simulator.h" | |
16 | |
17 #include "vm/assembler.h" | |
18 #include "vm/compiler.h" | |
19 #include "vm/constants_dbc.h" | |
20 #include "vm/cpu.h" | |
21 #include "vm/dart_entry.h" | |
22 #include "vm/debugger.h" | |
23 #include "vm/disassembler.h" | |
24 #include "vm/lockers.h" | |
25 #include "vm/native_arguments.h" | |
26 #include "vm/native_entry.h" | |
27 #include "vm/object.h" | |
28 #include "vm/object_store.h" | |
29 #include "vm/os_thread.h" | |
30 #include "vm/stack_frame.h" | |
31 | |
32 namespace dart { | |
33 | |
34 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, | |
35 "Trace simulator execution after instruction count reached."); | |
36 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, | |
37 "Instruction address or instruction count to stop simulator at."); | |
38 | |
39 // SimulatorSetjmpBuffer are linked together, and the last created one | |
40 // is referenced by the Simulator. When an exception is thrown, the exception | |
41 // runtime looks at where to jump and finds the corresponding | |
42 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. | |
43 // The runtime then does a Longjmp on that buffer to return to the simulator. | |
44 class SimulatorSetjmpBuffer { | |
45 public: | |
46 void Longjmp() { | |
47 // "This" is now the last setjmp buffer. | |
48 simulator_->set_last_setjmp_buffer(this); | |
49 longjmp(buffer_, 1); | |
50 } | |
51 | |
52 explicit SimulatorSetjmpBuffer(Simulator* sim) { | |
53 simulator_ = sim; | |
54 link_ = sim->last_setjmp_buffer(); | |
55 sim->set_last_setjmp_buffer(this); | |
56 top_ = sim->top_; | |
57 base_ = sim->base_; | |
58 } | |
59 | |
60 ~SimulatorSetjmpBuffer() { | |
61 ASSERT(simulator_->last_setjmp_buffer() == this); | |
62 simulator_->set_last_setjmp_buffer(link_); | |
63 } | |
64 | |
65 SimulatorSetjmpBuffer* link() { return link_; } | |
66 | |
67 uintptr_t* top() const { return top_; } | |
68 uword base() const { return reinterpret_cast<uword>(base_); } | |
69 | |
70 jmp_buf buffer_; | |
71 | |
72 private: | |
73 uintptr_t* top_; | |
74 uintptr_t* base_; | |
75 Simulator* simulator_; | |
76 SimulatorSetjmpBuffer* link_; | |
77 | |
78 friend class Simulator; | |
79 }; | |
80 | |
81 | |
82 DART_FORCE_INLINE static RawObject** SavedCallerFP(RawObject** FP) { | |
83 return reinterpret_cast<RawObject**>(FP[kSavedCallerFpSlotFromFp]); | |
84 } | |
85 | |
86 | |
87 DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) { | |
88 return static_cast<RawCode*>(FP[kPcMarkerSlotFromFp]); | |
89 } | |
90 | |
91 | |
92 DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) { | |
93 FP[kPcMarkerSlotFromFp] = code; | |
94 } | |
95 | |
96 | |
97 DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, | |
98 intptr_t argc) { | |
99 return FP - (kDartFrameFixedSize + argc); | |
100 } | |
101 | |
102 | |
103 class SimulatorHelpers { | |
104 public: | |
105 DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { | |
106 return Smi::New(obj->IsHeapObject() ? obj->GetClassId() : kSmiCid); | |
107 } | |
108 | |
109 DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { | |
110 return obj->IsHeapObject() ? obj->GetClassId() : kSmiCid; | |
111 } | |
112 | |
113 DART_FORCE_INLINE static void IncrementUsageCounter(RawICData* icdata) { | |
114 reinterpret_cast<RawFunction*>(icdata->ptr()->owner_) | |
115 ->ptr() | |
116 ->usage_counter_++; | |
117 } | |
118 | |
119 DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, | |
120 RawObject* rhs) { | |
121 if (lhs == rhs) { | |
122 return true; | |
123 } | |
124 | |
125 if (lhs->IsHeapObject() && rhs->IsHeapObject()) { | |
126 const intptr_t lhs_cid = lhs->GetClassId(); | |
127 const intptr_t rhs_cid = rhs->GetClassId(); | |
128 if (lhs_cid == rhs_cid) { | |
129 switch (lhs_cid) { | |
130 case kDoubleCid: | |
131 return (bit_cast<uint64_t, double>( | |
132 static_cast<RawDouble*>(lhs)->ptr()->value_) == | |
133 bit_cast<uint64_t, double>( | |
134 static_cast<RawDouble*>(rhs)->ptr()->value_)); | |
135 | |
136 case kMintCid: | |
137 return (static_cast<RawMint*>(lhs)->ptr()->value_ == | |
138 static_cast<RawMint*>(rhs)->ptr()->value_); | |
139 | |
140 case kBigintCid: | |
141 return (DLRT_BigintCompare(static_cast<RawBigint*>(lhs), | |
142 static_cast<RawBigint*>(rhs)) == 0); | |
143 } | |
144 } | |
145 } | |
146 | |
147 return false; | |
148 } | |
149 | |
150 template <typename T> | |
151 DART_FORCE_INLINE static T* Untag(T* tagged) { | |
152 return tagged->ptr(); | |
153 } | |
154 | |
155 static bool ObjectArraySetIndexed(Thread* thread, RawObject** B, | |
156 RawObject** result) { | |
157 if (thread->isolate()->type_checks()) { | |
158 return false; | |
159 } | |
160 | |
161 RawObject** args = FrameArguments(B, 3); | |
162 RawSmi* index = static_cast<RawSmi*>(args[1]); | |
163 RawArray* array = static_cast<RawArray*>(args[0]); | |
164 if (!index->IsHeapObject() && reinterpret_cast<intptr_t>(index) >= 0 && | |
165 reinterpret_cast<intptr_t>(index) < | |
166 reinterpret_cast<intptr_t>(array->ptr()->length_)) { | |
167 array->StorePointer(array->ptr()->data() + Smi::Value(index), args[2]); | |
168 return true; | |
169 } | |
170 return false; | |
171 } | |
172 | |
173 static bool ObjectArrayGetIndexed(Thread* thread, RawObject** B, | |
174 RawObject** result) { | |
175 RawObject** args = FrameArguments(B, 2); | |
176 RawSmi* index = static_cast<RawSmi*>(args[1]); | |
177 RawArray* array = static_cast<RawArray*>(args[0]); | |
178 if (!index->IsHeapObject() && reinterpret_cast<intptr_t>(index) >= 0 && | |
179 reinterpret_cast<intptr_t>(index) < | |
180 reinterpret_cast<intptr_t>(array->ptr()->length_)) { | |
181 *result = array->ptr()->data()[Smi::Value(index)]; | |
182 return true; | |
183 } | |
184 return false; | |
185 } | |
186 | |
187 static bool GrowableArraySetIndexed(Thread* thread, RawObject** B, | |
188 RawObject** result) { | |
189 if (thread->isolate()->type_checks()) { | |
190 return false; | |
191 } | |
192 | |
193 RawObject** args = FrameArguments(B, 3); | |
194 RawSmi* index = static_cast<RawSmi*>(args[1]); | |
195 RawGrowableObjectArray* array = | |
196 static_cast<RawGrowableObjectArray*>(args[0]); | |
197 if (!index->IsHeapObject() && reinterpret_cast<intptr_t>(index) >= 0 && | |
198 reinterpret_cast<intptr_t>(index) < | |
199 reinterpret_cast<intptr_t>(array->ptr()->length_)) { | |
200 RawArray* data = array->ptr()->data_; | |
201 data->StorePointer(data->ptr()->data() + Smi::Value(index), args[2]); | |
202 return true; | |
203 } | |
204 return false; | |
205 } | |
206 | |
207 static bool GrowableArrayGetIndexed(Thread* thread, RawObject** B, | |
208 RawObject** result) { | |
209 RawObject** args = FrameArguments(B, 2); | |
210 RawSmi* index = static_cast<RawSmi*>(args[1]); | |
211 RawGrowableObjectArray* array = | |
212 static_cast<RawGrowableObjectArray*>(args[0]); | |
213 if (!index->IsHeapObject() && reinterpret_cast<intptr_t>(index) >= 0 && | |
214 reinterpret_cast<intptr_t>(index) < | |
215 reinterpret_cast<intptr_t>(array->ptr()->length_)) { | |
216 *result = array->ptr()->data_->ptr()->data()[Smi::Value(index)]; | |
217 return true; | |
218 } | |
219 return false; | |
220 } | |
221 }; | |
222 | |
223 | |
224 DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) { | |
225 return reinterpret_cast<uint32_t*>(FP[kSavedCallerPcSlotFromFp]); | |
226 } | |
227 | |
228 | |
229 DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) { | |
230 RawFunction* function = static_cast<RawFunction*>(FP[kFunctionSlotFromFp]); | |
231 ASSERT(SimulatorHelpers::GetClassId(function) == kFunctionCid); | |
232 return function; | |
233 } | |
234 | |
235 | |
236 IntrinsicHandler Simulator::intrinsics_[Simulator::kIntrinsicCount]; | |
237 | |
238 | |
239 // Synchronization primitives support. | |
240 void Simulator::InitOnce() { | |
241 for (intptr_t i = 0; i < kIntrinsicCount; i++) { | |
242 intrinsics_[i] = 0; | |
243 } | |
244 | |
245 intrinsics_[kObjectArraySetIndexedIntrinsic] = | |
246 SimulatorHelpers::ObjectArraySetIndexed; | |
247 intrinsics_[kObjectArrayGetIndexedIntrinsic] = | |
248 SimulatorHelpers::ObjectArrayGetIndexed; | |
249 intrinsics_[kGrowableArraySetIndexedIntrinsic] = | |
250 SimulatorHelpers::GrowableArraySetIndexed; | |
251 intrinsics_[kGrowableArrayGetIndexedIntrinsic] = | |
252 SimulatorHelpers::GrowableArrayGetIndexed; | |
253 } | |
254 | |
255 | |
256 Simulator::Simulator() { | |
257 // Setup simulator support first. Some of this information is needed to | |
258 // setup the architecture state. | |
259 // We allocate the stack here, the size is computed as the sum of | |
260 // the size specified by the user and the buffer space needed for | |
261 // handling stack overflow exceptions. To be safe in potential | |
262 // stack underflows we also add some underflow buffer space. | |
263 stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() + | |
264 OSThread::kStackSizeBuffer + | |
265 kSimulatorStackUnderflowSize) / | |
266 sizeof(uintptr_t)]; | |
267 base_ = top_ = stack_; | |
268 last_setjmp_buffer_ = NULL; | |
269 top_exit_frame_info_ = 0; | |
270 } | |
271 | |
272 | |
273 Simulator::~Simulator() { | |
274 delete[] stack_; | |
275 Isolate* isolate = Isolate::Current(); | |
276 if (isolate != NULL) { | |
277 isolate->set_simulator(NULL); | |
278 } | |
279 } | |
280 | |
281 | |
282 // Get the active Simulator for the current isolate. | |
283 Simulator* Simulator::Current() { | |
284 Simulator* simulator = Isolate::Current()->simulator(); | |
285 if (simulator == NULL) { | |
286 simulator = new Simulator(); | |
287 Isolate::Current()->set_simulator(simulator); | |
288 } | |
289 return simulator; | |
290 } | |
291 | |
292 | |
293 // Returns the top of the stack area to enable checking for stack pointer | |
294 // validity. | |
295 uword Simulator::StackTop() const { | |
296 // To be safe in potential stack underflows we leave some buffer above and | |
297 // set the stack top. | |
298 return StackBase() + | |
299 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | |
300 } | |
301 | |
302 | |
303 // Calls into the Dart runtime are based on this interface. | |
304 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | |
305 | |
306 // Calls to leaf Dart runtime functions are based on this interface. | |
307 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, int32_t r1, int32_t r2, | |
Florian Schneider
2016/04/12 18:01:42
Formatting: one arg per line. Here and the places
Vyacheslav Egorov (Google)
2016/04/14 13:05:27
Done.
| |
308 int32_t r3); | |
309 | |
310 // Calls to leaf float Dart runtime functions are based on this interface. | |
311 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | |
312 | |
313 // Calls to native Dart functions are based on this interface. | |
314 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | |
315 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | |
316 | |
317 | |
318 void Simulator::Exit(Thread* thread, RawObject** base, RawObject** frame, | |
319 uint32_t* pc) { | |
320 frame[0] = Function::null(); | |
321 frame[1] = Code::null(); | |
322 frame[2] = reinterpret_cast<RawObject*>(pc); | |
323 frame[3] = reinterpret_cast<RawObject*>(base); | |
324 base_ = top_ = reinterpret_cast<uintptr_t*>(frame + kDartFrameFixedSize); | |
325 thread->set_top_exit_frame_info(reinterpret_cast<uword>(top_)); | |
326 } | |
327 | |
328 | |
329 #if defined(__has_builtin) | |
330 #if __has_builtin(__builtin_smul_overflow) | |
331 #define HAS_MUL_OVERFLOW | |
332 #endif | |
333 #if __has_builtin(__builtin_sadd_overflow) | |
334 #define HAS_ADD_OVERFLOW | |
335 #endif | |
336 #if __has_builtin(__builtin_ssub_overflow) | |
337 #define HAS_SUB_OVERFLOW | |
338 #endif | |
339 #endif | |
340 | |
341 | |
342 DART_FORCE_INLINE static int32_t SignedAddWithOverflow(int32_t lhs, int32_t rhs, | |
343 intptr_t* out) { | |
344 int32_t res = 1; | |
345 #if defined(HAS_ADD_OVERFLOW) | |
346 res = __builtin_sadd_overflow(lhs, rhs, out); | |
347 #elif defined(__i386__) | |
348 asm volatile( | |
349 "add %2, %1\n" | |
350 "jo 1f;\n" | |
351 "xor %0, %0\n" | |
352 "mov %1, 0(%3)\n" | |
353 "1: " | |
354 : "+r"(res), "+r"(lhs) | |
355 : "r"(rhs), "r"(out) | |
356 : "cc"); | |
357 #elif defined(__arm__) | |
358 asm volatile( | |
359 "adds %1, %1, %2;\n" | |
360 "bvs 1f;\n" | |
361 "mov %0, $0;\n" | |
362 "str %1, [%3, #0]\n" | |
363 "1:" | |
364 : "+r"(res), "+r"(lhs) | |
365 : "r"(rhs), "r"(out) | |
366 : "cc", "r12"); | |
367 #else | |
368 #error "Unsupported platform" | |
369 #endif | |
370 return res; | |
371 } | |
372 | |
373 | |
374 DART_FORCE_INLINE static int32_t SignedSubWithOverflow(int32_t lhs, int32_t rhs, | |
375 intptr_t* out) { | |
376 int32_t res = 1; | |
377 #if defined(HAS_SUB_OVERFLOW) | |
378 res = __builtin_ssub_overflow(lhs, rhs, out); | |
379 #elif defined(__i386__) | |
380 asm volatile( | |
381 "sub %2, %1\n" | |
382 "jo 1f;\n" | |
383 "xor %0, %0\n" | |
384 "mov %1, 0(%3)\n" | |
385 "1: " | |
386 : "+r"(res), "+r"(lhs) | |
387 : "r"(rhs), "r"(out) | |
388 : "cc"); | |
389 #elif defined(__arm__) | |
390 asm volatile( | |
391 "subs %1, %1, %2;\n" | |
392 "bvs 1f;\n" | |
393 "mov %0, $0;\n" | |
394 "str %1, [%3, #0]\n" | |
395 "1:" | |
396 : "+r"(res), "+r"(lhs) | |
397 : "r"(rhs), "r"(out) | |
398 : "cc", "r12"); | |
399 #else | |
400 #error "Unsupported platform" | |
401 #endif | |
402 return res; | |
403 } | |
404 | |
405 | |
406 DART_FORCE_INLINE static int32_t SignedMulWithOverflow(int32_t lhs, int32_t rhs, | |
407 intptr_t* out) { | |
408 int32_t res = 1; | |
409 #if defined(HAS_MUL_OVERFLOW) | |
410 res = __builtin_smul_overflow(lhs, rhs, out); | |
411 #elif defined(__i386__) | |
412 asm volatile( | |
413 "imul %2, %1\n" | |
414 "jo 1f;\n" | |
415 "xor %0, %0\n" | |
416 "mov %1, 0(%3)\n" | |
417 "1: " | |
418 : "+r"(res), "+r"(lhs) | |
419 : "r"(rhs), "r"(out) | |
420 : "cc"); | |
421 #elif defined(__arm__) | |
422 asm volatile( | |
423 "smull %1, ip, %1, %2;\n" | |
424 "cmp ip, %1, ASR #31;\n" | |
425 "bne 1f;\n" | |
426 "mov %0, $0;\n" | |
427 "str %1, [%3, #0]\n" | |
428 "1:" | |
429 : "+r"(res), "+r"(lhs) | |
430 : "r"(rhs), "r"(out) | |
431 : "cc", "r12"); | |
432 #else | |
433 #error "Unsupported platform" | |
434 #endif | |
435 return res; | |
436 } | |
437 | |
438 DART_FORCE_INLINE static int32_t SMI_DIV(int32_t lhs, int32_t rhs, | |
Florian Schneider
2016/04/12 18:01:42
I don't see uses of SMI_DIV? Is the fast-path code
Vyacheslav Egorov (Google)
2016/04/14 13:05:27
Deleted.
| |
439 intptr_t* out) { | |
440 if (rhs == 0) { | |
441 return 1; | |
442 } | |
443 | |
444 const int32_t res = (lhs >> 1) / (rhs >> 1); | |
445 if (res == 0x40000000) { | |
446 return 1; // Overflow | |
447 } | |
448 | |
449 *out = res << 1; | |
450 return 0; | |
451 } | |
452 | |
453 | |
454 #define LIKELY(cond) __builtin_expect((cond), 1) | |
455 | |
456 | |
457 DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { | |
458 return ((a | b) & kHeapObjectTag) == 0; | |
459 } | |
460 | |
461 | |
462 #define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres) | |
463 #define SMI_COND(cond, lhs, rhs, pres) \ | |
464 ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false) | |
465 #define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres) | |
466 #define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres) | |
467 #define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) | |
468 #define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) | |
469 #define SMI_BITAND(lhs, rhs, pres) ((*(pres) = (lhs & rhs)), false) | |
470 | |
471 | |
472 void Simulator::CallRuntime(Thread* thread, RawObject** base, | |
473 RawObject** exit_frame, uint32_t* pc, | |
474 intptr_t argc_tag, RawObject** args, | |
475 RawObject** result, uword target) { | |
476 Exit(thread, base, exit_frame, pc); | |
477 NativeArguments native_args(thread, argc_tag, args, result); | |
478 reinterpret_cast<RuntimeFunction>(target)(native_args); | |
479 } | |
480 | |
481 | |
482 DART_FORCE_INLINE void Simulator::Invoke(Thread* thread, RawObject** call_base, | |
483 RawObject** call_top, | |
484 RawObjectPool** pp, uint32_t** pc, | |
485 RawObject*** B, RawObject*** SP) { | |
486 RawObject** callee_fp = call_top + kDartFrameFixedSize; | |
487 | |
488 RawFunction* function = FrameFunction(callee_fp); | |
489 RawCode* code = function->ptr()->code_; | |
490 callee_fp[kPcMarkerSlotFromFp] = code; | |
491 callee_fp[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc); | |
492 callee_fp[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*B); | |
493 *pp = code->ptr()->object_pool_->ptr(); | |
494 *pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_); | |
495 *B = callee_fp; | |
496 *SP = *B - 1; | |
497 } | |
498 | |
499 | |
500 void Simulator::InlineCacheMiss(int checked_args, Thread* thread, | |
501 RawICData* icdata, RawObject** call_base, | |
502 RawObject** top, uint32_t* pc, RawObject** B, | |
503 RawObject** SP) { | |
504 RawObject** args = call_base; | |
505 for (intptr_t i = 0; i < checked_args; i++) { | |
506 top[1 + i] = args[i]; | |
507 } | |
508 top[1 + checked_args] = icdata; | |
509 RuntimeFunction handler = NULL; | |
510 switch (checked_args) { | |
511 case 1: | |
512 handler = DRT_InlineCacheMissHandlerOneArg; | |
513 break; | |
514 case 2: | |
515 handler = DRT_InlineCacheMissHandlerTwoArgs; | |
516 break; | |
517 case 3: | |
518 handler = DRT_InlineCacheMissHandlerThreeArgs; | |
519 break; | |
520 default: | |
521 UNREACHABLE(); | |
522 break; | |
523 } | |
524 CallRuntime(thread, B, top + checked_args + 1 + 1, pc, checked_args + 1, | |
525 top + 1, top, reinterpret_cast<uword>(handler)); | |
526 } | |
527 | |
528 | |
529 DART_FORCE_INLINE void Simulator::InstanceCall1( | |
530 Thread* thread, RawICData* icdata, RawObject** call_base, RawObject** top, | |
531 Array* argdesc, RawObjectPool** pp, uint32_t** pc, RawObject*** B, | |
532 RawObject*** SP) { | |
533 ASSERT(icdata->GetClassId() == kICDataCid); | |
534 SimulatorHelpers::IncrementUsageCounter(icdata); | |
535 | |
536 const intptr_t kCheckedArgs = 1; | |
537 RawObject** args = call_base; | |
538 RawArray* cache = icdata->ptr()->ic_data_->ptr(); | |
539 | |
540 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); | |
541 | |
542 bool found = false; | |
543 for (intptr_t i = 0, length = Smi::Value(cache->length_); | |
544 i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { | |
545 if (cache->data()[i + 0] == receiver_cid) { | |
546 top[0] = cache->data()[i + kCheckedArgs]; | |
547 found = true; | |
548 break; | |
549 } | |
550 } | |
551 | |
552 if (!found) { | |
553 InlineCacheMiss(kCheckedArgs, thread, icdata, call_base, top, *pc, *B, *SP); | |
554 } | |
555 | |
556 *argdesc = icdata->ptr()->args_descriptor_; | |
557 Invoke(thread, call_base, top, pp, pc, B, SP); | |
558 } | |
559 | |
560 | |
561 DART_FORCE_INLINE void Simulator::InstanceCall2( | |
562 Thread* thread, RawICData* icdata, RawObject** call_base, RawObject** top, | |
563 Array* argdesc, RawObjectPool** pp, uint32_t** pc, RawObject*** B, | |
564 RawObject*** SP) { | |
565 ASSERT(icdata->GetClassId() == kICDataCid); | |
566 SimulatorHelpers::IncrementUsageCounter(icdata); | |
567 | |
568 const intptr_t kCheckedArgs = 2; | |
569 RawObject** args = call_base; | |
570 RawArray* cache = icdata->ptr()->ic_data_->ptr(); | |
571 | |
572 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); | |
573 RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]); | |
574 | |
575 bool found = false; | |
576 for (intptr_t i = 0, length = Smi::Value(cache->length_); | |
577 i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { | |
578 if (cache->data()[i + 0] == receiver_cid && | |
579 cache->data()[i + 1] == arg0_cid) { | |
580 top[0] = cache->data()[i + kCheckedArgs]; | |
581 found = true; | |
582 break; | |
583 } | |
584 } | |
585 | |
586 if (!found) { | |
587 InlineCacheMiss(kCheckedArgs, thread, icdata, call_base, top, *pc, *B, *SP); | |
588 } | |
589 | |
590 *argdesc = icdata->ptr()->args_descriptor_; | |
591 Invoke(thread, call_base, top, pp, pc, B, SP); | |
592 } | |
593 | |
594 | |
595 DART_FORCE_INLINE void Simulator::InstanceCall3( | |
596 Thread* thread, RawICData* icdata, RawObject** call_base, RawObject** top, | |
597 Array* argdesc, RawObjectPool** pp, uint32_t** pc, RawObject*** B, | |
598 RawObject*** SP) { | |
599 ASSERT(icdata->GetClassId() == kICDataCid); | |
600 SimulatorHelpers::IncrementUsageCounter(icdata); | |
601 | |
602 const intptr_t kCheckedArgs = 3; | |
603 RawObject** args = call_base; | |
604 RawArray* cache = icdata->ptr()->ic_data_->ptr(); | |
605 | |
606 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); | |
607 RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]); | |
608 RawSmi* arg1_cid = SimulatorHelpers::GetClassIdAsSmi(args[2]); | |
609 | |
610 bool found = false; | |
611 for (intptr_t i = 0, length = Smi::Value(cache->length_); | |
612 i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { | |
613 if (cache->data()[i + 0] == receiver_cid && | |
614 cache->data()[i + 1] == arg0_cid && cache->data()[i + 2] == arg1_cid) { | |
615 top[0] = cache->data()[i + kCheckedArgs]; | |
616 found = true; | |
617 break; | |
618 } | |
619 } | |
620 | |
621 if (!found) { | |
622 InlineCacheMiss(kCheckedArgs, thread, icdata, call_base, top, *pc, *B, *SP); | |
623 } | |
624 | |
625 *argdesc = icdata->ptr()->args_descriptor_; | |
626 Invoke(thread, call_base, top, pp, pc, B, SP); | |
627 } | |
628 | |
629 | |
630 static __attribute__((noinline)) bool InvokeRuntime( | |
631 Thread* thread, Simulator* sim, RuntimeFunction drt, | |
632 const NativeArguments& args) { | |
633 SimulatorSetjmpBuffer buffer(sim); | |
634 if (!setjmp(buffer.buffer_)) { | |
635 thread->set_vm_tag(reinterpret_cast<uword>(drt)); | |
636 drt(args); | |
637 thread->set_vm_tag(VMTag::kDartTagId); | |
638 return true; | |
639 } else { | |
640 return false; | |
641 } | |
642 } | |
643 | |
644 | |
645 static __attribute__((noinline)) bool InvokeNative( | |
646 Thread* thread, Simulator* sim, SimulatorBootstrapNativeCall f, | |
647 NativeArguments* args) { | |
648 SimulatorSetjmpBuffer buffer(sim); | |
649 if (!setjmp(buffer.buffer_)) { | |
650 thread->set_vm_tag(reinterpret_cast<uword>(f)); | |
651 f(args); | |
652 thread->set_vm_tag(VMTag::kDartTagId); | |
653 return true; | |
654 } else { | |
655 return false; | |
656 } | |
657 } | |
658 | |
659 | |
660 static __attribute__((noinline)) bool InvokeNativeWrapper( | |
661 Thread* thread, Simulator* sim, Dart_NativeFunction f, | |
662 NativeArguments* args) { | |
663 SimulatorSetjmpBuffer buffer(sim); | |
664 if (!setjmp(buffer.buffer_)) { | |
665 thread->set_vm_tag(reinterpret_cast<uword>(f)); | |
666 NativeEntry::NativeCallWrapper( | |
667 reinterpret_cast<Dart_NativeArguments>(args), f); | |
668 thread->set_vm_tag(VMTag::kDartTagId); | |
669 return true; | |
670 } else { | |
671 return false; | |
672 } | |
673 } | |
674 | |
675 | |
676 RawObject* Simulator::Call(const Code& code, const Array& arguments_descriptor, | |
677 const Array& arguments, Thread* thread) { | |
678 static const void* dispatch[] = { | |
679 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, | |
680 BYTECODES_LIST(TARGET) | |
681 #undef TARGET | |
682 }; | |
683 | |
684 const uword vm_tag = thread->vm_tag(); | |
685 thread->set_vm_tag(VMTag::kDartTagId); | |
686 | |
687 StackResource* top_resource = thread->top_resource(); | |
688 thread->set_top_resource(NULL); | |
689 | |
690 if (top_ == NULL) { | |
691 top_ = base_ = stack_; | |
692 } | |
693 | |
694 top_[0] = thread->top_exit_frame_info(); | |
695 | |
696 // Unpack arguments. | |
697 { | |
698 const intptr_t argc = arguments.Length(); | |
699 RawObject** call_base = reinterpret_cast<RawObject**>(top_ + 1); | |
700 RawObject** call_top = call_base + argc; | |
701 for (intptr_t i = 0; i < argc; i++) { | |
702 call_base[i] = arguments.At(i); | |
703 } | |
704 | |
705 call_top[0] = code.function(); | |
706 call_top[1] = code.raw(); | |
707 call_top[2] = | |
708 reinterpret_cast<RawObject*>((argc << 2) | 2); // Return address. | |
709 call_top[3] = reinterpret_cast<RawObject*>(top_); // Caller FP | |
710 } | |
711 | |
712 RawObject** B = | |
713 reinterpret_cast<RawObject**>(top_ + | |
714 arguments.Length() + | |
715 kDartFrameFixedSize + | |
716 1); | |
717 RawObject** SP = B - 1; | |
718 uint32_t* pc = reinterpret_cast<uint32_t*>(code.raw()->ptr()->entry_point_); | |
719 RawObjectPool* pp = code.object_pool(); | |
720 | |
721 pp = pp->ptr(); | |
722 RawBool* true_value = Bool::True().raw(); | |
723 RawBool* false_value = Bool::False().raw(); | |
724 RawObject* null_value = Object::null(); | |
725 RawObject* empty_context = thread->isolate()->object_store()->empty_context(); | |
726 | |
727 Array& argdesc = Array::Handle(); | |
728 #if defined(DEBUG) | |
729 Function& function_h = Function::Handle(); | |
730 #endif | |
731 argdesc = arguments_descriptor.raw(); | |
732 | |
733 #define DECLARE_A_B_C \ | |
734 uint16_t rB, rC; \ | |
735 USE(rB); \ | |
736 USE(rC) | |
737 #define DECODE_A_B_C(type, shiftB, shiftC, mask) \ | |
738 rB = ((__op >> shiftB) & mask) /* | rBx */; \ | |
739 rC = ((__op >> shiftC) & mask) /* | rCx */; | |
740 | |
741 #define DECLARE_0 | |
742 #define DECODE_0(type, shiftB, shiftC, mask) | |
743 | |
744 #define DECLARE_A | |
745 #define DECODE_A(type, shiftB, shiftC, mask) | |
746 | |
747 #define DECLARE_A_D \ | |
748 uint32_t rD; \ | |
749 USE(rD) | |
750 #define DECODE_A_D(type, shiftB, shiftC, mask) rD = (__op >> shiftB); | |
751 | |
752 #define DECLARE___D \ | |
753 uint32_t rD; \ | |
754 USE(rD) | |
755 #define DECODE___D(type, shiftB, shiftC, mask) rD = (__op >> shiftB); | |
756 | |
757 #define DECLARE_A_X \ | |
758 int32_t rD; \ | |
759 USE(rD) | |
760 #define DECODE_A_X(type, shiftB, shiftC, mask) \ | |
761 rD = (static_cast<int32_t>(__op) >> shiftB); | |
762 | |
763 #define BYTECODE_HEADER(Name, Declare, Decode) \ | |
764 Declare; \ | |
765 bc##Name : Decode(uint8_t, 16, 24, 0xFF); \ | |
766 goto bc##Name##Entry; \ | |
767 bc##Name##Entry: | |
768 | |
769 #define BYTECODE(Name, type) \ | |
770 BYTECODE_HEADER(Name, DECLARE_##type, DECODE_##type) | |
771 | |
772 #define DISPATCH_OP(val) \ | |
773 do { \ | |
774 __op = (val); \ | |
775 rA = ((__op >> 8) & 0xFF); \ | |
776 goto* dispatch[__op & 0xFF]; \ | |
777 } while (0) | |
778 | |
779 #define DISPATCH() DISPATCH_OP(*pc++) | |
780 | |
781 #define SMI_FASTPATH_TOS(ResultT, F) \ | |
782 { \ | |
783 const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]); \ | |
784 const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]); \ | |
785 ResultT* slot = reinterpret_cast<ResultT*>(SP - 1); \ | |
786 if (LIKELY(AreBothSmis(lhs, rhs) && !F(lhs, rhs, slot))) { \ | |
787 pc += 1; \ | |
788 --SP; \ | |
789 } \ | |
790 DISPATCH(); \ | |
791 } | |
792 | |
793 #define FALLTHROUGH | |
794 | |
795 #define HANDLE_EXCEPTION(name, ON_EXCEPTION) \ | |
796 do { \ | |
797 B = reinterpret_cast<RawObject**>(base_); \ | |
798 pc = reinterpret_cast<uint32_t*>(pc_); \ | |
799 if ((reinterpret_cast<uword>(pc) & 2) != 0) { \ | |
800 base_ = top_ = reinterpret_cast<uintptr_t*>(base_[0]); \ | |
801 thread->set_top_exit_frame_info(reinterpret_cast<uword>(top_)); \ | |
802 thread->set_top_resource(top_resource); \ | |
803 thread->set_vm_tag(vm_tag); \ | |
804 return special_[0]; \ | |
805 } \ | |
806 pp = FrameCode(B)->ptr()->object_pool_->ptr(); \ | |
807 ON_EXCEPTION; \ | |
808 } while (0) | |
809 | |
810 #define INVOKE_RUNTIME(func, args, onexception) \ | |
811 if (!InvokeRuntime(thread, this, func, args)) { \ | |
812 HANDLE_EXCEPTION(InvokeRuntime, onexception); \ | |
813 } | |
814 | |
815 #define INVOKE_NATIVE(func, args, onexception) \ | |
816 if (!InvokeNative(thread, this, func, &args)) { \ | |
817 HANDLE_EXCEPTION(InvokeRuntime, onexception); \ | |
818 } | |
819 | |
820 #define INVOKE_NATIVE_WRAPPER(func, args, onexception) \ | |
821 if (!InvokeNativeWrapper(thread, this, func, &args)) { \ | |
822 HANDLE_EXCEPTION(InvokeRuntime, onexception); \ | |
823 } | |
824 | |
825 uint16_t rA; | |
826 uint32_t __op; | |
827 DISPATCH(); | |
828 while (true) { | |
829 { | |
830 { | |
831 ClosureNoSuchMethod: | |
832 #if defined(DEBUG) | |
833 function_h ^= FrameFunction(B); | |
834 ASSERT(function_h.IsClosureFunction()); | |
835 #endif | |
836 pc = SavedCallerPC(B); | |
837 | |
838 const bool has_dart_callee = (reinterpret_cast<uword>(pc) & 2) == 0; | |
839 const intptr_t argc = has_dart_callee | |
840 ? Bytecode::DecodeArgc(pc[-1]) | |
841 : (reinterpret_cast<uword>(pc) >> 2); | |
842 | |
843 SP = FrameArguments(B, 0); | |
844 RawObject** args = SP - argc; | |
845 B = SavedCallerFP(B); | |
846 if (has_dart_callee) { | |
847 pp = FrameCode(B)->ptr()->object_pool_->ptr(); | |
848 } | |
849 | |
850 *++SP = null_value; | |
851 *++SP = args[0]; | |
852 *++SP = argdesc.raw(); | |
853 *++SP = null_value; // will contain array | |
854 { | |
855 SP[1] = Smi::New(argc); // length | |
856 SP[2] = null_value; // type | |
857 Exit(thread, B, SP + 3, pc); | |
858 NativeArguments native_args(thread, 2, SP + 1, SP); | |
859 INVOKE_RUNTIME(DRT_AllocateArray, native_args, | |
860 goto ClosureNoSuchMethodDispatch); | |
861 | |
862 RawArray* array = static_cast<RawArray*>(SP[0]); | |
863 ASSERT(array->GetClassId() == kArrayCid); | |
864 for (intptr_t i = 0; i < argc; i++) { | |
865 array->ptr()->data()[i] = args[i]; | |
866 } | |
867 } | |
868 { | |
869 Exit(thread, B, SP + 1, pc); | |
870 NativeArguments native_args(thread, 3, SP - 2, SP - 3); | |
871 INVOKE_RUNTIME(DRT_InvokeClosureNoSuchMethod, native_args, | |
872 goto ClosureNoSuchMethodDispatch); | |
873 UNREACHABLE(); | |
874 } | |
875 ClosureNoSuchMethodDispatch: | |
876 DISPATCH(); | |
877 } | |
878 | |
879 { | |
880 BYTECODE(Entry, A_B_C); | |
881 const uint16_t num_locals = rB; | |
882 const uint16_t context_reg = rC; | |
883 const intptr_t pos_count = Smi::Value( | |
884 *reinterpret_cast<RawSmi**>( | |
885 reinterpret_cast<uword>(argdesc.raw()->ptr()) + | |
886 Array::element_offset( | |
887 ArgumentsDescriptor::kPositionalCountIndex))); | |
888 | |
889 if (pos_count != rA) { | |
890 goto ClosureNoSuchMethod; | |
891 } | |
892 | |
893 { | |
894 RawObject** L = B; | |
895 for (intptr_t i = 0; i < num_locals; i++) { | |
896 L[i] = null_value; | |
897 } | |
898 L[context_reg] = empty_context; | |
899 SP = B + num_locals - 1; | |
900 } | |
901 | |
902 DISPATCH(); | |
903 } | |
904 | |
905 { | |
906 BYTECODE(DebugStep, A); | |
907 if (thread->isolate()->single_step()) { | |
908 Exit(thread, B, SP + 1, pc); | |
909 NativeArguments args(thread, 0, NULL, NULL); | |
910 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH); | |
911 } | |
912 DISPATCH(); | |
913 } | |
914 | |
915 { | |
916 BYTECODE(DebugBreak, A); | |
917 { | |
918 const uint32_t original_bc = | |
919 static_cast<uint32_t>(reinterpret_cast<uintptr_t>( | |
920 thread->isolate()->debugger()->GetPatchedStubAddress( | |
921 reinterpret_cast<uword>(pc)))); | |
922 | |
923 SP[1] = null_value; | |
924 Exit(thread, B, SP + 2, pc); | |
925 NativeArguments args(thread, 0, NULL, SP + 1); | |
926 INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args, FALLTHROUGH) else { | |
927 DISPATCH_OP(original_bc); | |
928 } | |
929 } | |
930 DISPATCH(); | |
931 } | |
932 | |
933 { | |
934 BYTECODE(CheckStack, A); | |
935 { | |
936 if (reinterpret_cast<uword>(SP) >= thread->isolate()->stack_limit()) { | |
937 Exit(thread, B, SP + 1, pc); | |
938 NativeArguments args(thread, 0, NULL, NULL); | |
939 INVOKE_RUNTIME(DRT_StackOverflow, args, FALLTHROUGH); | |
940 } | |
941 } | |
942 DISPATCH(); | |
943 } | |
944 | |
945 { | |
946 BYTECODE(EntryOpt, A_B_C); | |
947 const uint16_t num_fixed_params = rA; | |
948 const uint16_t num_opt_pos_params = rB; | |
949 const uint16_t num_opt_named_params = rC; | |
950 | |
951 const intptr_t min_num_pos_args = num_fixed_params; | |
952 const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params; | |
953 const intptr_t arg_count = Smi::Value(*reinterpret_cast<RawSmi**>( | |
954 reinterpret_cast<uword>(argdesc.raw()->ptr()) + | |
955 Array::element_offset(ArgumentsDescriptor::kCountIndex))); | |
956 const intptr_t pos_count = Smi::Value(*reinterpret_cast<RawSmi**>( | |
957 reinterpret_cast<uword>(argdesc.raw()->ptr()) + | |
958 Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex))); | |
959 const intptr_t named_count = (arg_count - pos_count); | |
960 if (!(min_num_pos_args <= pos_count && pos_count <= max_num_pos_args)) { | |
961 goto ClosureNoSuchMethod; | |
962 } | |
963 | |
964 // Copy all passed position arguments.Entry | |
965 RawObject** first_arg = FrameArguments(B, arg_count); | |
966 memmove(B, first_arg, pos_count * kWordSize); | |
967 if (num_opt_named_params != 0) { | |
968 // RawObject** opt_copy = first_arg + pos_count; | |
969 | |
970 intptr_t i = named_count - 1; | |
971 intptr_t j = num_opt_named_params - 1; | |
972 while (j >= 0 && i >= 0) { | |
973 const uint32_t load_name = pc[2 * j]; | |
974 const uint32_t load_value = pc[2 * j + 1]; | |
975 ASSERT((load_name & 0xFF) == Bytecode::kLoadConstant); | |
976 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant); | |
977 ASSERT((load_value & 0xFF00) == (load_name & 0xFF00)); | |
978 const uint8_t reg = (load_name >> 8) & 0xFF; | |
979 RawString* name = reinterpret_cast<RawString*>( | |
980 pp->data()[load_name >> 16].raw_obj_); | |
981 if (name == argdesc.At(ArgumentsDescriptor::name_index(i))) { | |
982 const intptr_t copy_idx = Smi::Value(static_cast<RawSmi*>( | |
983 argdesc.At(ArgumentsDescriptor::position_index(i)))); | |
984 B[reg] = first_arg[copy_idx]; | |
985 i--; | |
986 } else { | |
987 RawObject* value = pp->data()[load_value >> 16].raw_obj_; | |
988 B[reg] = value; | |
989 } | |
990 j--; | |
991 } | |
992 | |
993 while (j >= 0) { | |
994 const uint32_t load_name = pc[2 * j]; | |
995 const uint32_t load_value = pc[2 * j + 1]; | |
996 ASSERT((load_name & 0xFF) == Bytecode::kLoadConstant); | |
997 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant); | |
998 ASSERT((load_value & 0xFF00) == (load_name & 0xFF00)); | |
999 const uint8_t reg = (load_name >> 8) & 0xFF; | |
1000 RawObject* value = pp->data()[load_value >> 16].raw_obj_; | |
1001 B[reg] = value; | |
1002 j--; | |
1003 } | |
1004 | |
1005 if (i != -1) { | |
1006 goto ClosureNoSuchMethod; | |
1007 } | |
1008 | |
1009 pc += num_opt_named_params * 2; | |
1010 SP = B + num_fixed_params + num_opt_named_params - 1; | |
1011 } else { | |
1012 ASSERT(num_opt_pos_params != 0); | |
1013 if (named_count != 0) { | |
1014 goto ClosureNoSuchMethod; | |
1015 } | |
1016 | |
1017 RawObject** opt_base = B + rA; | |
1018 for (intptr_t i = pos_count - rA; i < num_opt_pos_params; i++) { | |
1019 const uint32_t load_value = pc[i]; | |
1020 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant); | |
1021 const uint8_t reg = (load_value >> 8) & 0xFF; | |
1022 RawObject* value = pp->data()[load_value >> 16].raw_obj_; | |
1023 ASSERT((i + rA) == reg); | |
1024 opt_base[i] = value; | |
1025 } | |
1026 | |
1027 pc += num_opt_pos_params; | |
1028 SP = B + max_num_pos_args - 1; | |
1029 } | |
1030 | |
1031 DISPATCH(); | |
1032 } | |
1033 | |
1034 { | |
1035 BYTECODE(InstantiateType, A_D); | |
1036 RawObject* type = pp->data()[rD].raw_obj_; | |
1037 SP[1] = type; | |
1038 SP[2] = SP[0]; | |
1039 SP[0] = null_value; | |
1040 Exit(thread, B, SP + 3, pc); | |
1041 { | |
1042 NativeArguments args(thread, 2, SP + 1, SP); | |
1043 INVOKE_RUNTIME(DRT_InstantiateType, args, FALLTHROUGH); | |
1044 } | |
1045 DISPATCH(); | |
1046 } | |
1047 | |
1048 { | |
1049 BYTECODE(InstantiateTypeArgumentsTOS, A_D); | |
1050 RawTypeArguments* type_arguments = | |
1051 static_cast<RawTypeArguments*>(pp->data()[rD].raw_obj_); | |
1052 | |
1053 RawObject* instantiator = SP[0]; | |
1054 // If the instantiator is null and if the type argument vector | |
1055 // instantiated from null becomes a vector of dynamic, then use null as | |
1056 // the type arguments. | |
1057 if (rA == 0 || null_value != instantiator) { | |
1058 RawArray* instantiations = type_arguments->ptr()->instantiations_; | |
1059 for (intptr_t i = 0; | |
1060 instantiations->ptr()->data()[i] != NULL; // kNoInstantiator | |
1061 i += 2) { | |
1062 if (instantiations->ptr()->data()[i] == instantiator) { | |
1063 SP[0] = instantiations->ptr()->data()[i + 1]; | |
1064 goto InstantiateTypeArgumentsTOSDone; | |
1065 } | |
1066 } | |
1067 | |
1068 SP[1] = type_arguments; | |
1069 SP[2] = instantiator; | |
1070 | |
1071 Exit(thread, B, SP + 3, pc); | |
1072 NativeArguments args(thread, 2, SP + 1, SP); | |
1073 INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args, FALLTHROUGH); | |
1074 } | |
1075 | |
1076 InstantiateTypeArgumentsTOSDone: | |
1077 DISPATCH(); | |
1078 } | |
1079 | |
1080 { | |
1081 BYTECODE(Throw, A); | |
1082 { | |
1083 SP[1] = 0; | |
1084 Exit(thread, B, SP + 2, pc); | |
1085 if (rA == 0) { | |
1086 NativeArguments args(thread, 1, SP, SP + 1); | |
1087 INVOKE_RUNTIME(DRT_Throw, args, FALLTHROUGH); | |
1088 } else { | |
1089 NativeArguments args(thread, 2, SP - 1, SP + 1); | |
1090 INVOKE_RUNTIME(DRT_ReThrow, args, FALLTHROUGH); | |
1091 } | |
1092 } | |
1093 DISPATCH(); | |
1094 } | |
1095 | |
1096 { | |
1097 BYTECODE(Frame, A_D); | |
1098 const uint16_t num_locals = rD; | |
1099 for (intptr_t i = 1; i <= num_locals; i++) { | |
1100 SP[i] = null_value; | |
1101 } | |
1102 SP += num_locals; | |
1103 | |
1104 DISPATCH(); | |
1105 } | |
1106 | |
1107 { | |
1108 BYTECODE(SetFrame, A); | |
1109 SP = B + rA - 1; | |
1110 DISPATCH(); | |
1111 } | |
1112 | |
1113 { | |
1114 BYTECODE(Drop1, 0); | |
1115 SP--; | |
1116 DISPATCH(); | |
1117 } | |
1118 | |
1119 { | |
1120 BYTECODE(Drop, 0); | |
1121 SP -= rA; | |
1122 DISPATCH(); | |
1123 } | |
1124 | |
1125 { | |
1126 BYTECODE(DropR, 0); | |
1127 RawObject* result = SP[0]; | |
1128 SP -= rA; | |
1129 SP[0] = result; | |
1130 DISPATCH(); | |
1131 } | |
1132 | |
1133 { | |
1134 BYTECODE(LoadConstant, A_D); | |
1135 B[rA] = pp->data()[rD].raw_obj_; | |
1136 DISPATCH(); | |
1137 } | |
1138 | |
1139 { | |
1140 BYTECODE(PushConstant, __D); | |
1141 *++SP = pp->data()[rD].raw_obj_; | |
1142 DISPATCH(); | |
1143 } | |
1144 | |
1145 { | |
1146 BYTECODE(Push, A_X); | |
1147 *++SP = B[rD]; | |
1148 DISPATCH(); | |
1149 } | |
1150 | |
1151 { | |
1152 BYTECODE(Move, A_X); | |
1153 B[rA] = B[rD]; | |
1154 DISPATCH(); | |
1155 } | |
1156 | |
1157 { | |
1158 BYTECODE(StoreLocal, A_X); | |
1159 B[rD] = *SP; | |
1160 DISPATCH(); | |
1161 } | |
1162 | |
1163 { | |
1164 BYTECODE(PopLocal, A_X); | |
1165 B[rD] = *SP--; | |
1166 DISPATCH(); | |
1167 } | |
1168 | |
1169 { | |
1170 BYTECODE(MoveSpecial, A_D); | |
1171 B[rA] = special_[rD]; | |
1172 DISPATCH(); | |
1173 } | |
1174 | |
1175 { | |
1176 BYTECODE(BooleanNegateTOS, 0); | |
1177 SP[0] = (SP[0] == true_value) ? false_value : true_value; | |
1178 DISPATCH(); | |
1179 } | |
1180 | |
1181 { | |
1182 BYTECODE(StaticCall, A_D); | |
1183 if (thread->isolate()->single_step()) { | |
1184 Exit(thread, B, SP + 1, pc); | |
1185 NativeArguments args(thread, 0, NULL, NULL); | |
1186 INVOKE_RUNTIME(DRT_SingleStepHandler, args, goto StaticCallDispatch); | |
1187 } | |
1188 | |
1189 { | |
1190 const uint16_t argc = rA; | |
1191 RawObject** call_base = SP - argc; | |
1192 RawObject** call_top = SP; // *SP contains function | |
1193 argdesc ^= pp->data()[rD].raw_obj_; | |
1194 Invoke(thread, call_base, call_top, &pp, &pc, &B, &SP); | |
1195 } | |
1196 | |
1197 StaticCallDispatch: | |
1198 DISPATCH(); | |
1199 } | |
1200 | |
1201 { | |
1202 BYTECODE(InstanceCall, A_D); | |
1203 if (thread->isolate()->single_step()) { | |
1204 Exit(thread, B, SP + 1, pc); | |
1205 NativeArguments args(thread, 0, NULL, NULL); | |
1206 INVOKE_RUNTIME(DRT_SingleStepHandler, args, | |
1207 goto InstanceCallDispatch); | |
1208 } | |
1209 | |
1210 { | |
1211 const uint16_t argc = rA; | |
1212 const uint16_t kidx = rD; | |
1213 | |
1214 RawObject** call_base = SP - argc + 1; | |
1215 RawObject** call_top = SP + 1; | |
1216 InstanceCall1(thread, | |
1217 static_cast<RawICData*>(pp->data()[kidx].raw_obj_), | |
1218 call_base, call_top, &argdesc, &pp, &pc, &B, &SP); | |
1219 } | |
1220 | |
1221 InstanceCallDispatch: | |
1222 DISPATCH(); | |
1223 } | |
1224 | |
1225 { | |
1226 BYTECODE(InstanceCall2, A_D); | |
1227 if (thread->isolate()->single_step()) { | |
1228 Exit(thread, B, SP + 1, pc); | |
1229 NativeArguments args(thread, 0, NULL, NULL); | |
1230 INVOKE_RUNTIME(DRT_SingleStepHandler, args, | |
1231 goto InstanceCall2Dispatch); | |
1232 } | |
1233 | |
1234 { | |
1235 const uint16_t argc = rA; | |
1236 const uint16_t kidx = rD; | |
1237 | |
1238 RawObject** call_base = SP - argc + 1; | |
1239 RawObject** call_top = SP + 1; | |
1240 InstanceCall2(thread, | |
1241 static_cast<RawICData*>(pp->data()[kidx].raw_obj_), | |
1242 call_base, call_top, &argdesc, &pp, &pc, &B, &SP); | |
1243 } | |
1244 | |
1245 InstanceCall2Dispatch: | |
1246 DISPATCH(); | |
1247 } | |
1248 | |
1249 { | |
1250 BYTECODE(InstanceCall3, A_D); | |
1251 if (thread->isolate()->single_step()) { | |
1252 Exit(thread, B, SP + 1, pc); | |
1253 NativeArguments args(thread, 0, NULL, NULL); | |
1254 INVOKE_RUNTIME(DRT_SingleStepHandler, args, | |
1255 goto InstanceCall3Dispatch); | |
1256 } | |
1257 | |
1258 { | |
1259 const uint16_t argc = rA; | |
1260 const uint16_t kidx = rD; | |
1261 | |
1262 RawObject** call_base = SP - argc + 1; | |
1263 RawObject** call_top = SP + 1; | |
1264 InstanceCall3(thread, | |
1265 static_cast<RawICData*>(pp->data()[kidx].raw_obj_), | |
1266 call_base, call_top, &argdesc, &pp, &pc, &B, &SP); | |
1267 } | |
1268 | |
1269 InstanceCall3Dispatch: | |
1270 DISPATCH(); | |
1271 } | |
1272 | |
1273 { | |
1274 BYTECODE(NativeBootstrapCall, 0); | |
1275 RawFunction* function = FrameFunction(B); | |
1276 RawObject** incoming_args = | |
1277 function->ptr()->num_optional_parameters_ == 0 | |
1278 ? FrameArguments(B, function->ptr()->num_fixed_parameters_) | |
1279 : B; | |
1280 | |
1281 SimulatorBootstrapNativeCall native_target = | |
1282 reinterpret_cast<SimulatorBootstrapNativeCall>(SP[-1]); | |
1283 intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]); | |
1284 SP[-0] = 0; // Note: argc_tag is not smi-tagged. | |
1285 SP[-1] = null_value; | |
1286 Exit(thread, B, SP + 1, pc); | |
1287 NativeArguments args(thread, argc_tag, incoming_args, SP - 1); | |
1288 INVOKE_NATIVE(native_target, args, FALLTHROUGH) else { SP -= 1; } | |
Florian Schneider
2016/04/12 18:01:42
Formatting: newline after {
Vyacheslav Egorov (Google)
2016/04/14 13:05:27
Done.
| |
1289 DISPATCH(); | |
1290 } | |
1291 | |
1292 { | |
1293 BYTECODE(NativeCall, 0); | |
1294 RawFunction* function = FrameFunction(B); | |
1295 RawObject** incoming_args = | |
1296 function->ptr()->num_optional_parameters_ == 0 | |
1297 ? FrameArguments(B, function->ptr()->num_fixed_parameters_) | |
1298 : B; | |
1299 | |
1300 Dart_NativeFunction native_target = | |
1301 reinterpret_cast<Dart_NativeFunction>(SP[-1]); | |
1302 intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]); | |
1303 SP[-0] = 0; // argc_tag is not smi tagged! | |
1304 SP[-1] = null_value; | |
1305 Exit(thread, B, SP + 1, pc); | |
1306 NativeArguments args(thread, argc_tag, incoming_args, SP - 1); | |
1307 INVOKE_NATIVE_WRAPPER(native_target, args, FALLTHROUGH) else { | |
1308 SP -= 1; | |
1309 } | |
1310 DISPATCH(); | |
1311 } | |
1312 | |
1313 { | |
1314 BYTECODE(AddTOS, A_B_C); | |
1315 SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow); | |
1316 } | |
1317 { | |
1318 BYTECODE(SubTOS, A_B_C); | |
1319 SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow); | |
1320 } | |
1321 { | |
1322 BYTECODE(MulTOS, A_B_C); | |
1323 SMI_FASTPATH_TOS(intptr_t, SMI_MUL); | |
1324 } | |
1325 { | |
1326 BYTECODE(BitOrTOS, A_B_C); | |
1327 SMI_FASTPATH_TOS(intptr_t, SMI_BITOR); | |
1328 } | |
1329 { | |
1330 BYTECODE(BitAndTOS, A_B_C); | |
1331 SMI_FASTPATH_TOS(intptr_t, SMI_BITAND); | |
1332 } | |
1333 { | |
1334 BYTECODE(EqualTOS, A_B_C); | |
1335 SMI_FASTPATH_TOS(RawObject*, SMI_EQ); | |
1336 } | |
1337 { | |
1338 BYTECODE(LessThanTOS, A_B_C); | |
1339 SMI_FASTPATH_TOS(RawObject*, SMI_LT); | |
1340 } | |
1341 { | |
1342 BYTECODE(GreaterThanTOS, A_B_C); | |
1343 SMI_FASTPATH_TOS(RawObject*, SMI_GT); | |
1344 } | |
1345 | |
1346 { | |
1347 BYTECODE(Compile, 0); | |
1348 B[0] = FrameFunction(B); | |
1349 B[1] = 0; | |
1350 Exit(thread, B, B + 2, pc); | |
1351 NativeArguments args(thread, 1, B, B + 1); | |
1352 INVOKE_RUNTIME(DRT_CompileFunction, args, FALLTHROUGH) else { | |
1353 // Function should be compiled now. | |
1354 RawCode* code = FrameFunction(B)->ptr()->code_; | |
1355 SetFrameCode(B, code); | |
1356 pp = code->ptr()->object_pool_->ptr(); | |
1357 pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_); | |
1358 } | |
1359 DISPATCH(); | |
1360 } | |
1361 | |
1362 { | |
1363 RawObject* result; | |
1364 | |
1365 BYTECODE(Intrinsic, A); | |
1366 result = null_value; | |
1367 if (!intrinsics_[rA](thread, B, &result)) { | |
1368 DISPATCH(); | |
1369 } | |
1370 goto ReturnImpl; | |
1371 | |
1372 BYTECODE(Return, A); | |
1373 result = B[rA]; | |
1374 goto ReturnImpl; | |
1375 | |
1376 BYTECODE(ReturnTOS, 0); | |
1377 result = *SP; | |
1378 | |
1379 ReturnImpl: | |
1380 pc = SavedCallerPC(B); | |
1381 if ((reinterpret_cast<uword>(pc) & 2) != 0) { | |
1382 const intptr_t argc = reinterpret_cast<uword>(pc) >> 2; | |
1383 base_ = top_ = reinterpret_cast<uintptr_t*>( | |
1384 FrameArguments(B, argc + 1)[0]); | |
1385 thread->set_top_exit_frame_info(reinterpret_cast<uword>(top_)); | |
1386 thread->set_top_resource(top_resource); | |
1387 thread->set_vm_tag(vm_tag); | |
1388 return result; | |
1389 } | |
1390 const uint8_t argc = Bytecode::DecodeArgc(pc[-1]); | |
1391 SP = FrameArguments(B, argc); | |
1392 B = SavedCallerFP(B); | |
1393 *SP = result; | |
1394 RawCode* code = FrameCode(B); | |
1395 pp = code->ptr()->object_pool_->ptr(); | |
1396 DISPATCH(); | |
1397 } | |
1398 | |
1399 { | |
1400 BYTECODE(StoreStaticTOS, A_D); | |
1401 RawField* field = reinterpret_cast<RawField*>(pp->data()[rD].raw_obj_); | |
1402 RawInstance* value = static_cast<RawInstance*>(*SP--); | |
1403 field->StorePointer(&field->ptr()->value_.static_value_, value); | |
1404 DISPATCH(); | |
1405 } | |
1406 | |
1407 { | |
1408 BYTECODE(PushStatic, A_D); | |
1409 RawField* field = reinterpret_cast<RawField*>(pp->data()[rD].raw_obj_); | |
1410 *SP = field->ptr()->value_.static_value_; // Note: field on the stack. | |
1411 DISPATCH(); | |
1412 } | |
1413 | |
1414 { | |
1415 BYTECODE(StoreField, A_B_C); | |
1416 const uint16_t offset_in_words = rB; | |
1417 const uint16_t value_reg = rC; | |
1418 | |
1419 RawInstance* instance = reinterpret_cast<RawInstance*>(B[rA]); | |
1420 RawObject* value = reinterpret_cast<RawObject*>(B[value_reg]); | |
1421 | |
1422 instance->StorePointer( | |
1423 reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, | |
1424 value); | |
1425 DISPATCH(); | |
1426 } | |
1427 | |
1428 { | |
1429 BYTECODE(StoreFieldTOS, A_D); | |
1430 const uint16_t offset_in_words = rD; | |
1431 RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]); | |
1432 RawObject* value = reinterpret_cast<RawObject*>(SP[0]); | |
1433 SP -= 2; | |
1434 instance->StorePointer( | |
1435 reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, | |
1436 value); | |
1437 | |
1438 DISPATCH(); | |
1439 } | |
1440 | |
1441 { | |
1442 BYTECODE(LoadField, A_B_C); | |
1443 const uint16_t instance_reg = rB; | |
1444 const uint16_t offset_in_words = rC; | |
1445 RawInstance* instance = reinterpret_cast<RawInstance*>(B[instance_reg]); | |
1446 B[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words]; | |
1447 DISPATCH(); | |
1448 } | |
1449 | |
1450 { | |
1451 BYTECODE(LoadFieldTOS, A_D); | |
1452 const uint16_t offset_in_words = rD; | |
1453 RawInstance* instance = static_cast<RawInstance*>(SP[0]); | |
1454 SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words]; | |
1455 DISPATCH(); | |
1456 } | |
1457 | |
1458 { | |
1459 BYTECODE(InitStaticTOS, A); | |
1460 RawField* field = static_cast<RawField*>(*SP--); | |
1461 RawObject* value = field->ptr()->value_.static_value_; | |
1462 if ((value == Object::sentinel().raw()) || | |
1463 (value == Object::transition_sentinel().raw())) { | |
1464 /* SP[1] field */ | |
1465 SP[2] = 0; | |
1466 Exit(thread, B, SP + 3, pc); | |
1467 NativeArguments args(thread, 1, SP + 1, SP + 2); | |
1468 INVOKE_RUNTIME(DRT_InitStaticField, args, FALLTHROUGH); | |
1469 } | |
1470 DISPATCH(); | |
1471 } | |
1472 | |
1473 // TODO(vegorov) allocation bytecodes can benefit from the new-space | |
1474 // allocation fast-path that does not transition into the runtime system. | |
1475 { | |
1476 BYTECODE(AllocateContext, A_D); | |
1477 const uint16_t num_context_variables = rD; | |
1478 { | |
1479 *++SP = 0; | |
1480 SP[1] = Smi::New(num_context_variables); | |
1481 Exit(thread, B, SP + 2, pc); | |
1482 NativeArguments args(thread, 1, SP + 1, SP); | |
1483 INVOKE_RUNTIME(DRT_AllocateContext, args, FALLTHROUGH); | |
1484 } | |
1485 DISPATCH(); | |
1486 } | |
1487 | |
1488 { | |
1489 BYTECODE(CloneContext, A); | |
1490 { | |
1491 SP[1] = SP[0]; | |
1492 Exit(thread, B, SP + 2, pc); | |
1493 NativeArguments args(thread, 1, SP + 1, SP); | |
1494 INVOKE_RUNTIME(DRT_CloneContext, args, FALLTHROUGH); | |
1495 } | |
1496 DISPATCH(); | |
1497 } | |
1498 | |
1499 { | |
1500 BYTECODE(Allocate, A_D); | |
1501 SP[1] = 0; // result | |
1502 SP[2] = pp->data()[rD].raw_obj_; | |
1503 SP[3] = null_value; | |
1504 Exit(thread, B, SP + 4, pc); | |
1505 NativeArguments args(thread, 2, SP + 2, SP + 1); | |
1506 INVOKE_RUNTIME(DRT_AllocateObject, args, FALLTHROUGH); | |
1507 SP++; | |
1508 DISPATCH(); | |
1509 } | |
1510 | |
1511 { | |
1512 BYTECODE(AllocateT, 0); | |
1513 SP[1] = SP[-0]; // class | |
1514 SP[2] = SP[-1]; // type arguments | |
1515 Exit(thread, B, SP + 3, pc); | |
1516 NativeArguments args(thread, 2, SP + 1, SP - 1); | |
1517 INVOKE_RUNTIME(DRT_AllocateObject, args, FALLTHROUGH); | |
1518 SP -= 1; | |
1519 DISPATCH(); | |
1520 } | |
1521 | |
1522 { | |
1523 BYTECODE(CreateArrayTOS, 0); | |
1524 SP[1] = SP[-0]; // length | |
1525 SP[2] = SP[-1]; // type | |
1526 Exit(thread, B, SP + 3, pc); | |
1527 NativeArguments args(thread, 2, SP + 1, SP - 1); | |
1528 INVOKE_RUNTIME(DRT_AllocateArray, args, FALLTHROUGH); | |
1529 SP -= 1; | |
1530 DISPATCH(); | |
1531 } | |
1532 | |
1533 { | |
1534 BYTECODE(AssertAssignable, A_D); // instance, type args, type, name | |
1535 RawObject** args = SP - 3; | |
1536 if (args[0] != null_value) { | |
1537 RawSubtypeTestCache* cache = | |
1538 static_cast<RawSubtypeTestCache*>(pp->data()[rD].raw_obj_); | |
1539 if (cache != null_value) { | |
1540 RawInstance* instance = static_cast<RawInstance*>(args[0]); | |
1541 RawTypeArguments* instantiator_type_arguments = | |
1542 static_cast<RawTypeArguments*>(args[1]); | |
1543 | |
1544 const intptr_t cid = SimulatorHelpers::GetClassId(instance); | |
1545 | |
1546 RawTypeArguments* instance_type_arguments = | |
1547 static_cast<RawTypeArguments*>(null_value); | |
1548 RawObject* instance_cid_or_function; | |
1549 if (cid == kClosureCid) { | |
1550 RawClosure* closure = static_cast<RawClosure*>(instance); | |
1551 instance_type_arguments = closure->ptr()->type_arguments_; | |
1552 instance_cid_or_function = closure->ptr()->function_; | |
1553 } else { | |
1554 instance_cid_or_function = Smi::New(cid); | |
1555 | |
1556 RawClass* instance_class = | |
1557 thread->isolate()->class_table()->At(cid); | |
1558 if (instance_class->ptr()->num_type_arguments_ < 0) { | |
1559 goto AssertAssignableCallRuntime; | |
1560 } else if (instance_class->ptr()->num_type_arguments_ > 0) { | |
1561 instance_type_arguments = reinterpret_cast<RawTypeArguments**>( | |
1562 instance | |
1563 ->ptr())[instance_class->ptr() | |
1564 ->type_arguments_field_offset_in_words_]; | |
1565 } | |
1566 } | |
1567 | |
1568 for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); | |
1569 entries[0] != null_value; | |
1570 entries += SubtypeTestCache::kTestEntryLength) { | |
1571 if (entries[SubtypeTestCache::kInstanceClassIdOrFunction] == | |
1572 instance_cid_or_function && | |
1573 entries[SubtypeTestCache::kInstanceTypeArguments] == | |
1574 instance_type_arguments && | |
1575 entries[SubtypeTestCache::kInstantiatorTypeArguments] == | |
1576 instantiator_type_arguments) { | |
1577 if (true_value == entries[SubtypeTestCache::kTestResult]) { | |
1578 goto AssertAssignableOk; | |
1579 } else { | |
1580 break; | |
1581 } | |
1582 } | |
1583 } | |
1584 } | |
1585 | |
1586 AssertAssignableCallRuntime: | |
1587 SP[1] = args[0]; // instance | |
1588 SP[2] = args[2]; // type | |
1589 SP[3] = args[1]; // type args | |
1590 SP[4] = args[3]; // name | |
1591 SP[5] = cache; | |
1592 Exit(thread, B, SP + 6, pc); | |
1593 NativeArguments args(thread, 5, SP + 1, SP - 3); | |
1594 INVOKE_RUNTIME(DRT_TypeCheck, args, FALLTHROUGH); | |
1595 } | |
1596 | |
1597 AssertAssignableOk: | |
1598 SP -= 3; | |
1599 DISPATCH(); | |
1600 } | |
1601 | |
1602 { | |
1603 BYTECODE(AssertBoolean, A); | |
1604 RawObject* value = SP[0]; | |
1605 if (rA) { | |
1606 if (value == true_value || value == false_value) { | |
1607 goto AssertBooleanOk; | |
1608 } | |
1609 } else if (value != null_value) { | |
1610 goto AssertBooleanOk; | |
1611 } | |
1612 | |
1613 { | |
1614 SP[1] = SP[0]; // instance | |
1615 Exit(thread, B, SP + 2, pc); | |
1616 NativeArguments args(thread, 1, SP + 1, SP); | |
1617 INVOKE_RUNTIME(DRT_NonBoolTypeError, args, FALLTHROUGH); | |
1618 } | |
1619 | |
1620 AssertBooleanOk: | |
1621 DISPATCH(); | |
1622 } | |
1623 | |
1624 { | |
1625 BYTECODE(IfEqStrictTOS, A_D); | |
1626 SP -= 2; | |
1627 if (SP[1] != SP[2]) { | |
1628 pc++; | |
1629 } | |
1630 DISPATCH(); | |
1631 } | |
1632 | |
1633 { | |
1634 BYTECODE(IfNeStrictTOS, A_D); | |
1635 SP -= 2; | |
1636 if (SP[1] == SP[2]) { | |
1637 pc++; | |
1638 } | |
1639 DISPATCH(); | |
1640 } | |
1641 | |
1642 { | |
1643 BYTECODE(IfEqStrictNumTOS, A_D); | |
1644 if (thread->isolate()->single_step()) { | |
1645 Exit(thread, B, SP + 1, pc); | |
1646 NativeArguments args(thread, 0, NULL, NULL); | |
1647 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH); | |
1648 } | |
1649 | |
1650 SP -= 2; | |
1651 if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { | |
1652 pc++; | |
1653 } | |
1654 DISPATCH(); | |
1655 } | |
1656 | |
1657 { | |
1658 BYTECODE(IfNeStrictNumTOS, A_D); | |
1659 if (thread->isolate()->single_step()) { | |
1660 Exit(thread, B, SP + 1, pc); | |
1661 NativeArguments args(thread, 0, NULL, NULL); | |
1662 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH); | |
1663 } | |
1664 | |
1665 SP -= 2; | |
1666 if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { | |
1667 pc++; | |
1668 } | |
1669 DISPATCH(); | |
1670 } | |
1671 | |
1672 { | |
1673 BYTECODE(Jump, 0); | |
1674 const int32_t tgt = static_cast<int32_t>(__op) >> 8; | |
1675 pc += (tgt - 1); | |
1676 DISPATCH(); | |
1677 } | |
1678 | |
1679 { | |
1680 BYTECODE(StoreIndexedTOS, 0); | |
1681 SP -= 3; | |
1682 RawArray* array = static_cast<RawArray*>(SP[1]); | |
1683 RawSmi* index = static_cast<RawSmi*>(SP[2]); | |
1684 RawObject* value = SP[3]; | |
1685 ASSERT(array->GetClassId() == kArrayCid); | |
1686 ASSERT(!index->IsHeapObject()); | |
1687 array->StorePointer(array->ptr()->data() + Smi::Value(index), value); | |
1688 DISPATCH(); | |
1689 } | |
1690 | |
1691 { | |
1692 BYTECODE(Trap, 0); | |
1693 UNIMPLEMENTED(); | |
1694 DISPATCH(); | |
1695 } | |
1696 } | |
1697 } | |
1698 | |
1699 UNREACHABLE(); | |
1700 return 0; | |
1701 } | |
1702 | |
1703 void Simulator::Longjmp(uword pc, uword sp, uword fp, RawObject* raw_exception, | |
1704 RawObject* raw_stacktrace, Thread* thread) { | |
1705 // Walk over all setjmp buffers (simulated --> C++ transitions) | |
1706 // and try to find the setjmp associated with the simulated stack pointer. | |
1707 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); | |
1708 while ((buf->link() != NULL) && (buf->link()->base() > fp)) { | |
1709 buf = buf->link(); | |
1710 } | |
1711 ASSERT(buf != NULL); | |
1712 ASSERT(last_setjmp_buffer() == buf); | |
1713 | |
1714 // The C++ caller has not cleaned up the stack memory of C++ frames. | |
1715 // Prepare for unwinding frames by destroying all the stack resources | |
1716 // in the previous C++ frames. | |
1717 StackResource::Unwind(thread); | |
1718 | |
1719 // Set the tag. | |
1720 thread->set_vm_tag(VMTag::kDartTagId); | |
1721 // Clear top exit frame. | |
1722 thread->set_top_exit_frame_info(0); | |
1723 | |
1724 ASSERT(raw_exception != Object::null()); | |
1725 top_ = reinterpret_cast<uintptr_t*>(sp); | |
1726 base_ = reinterpret_cast<uintptr_t*>(fp); | |
1727 pc_ = pc; | |
1728 special_[kExceptionSpecialIndex] = raw_exception; | |
1729 special_[kStacktraceSpecialIndex] = raw_stacktrace; | |
1730 buf->Longjmp(); | |
1731 UNREACHABLE(); | |
1732 } | |
1733 | |
1734 } // namespace dart | |
1735 | |
1736 | |
1737 #endif // defined TARGET_ARCH_DBC | |
OLD | NEW |