1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/execution/simulator-base.h"
6 
7 #include "src/execution/isolate.h"
8 #include "src/execution/simulator.h"
9 
10 #if defined(USE_SIMULATOR)
11 
12 namespace v8 {
13 namespace internal {
14 
15 // static
16 base::Mutex* SimulatorBase::redirection_mutex_ = nullptr;
17 
18 // static
19 Redirection* SimulatorBase::redirection_ = nullptr;
20 
21 // static
22 base::Mutex* SimulatorBase::i_cache_mutex_ = nullptr;
23 
24 // static
25 base::CustomMatcherHashMap* SimulatorBase::i_cache_ = nullptr;
26 
27 // static
InitializeOncePerProcess()28 void SimulatorBase::InitializeOncePerProcess() {
29   DCHECK_NULL(redirection_mutex_);
30   redirection_mutex_ = new base::Mutex();
31 
32   DCHECK_NULL(i_cache_mutex_);
33   i_cache_mutex_ = new base::Mutex();
34 
35   DCHECK_NULL(i_cache_);
36   i_cache_ = new base::CustomMatcherHashMap(&Simulator::ICacheMatch);
37 }
38 
39 // static
GlobalTearDown()40 void SimulatorBase::GlobalTearDown() {
41   delete redirection_mutex_;
42   redirection_mutex_ = nullptr;
43 
44   Redirection::DeleteChain(redirection_);
45   redirection_ = nullptr;
46 
47   delete i_cache_mutex_;
48   i_cache_mutex_ = nullptr;
49 
50   if (i_cache_ != nullptr) {
51     for (base::HashMap::Entry* entry = i_cache_->Start(); entry != nullptr;
52          entry = i_cache_->Next(entry)) {
53       delete static_cast<CachePage*>(entry->value);
54     }
55   }
56   delete i_cache_;
57   i_cache_ = nullptr;
58 }
59 
60 // static
RedirectExternalReference(Address external_function,ExternalReference::Type type)61 Address SimulatorBase::RedirectExternalReference(Address external_function,
62                                                  ExternalReference::Type type) {
63   base::MutexGuard lock_guard(Simulator::redirection_mutex());
64   Redirection* redirection = Redirection::Get(external_function, type);
65   return redirection->address_of_instruction();
66 }
67 
Redirection(Address external_function,ExternalReference::Type type)68 Redirection::Redirection(Address external_function,
69                          ExternalReference::Type type)
70     : external_function_(external_function), type_(type), next_(nullptr) {
71   next_ = Simulator::redirection();
72   base::MutexGuard lock_guard(Simulator::i_cache_mutex());
73   Simulator::SetRedirectInstruction(
74       reinterpret_cast<Instruction*>(address_of_instruction()));
75   Simulator::FlushICache(Simulator::i_cache(),
76                          reinterpret_cast<void*>(&instruction_),
77                          sizeof(instruction_));
78   Simulator::set_redirection(this);
79 #if ABI_USES_FUNCTION_DESCRIPTORS
80   function_descriptor_[0] = reinterpret_cast<intptr_t>(&instruction_);
81   function_descriptor_[1] = 0;
82   function_descriptor_[2] = 0;
83 #endif
84 }
85 
86 // static
Get(Address external_function,ExternalReference::Type type)87 Redirection* Redirection::Get(Address external_function,
88                               ExternalReference::Type type) {
89   Redirection* current = Simulator::redirection();
90   for (; current != nullptr; current = current->next_) {
91     if (current->external_function_ == external_function &&
92         current->type_ == type) {
93       return current;
94     }
95   }
96   return new Redirection(external_function, type);
97 }
98 
99 }  // namespace internal
100 }  // namespace v8
101 
102 #endif  // defined(USE_SIMULATOR)
103