| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM) | 10 #if defined(TARGET_ARCH_ARM) |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 class Redirection { | 794 class Redirection { |
| 795 public: | 795 public: |
| 796 uword address_of_svc_instruction() { | 796 uword address_of_svc_instruction() { |
| 797 return reinterpret_cast<uword>(&svc_instruction_); | 797 return reinterpret_cast<uword>(&svc_instruction_); |
| 798 } | 798 } |
| 799 | 799 |
| 800 uword external_function() const { return external_function_; } | 800 uword external_function() const { return external_function_; } |
| 801 | 801 |
| 802 Simulator::CallKind call_kind() const { return call_kind_; } | 802 Simulator::CallKind call_kind() const { return call_kind_; } |
| 803 | 803 |
| 804 int argument_count() const { return argument_count_; } |
| 805 |
| 804 static Redirection* Get(uword external_function, | 806 static Redirection* Get(uword external_function, |
| 805 Simulator::CallKind call_kind) { | 807 Simulator::CallKind call_kind, |
| 808 int argument_count) { |
| 806 Redirection* current; | 809 Redirection* current; |
| 807 for (current = list_; current != NULL; current = current->next_) { | 810 for (current = list_; current != NULL; current = current->next_) { |
| 808 if (current->external_function_ == external_function) return current; | 811 if (current->external_function_ == external_function) return current; |
| 809 } | 812 } |
| 810 return new Redirection(external_function, call_kind); | 813 return new Redirection(external_function, call_kind, argument_count); |
| 811 } | 814 } |
| 812 | 815 |
| 813 static Redirection* FromSvcInstruction(Instr* svc_instruction) { | 816 static Redirection* FromSvcInstruction(Instr* svc_instruction) { |
| 814 char* addr_of_svc = reinterpret_cast<char*>(svc_instruction); | 817 char* addr_of_svc = reinterpret_cast<char*>(svc_instruction); |
| 815 char* addr_of_redirection = | 818 char* addr_of_redirection = |
| 816 addr_of_svc - OFFSET_OF(Redirection, svc_instruction_); | 819 addr_of_svc - OFFSET_OF(Redirection, svc_instruction_); |
| 817 return reinterpret_cast<Redirection*>(addr_of_redirection); | 820 return reinterpret_cast<Redirection*>(addr_of_redirection); |
| 818 } | 821 } |
| 819 | 822 |
| 820 private: | 823 private: |
| 821 static const int32_t kRedirectSvcInstruction = | 824 static const int32_t kRedirectSvcInstruction = |
| 822 ((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode); | 825 ((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode); |
| 823 Redirection(uword external_function, Simulator::CallKind call_kind) | 826 Redirection(uword external_function, |
| 827 Simulator::CallKind call_kind, |
| 828 int argument_count) |
| 824 : external_function_(external_function), | 829 : external_function_(external_function), |
| 825 call_kind_(call_kind), | 830 call_kind_(call_kind), |
| 831 argument_count_(argument_count), |
| 826 svc_instruction_(kRedirectSvcInstruction), | 832 svc_instruction_(kRedirectSvcInstruction), |
| 827 next_(list_) { | 833 next_(list_) { |
| 828 list_ = this; | 834 list_ = this; |
| 829 } | 835 } |
| 830 | 836 |
| 831 uword external_function_; | 837 uword external_function_; |
| 832 Simulator::CallKind call_kind_; | 838 Simulator::CallKind call_kind_; |
| 839 int argument_count_; |
| 833 uint32_t svc_instruction_; | 840 uint32_t svc_instruction_; |
| 834 Redirection* next_; | 841 Redirection* next_; |
| 835 static Redirection* list_; | 842 static Redirection* list_; |
| 836 }; | 843 }; |
| 837 | 844 |
| 838 | 845 |
| 839 Redirection* Redirection::list_ = NULL; | 846 Redirection* Redirection::list_ = NULL; |
| 840 | 847 |
| 841 | 848 |
| 842 uword Simulator::RedirectExternalReference(uword function, CallKind call_kind) { | 849 uword Simulator::RedirectExternalReference(uword function, |
| 843 Redirection* redirection = Redirection::Get(function, call_kind); | 850 CallKind call_kind, |
| 851 int argument_count) { |
| 852 Redirection* redirection = |
| 853 Redirection::Get(function, call_kind, argument_count); |
| 844 return redirection->address_of_svc_instruction(); | 854 return redirection->address_of_svc_instruction(); |
| 845 } | 855 } |
| 846 | 856 |
| 847 | 857 |
| 848 // Get the active Simulator for the current isolate. | 858 // Get the active Simulator for the current isolate. |
| 849 Simulator* Simulator::Current() { | 859 Simulator* Simulator::Current() { |
| 850 Simulator* simulator = Isolate::Current()->simulator(); | 860 Simulator* simulator = Isolate::Current()->simulator(); |
| 851 if (simulator == NULL) { | 861 if (simulator == NULL) { |
| 852 simulator = new Simulator(); | 862 simulator = new Simulator(); |
| 853 Isolate::Current()->set_simulator(simulator); | 863 Isolate::Current()->set_simulator(simulator); |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 } | 1433 } |
| 1424 | 1434 |
| 1425 | 1435 |
| 1426 // Calls into the Dart runtime are based on this interface. | 1436 // Calls into the Dart runtime are based on this interface. |
| 1427 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1437 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 1428 | 1438 |
| 1429 // Calls to leaf Dart runtime functions are based on this interface. | 1439 // Calls to leaf Dart runtime functions are based on this interface. |
| 1430 typedef int32_t (*SimulatorLeafRuntimeCall)( | 1440 typedef int32_t (*SimulatorLeafRuntimeCall)( |
| 1431 int32_t r0, int32_t r1, int32_t r2, int32_t r3); | 1441 int32_t r0, int32_t r1, int32_t r2, int32_t r3); |
| 1432 | 1442 |
| 1443 // Calls to leaf float Dart runtime functions are based on this interface. |
| 1444 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
| 1445 |
| 1433 // Calls to native Dart functions are based on this interface. | 1446 // Calls to native Dart functions are based on this interface. |
| 1434 typedef void (*SimulatorNativeCall)(NativeArguments* arguments); | 1447 typedef void (*SimulatorNativeCall)(NativeArguments* arguments); |
| 1435 | 1448 |
| 1436 | 1449 |
| 1437 void Simulator::SupervisorCall(Instr* instr) { | 1450 void Simulator::SupervisorCall(Instr* instr) { |
| 1438 int svc = instr->SvcField(); | 1451 int svc = instr->SvcField(); |
| 1439 switch (svc) { | 1452 switch (svc) { |
| 1440 case kRedirectionSvcCode: { | 1453 case kRedirectionSvcCode: { |
| 1441 SimulatorSetjmpBuffer buffer(this); | 1454 SimulatorSetjmpBuffer buffer(this); |
| 1442 | 1455 |
| 1443 if (!setjmp(buffer.buffer_)) { | 1456 if (!setjmp(buffer.buffer_)) { |
| 1444 int32_t saved_lr = get_register(LR); | 1457 int32_t saved_lr = get_register(LR); |
| 1445 Redirection* redirection = Redirection::FromSvcInstruction(instr); | 1458 Redirection* redirection = Redirection::FromSvcInstruction(instr); |
| 1446 uword external = redirection->external_function(); | 1459 uword external = redirection->external_function(); |
| 1447 if (FLAG_trace_sim) { | 1460 if (FLAG_trace_sim) { |
| 1448 OS::Print("Call to host function at 0x%"Pd"\n", external); | 1461 OS::Print("Call to host function at 0x%"Pd"\n", external); |
| 1449 } | 1462 } |
| 1450 | 1463 |
| 1451 if (redirection->call_kind() != kLeafRuntimeCall) { | 1464 if ((redirection->call_kind() == kRuntimeCall) || |
| 1465 (redirection->call_kind() == kNativeCall)) { |
| 1452 // The top_exit_frame_info of the current isolate points to the top of | 1466 // The top_exit_frame_info of the current isolate points to the top of |
| 1453 // the simulator stack. | 1467 // the simulator stack. |
| 1454 ASSERT((StackTop() - Isolate::Current()->top_exit_frame_info()) < | 1468 ASSERT((StackTop() - Isolate::Current()->top_exit_frame_info()) < |
| 1455 Isolate::GetSpecifiedStackSize()); | 1469 Isolate::GetSpecifiedStackSize()); |
| 1456 // Set the top_exit_frame_info of this simulator to the native stack. | 1470 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1457 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1471 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1458 } | 1472 } |
| 1459 if (redirection->call_kind() == kRuntimeCall) { | 1473 if (redirection->call_kind() == kRuntimeCall) { |
| 1460 NativeArguments arguments; | 1474 NativeArguments arguments; |
| 1461 ASSERT(sizeof(NativeArguments) == 4*kWordSize); | 1475 ASSERT(sizeof(NativeArguments) == 4*kWordSize); |
| 1462 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); | 1476 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); |
| 1463 arguments.argc_tag_ = get_register(R1); | 1477 arguments.argc_tag_ = get_register(R1); |
| 1464 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); | 1478 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); |
| 1465 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); | 1479 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); |
| 1466 SimulatorRuntimeCall target = | 1480 SimulatorRuntimeCall target = |
| 1467 reinterpret_cast<SimulatorRuntimeCall>(external); | 1481 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1468 target(arguments); | 1482 target(arguments); |
| 1469 set_register(R0, icount_); // Zap result register from void function. | 1483 set_register(R0, icount_); // Zap result register from void function. |
| 1470 } else if (redirection->call_kind() == kLeafRuntimeCall) { | 1484 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
| 1485 ASSERT((0 <= redirection->argument_count()) && |
| 1486 (redirection->argument_count() <= 4)); |
| 1471 int32_t r0 = get_register(R0); | 1487 int32_t r0 = get_register(R0); |
| 1472 int32_t r1 = get_register(R1); | 1488 int32_t r1 = get_register(R1); |
| 1473 int32_t r2 = get_register(R2); | 1489 int32_t r2 = get_register(R2); |
| 1474 int32_t r3 = get_register(R3); | 1490 int32_t r3 = get_register(R3); |
| 1475 SimulatorLeafRuntimeCall target = | 1491 SimulatorLeafRuntimeCall target = |
| 1476 reinterpret_cast<SimulatorLeafRuntimeCall>(external); | 1492 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
| 1477 r0 = target(r0, r1, r2, r3); | 1493 r0 = target(r0, r1, r2, r3); |
| 1478 set_register(R0, r0); // Set returned result from function. | 1494 set_register(R0, r0); // Set returned result from function. |
| 1495 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
| 1496 ASSERT((0 <= redirection->argument_count()) && |
| 1497 (redirection->argument_count() <= 2)); |
| 1498 // We currently use 'hardfp' ('gnueabihf') rather than 'softfp' |
| 1499 // ('gnueabi') float ABI for leaf runtime calls, i.e. double values |
| 1500 // are passed and returned in vfp registers rather than in integer |
| 1501 // register pairs. |
| 1502 SimulatorLeafFloatRuntimeCall target = |
| 1503 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
| 1504 double d0 = get_dregister(D0); |
| 1505 double d1 = get_dregister(D1); |
| 1506 d0 = target(d0, d1); |
| 1507 set_dregister(D0, d0); |
| 1479 } else { | 1508 } else { |
| 1480 ASSERT(redirection->call_kind() == kNativeCall); | 1509 ASSERT(redirection->call_kind() == kNativeCall); |
| 1481 NativeArguments* arguments; | 1510 NativeArguments* arguments; |
| 1482 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); | 1511 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1483 SimulatorNativeCall target = | 1512 SimulatorNativeCall target = |
| 1484 reinterpret_cast<SimulatorNativeCall>(external); | 1513 reinterpret_cast<SimulatorNativeCall>(external); |
| 1485 target(arguments); | 1514 target(arguments); |
| 1486 set_register(R0, icount_); // Zap result register from void function. | 1515 set_register(R0, icount_); // Zap result register from void function. |
| 1487 } | 1516 } |
| 1488 set_top_exit_frame_info(0); | 1517 set_top_exit_frame_info(0); |
| 1489 | 1518 |
| 1490 // Zap caller-saved registers, since the actual runtime call could have | 1519 // Zap caller-saved registers, since the actual runtime call could have |
| 1491 // used them. | 1520 // used them. |
| 1492 set_register(R1, icount_); | 1521 set_register(R1, icount_); |
| 1493 set_register(R2, icount_); | 1522 set_register(R2, icount_); |
| 1494 set_register(R3, icount_); | 1523 set_register(R3, icount_); |
| 1495 set_register(IP, icount_); | 1524 set_register(IP, icount_); |
| 1496 set_register(LR, icount_); | 1525 set_register(LR, icount_); |
| 1497 double zap_dvalue = static_cast<double>(icount_); | 1526 double zap_dvalue = static_cast<double>(icount_); |
| 1498 for (int i = D0; i <= D7; i++) { | 1527 // Do not zap D0, as it may contain a float result. |
| 1528 for (int i = D1; i <= D7; i++) { |
| 1499 set_dregister(static_cast<DRegister>(i), zap_dvalue); | 1529 set_dregister(static_cast<DRegister>(i), zap_dvalue); |
| 1500 } | 1530 } |
| 1501 // The above loop also zaps overlapping registers S0-S15. | 1531 // The above loop also zaps overlapping registers S2-S15. |
| 1502 // Registers D8-D15 (overlapping with S16-S31) are preserved. | 1532 // Registers D8-D15 (overlapping with S16-S31) are preserved. |
| 1503 #ifdef VFPv3_D32 | 1533 #ifdef VFPv3_D32 |
| 1504 for (int i = D16; i <= D31; i++) { | 1534 for (int i = D16; i <= D31; i++) { |
| 1505 set_dregister(static_cast<DRegister>(i), zap_dvalue); | 1535 set_dregister(static_cast<DRegister>(i), zap_dvalue); |
| 1506 } | 1536 } |
| 1507 #endif // VFPv3_D32 | 1537 #endif // VFPv3_D32 |
| 1508 | 1538 |
| 1509 // Return. | 1539 // Return. |
| 1510 set_pc(saved_lr); | 1540 set_pc(saved_lr); |
| 1511 } else { | 1541 } else { |
| (...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3049 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3079 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
| 3050 } | 3080 } |
| 3051 buf->Longjmp(); | 3081 buf->Longjmp(); |
| 3052 } | 3082 } |
| 3053 | 3083 |
| 3054 } // namespace dart | 3084 } // namespace dart |
| 3055 | 3085 |
| 3056 #endif // !defined(HOST_ARCH_ARM) | 3086 #endif // !defined(HOST_ARCH_ARM) |
| 3057 | 3087 |
| 3058 #endif // defined TARGET_ARCH_ARM | 3088 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |