| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 | 99 |
| 100 DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, | 100 DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, |
| 101 intptr_t argc) { | 101 intptr_t argc) { |
| 102 return FP - (kDartFrameFixedSize + argc); | 102 return FP - (kDartFrameFixedSize + argc); |
| 103 } | 103 } |
| 104 | 104 |
| 105 | 105 |
| 106 class SimulatorHelpers { | 106 class SimulatorHelpers { |
| 107 public: | 107 public: |
| 108 DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { | 108 DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { |
| 109 return Smi::New(obj->IsHeapObject() ? obj->GetClassId() : kSmiCid); | 109 return Smi::New(obj->IsHeapObject() ? obj->GetClassId() |
| 110 : static_cast<intptr_t>(kSmiCid)); |
| 110 } | 111 } |
| 111 | 112 |
| 112 DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { | 113 DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { |
| 113 return obj->IsHeapObject() ? obj->GetClassId() : kSmiCid; | 114 return obj->IsHeapObject() ? obj->GetClassId() |
| 115 : static_cast<intptr_t>(kSmiCid); |
| 114 } | 116 } |
| 115 | 117 |
| 116 DART_FORCE_INLINE static void IncrementUsageCounter(RawICData* icdata) { | 118 DART_FORCE_INLINE static void IncrementUsageCounter(RawICData* icdata) { |
| 117 reinterpret_cast<RawFunction*>(icdata->ptr()->owner_) | 119 reinterpret_cast<RawFunction*>(icdata->ptr()->owner_) |
| 118 ->ptr() | 120 ->ptr() |
| 119 ->usage_counter_++; | 121 ->usage_counter_++; |
| 120 } | 122 } |
| 121 | 123 |
| 122 DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, | 124 DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, |
| 123 RawObject* rhs) { | 125 RawObject* rhs) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 // set the stack top. | 307 // set the stack top. |
| 306 return StackBase() + | 308 return StackBase() + |
| 307 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 309 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
| 308 } | 310 } |
| 309 | 311 |
| 310 | 312 |
| 311 // Calls into the Dart runtime are based on this interface. | 313 // Calls into the Dart runtime are based on this interface. |
| 312 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 314 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 313 | 315 |
| 314 // Calls to leaf Dart runtime functions are based on this interface. | 316 // Calls to leaf Dart runtime functions are based on this interface. |
| 315 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, | 317 typedef intptr_t (*SimulatorLeafRuntimeCall)(intptr_t r0, |
| 316 int32_t r1, | 318 intptr_t r1, |
| 317 int32_t r2, | 319 intptr_t r2, |
| 318 int32_t r3); | 320 intptr_t r3); |
| 319 | 321 |
| 320 // Calls to leaf float Dart runtime functions are based on this interface. | 322 // Calls to leaf float Dart runtime functions are based on this interface. |
| 321 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | 323 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
| 322 | 324 |
| 323 // Calls to native Dart functions are based on this interface. | 325 // Calls to native Dart functions are based on this interface. |
| 324 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 326 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
| 325 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 327 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
| 326 | 328 |
| 327 | 329 |
| 328 void Simulator::Exit(Thread* thread, | 330 void Simulator::Exit(Thread* thread, |
| 329 RawObject** base, | 331 RawObject** base, |
| 330 RawObject** frame, | 332 RawObject** frame, |
| 331 uint32_t* pc) { | 333 uint32_t* pc) { |
| 332 frame[0] = Function::null(); | 334 frame[0] = Function::null(); |
| 333 frame[1] = Code::null(); | 335 frame[1] = Code::null(); |
| 334 frame[2] = reinterpret_cast<RawObject*>(pc); | 336 frame[2] = reinterpret_cast<RawObject*>(pc); |
| 335 frame[3] = reinterpret_cast<RawObject*>(base); | 337 frame[3] = reinterpret_cast<RawObject*>(base); |
| 336 fp_ = sp_ = frame + kDartFrameFixedSize; | 338 fp_ = sp_ = frame + kDartFrameFixedSize; |
| 337 thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_)); | 339 thread->set_top_exit_frame_info(reinterpret_cast<uword>(sp_)); |
| 338 } | 340 } |
| 339 | 341 |
| 340 | 342 // TODO(vegorov): Investigate advantages of using |
| 341 #if defined(__has_builtin) | 343 // __builtin_s{add,sub,mul}_overflow() intrinsics here and below. |
| 342 #if __has_builtin(__builtin_smul_overflow) | 344 // Note that they may clobber the output location even when there is overflow: |
| 343 #define HAS_MUL_OVERFLOW | 345 // https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html |
| 344 #endif | 346 DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs, |
| 345 #if __has_builtin(__builtin_sadd_overflow) | 347 intptr_t rhs, |
| 346 #define HAS_ADD_OVERFLOW | |
| 347 #endif | |
| 348 #if __has_builtin(__builtin_ssub_overflow) | |
| 349 #define HAS_SUB_OVERFLOW | |
| 350 #endif | |
| 351 #endif | |
| 352 | |
| 353 | |
| 354 DART_FORCE_INLINE static bool SignedAddWithOverflow(int32_t lhs, | |
| 355 int32_t rhs, | |
| 356 intptr_t* out) { | 348 intptr_t* out) { |
| 357 int32_t res = 1; | 349 intptr_t res = 1; |
| 358 #if defined(HAS_ADD_OVERFLOW) | 350 #if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) |
| 359 res = static_cast<int32_t>(__builtin_sadd_overflow( | |
| 360 lhs, rhs, reinterpret_cast<int32_t*>(out))); | |
| 361 #elif defined(__i386__) | |
| 362 asm volatile( | 351 asm volatile( |
| 363 "add %2, %1\n" | 352 "add %2, %1\n" |
| 364 "jo 1f;\n" | 353 "jo 1f;\n" |
| 365 "xor %0, %0\n" | 354 "xor %0, %0\n" |
| 366 "mov %1, 0(%3)\n" | 355 "mov %1, 0(%3)\n" |
| 367 "1: " | 356 "1: " |
| 368 : "+r"(res), "+r"(lhs) | 357 : "+r"(res), "+r"(lhs) |
| 369 : "r"(rhs), "r"(out) | 358 : "r"(rhs), "r"(out) |
| 370 : "cc"); | 359 : "cc"); |
| 371 #elif defined(__arm__) | 360 #elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) |
| 372 asm volatile( | 361 asm volatile( |
| 373 "adds %1, %1, %2;\n" | 362 "adds %1, %1, %2;\n" |
| 374 "bvs 1f;\n" | 363 "bvs 1f;\n" |
| 375 "mov %0, $0;\n" | 364 "mov %0, #0;\n" |
| 376 "str %1, [%3, #0]\n" | 365 "str %1, [%3, #0]\n" |
| 377 "1:" | 366 "1:" |
| 378 : "+r"(res), "+r"(lhs) | 367 : "+r"(res), "+r"(lhs) |
| 379 : "r"(rhs), "r"(out) | 368 : "r"(rhs), "r"(out) |
| 380 : "cc", "r12"); | 369 : "cc"); |
| 381 #else | 370 #else |
| 382 #error "Unsupported platform" | 371 #error "Unsupported platform" |
| 383 #endif | 372 #endif |
| 384 return (res != 0); | 373 return (res != 0); |
| 385 } | 374 } |
| 386 | 375 |
| 387 | 376 |
| 388 DART_FORCE_INLINE static bool SignedSubWithOverflow(int32_t lhs, | 377 DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs, |
| 389 int32_t rhs, | 378 intptr_t rhs, |
| 390 intptr_t* out) { | 379 intptr_t* out) { |
| 391 int32_t res = 1; | 380 intptr_t res = 1; |
| 392 #if defined(HAS_SUB_OVERFLOW) | 381 #if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) |
| 393 res = static_cast<int32_t>(__builtin_ssub_overflow( | |
| 394 lhs, rhs, reinterpret_cast<int32_t*>(out))); | |
| 395 #elif defined(__i386__) | |
| 396 asm volatile( | 382 asm volatile( |
| 397 "sub %2, %1\n" | 383 "sub %2, %1\n" |
| 398 "jo 1f;\n" | 384 "jo 1f;\n" |
| 399 "xor %0, %0\n" | 385 "xor %0, %0\n" |
| 400 "mov %1, 0(%3)\n" | 386 "mov %1, 0(%3)\n" |
| 401 "1: " | 387 "1: " |
| 402 : "+r"(res), "+r"(lhs) | 388 : "+r"(res), "+r"(lhs) |
| 403 : "r"(rhs), "r"(out) | 389 : "r"(rhs), "r"(out) |
| 404 : "cc"); | 390 : "cc"); |
| 405 #elif defined(__arm__) | 391 #elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) |
| 406 asm volatile( | 392 asm volatile( |
| 407 "subs %1, %1, %2;\n" | 393 "subs %1, %1, %2;\n" |
| 408 "bvs 1f;\n" | 394 "bvs 1f;\n" |
| 409 "mov %0, $0;\n" | 395 "mov %0, #0;\n" |
| 410 "str %1, [%3, #0]\n" | 396 "str %1, [%3, #0]\n" |
| 411 "1:" | 397 "1:" |
| 412 : "+r"(res), "+r"(lhs) | 398 : "+r"(res), "+r"(lhs) |
| 413 : "r"(rhs), "r"(out) | 399 : "r"(rhs), "r"(out) |
| 414 : "cc", "r12"); | 400 : "cc"); |
| 415 #else | 401 #else |
| 416 #error "Unsupported platform" | 402 #error "Unsupported platform" |
| 417 #endif | 403 #endif |
| 418 return (res != 0); | 404 return (res != 0); |
| 419 } | 405 } |
| 420 | 406 |
| 421 | 407 |
| 422 DART_FORCE_INLINE static bool SignedMulWithOverflow(int32_t lhs, | 408 DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs, |
| 423 int32_t rhs, | 409 intptr_t rhs, |
| 424 intptr_t* out) { | 410 intptr_t* out) { |
| 425 int32_t res = 1; | 411 intptr_t res = 1; |
| 426 #if defined(HAS_MUL_OVERFLOW) | 412 #if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) |
| 427 res = static_cast<int32_t>(__builtin_smul_overflow( | |
| 428 lhs, rhs, reinterpret_cast<int32_t*>(out))); | |
| 429 #elif defined(__i386__) | |
| 430 asm volatile( | 413 asm volatile( |
| 431 "imul %2, %1\n" | 414 "imul %2, %1\n" |
| 432 "jo 1f;\n" | 415 "jo 1f;\n" |
| 433 "xor %0, %0\n" | 416 "xor %0, %0\n" |
| 434 "mov %1, 0(%3)\n" | 417 "mov %1, 0(%3)\n" |
| 435 "1: " | 418 "1: " |
| 436 : "+r"(res), "+r"(lhs) | 419 : "+r"(res), "+r"(lhs) |
| 437 : "r"(rhs), "r"(out) | 420 : "r"(rhs), "r"(out) |
| 438 : "cc"); | 421 : "cc"); |
| 439 #elif defined(__arm__) | 422 #elif defined(HOST_ARCH_ARM) |
| 440 asm volatile( | 423 asm volatile( |
| 441 "smull %1, ip, %1, %2;\n" | 424 "smull %1, ip, %1, %2;\n" |
| 442 "cmp ip, %1, ASR #31;\n" | 425 "cmp ip, %1, ASR #31;\n" |
| 443 "bne 1f;\n" | 426 "bne 1f;\n" |
| 444 "mov %0, $0;\n" | 427 "mov %0, $0;\n" |
| 445 "str %1, [%3, #0]\n" | 428 "str %1, [%3, #0]\n" |
| 446 "1:" | 429 "1:" |
| 447 : "+r"(res), "+r"(lhs) | 430 : "+r"(res), "+r"(lhs) |
| 448 : "r"(rhs), "r"(out) | 431 : "r"(rhs), "r"(out) |
| 449 : "cc", "r12"); | 432 : "cc", "r12"); |
| 433 #elif defined(HOST_ARCH_ARM64) |
| 434 int64_t prod_lo; |
| 435 asm volatile( |
| 436 "mul %1, %2, %3\n" |
| 437 "smulh %2, %2, %3\n" |
| 438 "cmp %2, %1, ASR #63;\n" |
| 439 "bne 1f;\n" |
| 440 "mov %0, #0;\n" |
| 441 "str %1, [%4, #0]\n" |
| 442 "1:" |
| 443 : "+r"(res), "=r"(prod_lo), "+r"(lhs) |
| 444 : "r"(rhs), "r"(out) |
| 445 : "cc"); |
| 450 #else | 446 #else |
| 451 #error "Unsupported platform" | 447 #error "Unsupported platform" |
| 452 #endif | 448 #endif |
| 453 return (res != 0); | 449 return (res != 0); |
| 454 } | 450 } |
| 455 | 451 |
| 456 | 452 |
| 457 #define LIKELY(cond) __builtin_expect((cond), 1) | 453 #define LIKELY(cond) __builtin_expect((cond), 1) |
| 458 | 454 |
| 459 | 455 |
| (...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 special_[kExceptionSpecialIndex] = raw_exception; | 1893 special_[kExceptionSpecialIndex] = raw_exception; |
| 1898 special_[kStacktraceSpecialIndex] = raw_stacktrace; | 1894 special_[kStacktraceSpecialIndex] = raw_stacktrace; |
| 1899 buf->Longjmp(); | 1895 buf->Longjmp(); |
| 1900 UNREACHABLE(); | 1896 UNREACHABLE(); |
| 1901 } | 1897 } |
| 1902 | 1898 |
| 1903 } // namespace dart | 1899 } // namespace dart |
| 1904 | 1900 |
| 1905 | 1901 |
| 1906 #endif // defined TARGET_ARCH_DBC | 1902 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |