 Chromium Code Reviews
 Chromium Code Reviews Issue 6170001:
  Direct call api functions (arm implementation)  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
    
  
    Issue 6170001:
  Direct call api functions (arm implementation)  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/| 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 30 matching lines...) Expand all Loading... | |
| 41 | 41 | 
| 42 // Only build the simulator if not compiling for real ARM hardware. | 42 // Only build the simulator if not compiling for real ARM hardware. | 
| 43 namespace assembler { | 43 namespace assembler { | 
| 44 namespace arm { | 44 namespace arm { | 
| 45 | 45 | 
| 46 using ::v8::internal::Object; | 46 using ::v8::internal::Object; | 
| 47 using ::v8::internal::PrintF; | 47 using ::v8::internal::PrintF; | 
| 48 using ::v8::internal::OS; | 48 using ::v8::internal::OS; | 
| 49 using ::v8::internal::ReadLine; | 49 using ::v8::internal::ReadLine; | 
| 50 using ::v8::internal::DeleteArray; | 50 using ::v8::internal::DeleteArray; | 
| 51 using ::v8::internal::ExternalReference; | |
| 51 | 52 | 
| 52 // This macro provides a platform independent use of sscanf. The reason for | 53 // This macro provides a platform independent use of sscanf. The reason for | 
| 53 // SScanF not being implemented in a platform independent way through | 54 // SScanF not being implemented in a platform independent way through | 
| 54 // ::v8::internal::OS in the same way as SNPrintF is that the | 55 // ::v8::internal::OS in the same way as SNPrintF is that the | 
| 55 // Windows C Run-Time Library does not provide vsscanf. | 56 // Windows C Run-Time Library does not provide vsscanf. | 
| 56 #define SScanF sscanf // NOLINT | 57 #define SScanF sscanf // NOLINT | 
| 57 | 58 | 
| 58 // The Debugger class is used by the simulator while debugging simulated ARM | 59 // The Debugger class is used by the simulator while debugging simulated ARM | 
| 59 // code. | 60 // code. | 
| 60 class Debugger { | 61 class Debugger { | 
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 | 739 | 
| 739 // When the generated code calls an external reference we need to catch that in | 740 // When the generated code calls an external reference we need to catch that in | 
| 740 // the simulator. The external reference will be a function compiled for the | 741 // the simulator. The external reference will be a function compiled for the | 
| 741 // host architecture. We need to call that function instead of trying to | 742 // host architecture. We need to call that function instead of trying to | 
| 742 // execute it with the simulator. We do that by redirecting the external | 743 // execute it with the simulator. We do that by redirecting the external | 
| 743 // reference to a svc (Supervisor Call) instruction that is handled by | 744 // reference to a svc (Supervisor Call) instruction that is handled by | 
| 744 // the simulator. We write the original destination of the jump just at a known | 745 // the simulator. We write the original destination of the jump just at a known | 
| 745 // offset from the svc instruction so the simulator knows what to call. | 746 // offset from the svc instruction so the simulator knows what to call. | 
| 746 class Redirection { | 747 class Redirection { | 
| 747 public: | 748 public: | 
| 748 Redirection(void* external_function, bool fp_return) | 749 Redirection(void* external_function, ExternalReference::Type type) | 
| 749 : external_function_(external_function), | 750 : external_function_(external_function), | 
| 750 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 751 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 
| 751 fp_return_(fp_return), | 752 type_(type), | 
| 752 next_(list_) { | 753 next_(list_) { | 
| 753 Simulator::current()-> | 754 Simulator::current()-> | 
| 754 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 755 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 
| 755 Instr::kInstrSize); | 756 Instr::kInstrSize); | 
| 756 list_ = this; | 757 list_ = this; | 
| 757 } | 758 } | 
| 758 | 759 | 
| 759 void* address_of_swi_instruction() { | 760 void* address_of_swi_instruction() { | 
| 760 return reinterpret_cast<void*>(&swi_instruction_); | 761 return reinterpret_cast<void*>(&swi_instruction_); | 
| 761 } | 762 } | 
| 762 | 763 | 
| 763 void* external_function() { return external_function_; } | 764 void* external_function() { return external_function_; } | 
| 764 bool fp_return() { return fp_return_; } | 765 ExternalReference::Type type() { return type_; } | 
| 765 | 766 | 
| 766 static Redirection* Get(void* external_function, bool fp_return) { | 767 static Redirection* Get(void* external_function, | 
| 768 ExternalReference::Type type) { | |
| 767 Redirection* current; | 769 Redirection* current; | 
| 768 for (current = list_; current != NULL; current = current->next_) { | 770 for (current = list_; current != NULL; current = current->next_) { | 
| 769 if (current->external_function_ == external_function) return current; | 771 if (current->external_function_ == external_function) return current; | 
| 770 } | 772 } | 
| 771 return new Redirection(external_function, fp_return); | 773 return new Redirection(external_function, type); | 
| 772 } | 774 } | 
| 773 | 775 | 
| 774 static Redirection* FromSwiInstruction(Instr* swi_instruction) { | 776 static Redirection* FromSwiInstruction(Instr* swi_instruction) { | 
| 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 777 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 
| 776 char* addr_of_redirection = | 778 char* addr_of_redirection = | 
| 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 779 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 
| 778 return reinterpret_cast<Redirection*>(addr_of_redirection); | 780 return reinterpret_cast<Redirection*>(addr_of_redirection); | 
| 779 } | 781 } | 
| 780 | 782 | 
| 781 private: | 783 private: | 
| 782 void* external_function_; | 784 void* external_function_; | 
| 783 uint32_t swi_instruction_; | 785 uint32_t swi_instruction_; | 
| 784 bool fp_return_; | 786 ExternalReference::Type type_; | 
| 785 Redirection* next_; | 787 Redirection* next_; | 
| 786 static Redirection* list_; | 788 static Redirection* list_; | 
| 787 }; | 789 }; | 
| 788 | 790 | 
| 789 | 791 | 
| 790 Redirection* Redirection::list_ = NULL; | 792 Redirection* Redirection::list_ = NULL; | 
| 791 | 793 | 
| 792 | 794 | 
| 793 void* Simulator::RedirectExternalReference(void* external_function, | 795 void* Simulator::RedirectExternalReference(void* external_function, | 
| 794 bool fp_return) { | 796 ExternalReference::Type type) { | 
| 795 Redirection* redirection = Redirection::Get(external_function, fp_return); | 797 Redirection* redirection = Redirection::Get(external_function, type); | 
| 796 return redirection->address_of_swi_instruction(); | 798 return redirection->address_of_swi_instruction(); | 
| 797 } | 799 } | 
| 798 | 800 | 
| 799 | 801 | 
| 800 // Get the active Simulator for the current thread. | 802 // Get the active Simulator for the current thread. | 
| 801 Simulator* Simulator::current() { | 803 Simulator* Simulator::current() { | 
| 802 Initialize(); | 804 Initialize(); | 
| 803 Simulator* sim = reinterpret_cast<Simulator*>( | 805 Simulator* sim = reinterpret_cast<Simulator*>( | 
| 804 v8::internal::Thread::GetThreadLocal(simulator_key)); | 806 v8::internal::Thread::GetThreadLocal(simulator_key)); | 
| 805 if (sim == NULL) { | 807 if (sim == NULL) { | 
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1526 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1528 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 
| 1527 int32_t arg1, | 1529 int32_t arg1, | 
| 1528 int32_t arg2, | 1530 int32_t arg2, | 
| 1529 int32_t arg3, | 1531 int32_t arg3, | 
| 1530 int32_t arg4); | 1532 int32_t arg4); | 
| 1531 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1533 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 
| 1532 int32_t arg1, | 1534 int32_t arg1, | 
| 1533 int32_t arg2, | 1535 int32_t arg2, | 
| 1534 int32_t arg3); | 1536 int32_t arg3); | 
| 1535 | 1537 | 
| 1538 // This signature supports direct call in to API function native callback | |
| 1539 // (refer to InvocationCallback in v8.h). | |
| 1540 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); | |
| 1536 | 1541 | 
| 1537 // Software interrupt instructions are used by the simulator to call into the | 1542 // Software interrupt instructions are used by the simulator to call into the | 
| 1538 // C-based V8 runtime. | 1543 // C-based V8 runtime. | 
| 1539 void Simulator::SoftwareInterrupt(Instr* instr) { | 1544 void Simulator::SoftwareInterrupt(Instr* instr) { | 
| 1540 int svc = instr->SvcField(); | 1545 int svc = instr->SvcField(); | 
| 1541 switch (svc) { | 1546 switch (svc) { | 
| 1542 case call_rt_redirected: { | 1547 case call_rt_redirected: { | 
| 1543 // Check if stack is aligned. Error if not aligned is reported below to | 1548 // Check if stack is aligned. Error if not aligned is reported below to | 
| 1544 // include information on the function called. | 1549 // include information on the function called. | 
| 1545 bool stack_aligned = | 1550 bool stack_aligned = | 
| 1546 (get_register(sp) | 1551 (get_register(sp) | 
| 1547 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1552 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 
| 1548 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1553 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 
| 1549 int32_t arg0 = get_register(r0); | 1554 int32_t arg0 = get_register(r0); | 
| 1550 int32_t arg1 = get_register(r1); | 1555 int32_t arg1 = get_register(r1); | 
| 1551 int32_t arg2 = get_register(r2); | 1556 int32_t arg2 = get_register(r2); | 
| 1552 int32_t arg3 = get_register(r3); | 1557 int32_t arg3 = get_register(r3); | 
| 1553 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1558 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 
| 1554 int32_t arg4 = *stack_pointer; | 1559 int32_t arg4 = *stack_pointer; | 
| 1555 // This is dodgy but it works because the C entry stubs are never moved. | 1560 // This is dodgy but it works because the C entry stubs are never moved. | 
| 1556 // See comment in codegen-arm.cc and bug 1242173. | 1561 // See comment in codegen-arm.cc and bug 1242173. | 
| 1557 int32_t saved_lr = get_register(lr); | 1562 int32_t saved_lr = get_register(lr); | 
| 1558 if (redirection->fp_return()) { | 1563 intptr_t external = | 
| 1559 intptr_t external = | 1564 reinterpret_cast<intptr_t>(redirection->external_function()); | 
| 1560 reinterpret_cast<intptr_t>(redirection->external_function()); | 1565 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { | 
| 1561 SimulatorRuntimeFPCall target = | 1566 SimulatorRuntimeFPCall target = | 
| 1562 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1567 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 
| 1563 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1568 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 
| 1564 double x, y; | 1569 double x, y; | 
| 1565 GetFpArgs(&x, &y); | 1570 GetFpArgs(&x, &y); | 
| 1566 PrintF("Call to host function at %p with args %f, %f", | 1571 PrintF("Call to host function at %p with args %f, %f", | 
| 1567 FUNCTION_ADDR(target), x, y); | 1572 FUNCTION_ADDR(target), x, y); | 
| 1568 if (!stack_aligned) { | 1573 if (!stack_aligned) { | 
| 1569 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1574 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 
| 1570 } | 1575 } | 
| 1571 PrintF("\n"); | 1576 PrintF("\n"); | 
| 1572 } | 1577 } | 
| 1573 CHECK(stack_aligned); | 1578 CHECK(stack_aligned); | 
| 1574 double result = target(arg0, arg1, arg2, arg3); | 1579 double result = target(arg0, arg1, arg2, arg3); | 
| 1575 SetFpResult(result); | 1580 SetFpResult(result); | 
| 1581 } else if (redirection->type() == ExternalReference::DIRECT_CALL) { | |
| 1582 SimulatorRuntimeApiCall target = | |
| 1583 reinterpret_cast<SimulatorRuntimeApiCall>(external); | |
| 1584 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | |
| 1585 PrintF( | |
| 1586 "Call to host function at %p args %08x", | |
| 1587 FUNCTION_ADDR(target), | |
| 1588 arg0); | |
| 1589 if (!stack_aligned) { | |
| 1590 PrintF(" with unaligned stack %08x\n", get_register(sp)); | |
| 1591 } | |
| 1592 PrintF("\n"); | |
| 1593 } | |
| 1594 CHECK(stack_aligned); | |
| 1595 v8::Handle<v8::Value> result = target(arg0); | |
| 1596 if (::v8::internal::FLAG_trace_sim) { | |
| 1597 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); | |
| 1598 } | |
| 1599 set_register(r0, (int32_t) *result); | |
| 1576 } else { | 1600 } else { | 
| 
Erik Corry
2011/01/24 21:45:16
The usual pattern in V8 is to add a line here sayi
 
Zaheer
2011/01/25 07:39:52
Done.
 | |
| 1577 intptr_t external = | |
| 1578 reinterpret_cast<int32_t>(redirection->external_function()); | |
| 1579 SimulatorRuntimeCall target = | 1601 SimulatorRuntimeCall target = | 
| 1580 reinterpret_cast<SimulatorRuntimeCall>(external); | 1602 reinterpret_cast<SimulatorRuntimeCall>(external); | 
| 1581 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1603 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 
| 1582 PrintF( | 1604 PrintF( | 
| 1583 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1605 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 
| 1584 FUNCTION_ADDR(target), | 1606 FUNCTION_ADDR(target), | 
| 1585 arg0, | 1607 arg0, | 
| 1586 arg1, | 1608 arg1, | 
| 1587 arg2, | 1609 arg2, | 
| 1588 arg3, | 1610 arg3, | 
| (...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3044 uintptr_t address = *stack_slot; | 3066 uintptr_t address = *stack_slot; | 
| 3045 set_register(sp, current_sp + sizeof(uintptr_t)); | 3067 set_register(sp, current_sp + sizeof(uintptr_t)); | 
| 3046 return address; | 3068 return address; | 
| 3047 } | 3069 } | 
| 3048 | 3070 | 
| 3049 } } // namespace assembler::arm | 3071 } } // namespace assembler::arm | 
| 3050 | 3072 | 
| 3051 #endif // USE_SIMULATOR | 3073 #endif // USE_SIMULATOR | 
| 3052 | 3074 | 
| 3053 #endif // V8_TARGET_ARCH_ARM | 3075 #endif // V8_TARGET_ARCH_ARM | 
| OLD | NEW |