Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: runtime/vm/simulator_dbc.cc

Issue 1858283002: Initial SIMDBC interpreter. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: cleanup Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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,
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,
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 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
885 *reinterpret_cast<RawSmi**>(
886 reinterpret_cast<uword>(argdesc.raw()->ptr()) +
887 Array::element_offset(
888 ArgumentsDescriptor::
889 kPositionalCountIndex))); /* desc.PositionalCount(); */
890 if (pos_count != rA) {
891 goto ClosureNoSuchMethod;
892 }
893
894 {
895 RawObject** L = B;
896 for (intptr_t i = 0; i < num_locals; i++) {
897 L[i] = null_value;
898 }
899 L[context_reg] = empty_context;
900 SP = B + num_locals - 1;
901 }
902
903 DISPATCH();
904 }
905
906 {
907 BYTECODE(DebugStep, A);
908 if (thread->isolate()->single_step()) {
909 Exit(thread, B, SP + 1, pc);
910 NativeArguments args(thread, 0, NULL, NULL);
911 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH);
912 }
913 DISPATCH();
914 }
915
916 {
917 BYTECODE(DebugBreak, A);
918 {
919 const uint32_t original_bc =
920 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
921 thread->isolate()->debugger()->GetPatchedStubAddress(
922 reinterpret_cast<uword>(pc))));
923
924 SP[1] = null_value;
925 Exit(thread, B, SP + 2, pc);
926 NativeArguments args(thread, 0, NULL, SP + 1);
927 INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args, FALLTHROUGH) else {
928 DISPATCH_OP(original_bc);
929 }
930 }
931 DISPATCH();
932 }
933
934 {
935 BYTECODE(CheckStack, A);
936 {
937 if (reinterpret_cast<uword>(SP) >= thread->isolate()->stack_limit()) {
938 Exit(thread, B, SP + 1, pc);
939 NativeArguments args(thread, 0, NULL, NULL);
940 INVOKE_RUNTIME(DRT_StackOverflow, args, FALLTHROUGH);
941 }
942 }
943 DISPATCH();
944 }
945
946 {
947 BYTECODE(EntryOpt, A_B_C);
948 const uint16_t num_fixed_params = rA;
949 const uint16_t num_opt_pos_params = rB;
950 const uint16_t num_opt_named_params = rC;
951
952 const intptr_t min_num_pos_args = num_fixed_params;
953 const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params;
954 const intptr_t arg_count = Smi::Value(*reinterpret_cast<RawSmi**>(
955 reinterpret_cast<uword>(argdesc.raw()->ptr()) +
956 Array::element_offset(ArgumentsDescriptor::kCountIndex)));
957 const intptr_t pos_count = Smi::Value(*reinterpret_cast<RawSmi**>(
958 reinterpret_cast<uword>(argdesc.raw()->ptr()) +
959 Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex)));
960 const intptr_t named_count = (arg_count - pos_count);
961 if (!(min_num_pos_args <= pos_count && pos_count <= max_num_pos_args)) {
962 goto ClosureNoSuchMethod;
963 }
964
965 // Copy all passed position arguments.Entry
966 RawObject** first_arg = FrameArguments(B, arg_count);
967 memmove(B, first_arg, pos_count * kWordSize);
968 if (num_opt_named_params != 0) {
969 // RawObject** opt_copy = first_arg + pos_count;
970
971 intptr_t i = named_count - 1;
972 intptr_t j = num_opt_named_params - 1;
973 while (j >= 0 && i >= 0) {
974 const uint32_t load_name = pc[2 * j];
975 const uint32_t load_value = pc[2 * j + 1];
976 ASSERT((load_name & 0xFF) == Bytecode::kLoadConstant);
977 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant);
978 ASSERT((load_value & 0xFF00) == (load_name & 0xFF00));
979 const uint8_t reg = (load_name >> 8) & 0xFF;
980 RawString* name = reinterpret_cast<RawString*>(
981 pp->data()[load_name >> 16].raw_obj_);
982 if (name == argdesc.At(ArgumentsDescriptor::name_index(i))) {
983 const intptr_t copy_idx = Smi::Value(static_cast<RawSmi*>(
984 argdesc.At(ArgumentsDescriptor::position_index(i))));
985 B[reg] = first_arg[copy_idx];
986 i--;
987 } else {
988 RawObject* value = pp->data()[load_value >> 16].raw_obj_;
989 B[reg] = value;
990 }
991 j--;
992 }
993
994 while (j >= 0) {
995 const uint32_t load_name = pc[2 * j];
996 const uint32_t load_value = pc[2 * j + 1];
997 ASSERT((load_name & 0xFF) == Bytecode::kLoadConstant);
998 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant);
999 ASSERT((load_value & 0xFF00) == (load_name & 0xFF00));
1000 const uint8_t reg = (load_name >> 8) & 0xFF;
1001 RawObject* value = pp->data()[load_value >> 16].raw_obj_;
1002 B[reg] = value;
1003 j--;
1004 }
1005
1006 if (i != -1) {
1007 goto ClosureNoSuchMethod;
1008 }
1009
1010 pc += num_opt_named_params * 2;
1011 SP = B + num_fixed_params + num_opt_named_params - 1;
1012 } else {
1013 ASSERT(num_opt_pos_params != 0);
1014 if (named_count != 0) {
1015 goto ClosureNoSuchMethod;
1016 }
1017
1018 RawObject** opt_base = B + rA;
1019 for (intptr_t i = pos_count - rA; i < num_opt_pos_params; i++) {
1020 const uint32_t load_value = pc[i];
1021 ASSERT((load_value & 0xFF) == Bytecode::kLoadConstant);
1022 const uint8_t reg = (load_value >> 8) & 0xFF;
1023 RawObject* value = pp->data()[load_value >> 16].raw_obj_;
1024 ASSERT((i + rA) == reg);
1025 opt_base[i] = value;
1026 }
1027
1028 pc += num_opt_pos_params;
1029 SP = B + max_num_pos_args - 1;
1030 }
1031
1032 DISPATCH();
1033 }
1034
1035 {
1036 BYTECODE(InstantiateType, A_D);
1037 RawObject* type = pp->data()[rD].raw_obj_;
1038 SP[1] = type;
1039 SP[2] = SP[0];
1040 SP[0] = null_value;
1041 Exit(thread, B, SP + 3, pc);
1042 {
1043 NativeArguments args(thread, 2, SP + 1, SP);
1044 INVOKE_RUNTIME(DRT_InstantiateType, args, FALLTHROUGH);
1045 }
1046 DISPATCH();
1047 }
1048
1049 {
1050 BYTECODE(InstantiateTypeArgumentsTOS, A_D);
1051 RawTypeArguments* type_arguments =
1052 static_cast<RawTypeArguments*>(pp->data()[rD].raw_obj_);
1053
1054 RawObject* instantiator = SP[0];
1055 // If the instantiator is null and if the type argument vector
1056 // instantiated from null becomes a vector of dynamic, then use null as
1057 // the type arguments.
1058 if (rA == 0 || null_value != instantiator) {
1059 RawArray* instantiations = type_arguments->ptr()->instantiations_;
1060 for (intptr_t i = 0;
1061 instantiations->ptr()->data()[i] != NULL; // kNoInstantiator
1062 i += 2) {
1063 if (instantiations->ptr()->data()[i] == instantiator) {
1064 SP[0] = instantiations->ptr()->data()[i + 1];
1065 goto InstantiateTypeArgumentsTOSDone;
1066 }
1067 }
1068
1069 SP[1] = type_arguments;
1070 SP[2] = instantiator;
1071
1072 Exit(thread, B, SP + 3, pc);
1073 NativeArguments args(thread, 2, SP + 1, SP);
1074 INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args, FALLTHROUGH);
1075 }
1076
1077 InstantiateTypeArgumentsTOSDone:
1078 DISPATCH();
1079 }
1080
1081 {
1082 BYTECODE(Throw, A);
1083 {
1084 SP[1] = 0;
1085 Exit(thread, B, SP + 2, pc);
1086 if (rA == 0) {
1087 NativeArguments args(thread, 1, SP, SP + 1);
1088 INVOKE_RUNTIME(DRT_Throw, args, FALLTHROUGH);
1089 } else {
1090 NativeArguments args(thread, 2, SP - 1, SP + 1);
1091 INVOKE_RUNTIME(DRT_ReThrow, args, FALLTHROUGH);
1092 }
1093 }
1094 DISPATCH();
1095 }
1096
1097 {
1098 BYTECODE(Frame, A_D);
1099 const uint16_t num_locals = rD;
1100 for (intptr_t i = 1; i <= num_locals; i++) {
1101 SP[i] = null_value;
1102 }
1103 SP += num_locals;
1104
1105 DISPATCH();
1106 }
1107
1108 {
1109 BYTECODE(SetFrame, A);
1110 SP = B + rA - 1;
1111 DISPATCH();
1112 }
1113
1114 {
1115 BYTECODE(Drop1, 0);
1116 SP--;
1117 DISPATCH();
1118 }
1119
1120 {
1121 BYTECODE(Drop, 0);
1122 SP -= rA;
1123 DISPATCH();
1124 }
1125
1126 {
1127 BYTECODE(DropR, 0);
1128 RawObject* result = SP[0];
1129 SP -= rA;
1130 SP[0] = result;
1131 DISPATCH();
1132 }
1133
1134 {
1135 BYTECODE(LoadConstant, A_D);
1136 B[rA] = pp->data()[rD].raw_obj_;
1137 DISPATCH();
1138 }
1139
1140 {
1141 BYTECODE(PushConstant, __D);
1142 *++SP = pp->data()[rD].raw_obj_;
1143 DISPATCH();
1144 }
1145
1146 {
1147 BYTECODE(Push, A_X);
1148 *++SP = B[rD];
1149 DISPATCH();
1150 }
1151
1152 {
1153 BYTECODE(Move, A_X);
1154 B[rA] = B[rD];
1155 DISPATCH();
1156 }
1157
1158 {
1159 BYTECODE(StoreLocal, A_X);
1160 B[rD] = *SP;
1161 DISPATCH();
1162 }
1163
1164 {
1165 BYTECODE(PopLocal, A_X);
1166 B[rD] = *SP--;
1167 DISPATCH();
1168 }
1169
1170 {
1171 BYTECODE(MoveSpecial, A_D);
1172 B[rA] = special_[rD];
1173 DISPATCH();
1174 }
1175
1176 {
1177 BYTECODE(BooleanNegateTOS, 0);
1178 SP[0] = (SP[0] == true_value) ? false_value : true_value;
1179 DISPATCH();
1180 }
1181
1182 {
1183 BYTECODE(StaticCall, A_D);
1184 if (thread->isolate()->single_step()) {
1185 Exit(thread, B, SP + 1, pc);
1186 NativeArguments args(thread, 0, NULL, NULL);
1187 INVOKE_RUNTIME(DRT_SingleStepHandler, args, goto StaticCallDispatch);
1188 }
1189
1190 {
1191 const uint16_t argc = rA;
1192 RawObject** call_base = SP - argc;
1193 RawObject** call_top = SP; // *SP contains function
1194 argdesc ^= pp->data()[rD].raw_obj_;
1195 Invoke(thread, call_base, call_top, &pp, &pc, &B, &SP);
1196 }
1197
1198 StaticCallDispatch:
1199 DISPATCH();
1200 }
1201
1202 {
1203 BYTECODE(InstanceCall, A_D);
1204 if (thread->isolate()->single_step()) {
1205 Exit(thread, B, SP + 1, pc);
1206 NativeArguments args(thread, 0, NULL, NULL);
1207 INVOKE_RUNTIME(DRT_SingleStepHandler, args,
1208 goto InstanceCallDispatch);
1209 }
1210
1211 {
1212 const uint16_t argc = rA;
1213 const uint16_t kidx = rD;
1214
1215 RawObject** call_base = SP - argc + 1;
1216 RawObject** call_top = SP + 1;
1217 InstanceCall1(thread,
1218 static_cast<RawICData*>(pp->data()[kidx].raw_obj_),
1219 call_base, call_top, &argdesc, &pp, &pc, &B, &SP);
1220 }
1221
1222 InstanceCallDispatch:
1223 DISPATCH();
1224 }
1225
1226 {
1227 BYTECODE(InstanceCall2, A_D);
1228 if (thread->isolate()->single_step()) {
1229 Exit(thread, B, SP + 1, pc);
1230 NativeArguments args(thread, 0, NULL, NULL);
1231 INVOKE_RUNTIME(DRT_SingleStepHandler, args,
1232 goto InstanceCall2Dispatch);
1233 }
1234
1235 {
1236 const uint16_t argc = rA;
1237 const uint16_t kidx = rD;
1238
1239 RawObject** call_base = SP - argc + 1;
1240 RawObject** call_top = SP + 1;
1241 InstanceCall2(thread,
1242 static_cast<RawICData*>(pp->data()[kidx].raw_obj_),
1243 call_base, call_top, &argdesc, &pp, &pc, &B, &SP);
1244 }
1245
1246 InstanceCall2Dispatch:
1247 DISPATCH();
1248 }
1249
1250 {
1251 BYTECODE(InstanceCall3, A_D);
1252 if (thread->isolate()->single_step()) {
1253 Exit(thread, B, SP + 1, pc);
1254 NativeArguments args(thread, 0, NULL, NULL);
1255 INVOKE_RUNTIME(DRT_SingleStepHandler, args,
1256 goto InstanceCall3Dispatch);
1257 }
1258
1259 {
1260 const uint16_t argc = rA;
1261 const uint16_t kidx = rD;
1262
1263 RawObject** call_base = SP - argc + 1;
1264 RawObject** call_top = SP + 1;
1265 InstanceCall3(thread,
1266 static_cast<RawICData*>(pp->data()[kidx].raw_obj_),
1267 call_base, call_top, &argdesc, &pp, &pc, &B, &SP);
1268 }
1269
1270 InstanceCall3Dispatch:
1271 DISPATCH();
1272 }
1273
1274 {
1275 BYTECODE(NativeBootstrapCall, 0);
1276 RawFunction* function = FrameFunction(B);
1277 RawObject** incoming_args =
1278 function->ptr()->num_optional_parameters_ == 0
1279 ? FrameArguments(B, function->ptr()->num_fixed_parameters_)
1280 : B;
1281
1282 SimulatorBootstrapNativeCall native_target =
1283 reinterpret_cast<SimulatorBootstrapNativeCall>(SP[-1]);
1284 intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]);
1285 SP[-0] = 0; // Note: argc_tag is not smi-tagged.
1286 SP[-1] = null_value;
1287 Exit(thread, B, SP + 1, pc);
1288 NativeArguments args(thread, argc_tag, incoming_args, SP - 1);
1289 INVOKE_NATIVE(native_target, args, FALLTHROUGH) else { SP -= 1; }
1290 DISPATCH();
1291 }
1292
1293 {
1294 BYTECODE(NativeCall, 0);
1295 RawFunction* function = FrameFunction(B);
1296 RawObject** incoming_args =
1297 function->ptr()->num_optional_parameters_ == 0
1298 ? FrameArguments(B, function->ptr()->num_fixed_parameters_)
1299 : B;
1300
1301 Dart_NativeFunction native_target =
1302 reinterpret_cast<Dart_NativeFunction>(SP[-1]);
1303 intptr_t argc_tag = reinterpret_cast<intptr_t>(SP[-0]);
1304 SP[-0] = 0; // argc_tag is not smi tagged!
1305 SP[-1] = null_value;
1306 Exit(thread, B, SP + 1, pc);
1307 NativeArguments args(thread, argc_tag, incoming_args, SP - 1);
1308 INVOKE_NATIVE_WRAPPER(native_target, args, FALLTHROUGH) else {
1309 SP -= 1;
1310 }
1311 DISPATCH();
1312 }
1313
1314 {
1315 BYTECODE(AddTOS, A_B_C);
1316 SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow);
1317 }
1318 {
1319 BYTECODE(SubTOS, A_B_C);
1320 SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow);
1321 }
1322 {
1323 BYTECODE(MulTOS, A_B_C);
1324 SMI_FASTPATH_TOS(intptr_t, SMI_MUL);
1325 }
1326 {
1327 BYTECODE(BitOrTOS, A_B_C);
1328 SMI_FASTPATH_TOS(intptr_t, SMI_BITOR);
1329 }
1330 {
1331 BYTECODE(BitAndTOS, A_B_C);
1332 SMI_FASTPATH_TOS(intptr_t, SMI_BITAND);
1333 }
1334 {
1335 BYTECODE(EqualTOS, A_B_C);
1336 SMI_FASTPATH_TOS(RawObject*, SMI_EQ);
1337 }
1338 {
1339 BYTECODE(LessThanTOS, A_B_C);
1340 SMI_FASTPATH_TOS(RawObject*, SMI_LT);
1341 }
1342 {
1343 BYTECODE(GreaterThanTOS, A_B_C);
1344 SMI_FASTPATH_TOS(RawObject*, SMI_GT);
1345 }
1346
1347 {
1348 BYTECODE(Compile, 0);
1349 B[0] = FrameFunction(B);
1350 B[1] = 0;
1351 Exit(thread, B, B + 2, pc);
1352 NativeArguments args(thread, 1, B, B + 1);
1353 INVOKE_RUNTIME(DRT_CompileFunction, args, FALLTHROUGH) else {
1354 // Function should be compiled now.
1355 RawCode* code = FrameFunction(B)->ptr()->code_;
1356 SetFrameCode(B, code);
1357 pp = code->ptr()->object_pool_->ptr();
1358 pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
1359 }
1360 DISPATCH();
1361 }
1362
1363 {
1364 RawObject* result;
1365
1366 BYTECODE(Intrinsic, A);
1367 result = null_value;
1368 if (!intrinsics_[rA](thread, B, &result)) {
1369 DISPATCH();
1370 }
1371 goto ReturnImpl;
1372
1373 BYTECODE(Return, A);
1374 result = B[rA];
1375 goto ReturnImpl;
1376
1377 BYTECODE(ReturnTOS, 0);
1378 result = *SP;
1379
1380 ReturnImpl:
1381 pc = SavedCallerPC(B);
1382 if ((reinterpret_cast<uword>(pc) & 2) != 0) {
1383 const intptr_t argc = reinterpret_cast<uword>(pc) >> 2;
1384 base_ = top_ = reinterpret_cast<uintptr_t*>(
1385 FrameArguments(B, argc + 1)[0]);
1386 thread->set_top_exit_frame_info(reinterpret_cast<uword>(top_));
1387 thread->set_top_resource(top_resource);
1388 thread->set_vm_tag(vm_tag);
1389 return result;
1390 }
1391 const uint8_t argc = Bytecode::DecodeArgc(pc[-1]);
1392 SP = FrameArguments(B, argc);
1393 B = SavedCallerFP(B);
1394 *SP = result;
1395 RawCode* code = FrameCode(B);
1396 pp = code->ptr()->object_pool_->ptr();
1397 DISPATCH();
1398 }
1399
1400 {
1401 BYTECODE(StoreStaticTOS, A_D);
1402 RawField* field = reinterpret_cast<RawField*>(pp->data()[rD].raw_obj_);
1403 RawInstance* value = static_cast<RawInstance*>(*SP--);
1404 field->StorePointer(&field->ptr()->value_.static_value_, value);
1405 DISPATCH();
1406 }
1407
1408 {
1409 BYTECODE(PushStatic, A_D);
1410 RawField* field = reinterpret_cast<RawField*>(pp->data()[rD].raw_obj_);
1411 *SP = field->ptr()->value_.static_value_; // Note: field on the stack.
1412 DISPATCH();
1413 }
1414
1415 {
1416 BYTECODE(StoreField, A_B_C);
1417 const uint16_t offset_in_words = rB;
1418 const uint16_t value_reg = rC;
1419
1420 RawInstance* instance = reinterpret_cast<RawInstance*>(B[rA]);
1421 RawObject* value = reinterpret_cast<RawObject*>(B[value_reg]);
1422
1423 instance->StorePointer(
1424 reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
1425 value);
1426 DISPATCH();
1427 }
1428
1429 {
1430 BYTECODE(StoreFieldTOS, A_D);
1431 const uint16_t offset_in_words = rD;
1432 RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
1433 RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
1434 SP -= 2;
1435 instance->StorePointer(
1436 reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
1437 value);
1438
1439 DISPATCH();
1440 }
1441
1442 {
1443 BYTECODE(LoadField, A_B_C);
1444 const uint16_t instance_reg = rB;
1445 const uint16_t offset_in_words = rC;
1446 RawInstance* instance = reinterpret_cast<RawInstance*>(B[instance_reg]);
1447 B[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
1448 DISPATCH();
1449 }
1450
1451 {
1452 BYTECODE(LoadFieldTOS, A_D);
1453 const uint16_t offset_in_words = rD;
1454 RawInstance* instance = static_cast<RawInstance*>(SP[0]);
1455 SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
1456 DISPATCH();
1457 }
1458
1459 {
1460 BYTECODE(InitStaticTOS, A);
1461 RawField* field = static_cast<RawField*>(*SP--);
1462 RawObject* value = field->ptr()->value_.static_value_;
1463 if ((value == Object::sentinel().raw()) ||
1464 (value == Object::transition_sentinel().raw())) {
1465 /* SP[1] field */
1466 SP[2] = 0;
1467 Exit(thread, B, SP + 3, pc);
1468 NativeArguments args(thread, 1, SP + 1, SP + 2);
1469 INVOKE_RUNTIME(DRT_InitStaticField, args, FALLTHROUGH);
1470 }
1471 DISPATCH();
1472 }
1473
1474 {
1475 BYTECODE(AllocateContext, A_D);
1476 const uint16_t num_context_variables = rD;
1477 {
1478 *++SP = 0;
1479 SP[1] = Smi::New(num_context_variables);
1480 Exit(thread, B, SP + 2, pc);
1481 NativeArguments args(thread, 1, SP + 1, SP);
1482 INVOKE_RUNTIME(DRT_AllocateContext, args, FALLTHROUGH);
1483 }
1484 DISPATCH();
1485 }
1486
1487 {
1488 BYTECODE(CloneContext, A);
1489 {
1490 SP[1] = SP[0];
1491 Exit(thread, B, SP + 2, pc);
1492 NativeArguments args(thread, 1, SP + 1, SP);
1493 INVOKE_RUNTIME(DRT_CloneContext, args, FALLTHROUGH);
1494 }
1495 DISPATCH();
1496 }
1497
1498 {
1499 BYTECODE(Allocate, A_D);
1500 SP[1] = 0; // result
1501 SP[2] = pp->data()[rD].raw_obj_;
1502 SP[3] = null_value;
1503 Exit(thread, B, SP + 4, pc);
1504 NativeArguments args(thread, 2, SP + 2, SP + 1);
1505 INVOKE_RUNTIME(DRT_AllocateObject, args, FALLTHROUGH);
1506 SP++;
1507 DISPATCH();
1508 }
1509
1510 {
1511 BYTECODE(AllocateT, 0);
1512 SP[1] = SP[-0]; // class
1513 SP[2] = SP[-1]; // type arguments
1514 Exit(thread, B, SP + 3, pc);
1515 NativeArguments args(thread, 2, SP + 1, SP - 1);
1516 INVOKE_RUNTIME(DRT_AllocateObject, args, FALLTHROUGH);
1517 SP -= 1;
1518 DISPATCH();
1519 }
1520
1521 {
1522 BYTECODE(CreateArrayTOS, 0);
1523 SP[1] = SP[-0]; // length
1524 SP[2] = SP[-1]; // type
Florian Schneider 2016/04/12 02:29:58 Would it make sense to have a fast-path new-space
Vyacheslav Egorov (Google) 2016/04/12 09:01:21 Yes, I think it does makes sense to have a fast-pa
1525 Exit(thread, B, SP + 3, pc);
1526 NativeArguments args(thread, 2, SP + 1, SP - 1);
1527 INVOKE_RUNTIME(DRT_AllocateArray, args, FALLTHROUGH);
1528 SP -= 1;
1529 DISPATCH();
1530 }
1531
1532 {
1533 BYTECODE(AssertAssignable, A_D); // instance, type args, type, name
1534 RawObject** args = SP - 3;
1535 if (args[0] != null_value) {
1536 RawSubtypeTestCache* cache =
1537 static_cast<RawSubtypeTestCache*>(pp->data()[rD].raw_obj_);
1538 if (cache != null_value) {
1539 RawInstance* instance = static_cast<RawInstance*>(args[0]);
1540 RawTypeArguments* instantiator_type_arguments =
1541 static_cast<RawTypeArguments*>(args[1]);
1542
1543 const intptr_t cid = SimulatorHelpers::GetClassId(instance);
1544
1545 RawTypeArguments* instance_type_arguments =
1546 static_cast<RawTypeArguments*>(null_value);
1547 RawObject* instance_cid_or_function;
1548 if (cid == kClosureCid) {
1549 RawClosure* closure = static_cast<RawClosure*>(instance);
1550 instance_type_arguments = closure->ptr()->type_arguments_;
1551 instance_cid_or_function = closure->ptr()->function_;
1552 } else {
1553 instance_cid_or_function = Smi::New(cid);
1554
1555 RawClass* instance_class =
1556 thread->isolate()->class_table()->At(cid);
1557 if (instance_class->ptr()->num_type_arguments_ < 0) {
1558 goto AssertAssignableCallRuntime;
1559 } else if (instance_class->ptr()->num_type_arguments_ > 0) {
1560 instance_type_arguments = reinterpret_cast<RawTypeArguments**>(
1561 instance
1562 ->ptr())[instance_class->ptr()
1563 ->type_arguments_field_offset_in_words_];
1564 }
1565 }
1566
1567 for (RawObject** entries = cache->ptr()->cache_->ptr()->data();
1568 entries[0] != null_value;
1569 entries += SubtypeTestCache::kTestEntryLength) {
1570 if (entries[SubtypeTestCache::kInstanceClassIdOrFunction] ==
1571 instance_cid_or_function &&
1572 entries[SubtypeTestCache::kInstanceTypeArguments] ==
1573 instance_type_arguments &&
1574 entries[SubtypeTestCache::kInstantiatorTypeArguments] ==
1575 instantiator_type_arguments) {
1576 if (true_value == entries[SubtypeTestCache::kTestResult]) {
1577 goto AssertAssignableOk;
1578 } else {
1579 break;
1580 }
1581 }
1582 }
1583 }
1584
1585 AssertAssignableCallRuntime:
1586 SP[1] = args[0]; // instance
1587 SP[2] = args[2]; // type
1588 SP[3] = args[1]; // type args
1589 SP[4] = args[3]; // name
1590 SP[5] = cache;
1591 Exit(thread, B, SP + 6, pc);
1592 NativeArguments args(thread, 5, SP + 1, SP - 3);
1593 INVOKE_RUNTIME(DRT_TypeCheck, args, FALLTHROUGH);
1594 }
1595
1596 AssertAssignableOk:
1597 SP -= 3;
1598 DISPATCH();
1599 }
1600
1601 {
1602 BYTECODE(AssertBoolean, A);
1603 RawObject* value = SP[0];
1604 if (rA) {
1605 if (value == true_value || value == false_value) {
1606 goto AssertBooleanOk;
1607 }
1608 } else if (value != null_value) {
1609 goto AssertBooleanOk;
1610 }
1611
1612 {
1613 SP[1] = SP[0]; // instance
1614 Exit(thread, B, SP + 2, pc);
1615 NativeArguments args(thread, 1, SP + 1, SP);
1616 INVOKE_RUNTIME(DRT_NonBoolTypeError, args, FALLTHROUGH);
1617 }
1618
1619 AssertBooleanOk:
1620 DISPATCH();
1621 }
1622
1623 {
1624 BYTECODE(IfEqStrictTOS, A_D);
1625 SP -= 2;
1626 if (SP[1] != SP[2]) {
1627 pc++;
1628 }
1629 DISPATCH();
1630 }
1631
1632 {
1633 BYTECODE(IfNeStrictTOS, A_D);
1634 SP -= 2;
1635 if (SP[1] == SP[2]) {
1636 pc++;
1637 }
1638 DISPATCH();
1639 }
1640
1641 {
1642 BYTECODE(IfEqStrictNumTOS, A_D);
1643 if (thread->isolate()->single_step()) {
1644 Exit(thread, B, SP + 1, pc);
1645 NativeArguments args(thread, 0, NULL, NULL);
1646 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH);
1647 }
1648
1649 SP -= 2;
1650 if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
1651 pc++;
1652 }
1653 DISPATCH();
1654 }
1655
1656 {
1657 BYTECODE(IfNeStrictNumTOS, A_D);
1658 if (thread->isolate()->single_step()) {
1659 Exit(thread, B, SP + 1, pc);
1660 NativeArguments args(thread, 0, NULL, NULL);
1661 INVOKE_RUNTIME(DRT_SingleStepHandler, args, FALLTHROUGH);
1662 }
1663
1664 SP -= 2;
1665 if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
1666 pc++;
1667 }
1668 DISPATCH();
1669 }
1670
1671 {
1672 BYTECODE(Jump, 0);
1673 const int32_t tgt = static_cast<int32_t>(__op) >> 8;
1674 pc += (tgt - 1);
1675 DISPATCH();
1676 }
1677
1678 {
1679 BYTECODE(StoreIndexedTOS, 0);
1680 SP -= 3;
1681 RawArray* array = static_cast<RawArray*>(SP[1]);
1682 RawSmi* index = static_cast<RawSmi*>(SP[2]);
1683 RawObject* value = SP[3];
1684 ASSERT(array->GetClassId() == kArrayCid);
1685 ASSERT(!index->IsHeapObject());
1686 array->StorePointer(array->ptr()->data() + Smi::Value(index), value);
1687 // THR_Print("{%p} %p[%d] = %p\n", pc, array, Smi::Value(index), value);
Florian Schneider 2016/04/12 02:29:59 Left over debug printing
Vyacheslav Egorov (Google) 2016/04/12 09:01:21 Done.
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698