| 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 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 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3100 uintptr_t address = *stack_slot; | 3123 uintptr_t address = *stack_slot; |
| 3101 set_register(sp, current_sp + sizeof(uintptr_t)); | 3124 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3102 return address; | 3125 return address; |
| 3103 } | 3126 } |
| 3104 | 3127 |
| 3105 } } // namespace v8::internal | 3128 } } // namespace v8::internal |
| 3106 | 3129 |
| 3107 #endif // USE_SIMULATOR | 3130 #endif // USE_SIMULATOR |
| 3108 | 3131 |
| 3109 #endif // V8_TARGET_ARCH_ARM | 3132 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |