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 |