OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 | 737 |
738 // When the generated code calls an external reference we need to catch that in | 738 // When the generated code calls an external reference we need to catch that in |
739 // the simulator. The external reference will be a function compiled for the | 739 // the simulator. The external reference will be a function compiled for the |
740 // host architecture. We need to call that function instead of trying to | 740 // host architecture. We need to call that function instead of trying to |
741 // execute it with the simulator. We do that by redirecting the external | 741 // execute it with the simulator. We do that by redirecting the external |
742 // reference to a svc (Supervisor Call) instruction that is handled by | 742 // reference to a svc (Supervisor Call) instruction that is handled by |
743 // the simulator. We write the original destination of the jump just at a known | 743 // the simulator. We write the original destination of the jump just at a known |
744 // offset from the svc instruction so the simulator knows what to call. | 744 // offset from the svc instruction so the simulator knows what to call. |
745 class Redirection { | 745 class Redirection { |
746 public: | 746 public: |
747 Redirection(void* external_function, bool fp_return) | 747 Redirection(void* external_function, ExternalReference::Type type) |
748 : external_function_(external_function), | 748 : external_function_(external_function), |
749 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), | 749 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), |
750 fp_return_(fp_return), | 750 type_(type), |
751 next_(list_) { | 751 next_(list_) { |
752 Simulator::current()-> | 752 Simulator::current()-> |
753 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 753 FlushICache(reinterpret_cast<void*>(&swi_instruction_), |
754 Instruction::kInstrSize); | 754 Instruction::kInstrSize); |
755 list_ = this; | 755 list_ = this; |
756 } | 756 } |
757 | 757 |
758 void* address_of_swi_instruction() { | 758 void* address_of_swi_instruction() { |
759 return reinterpret_cast<void*>(&swi_instruction_); | 759 return reinterpret_cast<void*>(&swi_instruction_); |
760 } | 760 } |
761 | 761 |
762 void* external_function() { return external_function_; } | 762 void* external_function() { return external_function_; } |
763 bool fp_return() { return fp_return_; } | 763 ExternalReference::Type type() { return type_; } |
764 | 764 |
765 static Redirection* Get(void* external_function, bool fp_return) { | 765 static Redirection* Get(void* external_function, |
| 766 ExternalReference::Type type) { |
766 Redirection* current; | 767 Redirection* current; |
767 for (current = list_; current != NULL; current = current->next_) { | 768 for (current = list_; current != NULL; current = current->next_) { |
768 if (current->external_function_ == external_function) return current; | 769 if (current->external_function_ == external_function) return current; |
769 } | 770 } |
770 return new Redirection(external_function, fp_return); | 771 return new Redirection(external_function, type); |
771 } | 772 } |
772 | 773 |
773 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { | 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { |
774 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
775 char* addr_of_redirection = | 776 char* addr_of_redirection = |
776 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
777 return reinterpret_cast<Redirection*>(addr_of_redirection); | 778 return reinterpret_cast<Redirection*>(addr_of_redirection); |
778 } | 779 } |
779 | 780 |
780 private: | 781 private: |
781 void* external_function_; | 782 void* external_function_; |
782 uint32_t swi_instruction_; | 783 uint32_t swi_instruction_; |
783 bool fp_return_; | 784 ExternalReference::Type type_; |
784 Redirection* next_; | 785 Redirection* next_; |
785 static Redirection* list_; | 786 static Redirection* list_; |
786 }; | 787 }; |
787 | 788 |
788 | 789 |
789 Redirection* Redirection::list_ = NULL; | 790 Redirection* Redirection::list_ = NULL; |
790 | 791 |
791 | 792 |
792 void* Simulator::RedirectExternalReference(void* external_function, | 793 void* Simulator::RedirectExternalReference(void* external_function, |
793 bool fp_return) { | 794 ExternalReference::Type type) { |
794 Redirection* redirection = Redirection::Get(external_function, fp_return); | 795 Redirection* redirection = Redirection::Get(external_function, type); |
795 return redirection->address_of_swi_instruction(); | 796 return redirection->address_of_swi_instruction(); |
796 } | 797 } |
797 | 798 |
798 | 799 |
799 // Get the active Simulator for the current thread. | 800 // Get the active Simulator for the current thread. |
800 Simulator* Simulator::current() { | 801 Simulator* Simulator::current() { |
801 Initialize(); | 802 Initialize(); |
802 Simulator* sim = reinterpret_cast<Simulator*>( | 803 Simulator* sim = reinterpret_cast<Simulator*>( |
803 v8::internal::Thread::GetThreadLocal(simulator_key)); | 804 v8::internal::Thread::GetThreadLocal(simulator_key)); |
804 if (sim == NULL) { | 805 if (sim == NULL) { |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1522 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
1522 int32_t arg1, | 1523 int32_t arg1, |
1523 int32_t arg2, | 1524 int32_t arg2, |
1524 int32_t arg3, | 1525 int32_t arg3, |
1525 int32_t arg4); | 1526 int32_t arg4); |
1526 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1527 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
1527 int32_t arg1, | 1528 int32_t arg1, |
1528 int32_t arg2, | 1529 int32_t arg2, |
1529 int32_t arg3); | 1530 int32_t arg3); |
1530 | 1531 |
| 1532 // This signature supports direct call in to API function native callback |
| 1533 // (refer to InvocationCallback in v8.h). |
| 1534 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); |
1531 | 1535 |
1532 // Software interrupt instructions are used by the simulator to call into the | 1536 // Software interrupt instructions are used by the simulator to call into the |
1533 // C-based V8 runtime. | 1537 // C-based V8 runtime. |
1534 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1538 void Simulator::SoftwareInterrupt(Instruction* instr) { |
1535 int svc = instr->SvcValue(); | 1539 int svc = instr->SvcValue(); |
1536 switch (svc) { | 1540 switch (svc) { |
1537 case kCallRtRedirected: { | 1541 case kCallRtRedirected: { |
1538 // Check if stack is aligned. Error if not aligned is reported below to | 1542 // Check if stack is aligned. Error if not aligned is reported below to |
1539 // include information on the function called. | 1543 // include information on the function called. |
1540 bool stack_aligned = | 1544 bool stack_aligned = |
1541 (get_register(sp) | 1545 (get_register(sp) |
1542 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1546 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
1543 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1547 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
1544 int32_t arg0 = get_register(r0); | 1548 int32_t arg0 = get_register(r0); |
1545 int32_t arg1 = get_register(r1); | 1549 int32_t arg1 = get_register(r1); |
1546 int32_t arg2 = get_register(r2); | 1550 int32_t arg2 = get_register(r2); |
1547 int32_t arg3 = get_register(r3); | 1551 int32_t arg3 = get_register(r3); |
1548 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1552 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
1549 int32_t arg4 = *stack_pointer; | 1553 int32_t arg4 = *stack_pointer; |
1550 // This is dodgy but it works because the C entry stubs are never moved. | 1554 // This is dodgy but it works because the C entry stubs are never moved. |
1551 // See comment in codegen-arm.cc and bug 1242173. | 1555 // See comment in codegen-arm.cc and bug 1242173. |
1552 int32_t saved_lr = get_register(lr); | 1556 int32_t saved_lr = get_register(lr); |
1553 if (redirection->fp_return()) { | 1557 intptr_t external = |
1554 intptr_t external = | 1558 reinterpret_cast<intptr_t>(redirection->external_function()); |
1555 reinterpret_cast<intptr_t>(redirection->external_function()); | 1559 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
1556 SimulatorRuntimeFPCall target = | 1560 SimulatorRuntimeFPCall target = |
1557 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1561 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
1558 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1562 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1559 double x, y; | 1563 double x, y; |
1560 GetFpArgs(&x, &y); | 1564 GetFpArgs(&x, &y); |
1561 PrintF("Call to host function at %p with args %f, %f", | 1565 PrintF("Call to host function at %p with args %f, %f", |
1562 FUNCTION_ADDR(target), x, y); | 1566 FUNCTION_ADDR(target), x, y); |
1563 if (!stack_aligned) { | 1567 if (!stack_aligned) { |
1564 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1568 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1565 } | 1569 } |
1566 PrintF("\n"); | 1570 PrintF("\n"); |
1567 } | 1571 } |
1568 CHECK(stack_aligned); | 1572 CHECK(stack_aligned); |
1569 double result = target(arg0, arg1, arg2, arg3); | 1573 double result = target(arg0, arg1, arg2, arg3); |
1570 SetFpResult(result); | 1574 SetFpResult(result); |
| 1575 } else if (redirection->type() == ExternalReference::DIRECT_CALL) { |
| 1576 SimulatorRuntimeApiCall target = |
| 1577 reinterpret_cast<SimulatorRuntimeApiCall>(external); |
| 1578 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1579 PrintF( |
| 1580 "Call to host function at %p args %08x", |
| 1581 FUNCTION_ADDR(target), |
| 1582 arg0); |
| 1583 if (!stack_aligned) { |
| 1584 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1585 } |
| 1586 PrintF("\n"); |
| 1587 } |
| 1588 CHECK(stack_aligned); |
| 1589 v8::Handle<v8::Value> result = target(arg0); |
| 1590 if (::v8::internal::FLAG_trace_sim) { |
| 1591 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); |
| 1592 } |
| 1593 set_register(r0, (int32_t) *result); |
1571 } else { | 1594 } else { |
1572 intptr_t external = | 1595 // builtin/runtime call. |
1573 reinterpret_cast<int32_t>(redirection->external_function()); | 1596 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); |
1574 SimulatorRuntimeCall target = | 1597 SimulatorRuntimeCall target = |
1575 reinterpret_cast<SimulatorRuntimeCall>(external); | 1598 reinterpret_cast<SimulatorRuntimeCall>(external); |
1576 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1599 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1577 PrintF( | 1600 PrintF( |
1578 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1601 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", |
1579 FUNCTION_ADDR(target), | 1602 FUNCTION_ADDR(target), |
1580 arg0, | 1603 arg0, |
1581 arg1, | 1604 arg1, |
1582 arg2, | 1605 arg2, |
1583 arg3, | 1606 arg3, |
(...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3052 uintptr_t address = *stack_slot; | 3075 uintptr_t address = *stack_slot; |
3053 set_register(sp, current_sp + sizeof(uintptr_t)); | 3076 set_register(sp, current_sp + sizeof(uintptr_t)); |
3054 return address; | 3077 return address; |
3055 } | 3078 } |
3056 | 3079 |
3057 } } // namespace v8::internal | 3080 } } // namespace v8::internal |
3058 | 3081 |
3059 #endif // USE_SIMULATOR | 3082 #endif // USE_SIMULATOR |
3060 | 3083 |
3061 #endif // V8_TARGET_ARCH_ARM | 3084 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |