| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #if defined(TARGET_ARCH_DBC) | 9 #if defined(TARGET_ARCH_DBC) |
| 10 | 10 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "vm/native_arguments.h" | 25 #include "vm/native_arguments.h" |
| 26 #include "vm/native_entry.h" | 26 #include "vm/native_entry.h" |
| 27 #include "vm/object.h" | 27 #include "vm/object.h" |
| 28 #include "vm/object_store.h" | 28 #include "vm/object_store.h" |
| 29 #include "vm/os_thread.h" | 29 #include "vm/os_thread.h" |
| 30 #include "vm/stack_frame.h" | 30 #include "vm/stack_frame.h" |
| 31 #include "vm/symbols.h" | 31 #include "vm/symbols.h" |
| 32 | 32 |
| 33 namespace dart { | 33 namespace dart { |
| 34 | 34 |
| 35 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, | 35 DEFINE_FLAG(uint64_t, |
| 36 trace_sim_after, |
| 37 ULLONG_MAX, |
| 36 "Trace simulator execution after instruction count reached."); | 38 "Trace simulator execution after instruction count reached."); |
| 37 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, | 39 DEFINE_FLAG(uint64_t, |
| 40 stop_sim_at, |
| 41 ULLONG_MAX, |
| 38 "Instruction address or instruction count to stop simulator at."); | 42 "Instruction address or instruction count to stop simulator at."); |
| 39 | 43 |
| 40 #define LIKELY(cond) __builtin_expect((cond), 1) | 44 #define LIKELY(cond) __builtin_expect((cond), 1) |
| 41 #define UNLIKELY(cond) __builtin_expect((cond), 0) | 45 #define UNLIKELY(cond) __builtin_expect((cond), 0) |
| 42 | 46 |
| 43 // SimulatorSetjmpBuffer are linked together, and the last created one | 47 // SimulatorSetjmpBuffer are linked together, and the last created one |
| 44 // is referenced by the Simulator. When an exception is thrown, the exception | 48 // is referenced by the Simulator. When an exception is thrown, the exception |
| 45 // runtime looks at where to jump and finds the corresponding | 49 // runtime looks at where to jump and finds the corresponding |
| 46 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. | 50 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. |
| 47 // The runtime then does a Longjmp on that buffer to return to the simulator. | 51 // The runtime then does a Longjmp on that buffer to return to the simulator. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 return reinterpret_cast<RawObject**>(FP[kSavedCallerFpSlotFromFp]); | 94 return reinterpret_cast<RawObject**>(FP[kSavedCallerFpSlotFromFp]); |
| 91 } | 95 } |
| 92 | 96 |
| 93 | 97 |
| 94 DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, | 98 DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, |
| 95 intptr_t argc) { | 99 intptr_t argc) { |
| 96 return FP - (kDartFrameFixedSize + argc); | 100 return FP - (kDartFrameFixedSize + argc); |
| 97 } | 101 } |
| 98 | 102 |
| 99 | 103 |
| 100 #define RAW_CAST(Type, val) (SimulatorHelpers::CastTo##Type(val)) | 104 #define RAW_CAST(Type, val) (SimulatorHelpers::CastTo##Type(val)) |
| 101 | 105 |
| 102 | 106 |
| 103 class SimulatorHelpers { | 107 class SimulatorHelpers { |
| 104 public: | 108 public: |
| 105 #define DEFINE_CASTS(Type) \ | 109 #define DEFINE_CASTS(Type) \ |
| 106 DART_FORCE_INLINE static Raw##Type* CastTo##Type(RawObject* obj) { \ | 110 DART_FORCE_INLINE static Raw##Type* CastTo##Type(RawObject* obj) { \ |
| 107 ASSERT((k##Type##Cid == kSmiCid) ? !obj->IsHeapObject() \ | 111 ASSERT((k##Type##Cid == kSmiCid) ? !obj->IsHeapObject() \ |
| 108 : obj->Is##Type()); \ | 112 : obj->Is##Type()); \ |
| 109 return reinterpret_cast<Raw##Type*>(obj); \ | 113 return reinterpret_cast<Raw##Type*>(obj); \ |
| 110 } | 114 } |
| 111 CLASS_LIST(DEFINE_CASTS) | 115 CLASS_LIST(DEFINE_CASTS) |
| 112 #undef DEFINE_CASTS | 116 #undef DEFINE_CASTS |
| 113 | 117 |
| 114 DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { | 118 DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { |
| 115 return Smi::New(obj->IsHeapObject() ? obj->GetClassId() | 119 return Smi::New(obj->IsHeapObject() ? obj->GetClassId() |
| 116 : static_cast<intptr_t>(kSmiCid)); | 120 : static_cast<intptr_t>(kSmiCid)); |
| 117 } | 121 } |
| 118 | 122 |
| 119 DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { | 123 DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { |
| 120 return obj->IsHeapObject() ? obj->GetClassId() | 124 return obj->IsHeapObject() ? obj->GetClassId() |
| 121 : static_cast<intptr_t>(kSmiCid); | 125 : static_cast<intptr_t>(kSmiCid); |
| 122 } | 126 } |
| 123 | 127 |
| 124 DART_FORCE_INLINE static void IncrementUsageCounter(RawFunction* f) { | 128 DART_FORCE_INLINE static void IncrementUsageCounter(RawFunction* f) { |
| 125 f->ptr()->usage_counter_++; | 129 f->ptr()->usage_counter_++; |
| 126 } | 130 } |
| 127 | 131 |
| 128 DART_FORCE_INLINE static void IncrementICUsageCount(RawObject** entries, | 132 DART_FORCE_INLINE static void IncrementICUsageCount(RawObject** entries, |
| 129 intptr_t offset, | 133 intptr_t offset, |
| 130 intptr_t args_tested) { | 134 intptr_t args_tested) { |
| 131 const intptr_t count_offset = ICData::CountIndexFor(args_tested); | 135 const intptr_t count_offset = ICData::CountIndexFor(args_tested); |
| 132 const intptr_t raw_smi_old = | 136 const intptr_t raw_smi_old = |
| 133 reinterpret_cast<intptr_t>(entries[offset + count_offset]); | 137 reinterpret_cast<intptr_t>(entries[offset + count_offset]); |
| 134 const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1); | 138 const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1); |
| 135 *reinterpret_cast<intptr_t*>(&entries[offset + count_offset]) = | 139 *reinterpret_cast<intptr_t*>(&entries[offset + count_offset]) = raw_smi_new; |
| 136 raw_smi_new; | |
| 137 } | 140 } |
| 138 | 141 |
| 139 DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, | 142 DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, |
| 140 RawObject* rhs) { | 143 RawObject* rhs) { |
| 141 if (lhs == rhs) { | 144 if (lhs == rhs) { |
| 142 return true; | 145 return true; |
| 143 } | 146 } |
| 144 | 147 |
| 145 if (lhs->IsHeapObject() && rhs->IsHeapObject()) { | 148 if (lhs->IsHeapObject() && rhs->IsHeapObject()) { |
| 146 const intptr_t lhs_cid = lhs->GetClassId(); | 149 const intptr_t lhs_cid = lhs->GetClassId(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 166 | 169 |
| 167 return false; | 170 return false; |
| 168 } | 171 } |
| 169 | 172 |
| 170 template <typename T> | 173 template <typename T> |
| 171 DART_FORCE_INLINE static T* Untag(T* tagged) { | 174 DART_FORCE_INLINE static T* Untag(T* tagged) { |
| 172 return tagged->ptr(); | 175 return tagged->ptr(); |
| 173 } | 176 } |
| 174 | 177 |
| 175 DART_FORCE_INLINE static bool CheckIndex(RawSmi* index, RawSmi* length) { | 178 DART_FORCE_INLINE static bool CheckIndex(RawSmi* index, RawSmi* length) { |
| 176 return !index->IsHeapObject() && | 179 return !index->IsHeapObject() && (reinterpret_cast<intptr_t>(index) >= 0) && |
| 177 (reinterpret_cast<intptr_t>(index) >= 0) && | |
| 178 (reinterpret_cast<intptr_t>(index) < | 180 (reinterpret_cast<intptr_t>(index) < |
| 179 reinterpret_cast<intptr_t>(length)); | 181 reinterpret_cast<intptr_t>(length)); |
| 180 } | 182 } |
| 181 | 183 |
| 182 static bool ObjectArraySetIndexed(Thread* thread, | 184 static bool ObjectArraySetIndexed(Thread* thread, |
| 183 RawObject** FP, | 185 RawObject** FP, |
| 184 RawObject** result) { | 186 RawObject** result) { |
| 185 if (thread->isolate()->type_checks()) { | 187 if (thread->isolate()->type_checks()) { |
| 186 return false; | 188 return false; |
| 187 } | 189 } |
| 188 | 190 |
| 189 RawObject** args = FrameArguments(FP, 3); | 191 RawObject** args = FrameArguments(FP, 3); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 return true; | 242 return true; |
| 241 } | 243 } |
| 242 return false; | 244 return false; |
| 243 } | 245 } |
| 244 | 246 |
| 245 static bool Double_getIsNan(Thread* thread, | 247 static bool Double_getIsNan(Thread* thread, |
| 246 RawObject** FP, | 248 RawObject** FP, |
| 247 RawObject** result) { | 249 RawObject** result) { |
| 248 RawObject** args = FrameArguments(FP, 1); | 250 RawObject** args = FrameArguments(FP, 1); |
| 249 RawDouble* d = static_cast<RawDouble*>(args[0]); | 251 RawDouble* d = static_cast<RawDouble*>(args[0]); |
| 250 *result = isnan(d->ptr()->value_) | 252 *result = |
| 251 ? Bool::True().raw() | 253 isnan(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw(); |
| 252 : Bool::False().raw(); | |
| 253 return true; | 254 return true; |
| 254 } | 255 } |
| 255 | 256 |
| 256 static bool Double_getIsInfinite(Thread* thread, | 257 static bool Double_getIsInfinite(Thread* thread, |
| 257 RawObject** FP, | 258 RawObject** FP, |
| 258 RawObject** result) { | 259 RawObject** result) { |
| 259 RawObject** args = FrameArguments(FP, 1); | 260 RawObject** args = FrameArguments(FP, 1); |
| 260 RawDouble* d = static_cast<RawDouble*>(args[0]); | 261 RawDouble* d = static_cast<RawDouble*>(args[0]); |
| 261 *result = isinf(d->ptr()->value_) | 262 *result = |
| 262 ? Bool::True().raw() | 263 isinf(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw(); |
| 263 : Bool::False().raw(); | |
| 264 return true; | 264 return true; |
| 265 } | 265 } |
| 266 | 266 |
| 267 static bool ObjectEquals(Thread* thread, | 267 static bool ObjectEquals(Thread* thread, RawObject** FP, RawObject** result) { |
| 268 RawObject** FP, | |
| 269 RawObject** result) { | |
| 270 RawObject** args = FrameArguments(FP, 2); | 268 RawObject** args = FrameArguments(FP, 2); |
| 271 *result = args[0] == args[1] ? Bool::True().raw() : Bool::False().raw(); | 269 *result = args[0] == args[1] ? Bool::True().raw() : Bool::False().raw(); |
| 272 return true; | 270 return true; |
| 273 } | 271 } |
| 274 | 272 |
| 275 static bool ObjectRuntimeType(Thread* thread, | 273 static bool ObjectRuntimeType(Thread* thread, |
| 276 RawObject** FP, | 274 RawObject** FP, |
| 277 RawObject** result) { | 275 RawObject** result) { |
| 278 RawObject** args = FrameArguments(FP, 1); | 276 RawObject** args = FrameArguments(FP, 1); |
| 279 const intptr_t cid = GetClassId(args[0]); | 277 const intptr_t cid = GetClassId(args[0]); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 300 if (typ == Object::null()) { | 298 if (typ == Object::null()) { |
| 301 return false; | 299 return false; |
| 302 } | 300 } |
| 303 *result = static_cast<RawObject*>(typ); | 301 *result = static_cast<RawObject*>(typ); |
| 304 return true; | 302 return true; |
| 305 } | 303 } |
| 306 | 304 |
| 307 static bool GetDoubleOperands(RawObject** args, double* d1, double* d2) { | 305 static bool GetDoubleOperands(RawObject** args, double* d1, double* d2) { |
| 308 RawObject* obj2 = args[1]; | 306 RawObject* obj2 = args[1]; |
| 309 if (!obj2->IsHeapObject()) { | 307 if (!obj2->IsHeapObject()) { |
| 310 *d2 = static_cast<double>( | 308 *d2 = |
| 311 reinterpret_cast<intptr_t>(obj2) >> kSmiTagSize); | 309 static_cast<double>(reinterpret_cast<intptr_t>(obj2) >> kSmiTagSize); |
| 312 } else if (obj2->GetClassId() == kDoubleCid) { | 310 } else if (obj2->GetClassId() == kDoubleCid) { |
| 313 RawDouble* obj2d = static_cast<RawDouble*>(obj2); | 311 RawDouble* obj2d = static_cast<RawDouble*>(obj2); |
| 314 *d2 = obj2d->ptr()->value_; | 312 *d2 = obj2d->ptr()->value_; |
| 315 } else { | 313 } else { |
| 316 return false; | 314 return false; |
| 317 } | 315 } |
| 318 RawDouble* obj1 = static_cast<RawDouble*>(args[0]); | 316 RawDouble* obj1 = static_cast<RawDouble*>(args[0]); |
| 319 *d1 = obj1->ptr()->value_; | 317 *d1 = obj1->ptr()->value_; |
| 320 return true; | 318 return true; |
| 321 } | 319 } |
| 322 | 320 |
| 323 static RawObject* AllocateDouble(Thread* thread, double value) { | 321 static RawObject* AllocateDouble(Thread* thread, double value) { |
| 324 const intptr_t instance_size = Double::InstanceSize(); | 322 const intptr_t instance_size = Double::InstanceSize(); |
| 325 const uword start = | 323 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); |
| 326 thread->heap()->new_space()->TryAllocate(instance_size); | |
| 327 if (LIKELY(start != 0)) { | 324 if (LIKELY(start != 0)) { |
| 328 uword tags = 0; | 325 uword tags = 0; |
| 329 tags = RawObject::ClassIdTag::update(kDoubleCid, tags); | 326 tags = RawObject::ClassIdTag::update(kDoubleCid, tags); |
| 330 tags = RawObject::SizeTag::update(instance_size, tags); | 327 tags = RawObject::SizeTag::update(instance_size, tags); |
| 331 *reinterpret_cast<uword*>(start + Double::tags_offset()) = tags; | 328 *reinterpret_cast<uword*>(start + Double::tags_offset()) = tags; |
| 332 *reinterpret_cast<double*>(start + Double::value_offset()) = value; | 329 *reinterpret_cast<double*>(start + Double::value_offset()) = value; |
| 333 return reinterpret_cast<RawObject*>(start + kHeapObjectTag); | 330 return reinterpret_cast<RawObject*>(start + kHeapObjectTag); |
| 334 } | 331 } |
| 335 return NULL; | 332 return NULL; |
| 336 } | 333 } |
| 337 | 334 |
| 338 static bool Double_add(Thread* thread, | 335 static bool Double_add(Thread* thread, RawObject** FP, RawObject** result) { |
| 339 RawObject** FP, | |
| 340 RawObject** result) { | |
| 341 double d1, d2; | 336 double d1, d2; |
| 342 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 337 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 343 return false; | 338 return false; |
| 344 } | 339 } |
| 345 RawObject* new_double = AllocateDouble(thread, d1 + d2); | 340 RawObject* new_double = AllocateDouble(thread, d1 + d2); |
| 346 if (new_double != NULL) { | 341 if (new_double != NULL) { |
| 347 *result = new_double; | 342 *result = new_double; |
| 348 return true; | 343 return true; |
| 349 } | 344 } |
| 350 return false; | 345 return false; |
| 351 } | 346 } |
| 352 | 347 |
| 353 static bool Double_mul(Thread* thread, | 348 static bool Double_mul(Thread* thread, RawObject** FP, RawObject** result) { |
| 354 RawObject** FP, | |
| 355 RawObject** result) { | |
| 356 double d1, d2; | 349 double d1, d2; |
| 357 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 350 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 358 return false; | 351 return false; |
| 359 } | 352 } |
| 360 RawObject* new_double = AllocateDouble(thread, d1 * d2); | 353 RawObject* new_double = AllocateDouble(thread, d1 * d2); |
| 361 if (new_double != NULL) { | 354 if (new_double != NULL) { |
| 362 *result = new_double; | 355 *result = new_double; |
| 363 return true; | 356 return true; |
| 364 } | 357 } |
| 365 return false; | 358 return false; |
| 366 } | 359 } |
| 367 | 360 |
| 368 static bool Double_sub(Thread* thread, | 361 static bool Double_sub(Thread* thread, RawObject** FP, RawObject** result) { |
| 369 RawObject** FP, | |
| 370 RawObject** result) { | |
| 371 double d1, d2; | 362 double d1, d2; |
| 372 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 363 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 373 return false; | 364 return false; |
| 374 } | 365 } |
| 375 RawObject* new_double = AllocateDouble(thread, d1 - d2); | 366 RawObject* new_double = AllocateDouble(thread, d1 - d2); |
| 376 if (new_double != NULL) { | 367 if (new_double != NULL) { |
| 377 *result = new_double; | 368 *result = new_double; |
| 378 return true; | 369 return true; |
| 379 } | 370 } |
| 380 return false; | 371 return false; |
| 381 } | 372 } |
| 382 | 373 |
| 383 static bool Double_div(Thread* thread, | 374 static bool Double_div(Thread* thread, RawObject** FP, RawObject** result) { |
| 384 RawObject** FP, | |
| 385 RawObject** result) { | |
| 386 double d1, d2; | 375 double d1, d2; |
| 387 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 376 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 388 return false; | 377 return false; |
| 389 } | 378 } |
| 390 RawObject* new_double = AllocateDouble(thread, d1 / d2); | 379 RawObject* new_double = AllocateDouble(thread, d1 / d2); |
| 391 if (new_double != NULL) { | 380 if (new_double != NULL) { |
| 392 *result = new_double; | 381 *result = new_double; |
| 393 return true; | 382 return true; |
| 394 } | 383 } |
| 395 return false; | 384 return false; |
| 396 } | 385 } |
| 397 | 386 |
| 398 static bool Double_greaterThan(Thread* thread, | 387 static bool Double_greaterThan(Thread* thread, |
| 399 RawObject** FP, | 388 RawObject** FP, |
| 400 RawObject** result) { | 389 RawObject** result) { |
| 401 double d1, d2; | 390 double d1, d2; |
| 402 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 391 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 403 return false; | 392 return false; |
| 404 } | 393 } |
| 405 *result = d1 > d2 ? Bool::True().raw() : Bool::False().raw(); | 394 *result = d1 > d2 ? Bool::True().raw() : Bool::False().raw(); |
| 406 return true; | 395 return true; |
| 407 } | 396 } |
| 408 | 397 |
| 409 static bool Double_greaterEqualThan(Thread* thread, | 398 static bool Double_greaterEqualThan(Thread* thread, |
| 410 RawObject** FP, | 399 RawObject** FP, |
| 411 RawObject** result) { | 400 RawObject** result) { |
| 412 double d1, d2; | 401 double d1, d2; |
| 413 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 402 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 414 return false; | 403 return false; |
| 415 } | 404 } |
| 416 *result = d1 >= d2 ? Bool::True().raw() : Bool::False().raw(); | 405 *result = d1 >= d2 ? Bool::True().raw() : Bool::False().raw(); |
| 417 return true; | 406 return true; |
| 418 } | 407 } |
| 419 | 408 |
| 420 static bool Double_lessThan(Thread* thread, | 409 static bool Double_lessThan(Thread* thread, |
| 421 RawObject** FP, | 410 RawObject** FP, |
| 422 RawObject** result) { | 411 RawObject** result) { |
| 423 double d1, d2; | 412 double d1, d2; |
| 424 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 413 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 425 return false; | 414 return false; |
| 426 } | 415 } |
| 427 *result = d1 < d2 ? Bool::True().raw() : Bool::False().raw(); | 416 *result = d1 < d2 ? Bool::True().raw() : Bool::False().raw(); |
| 428 return true; | 417 return true; |
| 429 } | 418 } |
| 430 | 419 |
| 431 static bool Double_equal(Thread* thread, | 420 static bool Double_equal(Thread* thread, RawObject** FP, RawObject** result) { |
| 432 RawObject** FP, | |
| 433 RawObject** result) { | |
| 434 double d1, d2; | 421 double d1, d2; |
| 435 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 422 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 436 return false; | 423 return false; |
| 437 } | 424 } |
| 438 *result = d1 == d2 ? Bool::True().raw() : Bool::False().raw(); | 425 *result = d1 == d2 ? Bool::True().raw() : Bool::False().raw(); |
| 439 return true; | 426 return true; |
| 440 } | 427 } |
| 441 | 428 |
| 442 static bool Double_lessEqualThan(Thread* thread, | 429 static bool Double_lessEqualThan(Thread* thread, |
| 443 RawObject** FP, | 430 RawObject** FP, |
| 444 RawObject** result) { | 431 RawObject** result) { |
| 445 double d1, d2; | 432 double d1, d2; |
| 446 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { | 433 if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { |
| 447 return false; | 434 return false; |
| 448 } | 435 } |
| 449 *result = d1 <= d2 ? Bool::True().raw() : Bool::False().raw(); | 436 *result = d1 <= d2 ? Bool::True().raw() : Bool::False().raw(); |
| 450 return true; | 437 return true; |
| 451 } | 438 } |
| 452 | 439 |
| 453 DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) { | 440 DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) { |
| 454 ASSERT(GetClassId(FP[kPcMarkerSlotFromFp]) == kCodeCid); | 441 ASSERT(GetClassId(FP[kPcMarkerSlotFromFp]) == kCodeCid); |
| 455 return static_cast<RawCode*>(FP[kPcMarkerSlotFromFp]); | 442 return static_cast<RawCode*>(FP[kPcMarkerSlotFromFp]); |
| 456 } | 443 } |
| 457 | 444 |
| 458 | 445 |
| 459 DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) { | 446 DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) { |
| 460 ASSERT(GetClassId(code) == kCodeCid); | 447 ASSERT(GetClassId(code) == kCodeCid); |
| 461 FP[kPcMarkerSlotFromFp] = code; | 448 FP[kPcMarkerSlotFromFp] = code; |
| 462 } | 449 } |
| 463 | 450 |
| 464 DART_FORCE_INLINE static uint8_t* GetTypedData( | 451 DART_FORCE_INLINE static uint8_t* GetTypedData(RawObject* obj, |
| 465 RawObject* obj, RawObject* index) { | 452 RawObject* index) { |
| 466 ASSERT(RawObject::IsTypedDataClassId(obj->GetClassId())); | 453 ASSERT(RawObject::IsTypedDataClassId(obj->GetClassId())); |
| 467 RawTypedData* array = reinterpret_cast<RawTypedData*>(obj); | 454 RawTypedData* array = reinterpret_cast<RawTypedData*>(obj); |
| 468 const intptr_t byte_offset = Smi::Value(RAW_CAST(Smi, index)); | 455 const intptr_t byte_offset = Smi::Value(RAW_CAST(Smi, index)); |
| 469 ASSERT(byte_offset >= 0); | 456 ASSERT(byte_offset >= 0); |
| 470 return array->ptr()->data() + byte_offset; | 457 return array->ptr()->data() + byte_offset; |
| 471 } | 458 } |
| 472 }; | 459 }; |
| 473 | 460 |
| 474 | 461 |
| 475 DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) { | 462 DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 494 } | 481 } |
| 495 | 482 |
| 496 intrinsics_[kObjectArraySetIndexedIntrinsic] = | 483 intrinsics_[kObjectArraySetIndexedIntrinsic] = |
| 497 SimulatorHelpers::ObjectArraySetIndexed; | 484 SimulatorHelpers::ObjectArraySetIndexed; |
| 498 intrinsics_[kObjectArrayGetIndexedIntrinsic] = | 485 intrinsics_[kObjectArrayGetIndexedIntrinsic] = |
| 499 SimulatorHelpers::ObjectArrayGetIndexed; | 486 SimulatorHelpers::ObjectArrayGetIndexed; |
| 500 intrinsics_[kGrowableArraySetIndexedIntrinsic] = | 487 intrinsics_[kGrowableArraySetIndexedIntrinsic] = |
| 501 SimulatorHelpers::GrowableArraySetIndexed; | 488 SimulatorHelpers::GrowableArraySetIndexed; |
| 502 intrinsics_[kGrowableArrayGetIndexedIntrinsic] = | 489 intrinsics_[kGrowableArrayGetIndexedIntrinsic] = |
| 503 SimulatorHelpers::GrowableArrayGetIndexed; | 490 SimulatorHelpers::GrowableArrayGetIndexed; |
| 504 intrinsics_[kObjectEqualsIntrinsic] = | 491 intrinsics_[kObjectEqualsIntrinsic] = SimulatorHelpers::ObjectEquals; |
| 505 SimulatorHelpers::ObjectEquals; | |
| 506 intrinsics_[kObjectRuntimeTypeIntrinsic] = | 492 intrinsics_[kObjectRuntimeTypeIntrinsic] = |
| 507 SimulatorHelpers::ObjectRuntimeType; | 493 SimulatorHelpers::ObjectRuntimeType; |
| 508 | 494 |
| 509 intrinsics_[kDouble_getIsNaNIntrinsic] = | 495 intrinsics_[kDouble_getIsNaNIntrinsic] = SimulatorHelpers::Double_getIsNan; |
| 510 SimulatorHelpers::Double_getIsNan; | |
| 511 intrinsics_[kDouble_getIsInfiniteIntrinsic] = | 496 intrinsics_[kDouble_getIsInfiniteIntrinsic] = |
| 512 SimulatorHelpers::Double_getIsInfinite; | 497 SimulatorHelpers::Double_getIsInfinite; |
| 513 intrinsics_[kDouble_addIntrinsic] = | 498 intrinsics_[kDouble_addIntrinsic] = SimulatorHelpers::Double_add; |
| 514 SimulatorHelpers::Double_add; | 499 intrinsics_[kDouble_mulIntrinsic] = SimulatorHelpers::Double_mul; |
| 515 intrinsics_[kDouble_mulIntrinsic] = | 500 intrinsics_[kDouble_subIntrinsic] = SimulatorHelpers::Double_sub; |
| 516 SimulatorHelpers::Double_mul; | 501 intrinsics_[kDouble_divIntrinsic] = SimulatorHelpers::Double_div; |
| 517 intrinsics_[kDouble_subIntrinsic] = | |
| 518 SimulatorHelpers::Double_sub; | |
| 519 intrinsics_[kDouble_divIntrinsic] = | |
| 520 SimulatorHelpers::Double_div; | |
| 521 intrinsics_[kDouble_greaterThanIntrinsic] = | 502 intrinsics_[kDouble_greaterThanIntrinsic] = |
| 522 SimulatorHelpers::Double_greaterThan; | 503 SimulatorHelpers::Double_greaterThan; |
| 523 intrinsics_[kDouble_greaterEqualThanIntrinsic] = | 504 intrinsics_[kDouble_greaterEqualThanIntrinsic] = |
| 524 SimulatorHelpers::Double_greaterEqualThan; | 505 SimulatorHelpers::Double_greaterEqualThan; |
| 525 intrinsics_[kDouble_lessThanIntrinsic] = | 506 intrinsics_[kDouble_lessThanIntrinsic] = SimulatorHelpers::Double_lessThan; |
| 526 SimulatorHelpers::Double_lessThan; | 507 intrinsics_[kDouble_equalIntrinsic] = SimulatorHelpers::Double_equal; |
| 527 intrinsics_[kDouble_equalIntrinsic] = | |
| 528 SimulatorHelpers::Double_equal; | |
| 529 intrinsics_[kDouble_lessEqualThanIntrinsic] = | 508 intrinsics_[kDouble_lessEqualThanIntrinsic] = |
| 530 SimulatorHelpers::Double_lessEqualThan; | 509 SimulatorHelpers::Double_lessEqualThan; |
| 531 } | 510 } |
| 532 | 511 |
| 533 | 512 |
| 534 Simulator::Simulator() | 513 Simulator::Simulator() : stack_(NULL), fp_(NULL), sp_(NULL) { |
| 535 : stack_(NULL), | |
| 536 fp_(NULL), | |
| 537 sp_(NULL) { | |
| 538 // Setup simulator support first. Some of this information is needed to | 514 // Setup simulator support first. Some of this information is needed to |
| 539 // setup the architecture state. | 515 // setup the architecture state. |
| 540 // We allocate the stack here, the size is computed as the sum of | 516 // We allocate the stack here, the size is computed as the sum of |
| 541 // the size specified by the user and the buffer space needed for | 517 // the size specified by the user and the buffer space needed for |
| 542 // handling stack overflow exceptions. To be safe in potential | 518 // handling stack overflow exceptions. To be safe in potential |
| 543 // stack underflows we also add some underflow buffer space. | 519 // stack underflows we also add some underflow buffer space. |
| 544 stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() + | 520 stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() + |
| 545 OSThread::kStackSizeBuffer + | 521 OSThread::kStackSizeBuffer + |
| 546 kSimulatorStackUnderflowSize) / | 522 kSimulatorStackUnderflowSize) / |
| 547 sizeof(uintptr_t)]; | 523 sizeof(uintptr_t)]; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 return (res != 0); | 695 return (res != 0); |
| 720 } | 696 } |
| 721 | 697 |
| 722 | 698 |
| 723 DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { | 699 DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { |
| 724 return ((a | b) & kHeapObjectTag) == 0; | 700 return ((a | b) & kHeapObjectTag) == 0; |
| 725 } | 701 } |
| 726 | 702 |
| 727 | 703 |
| 728 #define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres) | 704 #define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres) |
| 729 #define SMI_COND(cond, lhs, rhs, pres) \ | 705 #define SMI_COND(cond, lhs, rhs, pres) \ |
| 730 ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false) | 706 ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false) |
| 731 #define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres) | 707 #define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres) |
| 732 #define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres) | 708 #define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres) |
| 733 #define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) | 709 #define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) |
| 734 #define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) | 710 #define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) |
| 735 #define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false) | 711 #define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false) |
| 736 #define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false) | 712 #define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false) |
| 737 | 713 |
| 738 | 714 |
| 739 void Simulator::CallRuntime(Thread* thread, | 715 void Simulator::CallRuntime(Thread* thread, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 handler = DRT_InlineCacheMissHandlerThreeArgs; | 794 handler = DRT_InlineCacheMissHandlerThreeArgs; |
| 819 break; | 795 break; |
| 820 default: | 796 default: |
| 821 UNREACHABLE(); | 797 UNREACHABLE(); |
| 822 break; | 798 break; |
| 823 } | 799 } |
| 824 | 800 |
| 825 // Handler arguments: arguments to check and an ICData object. | 801 // Handler arguments: arguments to check and an ICData object. |
| 826 const intptr_t miss_handler_argc = checked_args + 1; | 802 const intptr_t miss_handler_argc = checked_args + 1; |
| 827 RawObject** exit_frame = miss_handler_args + miss_handler_argc; | 803 RawObject** exit_frame = miss_handler_args + miss_handler_argc; |
| 828 CallRuntime(thread, | 804 CallRuntime(thread, FP, exit_frame, pc, miss_handler_argc, miss_handler_args, |
| 829 FP, | 805 result, reinterpret_cast<uword>(handler)); |
| 830 exit_frame, | |
| 831 pc, | |
| 832 miss_handler_argc, | |
| 833 miss_handler_args, | |
| 834 result, | |
| 835 reinterpret_cast<uword>(handler)); | |
| 836 } | 806 } |
| 837 | 807 |
| 838 | 808 |
| 839 DART_FORCE_INLINE void Simulator::InstanceCall1(Thread* thread, | 809 DART_FORCE_INLINE void Simulator::InstanceCall1(Thread* thread, |
| 840 RawICData* icdata, | 810 RawICData* icdata, |
| 841 RawObject** call_base, | 811 RawObject** call_base, |
| 842 RawObject** top, | 812 RawObject** top, |
| 843 RawArray** argdesc, | 813 RawArray** argdesc, |
| 844 RawObjectPool** pp, | 814 RawObjectPool** pp, |
| 845 uint32_t** pc, | 815 uint32_t** pc, |
| 846 RawObject*** FP, | 816 RawObject*** FP, |
| 847 RawObject*** SP, | 817 RawObject*** SP, |
| 848 bool optimized) { | 818 bool optimized) { |
| 849 ASSERT(icdata->GetClassId() == kICDataCid); | 819 ASSERT(icdata->GetClassId() == kICDataCid); |
| 850 | 820 |
| 851 const intptr_t kCheckedArgs = 1; | 821 const intptr_t kCheckedArgs = 1; |
| 852 RawObject** args = call_base; | 822 RawObject** args = call_base; |
| 853 RawArray* cache = icdata->ptr()->ic_data_->ptr(); | 823 RawArray* cache = icdata->ptr()->ic_data_->ptr(); |
| 854 | 824 |
| 855 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); | 825 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); |
| 856 | 826 |
| 857 bool found = false; | 827 bool found = false; |
| 858 const intptr_t length = Smi::Value(cache->length_); | 828 const intptr_t length = Smi::Value(cache->length_); |
| 859 intptr_t i; | 829 intptr_t i; |
| 860 for (i = 0; | 830 for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { |
| 861 i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { | |
| 862 if (cache->data()[i + 0] == receiver_cid) { | 831 if (cache->data()[i + 0] == receiver_cid) { |
| 863 top[0] = cache->data()[i + kCheckedArgs]; | 832 top[0] = cache->data()[i + kCheckedArgs]; |
| 864 found = true; | 833 found = true; |
| 865 break; | 834 break; |
| 866 } | 835 } |
| 867 } | 836 } |
| 868 | 837 |
| 869 if (found) { | 838 if (found) { |
| 870 if (!optimized) { | 839 if (!optimized) { |
| 871 SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); | 840 SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); |
| 872 } | 841 } |
| 873 } else { | 842 } else { |
| 874 InlineCacheMiss( | 843 InlineCacheMiss(kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, |
| 875 kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP); | 844 *SP); |
| 876 } | 845 } |
| 877 | 846 |
| 878 *argdesc = icdata->ptr()->args_descriptor_; | 847 *argdesc = icdata->ptr()->args_descriptor_; |
| 879 Invoke(thread, call_base, top, pp, pc, FP, SP); | 848 Invoke(thread, call_base, top, pp, pc, FP, SP); |
| 880 } | 849 } |
| 881 | 850 |
| 882 | 851 |
| 883 DART_FORCE_INLINE void Simulator::InstanceCall2(Thread* thread, | 852 DART_FORCE_INLINE void Simulator::InstanceCall2(Thread* thread, |
| 884 RawICData* icdata, | 853 RawICData* icdata, |
| 885 RawObject** call_base, | 854 RawObject** call_base, |
| 886 RawObject** top, | 855 RawObject** top, |
| 887 RawArray** argdesc, | 856 RawArray** argdesc, |
| 888 RawObjectPool** pp, | 857 RawObjectPool** pp, |
| 889 uint32_t** pc, | 858 uint32_t** pc, |
| 890 RawObject*** FP, | 859 RawObject*** FP, |
| 891 RawObject*** SP, | 860 RawObject*** SP, |
| 892 bool optimized) { | 861 bool optimized) { |
| 893 ASSERT(icdata->GetClassId() == kICDataCid); | 862 ASSERT(icdata->GetClassId() == kICDataCid); |
| 894 | 863 |
| 895 const intptr_t kCheckedArgs = 2; | 864 const intptr_t kCheckedArgs = 2; |
| 896 RawObject** args = call_base; | 865 RawObject** args = call_base; |
| 897 RawArray* cache = icdata->ptr()->ic_data_->ptr(); | 866 RawArray* cache = icdata->ptr()->ic_data_->ptr(); |
| 898 | 867 |
| 899 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); | 868 RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[0]); |
| 900 RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]); | 869 RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[1]); |
| 901 | 870 |
| 902 bool found = false; | 871 bool found = false; |
| 903 const intptr_t length = Smi::Value(cache->length_); | 872 const intptr_t length = Smi::Value(cache->length_); |
| 904 intptr_t i; | 873 intptr_t i; |
| 905 for (i = 0; | 874 for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { |
| 906 i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { | |
| 907 if ((cache->data()[i + 0] == receiver_cid) && | 875 if ((cache->data()[i + 0] == receiver_cid) && |
| 908 (cache->data()[i + 1] == arg0_cid)) { | 876 (cache->data()[i + 1] == arg0_cid)) { |
| 909 top[0] = cache->data()[i + kCheckedArgs]; | 877 top[0] = cache->data()[i + kCheckedArgs]; |
| 910 found = true; | 878 found = true; |
| 911 break; | 879 break; |
| 912 } | 880 } |
| 913 } | 881 } |
| 914 | 882 |
| 915 if (found) { | 883 if (found) { |
| 916 if (!optimized) { | 884 if (!optimized) { |
| 917 SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); | 885 SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); |
| 918 } | 886 } |
| 919 } else { | 887 } else { |
| 920 InlineCacheMiss( | 888 InlineCacheMiss(kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, |
| 921 kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP); | 889 *SP); |
| 922 } | 890 } |
| 923 | 891 |
| 924 *argdesc = icdata->ptr()->args_descriptor_; | 892 *argdesc = icdata->ptr()->args_descriptor_; |
| 925 Invoke(thread, call_base, top, pp, pc, FP, SP); | 893 Invoke(thread, call_base, top, pp, pc, FP, SP); |
| 926 } | 894 } |
| 927 | 895 |
| 928 | 896 |
| 929 // Note: functions below are marked DART_NOINLINE to recover performance on | 897 // Note: functions below are marked DART_NOINLINE to recover performance on |
| 930 // ARM where inlining these functions into the interpreter loop seemed to cause | 898 // ARM where inlining these functions into the interpreter loop seemed to cause |
| 931 // some code quality issues. | 899 // some code quality issues. |
| 932 static DART_NOINLINE bool InvokeRuntime( | 900 static DART_NOINLINE bool InvokeRuntime(Thread* thread, |
| 933 Thread* thread, | 901 Simulator* sim, |
| 934 Simulator* sim, | 902 RuntimeFunction drt, |
| 935 RuntimeFunction drt, | 903 const NativeArguments& args) { |
| 936 const NativeArguments& args) { | |
| 937 SimulatorSetjmpBuffer buffer(sim); | 904 SimulatorSetjmpBuffer buffer(sim); |
| 938 if (!setjmp(buffer.buffer_)) { | 905 if (!setjmp(buffer.buffer_)) { |
| 939 thread->set_vm_tag(reinterpret_cast<uword>(drt)); | 906 thread->set_vm_tag(reinterpret_cast<uword>(drt)); |
| 940 drt(args); | 907 drt(args); |
| 941 thread->set_vm_tag(VMTag::kDartTagId); | 908 thread->set_vm_tag(VMTag::kDartTagId); |
| 942 thread->set_top_exit_frame_info(0); | 909 thread->set_top_exit_frame_info(0); |
| 943 return true; | 910 return true; |
| 944 } else { | 911 } else { |
| 945 return false; | 912 return false; |
| 946 } | 913 } |
| 947 } | 914 } |
| 948 | 915 |
| 949 | 916 |
| 950 static DART_NOINLINE bool InvokeNative( | 917 static DART_NOINLINE bool InvokeNative(Thread* thread, |
| 951 Thread* thread, | 918 Simulator* sim, |
| 952 Simulator* sim, | 919 SimulatorBootstrapNativeCall f, |
| 953 SimulatorBootstrapNativeCall f, | 920 NativeArguments* args) { |
| 954 NativeArguments* args) { | |
| 955 SimulatorSetjmpBuffer buffer(sim); | 921 SimulatorSetjmpBuffer buffer(sim); |
| 956 if (!setjmp(buffer.buffer_)) { | 922 if (!setjmp(buffer.buffer_)) { |
| 957 thread->set_vm_tag(reinterpret_cast<uword>(f)); | 923 thread->set_vm_tag(reinterpret_cast<uword>(f)); |
| 958 f(args); | 924 f(args); |
| 959 thread->set_vm_tag(VMTag::kDartTagId); | 925 thread->set_vm_tag(VMTag::kDartTagId); |
| 960 thread->set_top_exit_frame_info(0); | 926 thread->set_top_exit_frame_info(0); |
| 961 return true; | 927 return true; |
| 962 } else { | 928 } else { |
| 963 return false; | 929 return false; |
| 964 } | 930 } |
| 965 } | 931 } |
| 966 | 932 |
| 967 | 933 |
| 968 static DART_NOINLINE bool InvokeNativeWrapper( | 934 static DART_NOINLINE bool InvokeNativeWrapper(Thread* thread, |
| 969 Thread* thread, | 935 Simulator* sim, |
| 970 Simulator* sim, | 936 Dart_NativeFunction f, |
| 971 Dart_NativeFunction f, | 937 NativeArguments* args) { |
| 972 NativeArguments* args) { | |
| 973 SimulatorSetjmpBuffer buffer(sim); | 938 SimulatorSetjmpBuffer buffer(sim); |
| 974 if (!setjmp(buffer.buffer_)) { | 939 if (!setjmp(buffer.buffer_)) { |
| 975 thread->set_vm_tag(reinterpret_cast<uword>(f)); | 940 thread->set_vm_tag(reinterpret_cast<uword>(f)); |
| 976 NativeEntry::NativeCallWrapper(reinterpret_cast<Dart_NativeArguments>(args), | 941 NativeEntry::NativeCallWrapper(reinterpret_cast<Dart_NativeArguments>(args), |
| 977 f); | 942 f); |
| 978 thread->set_vm_tag(VMTag::kDartTagId); | 943 thread->set_vm_tag(VMTag::kDartTagId); |
| 979 thread->set_top_exit_frame_info(0); | 944 thread->set_top_exit_frame_info(0); |
| 980 return true; | 945 return true; |
| 981 } else { | 946 } else { |
| 982 return false; | 947 return false; |
| 983 } | 948 } |
| 984 } | 949 } |
| 985 | 950 |
| 986 // Note: all macro helpers are intended to be used only inside Simulator::Call. | 951 // Note: all macro helpers are intended to be used only inside Simulator::Call. |
| 987 | 952 |
| 988 // Decode opcode and A part of the given value and dispatch to the | 953 // Decode opcode and A part of the given value and dispatch to the |
| 989 // corresponding bytecode handler. | 954 // corresponding bytecode handler. |
| 990 #define DISPATCH_OP(val) \ | 955 #define DISPATCH_OP(val) \ |
| 991 do { \ | 956 do { \ |
| 992 op = (val); \ | 957 op = (val); \ |
| 993 rA = ((op >> 8) & 0xFF); \ | 958 rA = ((op >> 8) & 0xFF); \ |
| 994 goto* dispatch[op & 0xFF]; \ | 959 goto* dispatch[op & 0xFF]; \ |
| 995 } while (0) | 960 } while (0) |
| 996 | 961 |
| 997 // Fetch next operation from PC, increment program counter and dispatch. | 962 // Fetch next operation from PC, increment program counter and dispatch. |
| 998 #define DISPATCH() DISPATCH_OP(*pc++) | 963 #define DISPATCH() DISPATCH_OP(*pc++) |
| 999 | 964 |
| 1000 // Define entry point that handles bytecode Name with the given operand format. | 965 // Define entry point that handles bytecode Name with the given operand format. |
| 1001 #define BYTECODE(Name, Operands) \ | 966 #define BYTECODE(Name, Operands) \ |
| 1002 BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands) | 967 BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands) |
| 1003 | 968 |
| 1004 #define BYTECODE_HEADER(Name, Declare, Decode) \ | 969 #define BYTECODE_HEADER(Name, Declare, Decode) \ |
| 1005 Declare; \ | 970 Declare; \ |
| 1006 bc##Name : Decode \ | 971 bc##Name : Decode |
| 1007 | 972 |
| 1008 // Helpers to decode common instruction formats. Used in conjunction with | 973 // Helpers to decode common instruction formats. Used in conjunction with |
| 1009 // BYTECODE() macro. | 974 // BYTECODE() macro. |
| 1010 #define DECLARE_A_B_C uint16_t rB, rC; USE(rB); USE(rC) | 975 #define DECLARE_A_B_C \ |
| 1011 #define DECODE_A_B_C \ | 976 uint16_t rB, rC; \ |
| 1012 rB = ((op >> Bytecode::kBShift) & Bytecode::kBMask); \ | 977 USE(rB); \ |
| 978 USE(rC) |
| 979 #define DECODE_A_B_C \ |
| 980 rB = ((op >> Bytecode::kBShift) & Bytecode::kBMask); \ |
| 1013 rC = ((op >> Bytecode::kCShift) & Bytecode::kCMask); | 981 rC = ((op >> Bytecode::kCShift) & Bytecode::kCMask); |
| 1014 | 982 |
| 1015 #define DECLARE_0 | 983 #define DECLARE_0 |
| 1016 #define DECODE_0 | 984 #define DECODE_0 |
| 1017 | 985 |
| 1018 #define DECLARE_A | 986 #define DECLARE_A |
| 1019 #define DECODE_A | 987 #define DECODE_A |
| 1020 | 988 |
| 1021 #define DECLARE___D uint32_t rD; USE(rD) | 989 #define DECLARE___D \ |
| 990 uint32_t rD; \ |
| 991 USE(rD) |
| 1022 #define DECODE___D rD = (op >> Bytecode::kDShift); | 992 #define DECODE___D rD = (op >> Bytecode::kDShift); |
| 1023 | 993 |
| 1024 #define DECLARE_A_D DECLARE___D | 994 #define DECLARE_A_D DECLARE___D |
| 1025 #define DECODE_A_D DECODE___D | 995 #define DECODE_A_D DECODE___D |
| 1026 | 996 |
| 1027 #define DECLARE_A_X int32_t rD; USE(rD) | 997 #define DECLARE_A_X \ |
| 998 int32_t rD; \ |
| 999 USE(rD) |
| 1028 #define DECODE_A_X rD = (static_cast<int32_t>(op) >> Bytecode::kDShift); | 1000 #define DECODE_A_X rD = (static_cast<int32_t>(op) >> Bytecode::kDShift); |
| 1029 | 1001 |
| 1030 | 1002 |
| 1031 #define SMI_FASTPATH_ICDATA_INC \ | 1003 #define SMI_FASTPATH_ICDATA_INC \ |
| 1032 do { \ | 1004 do { \ |
| 1033 ASSERT(Bytecode::IsCallOpcode(*pc)); \ | 1005 ASSERT(Bytecode::IsCallOpcode(*pc)); \ |
| 1034 const uint16_t kidx = Bytecode::DecodeD(*pc); \ | 1006 const uint16_t kidx = Bytecode::DecodeD(*pc); \ |
| 1035 const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); \ | 1007 const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); \ |
| 1036 RawObject** entries = icdata->ptr()->ic_data_->ptr()->data(); \ | 1008 RawObject** entries = icdata->ptr()->ic_data_->ptr()->data(); \ |
| 1037 SimulatorHelpers::IncrementICUsageCount(entries, 0, 2); \ | 1009 SimulatorHelpers::IncrementICUsageCount(entries, 0, 2); \ |
| 1038 } while (0); \ | 1010 } while (0); |
| 1039 | 1011 |
| 1040 // Declare bytecode handler for a smi operation (e.g. AddTOS) with the | 1012 // Declare bytecode handler for a smi operation (e.g. AddTOS) with the |
| 1041 // given result type and the given behavior specified as a function | 1013 // given result type and the given behavior specified as a function |
| 1042 // that takes left and right operands and result slot and returns | 1014 // that takes left and right operands and result slot and returns |
| 1043 // true if fast-path succeeds. | 1015 // true if fast-path succeeds. |
| 1044 #define SMI_FASTPATH_TOS(ResultT, Func) \ | 1016 #define SMI_FASTPATH_TOS(ResultT, Func) \ |
| 1045 { \ | 1017 { \ |
| 1046 const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]); \ | 1018 const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]); \ |
| 1047 const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]); \ | 1019 const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]); \ |
| 1048 ResultT* slot = reinterpret_cast<ResultT*>(SP - 1); \ | 1020 ResultT* slot = reinterpret_cast<ResultT*>(SP - 1); \ |
| 1049 if (LIKELY(!thread->isolate()->single_step()) && \ | 1021 if (LIKELY(!thread->isolate()->single_step()) && \ |
| 1050 LIKELY(AreBothSmis(lhs, rhs) && \ | 1022 LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) { \ |
| 1051 !Func(lhs, rhs, slot))) { \ | |
| 1052 SMI_FASTPATH_ICDATA_INC; \ | 1023 SMI_FASTPATH_ICDATA_INC; \ |
| 1053 /* Fast path succeeded. Skip the generic call that follows. */ \ | 1024 /* Fast path succeeded. Skip the generic call that follows. */ \ |
| 1054 pc++; \ | 1025 pc++; \ |
| 1055 /* We dropped 2 arguments and push result */ \ | 1026 /* We dropped 2 arguments and push result */ \ |
| 1056 SP--; \ | 1027 SP--; \ |
| 1057 } \ | 1028 } \ |
| 1058 } | 1029 } |
| 1059 | 1030 |
| 1060 // Skip the next instruction if there is no overflow. | 1031 // Skip the next instruction if there is no overflow. |
| 1061 #define SMI_OP_CHECK(ResultT, Func) \ | 1032 #define SMI_OP_CHECK(ResultT, Func) \ |
| 1062 { \ | 1033 { \ |
| 1063 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ | 1034 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ |
| 1064 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ | 1035 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ |
| 1065 ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ | 1036 ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ |
| 1066 if (LIKELY(!Func(lhs, rhs, slot))) { \ | 1037 if (LIKELY(!Func(lhs, rhs, slot))) { \ |
| 1067 /* Success. Skip the instruction that follows. */ \ | 1038 /* Success. Skip the instruction that follows. */ \ |
| 1068 pc++; \ | 1039 pc++; \ |
| 1069 } \ | 1040 } \ |
| 1070 } | 1041 } |
| 1071 | 1042 |
| 1072 // Do not check for overflow. | 1043 // Do not check for overflow. |
| 1073 #define SMI_OP_NOCHECK(ResultT, Func) \ | 1044 #define SMI_OP_NOCHECK(ResultT, Func) \ |
| 1074 { \ | 1045 { \ |
| 1075 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ | 1046 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ |
| 1076 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ | 1047 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ |
| 1077 ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ | 1048 ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ |
| 1078 Func(lhs, rhs, slot); \ | 1049 Func(lhs, rhs, slot); \ |
| 1079 } \ | 1050 } |
| 1080 | 1051 |
| 1081 | 1052 |
| 1082 // Exception handling helper. Gets handler FP and PC from the Simulator where | 1053 // Exception handling helper. Gets handler FP and PC from the Simulator where |
| 1083 // they were stored by Simulator::Longjmp and proceeds to execute the handler. | 1054 // they were stored by Simulator::Longjmp and proceeds to execute the handler. |
| 1084 // Corner case: handler PC can be a fake marker that marks entry frame, which | 1055 // Corner case: handler PC can be a fake marker that marks entry frame, which |
| 1085 // means exception was not handled in the Dart code. In this case we return | 1056 // means exception was not handled in the Dart code. In this case we return |
| 1086 // caught exception from Simulator::Call. | 1057 // caught exception from Simulator::Call. |
| 1087 #define HANDLE_EXCEPTION \ | 1058 #define HANDLE_EXCEPTION \ |
| 1088 do { \ | 1059 do { \ |
| 1089 FP = reinterpret_cast<RawObject**>(fp_); \ | 1060 FP = reinterpret_cast<RawObject**>(fp_); \ |
| 1090 pc = reinterpret_cast<uint32_t*>(pc_); \ | 1061 pc = reinterpret_cast<uint32_t*>(pc_); \ |
| 1091 if ((reinterpret_cast<uword>(pc) & 2) != 0) { /* Entry frame? */ \ | 1062 if ((reinterpret_cast<uword>(pc) & 2) != 0) { /* Entry frame? */ \ |
| 1092 fp_ = sp_ = reinterpret_cast<RawObject**>(fp_[0]); \ | 1063 fp_ = sp_ = reinterpret_cast<RawObject**>(fp_[0]); \ |
| 1093 thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_)); \ | 1064 thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_)); \ |
| 1094 thread->set_top_resource(top_resource); \ | 1065 thread->set_top_resource(top_resource); \ |
| 1095 thread->set_vm_tag(vm_tag); \ | 1066 thread->set_vm_tag(vm_tag); \ |
| 1096 return special_[kExceptionSpecialIndex]; \ | 1067 return special_[kExceptionSpecialIndex]; \ |
| 1097 } \ | 1068 } \ |
| 1098 pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); \ | 1069 pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); \ |
| 1099 goto DispatchAfterException; \ | 1070 goto DispatchAfterException; \ |
| 1100 } while (0) \ | 1071 } while (0) |
| 1101 | 1072 |
| 1102 // Runtime call helpers: handle invocation and potential exception after return. | 1073 // Runtime call helpers: handle invocation and potential exception after return. |
| 1103 #define INVOKE_RUNTIME(Func, Args) \ | 1074 #define INVOKE_RUNTIME(Func, Args) \ |
| 1104 if (!InvokeRuntime(thread, this, Func, Args)) { \ | 1075 if (!InvokeRuntime(thread, this, Func, Args)) { \ |
| 1105 HANDLE_EXCEPTION; \ | 1076 HANDLE_EXCEPTION; \ |
| 1106 } \ | 1077 } |
| 1107 | 1078 |
| 1108 #define INVOKE_NATIVE(Func, Args) \ | 1079 #define INVOKE_NATIVE(Func, Args) \ |
| 1109 if (!InvokeNative(thread, this, Func, &Args)) { \ | 1080 if (!InvokeNative(thread, this, Func, &Args)) { \ |
| 1110 HANDLE_EXCEPTION; \ | 1081 HANDLE_EXCEPTION; \ |
| 1111 } \ | 1082 } |
| 1112 | 1083 |
| 1113 #define INVOKE_NATIVE_WRAPPER(Func, Args) \ | 1084 #define INVOKE_NATIVE_WRAPPER(Func, Args) \ |
| 1114 if (!InvokeNativeWrapper(thread, this, Func, &Args)) { \ | 1085 if (!InvokeNativeWrapper(thread, this, Func, &Args)) { \ |
| 1115 HANDLE_EXCEPTION; \ | 1086 HANDLE_EXCEPTION; \ |
| 1116 } \ | 1087 } |
| 1117 | 1088 |
| 1118 #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_) | 1089 #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_) |
| 1119 | 1090 |
| 1120 RawObject* Simulator::Call(const Code& code, | 1091 RawObject* Simulator::Call(const Code& code, |
| 1121 const Array& arguments_descriptor, | 1092 const Array& arguments_descriptor, |
| 1122 const Array& arguments, | 1093 const Array& arguments, |
| 1123 Thread* thread) { | 1094 Thread* thread) { |
| 1124 // Dispatch used to interpret bytecode. Contains addresses of | 1095 // Dispatch used to interpret bytecode. Contains addresses of |
| 1125 // labels of bytecode handlers. Handlers themselves are defined below. | 1096 // labels of bytecode handlers. Handlers themselves are defined below. |
| 1126 static const void* dispatch[] = { | 1097 static const void* dispatch[] = { |
| 1127 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, | 1098 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, |
| 1128 BYTECODES_LIST(TARGET) | 1099 BYTECODES_LIST(TARGET) |
| 1129 #undef TARGET | 1100 #undef TARGET |
| 1130 }; | 1101 }; |
| 1131 | 1102 |
| 1132 // Interpreter state (see constants_dbc.h for high-level overview). | 1103 // Interpreter state (see constants_dbc.h for high-level overview). |
| 1133 uint32_t* pc; // Program Counter: points to the next op to execute. | 1104 uint32_t* pc; // Program Counter: points to the next op to execute. |
| 1134 RawObjectPool* pp; // Pool Pointer. | 1105 RawObjectPool* pp; // Pool Pointer. |
| 1135 RawObject** FP; // Frame Pointer. | 1106 RawObject** FP; // Frame Pointer. |
| 1136 RawObject** SP; // Stack Pointer. | 1107 RawObject** SP; // Stack Pointer. |
| 1137 | 1108 |
| 1138 RawArray* argdesc; // Arguments Descriptor: used to pass information between | 1109 RawArray* argdesc; // Arguments Descriptor: used to pass information between |
| 1139 // call instruction and the function entry. | 1110 // call instruction and the function entry. |
| 1140 | 1111 |
| 1141 uint32_t op; // Currently executing op. | 1112 uint32_t op; // Currently executing op. |
| 1142 uint16_t rA; // A component of the currently executing op. | 1113 uint16_t rA; // A component of the currently executing op. |
| 1143 | 1114 |
| 1144 if (sp_ == NULL) { | 1115 if (sp_ == NULL) { |
| 1145 fp_ = sp_ = reinterpret_cast<RawObject**>(stack_); | 1116 fp_ = sp_ = reinterpret_cast<RawObject**>(stack_); |
| 1146 } | 1117 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 memmove(FP, first_arg, pos_count * kWordSize); | 1265 memmove(FP, first_arg, pos_count * kWordSize); |
| 1295 | 1266 |
| 1296 if (num_opt_named_params != 0) { | 1267 if (num_opt_named_params != 0) { |
| 1297 // This is a function with named parameters. | 1268 // This is a function with named parameters. |
| 1298 // Walk the list of named parameters and their | 1269 // Walk the list of named parameters and their |
| 1299 // default values encoded as pairs of LoadConstant instructions that | 1270 // default values encoded as pairs of LoadConstant instructions that |
| 1300 // follows the entry point and find matching values via arguments | 1271 // follows the entry point and find matching values via arguments |
| 1301 // descriptor. | 1272 // descriptor. |
| 1302 RawObject** argdesc_data = argdesc->ptr()->data(); | 1273 RawObject** argdesc_data = argdesc->ptr()->data(); |
| 1303 | 1274 |
| 1304 intptr_t i = named_count - 1; // argument position | 1275 intptr_t i = named_count - 1; // argument position |
| 1305 intptr_t j = num_opt_named_params - 1; // parameter position | 1276 intptr_t j = num_opt_named_params - 1; // parameter position |
| 1306 while ((j >= 0) && (i >= 0)) { | 1277 while ((j >= 0) && (i >= 0)) { |
| 1307 // Fetch formal parameter information: name, default value, target slot. | 1278 // Fetch formal parameter information: name, default value, target slot. |
| 1308 const uint32_t load_name = pc[2 * j]; | 1279 const uint32_t load_name = pc[2 * j]; |
| 1309 const uint32_t load_value = pc[2 * j + 1]; | 1280 const uint32_t load_value = pc[2 * j + 1]; |
| 1310 ASSERT(Bytecode::DecodeOpcode(load_name) == Bytecode::kLoadConstant); | 1281 ASSERT(Bytecode::DecodeOpcode(load_name) == Bytecode::kLoadConstant); |
| 1311 ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant); | 1282 ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant); |
| 1312 const uint8_t reg = Bytecode::DecodeA(load_name); | 1283 const uint8_t reg = Bytecode::DecodeA(load_name); |
| 1313 ASSERT(reg == Bytecode::DecodeA(load_value)); | 1284 ASSERT(reg == Bytecode::DecodeA(load_value)); |
| 1314 | 1285 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 if (named_count != 0) { | 1329 if (named_count != 0) { |
| 1359 // Function can't have both named and optional positional parameters. | 1330 // Function can't have both named and optional positional parameters. |
| 1360 // This kind of mismatch can only occur if the current function | 1331 // This kind of mismatch can only occur if the current function |
| 1361 // is a closure. | 1332 // is a closure. |
| 1362 goto ClosureNoSuchMethod; | 1333 goto ClosureNoSuchMethod; |
| 1363 } | 1334 } |
| 1364 | 1335 |
| 1365 // Process the list of default values encoded as a sequence of | 1336 // Process the list of default values encoded as a sequence of |
| 1366 // LoadConstant instructions after EntryOpt bytecode. | 1337 // LoadConstant instructions after EntryOpt bytecode. |
| 1367 // Execute only those that correspond to parameters the were not passed. | 1338 // Execute only those that correspond to parameters the were not passed. |
| 1368 for (intptr_t i = pos_count - num_fixed_params; | 1339 for (intptr_t i = pos_count - num_fixed_params; i < num_opt_pos_params; |
| 1369 i < num_opt_pos_params; | |
| 1370 i++) { | 1340 i++) { |
| 1371 const uint32_t load_value = pc[i]; | 1341 const uint32_t load_value = pc[i]; |
| 1372 ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant); | 1342 ASSERT(Bytecode::DecodeOpcode(load_value) == Bytecode::kLoadConstant); |
| 1373 #if defined(DEBUG) | 1343 #if defined(DEBUG) |
| 1374 const uint8_t reg = Bytecode::DecodeA(load_value); | 1344 const uint8_t reg = Bytecode::DecodeA(load_value); |
| 1375 ASSERT((num_fixed_params + i) == reg); | 1345 ASSERT((num_fixed_params + i) == reg); |
| 1376 #endif | 1346 #endif |
| 1377 FP[num_fixed_params + i] = LOAD_CONSTANT(Bytecode::DecodeD(load_value)); | 1347 FP[num_fixed_params + i] = LOAD_CONSTANT(Bytecode::DecodeD(load_value)); |
| 1378 } | 1348 } |
| 1379 | 1349 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_); | 1391 pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_); |
| 1422 pc_ = reinterpret_cast<uword>(pc); // For the profiler. | 1392 pc_ = reinterpret_cast<uword>(pc); // For the profiler. |
| 1423 } | 1393 } |
| 1424 DISPATCH(); | 1394 DISPATCH(); |
| 1425 } | 1395 } |
| 1426 | 1396 |
| 1427 { | 1397 { |
| 1428 BYTECODE(HotCheck, A_D); | 1398 BYTECODE(HotCheck, A_D); |
| 1429 const uint8_t increment = rA; | 1399 const uint8_t increment = rA; |
| 1430 const uint16_t threshold = rD; | 1400 const uint16_t threshold = rD; |
| 1431 RawFunction* f = FrameFunction(FP); | 1401 RawFunction* f = FrameFunction(FP); |
| 1432 int32_t counter = f->ptr()->usage_counter_; | 1402 int32_t counter = f->ptr()->usage_counter_; |
| 1433 // Note: we don't increment usage counter in the prologue of optimized | 1403 // Note: we don't increment usage counter in the prologue of optimized |
| 1434 // functions. | 1404 // functions. |
| 1435 if (increment) { | 1405 if (increment) { |
| 1436 counter += increment; | 1406 counter += increment; |
| 1437 f->ptr()->usage_counter_ = counter; | 1407 f->ptr()->usage_counter_ = counter; |
| 1438 } | 1408 } |
| 1439 if (UNLIKELY(counter >= threshold)) { | 1409 if (UNLIKELY(counter >= threshold)) { |
| 1440 FP[0] = f; | 1410 FP[0] = f; |
| 1441 FP[1] = 0; | 1411 FP[1] = 0; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1666 } | 1636 } |
| 1667 | 1637 |
| 1668 // Invoke target function. | 1638 // Invoke target function. |
| 1669 { | 1639 { |
| 1670 const uint16_t argc = rA; | 1640 const uint16_t argc = rA; |
| 1671 // Lookup the funciton in the ICData. | 1641 // Lookup the funciton in the ICData. |
| 1672 RawObject* ic_data_obj = SP[0]; | 1642 RawObject* ic_data_obj = SP[0]; |
| 1673 RawICData* ic_data = RAW_CAST(ICData, ic_data_obj); | 1643 RawICData* ic_data = RAW_CAST(ICData, ic_data_obj); |
| 1674 RawObject** data = ic_data->ptr()->ic_data_->ptr()->data(); | 1644 RawObject** data = ic_data->ptr()->ic_data_->ptr()->data(); |
| 1675 SimulatorHelpers::IncrementICUsageCount(data, 0, 0); | 1645 SimulatorHelpers::IncrementICUsageCount(data, 0, 0); |
| 1676 SP[0] = data[ICData::TargetIndexFor( | 1646 SP[0] = data[ICData::TargetIndexFor(ic_data->ptr()->state_bits_ & 0x3)]; |
| 1677 ic_data->ptr()->state_bits_ & 0x3)]; | |
| 1678 RawObject** call_base = SP - argc; | 1647 RawObject** call_base = SP - argc; |
| 1679 RawObject** call_top = SP; // *SP contains function | 1648 RawObject** call_top = SP; // *SP contains function |
| 1680 argdesc = static_cast<RawArray*>(LOAD_CONSTANT(rD)); | 1649 argdesc = static_cast<RawArray*>(LOAD_CONSTANT(rD)); |
| 1681 Invoke(thread, call_base, call_top, &pp, &pc, &FP, &SP); | 1650 Invoke(thread, call_base, call_top, &pp, &pc, &FP, &SP); |
| 1682 } | 1651 } |
| 1683 | 1652 |
| 1684 DISPATCH(); | 1653 DISPATCH(); |
| 1685 } | 1654 } |
| 1686 | 1655 |
| 1687 { | 1656 { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1707 { | 1676 { |
| 1708 const uint16_t argc = rA; | 1677 const uint16_t argc = rA; |
| 1709 const uint16_t kidx = rD; | 1678 const uint16_t kidx = rD; |
| 1710 | 1679 |
| 1711 RawObject** call_base = SP - argc + 1; | 1680 RawObject** call_base = SP - argc + 1; |
| 1712 RawObject** call_top = SP + 1; | 1681 RawObject** call_top = SP + 1; |
| 1713 | 1682 |
| 1714 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); | 1683 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); |
| 1715 SimulatorHelpers::IncrementUsageCounter( | 1684 SimulatorHelpers::IncrementUsageCounter( |
| 1716 RAW_CAST(Function, icdata->ptr()->owner_)); | 1685 RAW_CAST(Function, icdata->ptr()->owner_)); |
| 1717 InstanceCall1(thread, icdata, call_base, call_top, | 1686 InstanceCall1(thread, icdata, call_base, call_top, &argdesc, &pp, &pc, |
| 1718 &argdesc, &pp, &pc, &FP, &SP, | 1687 &FP, &SP, false /* optimized */); |
| 1719 false /* optimized */); | |
| 1720 } | 1688 } |
| 1721 | 1689 |
| 1722 DISPATCH(); | 1690 DISPATCH(); |
| 1723 } | 1691 } |
| 1724 | 1692 |
| 1725 { | 1693 { |
| 1726 BYTECODE(InstanceCall2, A_D); | 1694 BYTECODE(InstanceCall2, A_D); |
| 1727 if (thread->isolate()->single_step()) { | 1695 if (thread->isolate()->single_step()) { |
| 1728 Exit(thread, FP, SP + 1, pc); | 1696 Exit(thread, FP, SP + 1, pc); |
| 1729 NativeArguments args(thread, 0, NULL, NULL); | 1697 NativeArguments args(thread, 0, NULL, NULL); |
| 1730 INVOKE_RUNTIME(DRT_SingleStepHandler, args); | 1698 INVOKE_RUNTIME(DRT_SingleStepHandler, args); |
| 1731 } | 1699 } |
| 1732 | 1700 |
| 1733 { | 1701 { |
| 1734 const uint16_t argc = rA; | 1702 const uint16_t argc = rA; |
| 1735 const uint16_t kidx = rD; | 1703 const uint16_t kidx = rD; |
| 1736 | 1704 |
| 1737 RawObject** call_base = SP - argc + 1; | 1705 RawObject** call_base = SP - argc + 1; |
| 1738 RawObject** call_top = SP + 1; | 1706 RawObject** call_top = SP + 1; |
| 1739 | 1707 |
| 1740 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); | 1708 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); |
| 1741 SimulatorHelpers::IncrementUsageCounter( | 1709 SimulatorHelpers::IncrementUsageCounter( |
| 1742 RAW_CAST(Function, icdata->ptr()->owner_)); | 1710 RAW_CAST(Function, icdata->ptr()->owner_)); |
| 1743 InstanceCall2(thread, icdata, call_base, call_top, | 1711 InstanceCall2(thread, icdata, call_base, call_top, &argdesc, &pp, &pc, |
| 1744 &argdesc, &pp, &pc, &FP, &SP, | 1712 &FP, &SP, false /* optimized */); |
| 1745 false /* optimized */); | |
| 1746 } | 1713 } |
| 1747 | 1714 |
| 1748 DISPATCH(); | 1715 DISPATCH(); |
| 1749 } | 1716 } |
| 1750 | 1717 |
| 1751 { | 1718 { |
| 1752 BYTECODE(InstanceCall1Opt, A_D); | 1719 BYTECODE(InstanceCall1Opt, A_D); |
| 1753 | 1720 |
| 1754 { | 1721 { |
| 1755 const uint16_t argc = rA; | 1722 const uint16_t argc = rA; |
| 1756 const uint16_t kidx = rD; | 1723 const uint16_t kidx = rD; |
| 1757 | 1724 |
| 1758 RawObject** call_base = SP - argc + 1; | 1725 RawObject** call_base = SP - argc + 1; |
| 1759 RawObject** call_top = SP + 1; | 1726 RawObject** call_top = SP + 1; |
| 1760 | 1727 |
| 1761 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); | 1728 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); |
| 1762 SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); | 1729 SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); |
| 1763 InstanceCall1(thread, icdata, call_base, call_top, | 1730 InstanceCall1(thread, icdata, call_base, call_top, &argdesc, &pp, &pc, |
| 1764 &argdesc, &pp, &pc, &FP, &SP, | 1731 &FP, &SP, true /* optimized */); |
| 1765 true /* optimized */); | |
| 1766 } | 1732 } |
| 1767 | 1733 |
| 1768 DISPATCH(); | 1734 DISPATCH(); |
| 1769 } | 1735 } |
| 1770 | 1736 |
| 1771 { | 1737 { |
| 1772 BYTECODE(InstanceCall2Opt, A_D); | 1738 BYTECODE(InstanceCall2Opt, A_D); |
| 1773 | 1739 |
| 1774 { | 1740 { |
| 1775 const uint16_t argc = rA; | 1741 const uint16_t argc = rA; |
| 1776 const uint16_t kidx = rD; | 1742 const uint16_t kidx = rD; |
| 1777 | 1743 |
| 1778 RawObject** call_base = SP - argc + 1; | 1744 RawObject** call_base = SP - argc + 1; |
| 1779 RawObject** call_top = SP + 1; | 1745 RawObject** call_top = SP + 1; |
| 1780 | 1746 |
| 1781 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); | 1747 RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); |
| 1782 SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); | 1748 SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); |
| 1783 InstanceCall2(thread, icdata, call_base, call_top, | 1749 InstanceCall2(thread, icdata, call_base, call_top, &argdesc, &pp, &pc, |
| 1784 &argdesc, &pp, &pc, &FP, &SP, | 1750 &FP, &SP, true /* optimized */); |
| 1785 true /* optimized */); | |
| 1786 } | 1751 } |
| 1787 | 1752 |
| 1788 DISPATCH(); | 1753 DISPATCH(); |
| 1789 } | 1754 } |
| 1790 | 1755 |
| 1791 { | 1756 { |
| 1792 BYTECODE(PushPolymorphicInstanceCall, A_D); | 1757 BYTECODE(PushPolymorphicInstanceCall, A_D); |
| 1793 const uint8_t argc = rA; | 1758 const uint8_t argc = rA; |
| 1794 const intptr_t cids_length = rD; | 1759 const intptr_t cids_length = rD; |
| 1795 RawObject** args = SP - argc + 1; | 1760 RawObject** args = SP - argc + 1; |
| 1796 const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]); | 1761 const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]); |
| 1797 for (intptr_t i = 0; i < 2*cids_length; i+=2) { | 1762 for (intptr_t i = 0; i < 2 * cids_length; i += 2) { |
| 1798 const intptr_t icdata_cid = Bytecode::DecodeD(*(pc + i)); | 1763 const intptr_t icdata_cid = Bytecode::DecodeD(*(pc + i)); |
| 1799 if (receiver_cid == icdata_cid) { | 1764 if (receiver_cid == icdata_cid) { |
| 1800 RawFunction* target = | 1765 RawFunction* target = |
| 1801 RAW_CAST(Function, LOAD_CONSTANT(Bytecode::DecodeD(*(pc + i + 1)))); | 1766 RAW_CAST(Function, LOAD_CONSTANT(Bytecode::DecodeD(*(pc + i + 1)))); |
| 1802 *++SP = target; | 1767 *++SP = target; |
| 1803 pc++; | 1768 pc++; |
| 1804 break; | 1769 break; |
| 1805 } | 1770 } |
| 1806 } | 1771 } |
| 1807 pc += 2 * cids_length; | 1772 pc += 2 * cids_length; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 } | 1938 } |
| 1974 } | 1939 } |
| 1975 DISPATCH(); | 1940 DISPATCH(); |
| 1976 } | 1941 } |
| 1977 | 1942 |
| 1978 { | 1943 { |
| 1979 BYTECODE(Mod, A_B_C); | 1944 BYTECODE(Mod, A_B_C); |
| 1980 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); | 1945 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); |
| 1981 if (rhs != 0) { | 1946 if (rhs != 0) { |
| 1982 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); | 1947 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
| 1983 const intptr_t res = | 1948 const intptr_t res = ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) |
| 1984 ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) << kSmiTagSize; | 1949 << kSmiTagSize; |
| 1985 *reinterpret_cast<intptr_t*>(&FP[rA]) = | 1950 *reinterpret_cast<intptr_t*>(&FP[rA]) = |
| 1986 (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res; | 1951 (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res; |
| 1987 pc++; | 1952 pc++; |
| 1988 } | 1953 } |
| 1989 DISPATCH(); | 1954 DISPATCH(); |
| 1990 } | 1955 } |
| 1991 | 1956 |
| 1992 { | 1957 { |
| 1993 BYTECODE(Shl, A_B_C); | 1958 BYTECODE(Shl, A_B_C); |
| 1994 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; | 1959 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; |
| 1995 if (static_cast<uintptr_t>(rhs) < kBitsPerWord) { | 1960 if (static_cast<uintptr_t>(rhs) < kBitsPerWord) { |
| 1996 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); | 1961 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
| 1997 const intptr_t res = lhs << rhs; | 1962 const intptr_t res = lhs << rhs; |
| 1998 if (lhs == (res >> rhs)) { | 1963 if (lhs == (res >> rhs)) { |
| 1999 *reinterpret_cast<intptr_t*>(&FP[rA]) = res; | 1964 *reinterpret_cast<intptr_t*>(&FP[rA]) = res; |
| 2000 pc++; | 1965 pc++; |
| 2001 } | 1966 } |
| 2002 } | 1967 } |
| 2003 DISPATCH(); | 1968 DISPATCH(); |
| 2004 } | 1969 } |
| 2005 | 1970 |
| 2006 { | 1971 { |
| 2007 BYTECODE(Shr, A_B_C); | 1972 BYTECODE(Shr, A_B_C); |
| 2008 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; | 1973 const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; |
| 2009 if (rhs >= 0) { | 1974 if (rhs >= 0) { |
| 2010 const intptr_t shift_amount = | 1975 const intptr_t shift_amount = |
| 2011 (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs; | 1976 (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs; |
| 2012 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize; | 1977 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize; |
| 2013 *reinterpret_cast<intptr_t*>(&FP[rA]) = | 1978 *reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift_amount) |
| 2014 (lhs >> shift_amount) << kSmiTagSize; | 1979 << kSmiTagSize; |
| 2015 pc++; | 1980 pc++; |
| 2016 } | 1981 } |
| 2017 DISPATCH(); | 1982 DISPATCH(); |
| 2018 } | 1983 } |
| 2019 | 1984 |
| 2020 { | 1985 { |
| 2021 BYTECODE(ShlImm, A_B_C); | 1986 BYTECODE(ShlImm, A_B_C); |
| 2022 const uint8_t shift = rC; | 1987 const uint8_t shift = rC; |
| 2023 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); | 1988 const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
| 2024 FP[rA] = reinterpret_cast<RawObject*>(lhs << shift); | 1989 FP[rA] = reinterpret_cast<RawObject*>(lhs << shift); |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2358 } | 2323 } |
| 2359 | 2324 |
| 2360 { | 2325 { |
| 2361 BYTECODE(BoxUint32, A_D); | 2326 BYTECODE(BoxUint32, A_D); |
| 2362 // Casts to zero out high 32 bits. | 2327 // Casts to zero out high 32 bits. |
| 2363 const uintptr_t value = reinterpret_cast<uintptr_t>(FP[rD]); | 2328 const uintptr_t value = reinterpret_cast<uintptr_t>(FP[rD]); |
| 2364 const uint32_t value32 = static_cast<uint32_t>(value); | 2329 const uint32_t value32 = static_cast<uint32_t>(value); |
| 2365 FP[rA] = Smi::New(static_cast<intptr_t>(value32)); | 2330 FP[rA] = Smi::New(static_cast<intptr_t>(value32)); |
| 2366 DISPATCH(); | 2331 DISPATCH(); |
| 2367 } | 2332 } |
| 2368 #else // defined(ARCH_IS_64_BIT) | 2333 #else // defined(ARCH_IS_64_BIT) |
| 2369 { | 2334 { |
| 2370 BYTECODE(WriteIntoDouble, A_D); | 2335 BYTECODE(WriteIntoDouble, A_D); |
| 2371 UNIMPLEMENTED(); | 2336 UNIMPLEMENTED(); |
| 2372 DISPATCH(); | 2337 DISPATCH(); |
| 2373 } | 2338 } |
| 2374 | 2339 |
| 2375 { | 2340 { |
| 2376 BYTECODE(UnboxDouble, A_D); | 2341 BYTECODE(UnboxDouble, A_D); |
| 2377 UNIMPLEMENTED(); | 2342 UNIMPLEMENTED(); |
| 2378 DISPATCH(); | 2343 DISPATCH(); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2583 DISPATCH(); | 2548 DISPATCH(); |
| 2584 } | 2549 } |
| 2585 goto ReturnImpl; | 2550 goto ReturnImpl; |
| 2586 | 2551 |
| 2587 BYTECODE(Return, A); | 2552 BYTECODE(Return, A); |
| 2588 result = FP[rA]; | 2553 result = FP[rA]; |
| 2589 goto ReturnImpl; | 2554 goto ReturnImpl; |
| 2590 | 2555 |
| 2591 BYTECODE(ReturnTOS, 0); | 2556 BYTECODE(ReturnTOS, 0); |
| 2592 result = *SP; | 2557 result = *SP; |
| 2593 // Fall through to the ReturnImpl. | 2558 // Fall through to the ReturnImpl. |
| 2594 | 2559 |
| 2595 ReturnImpl: | 2560 ReturnImpl: |
| 2596 // Restore caller PC. | 2561 // Restore caller PC. |
| 2597 pc = SavedCallerPC(FP); | 2562 pc = SavedCallerPC(FP); |
| 2598 pc_ = reinterpret_cast<uword>(pc); // For the profiler. | 2563 pc_ = reinterpret_cast<uword>(pc); // For the profiler. |
| 2599 | 2564 |
| 2600 // Check if it is a fake PC marking the entry frame. | 2565 // Check if it is a fake PC marking the entry frame. |
| 2601 if ((reinterpret_cast<uword>(pc) & 2) != 0) { | 2566 if ((reinterpret_cast<uword>(pc) & 2) != 0) { |
| 2602 const intptr_t argc = reinterpret_cast<uword>(pc) >> 2; | 2567 const intptr_t argc = reinterpret_cast<uword>(pc) >> 2; |
| 2603 fp_ = sp_ = | 2568 fp_ = sp_ = |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 } | 2690 } |
| 2726 DISPATCH(); | 2691 DISPATCH(); |
| 2727 } | 2692 } |
| 2728 | 2693 |
| 2729 // TODO(vegorov) allocation bytecodes can benefit from the new-space | 2694 // TODO(vegorov) allocation bytecodes can benefit from the new-space |
| 2730 // allocation fast-path that does not transition into the runtime system. | 2695 // allocation fast-path that does not transition into the runtime system. |
| 2731 { | 2696 { |
| 2732 BYTECODE(AllocateUninitializedContext, A_D); | 2697 BYTECODE(AllocateUninitializedContext, A_D); |
| 2733 const uint16_t num_context_variables = rD; | 2698 const uint16_t num_context_variables = rD; |
| 2734 const intptr_t instance_size = Context::InstanceSize(num_context_variables); | 2699 const intptr_t instance_size = Context::InstanceSize(num_context_variables); |
| 2735 const uword start = | 2700 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); |
| 2736 thread->heap()->new_space()->TryAllocate(instance_size); | |
| 2737 if (LIKELY(start != 0)) { | 2701 if (LIKELY(start != 0)) { |
| 2738 uword tags = 0; | 2702 uword tags = 0; |
| 2739 tags = RawObject::ClassIdTag::update(kContextCid, tags); | 2703 tags = RawObject::ClassIdTag::update(kContextCid, tags); |
| 2740 tags = RawObject::SizeTag::update(instance_size, tags); | 2704 tags = RawObject::SizeTag::update(instance_size, tags); |
| 2741 *reinterpret_cast<uword*>(start + Array::tags_offset()) = tags; | 2705 *reinterpret_cast<uword*>(start + Array::tags_offset()) = tags; |
| 2742 *reinterpret_cast<uword*>(start + Context::num_variables_offset()) = | 2706 *reinterpret_cast<uword*>(start + Context::num_variables_offset()) = |
| 2743 num_context_variables; | 2707 num_context_variables; |
| 2744 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); | 2708 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); |
| 2745 pc += 2; | 2709 pc += 2; |
| 2746 } | 2710 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2773 | 2737 |
| 2774 { | 2738 { |
| 2775 BYTECODE(AllocateOpt, A_D); | 2739 BYTECODE(AllocateOpt, A_D); |
| 2776 const uword tags = | 2740 const uword tags = |
| 2777 static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD)))); | 2741 static_cast<uword>(Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD)))); |
| 2778 const intptr_t instance_size = RawObject::SizeTag::decode(tags); | 2742 const intptr_t instance_size = RawObject::SizeTag::decode(tags); |
| 2779 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); | 2743 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); |
| 2780 if (LIKELY(start != 0)) { | 2744 if (LIKELY(start != 0)) { |
| 2781 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; | 2745 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; |
| 2782 for (intptr_t current_offset = sizeof(RawInstance); | 2746 for (intptr_t current_offset = sizeof(RawInstance); |
| 2783 current_offset < instance_size; | 2747 current_offset < instance_size; current_offset += kWordSize) { |
| 2784 current_offset += kWordSize) { | |
| 2785 *reinterpret_cast<RawObject**>(start + current_offset) = null_value; | 2748 *reinterpret_cast<RawObject**>(start + current_offset) = null_value; |
| 2786 } | 2749 } |
| 2787 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); | 2750 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); |
| 2788 pc += 2; | 2751 pc += 2; |
| 2789 } | 2752 } |
| 2790 DISPATCH(); | 2753 DISPATCH(); |
| 2791 } | 2754 } |
| 2792 | 2755 |
| 2793 { | 2756 { |
| 2794 BYTECODE(Allocate, A_D); | 2757 BYTECODE(Allocate, A_D); |
| 2795 SP[1] = 0; // Space for the result. | 2758 SP[1] = 0; // Space for the result. |
| 2796 SP[2] = LOAD_CONSTANT(rD); // Class object. | 2759 SP[2] = LOAD_CONSTANT(rD); // Class object. |
| 2797 SP[3] = null_value; // Type arguments. | 2760 SP[3] = null_value; // Type arguments. |
| 2798 Exit(thread, FP, SP + 4, pc); | 2761 Exit(thread, FP, SP + 4, pc); |
| 2799 NativeArguments args(thread, 2, SP + 2, SP + 1); | 2762 NativeArguments args(thread, 2, SP + 2, SP + 1); |
| 2800 INVOKE_RUNTIME(DRT_AllocateObject, args); | 2763 INVOKE_RUNTIME(DRT_AllocateObject, args); |
| 2801 SP++; // Result is in SP[1]. | 2764 SP++; // Result is in SP[1]. |
| 2802 DISPATCH(); | 2765 DISPATCH(); |
| 2803 } | 2766 } |
| 2804 | 2767 |
| 2805 { | 2768 { |
| 2806 BYTECODE(AllocateTOpt, A_D); | 2769 BYTECODE(AllocateTOpt, A_D); |
| 2807 const uword tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); | 2770 const uword tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); |
| 2808 const intptr_t instance_size = RawObject::SizeTag::decode(tags); | 2771 const intptr_t instance_size = RawObject::SizeTag::decode(tags); |
| 2809 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); | 2772 const uword start = thread->heap()->new_space()->TryAllocate(instance_size); |
| 2810 if (LIKELY(start != 0)) { | 2773 if (LIKELY(start != 0)) { |
| 2811 RawObject* type_args = SP[0]; | 2774 RawObject* type_args = SP[0]; |
| 2812 const intptr_t type_args_offset = Bytecode::DecodeD(*pc); | 2775 const intptr_t type_args_offset = Bytecode::DecodeD(*pc); |
| 2813 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; | 2776 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; |
| 2814 for (intptr_t current_offset = sizeof(RawInstance); | 2777 for (intptr_t current_offset = sizeof(RawInstance); |
| 2815 current_offset < instance_size; | 2778 current_offset < instance_size; current_offset += kWordSize) { |
| 2816 current_offset += kWordSize) { | |
| 2817 *reinterpret_cast<RawObject**>(start + current_offset) = null_value; | 2779 *reinterpret_cast<RawObject**>(start + current_offset) = null_value; |
| 2818 } | 2780 } |
| 2819 *reinterpret_cast<RawObject**>(start + type_args_offset) = type_args; | 2781 *reinterpret_cast<RawObject**>(start + type_args_offset) = type_args; |
| 2820 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); | 2782 FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag); |
| 2821 SP -= 1; // Consume the type arguments on the stack. | 2783 SP -= 1; // Consume the type arguments on the stack. |
| 2822 pc += 4; | 2784 pc += 4; |
| 2823 } | 2785 } |
| 2824 DISPATCH(); | 2786 DISPATCH(); |
| 2825 } | 2787 } |
| 2826 | 2788 |
| 2827 { | 2789 { |
| 2828 BYTECODE(AllocateT, 0); | 2790 BYTECODE(AllocateT, 0); |
| 2829 SP[1] = SP[-0]; // Class object. | 2791 SP[1] = SP[-0]; // Class object. |
| 2830 SP[2] = SP[-1]; // Type arguments | 2792 SP[2] = SP[-1]; // Type arguments |
| 2831 Exit(thread, FP, SP + 3, pc); | 2793 Exit(thread, FP, SP + 3, pc); |
| 2832 NativeArguments args(thread, 2, SP + 1, SP - 1); | 2794 NativeArguments args(thread, 2, SP + 1, SP - 1); |
| 2833 INVOKE_RUNTIME(DRT_AllocateObject, args); | 2795 INVOKE_RUNTIME(DRT_AllocateObject, args); |
| 2834 SP -= 1; // Result is in SP - 1. | 2796 SP -= 1; // Result is in SP - 1. |
| 2835 DISPATCH(); | 2797 DISPATCH(); |
| 2836 } | 2798 } |
| 2837 | 2799 |
| 2838 { | 2800 { |
| 2839 BYTECODE(CreateArrayOpt, A_B_C); | 2801 BYTECODE(CreateArrayOpt, A_B_C); |
| 2840 const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB])); | 2802 const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB])); |
| 2841 if (LIKELY(length <= Array::kMaxElements)) { | 2803 if (LIKELY(length <= Array::kMaxElements)) { |
| 2842 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 2804 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 2843 const intptr_t instance_size = | 2805 const intptr_t instance_size = |
| 2844 (fixed_size + length*kWordSize) & ~(kObjectAlignment - 1); | 2806 (fixed_size + length * kWordSize) & ~(kObjectAlignment - 1); |
| 2845 const uword start = | 2807 const uword start = |
| 2846 thread->heap()->new_space()->TryAllocate(instance_size); | 2808 thread->heap()->new_space()->TryAllocate(instance_size); |
| 2847 if (LIKELY(start != 0)) { | 2809 if (LIKELY(start != 0)) { |
| 2848 const intptr_t cid = kArrayCid; | 2810 const intptr_t cid = kArrayCid; |
| 2849 uword tags = 0; | 2811 uword tags = 0; |
| 2850 if (LIKELY(instance_size < RawObject::SizeTag::kMaxSizeTag)) { | 2812 if (LIKELY(instance_size < RawObject::SizeTag::kMaxSizeTag)) { |
| 2851 tags = RawObject::SizeTag::update(instance_size, tags); | 2813 tags = RawObject::SizeTag::update(instance_size, tags); |
| 2852 } | 2814 } |
| 2853 tags = RawObject::ClassIdTag::update(cid, tags); | 2815 tags = RawObject::ClassIdTag::update(cid, tags); |
| 2854 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; | 2816 *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2892 RawTypeArguments* instance_type_arguments = | 2854 RawTypeArguments* instance_type_arguments = |
| 2893 static_cast<RawTypeArguments*>(null_value); | 2855 static_cast<RawTypeArguments*>(null_value); |
| 2894 RawObject* instance_cid_or_function; | 2856 RawObject* instance_cid_or_function; |
| 2895 if (cid == kClosureCid) { | 2857 if (cid == kClosureCid) { |
| 2896 RawClosure* closure = static_cast<RawClosure*>(instance); | 2858 RawClosure* closure = static_cast<RawClosure*>(instance); |
| 2897 instance_type_arguments = closure->ptr()->type_arguments_; | 2859 instance_type_arguments = closure->ptr()->type_arguments_; |
| 2898 instance_cid_or_function = closure->ptr()->function_; | 2860 instance_cid_or_function = closure->ptr()->function_; |
| 2899 } else { | 2861 } else { |
| 2900 instance_cid_or_function = Smi::New(cid); | 2862 instance_cid_or_function = Smi::New(cid); |
| 2901 | 2863 |
| 2902 RawClass* instance_class = | 2864 RawClass* instance_class = thread->isolate()->class_table()->At(cid); |
| 2903 thread->isolate()->class_table()->At(cid); | |
| 2904 if (instance_class->ptr()->num_type_arguments_ < 0) { | 2865 if (instance_class->ptr()->num_type_arguments_ < 0) { |
| 2905 goto InstanceOfCallRuntime; | 2866 goto InstanceOfCallRuntime; |
| 2906 } else if (instance_class->ptr()->num_type_arguments_ > 0) { | 2867 } else if (instance_class->ptr()->num_type_arguments_ > 0) { |
| 2907 instance_type_arguments = reinterpret_cast<RawTypeArguments**>( | 2868 instance_type_arguments = reinterpret_cast<RawTypeArguments**>( |
| 2908 instance | 2869 instance->ptr())[instance_class->ptr() |
| 2909 ->ptr())[instance_class->ptr() | 2870 ->type_arguments_field_offset_in_words_]; |
| 2910 ->type_arguments_field_offset_in_words_]; | |
| 2911 } | 2871 } |
| 2912 } | 2872 } |
| 2913 | 2873 |
| 2914 for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); | 2874 for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); |
| 2915 entries[0] != null_value; | 2875 entries[0] != null_value; |
| 2916 entries += SubtypeTestCache::kTestEntryLength) { | 2876 entries += SubtypeTestCache::kTestEntryLength) { |
| 2917 if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == | 2877 if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == |
| 2918 instance_cid_or_function) && | 2878 instance_cid_or_function) && |
| 2919 (entries[SubtypeTestCache::kInstanceTypeArguments] == | 2879 (entries[SubtypeTestCache::kInstanceTypeArguments] == |
| 2920 instance_type_arguments) && | 2880 instance_type_arguments) && |
| 2921 (entries[SubtypeTestCache::kInstantiatorTypeArguments] == | 2881 (entries[SubtypeTestCache::kInstantiatorTypeArguments] == |
| 2922 instantiator_type_arguments)) { | 2882 instantiator_type_arguments)) { |
| 2923 SP[-3] = entries[SubtypeTestCache::kTestResult]; | 2883 SP[-3] = entries[SubtypeTestCache::kTestResult]; |
| 2924 goto InstanceOfOk; | 2884 goto InstanceOfOk; |
| 2925 } | 2885 } |
| 2926 } | 2886 } |
| 2927 } | 2887 } |
| 2928 | 2888 |
| 2889 // clang-format off |
| 2929 InstanceOfCallRuntime: | 2890 InstanceOfCallRuntime: |
| 2930 { | 2891 { |
| 2931 SP[1] = instance; | 2892 SP[1] = instance; |
| 2932 SP[2] = type; | 2893 SP[2] = type; |
| 2933 SP[3] = instantiator_type_arguments; | 2894 SP[3] = instantiator_type_arguments; |
| 2934 SP[4] = cache; | 2895 SP[4] = cache; |
| 2935 Exit(thread, FP, SP + 5, pc); | 2896 Exit(thread, FP, SP + 5, pc); |
| 2936 NativeArguments native_args(thread, 4, SP + 1, SP - 3); | 2897 NativeArguments native_args(thread, 4, SP + 1, SP - 3); |
| 2937 INVOKE_RUNTIME(DRT_Instanceof, native_args); | 2898 INVOKE_RUNTIME(DRT_Instanceof, native_args); |
| 2938 } | 2899 } |
| 2900 // clang-format on |
| 2939 | 2901 |
| 2940 InstanceOfOk: | 2902 InstanceOfOk: |
| 2941 SP -= 3; | 2903 SP -= 3; |
| 2942 if (rA) { // Negate result. | 2904 if (rA) { // Negate result. |
| 2943 SP[0] = (SP[0] == true_value) ? false_value : true_value; | 2905 SP[0] = (SP[0] == true_value) ? false_value : true_value; |
| 2944 } | 2906 } |
| 2945 DISPATCH(); | 2907 DISPATCH(); |
| 2946 } | 2908 } |
| 2947 | 2909 |
| 2948 { | 2910 { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2981 RawTypeArguments* instance_type_arguments = | 2943 RawTypeArguments* instance_type_arguments = |
| 2982 static_cast<RawTypeArguments*>(null_value); | 2944 static_cast<RawTypeArguments*>(null_value); |
| 2983 RawObject* instance_cid_or_function; | 2945 RawObject* instance_cid_or_function; |
| 2984 if (cid == kClosureCid) { | 2946 if (cid == kClosureCid) { |
| 2985 RawClosure* closure = static_cast<RawClosure*>(instance); | 2947 RawClosure* closure = static_cast<RawClosure*>(instance); |
| 2986 instance_type_arguments = closure->ptr()->type_arguments_; | 2948 instance_type_arguments = closure->ptr()->type_arguments_; |
| 2987 instance_cid_or_function = closure->ptr()->function_; | 2949 instance_cid_or_function = closure->ptr()->function_; |
| 2988 } else { | 2950 } else { |
| 2989 instance_cid_or_function = Smi::New(cid); | 2951 instance_cid_or_function = Smi::New(cid); |
| 2990 | 2952 |
| 2991 RawClass* instance_class = | 2953 RawClass* instance_class = thread->isolate()->class_table()->At(cid); |
| 2992 thread->isolate()->class_table()->At(cid); | |
| 2993 if (instance_class->ptr()->num_type_arguments_ < 0) { | 2954 if (instance_class->ptr()->num_type_arguments_ < 0) { |
| 2994 goto AssertAssignableCallRuntime; | 2955 goto AssertAssignableCallRuntime; |
| 2995 } else if (instance_class->ptr()->num_type_arguments_ > 0) { | 2956 } else if (instance_class->ptr()->num_type_arguments_ > 0) { |
| 2996 instance_type_arguments = reinterpret_cast<RawTypeArguments**>( | 2957 instance_type_arguments = reinterpret_cast<RawTypeArguments**>( |
| 2997 instance | 2958 instance->ptr())[instance_class->ptr() |
| 2998 ->ptr())[instance_class->ptr() | 2959 ->type_arguments_field_offset_in_words_]; |
| 2999 ->type_arguments_field_offset_in_words_]; | |
| 3000 } | 2960 } |
| 3001 } | 2961 } |
| 3002 | 2962 |
| 3003 for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); | 2963 for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); |
| 3004 entries[0] != null_value; | 2964 entries[0] != null_value; |
| 3005 entries += SubtypeTestCache::kTestEntryLength) { | 2965 entries += SubtypeTestCache::kTestEntryLength) { |
| 3006 if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == | 2966 if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == |
| 3007 instance_cid_or_function) && | 2967 instance_cid_or_function) && |
| 3008 (entries[SubtypeTestCache::kInstanceTypeArguments] == | 2968 (entries[SubtypeTestCache::kInstanceTypeArguments] == |
| 3009 instance_type_arguments) && | 2969 instance_type_arguments) && |
| 3010 (entries[SubtypeTestCache::kInstantiatorTypeArguments] == | 2970 (entries[SubtypeTestCache::kInstantiatorTypeArguments] == |
| 3011 instantiator_type_arguments)) { | 2971 instantiator_type_arguments)) { |
| 3012 if (true_value == entries[SubtypeTestCache::kTestResult]) { | 2972 if (true_value == entries[SubtypeTestCache::kTestResult]) { |
| 3013 goto AssertAssignableOk; | 2973 goto AssertAssignableOk; |
| 3014 } else { | 2974 } else { |
| 3015 break; | 2975 break; |
| 3016 } | 2976 } |
| 3017 } | 2977 } |
| 3018 } | 2978 } |
| 3019 } | 2979 } |
| 3020 | 2980 |
| 3021 AssertAssignableCallRuntime: | 2981 AssertAssignableCallRuntime: |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3353 DISPATCH(); | 3313 DISPATCH(); |
| 3354 } | 3314 } |
| 3355 | 3315 |
| 3356 { | 3316 { |
| 3357 BYTECODE(IfDGt, A_D); | 3317 BYTECODE(IfDGt, A_D); |
| 3358 const double lhs = bit_cast<double, RawObject*>(FP[rA]); | 3318 const double lhs = bit_cast<double, RawObject*>(FP[rA]); |
| 3359 const double rhs = bit_cast<double, RawObject*>(FP[rD]); | 3319 const double rhs = bit_cast<double, RawObject*>(FP[rD]); |
| 3360 pc += (lhs > rhs) ? 0 : 1; | 3320 pc += (lhs > rhs) ? 0 : 1; |
| 3361 DISPATCH(); | 3321 DISPATCH(); |
| 3362 } | 3322 } |
| 3363 #else // defined(ARCH_IS_64_BIT) | 3323 #else // defined(ARCH_IS_64_BIT) |
| 3364 { | 3324 { |
| 3365 BYTECODE(IfDEq, A_D); | 3325 BYTECODE(IfDEq, A_D); |
| 3366 UNREACHABLE(); | 3326 UNREACHABLE(); |
| 3367 DISPATCH(); | 3327 DISPATCH(); |
| 3368 } | 3328 } |
| 3369 | 3329 |
| 3370 { | 3330 { |
| 3371 BYTECODE(IfDNe, A_D); | 3331 BYTECODE(IfDNe, A_D); |
| 3372 UNREACHABLE(); | 3332 UNREACHABLE(); |
| 3373 DISPATCH(); | 3333 DISPATCH(); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3670 ClosureNoSuchMethod: | 3630 ClosureNoSuchMethod: |
| 3671 #if defined(DEBUG) | 3631 #if defined(DEBUG) |
| 3672 function_h ^= FrameFunction(FP); | 3632 function_h ^= FrameFunction(FP); |
| 3673 ASSERT(function_h.IsClosureFunction()); | 3633 ASSERT(function_h.IsClosureFunction()); |
| 3674 #endif | 3634 #endif |
| 3675 | 3635 |
| 3676 // Restore caller context as we are going to throw NoSuchMethod. | 3636 // Restore caller context as we are going to throw NoSuchMethod. |
| 3677 pc = SavedCallerPC(FP); | 3637 pc = SavedCallerPC(FP); |
| 3678 | 3638 |
| 3679 const bool has_dart_caller = (reinterpret_cast<uword>(pc) & 2) == 0; | 3639 const bool has_dart_caller = (reinterpret_cast<uword>(pc) & 2) == 0; |
| 3680 const intptr_t argc = has_dart_caller | 3640 const intptr_t argc = has_dart_caller ? Bytecode::DecodeArgc(pc[-1]) |
| 3681 ? Bytecode::DecodeArgc(pc[-1]) | 3641 : (reinterpret_cast<uword>(pc) >> 2); |
| 3682 : (reinterpret_cast<uword>(pc) >> 2); | |
| 3683 | 3642 |
| 3684 SP = FrameArguments(FP, 0); | 3643 SP = FrameArguments(FP, 0); |
| 3685 RawObject** args = SP - argc; | 3644 RawObject** args = SP - argc; |
| 3686 FP = SavedCallerFP(FP); | 3645 FP = SavedCallerFP(FP); |
| 3687 if (has_dart_caller) { | 3646 if (has_dart_caller) { |
| 3688 pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); | 3647 pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); |
| 3689 } | 3648 } |
| 3690 | 3649 |
| 3691 *++SP = null_value; | 3650 *++SP = null_value; |
| 3692 *++SP = args[0]; // Closure object. | 3651 *++SP = args[0]; // Closure object. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3763 pc_ = pc; | 3722 pc_ = pc; |
| 3764 special_[kExceptionSpecialIndex] = raw_exception; | 3723 special_[kExceptionSpecialIndex] = raw_exception; |
| 3765 special_[kStacktraceSpecialIndex] = raw_stacktrace; | 3724 special_[kStacktraceSpecialIndex] = raw_stacktrace; |
| 3766 buf->Longjmp(); | 3725 buf->Longjmp(); |
| 3767 UNREACHABLE(); | 3726 UNREACHABLE(); |
| 3768 } | 3727 } |
| 3769 | 3728 |
| 3770 } // namespace dart | 3729 } // namespace dart |
| 3771 | 3730 |
| 3772 #endif // defined TARGET_ARCH_DBC | 3731 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |