OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/instructions.h" | 10 #include "vm/instructions.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 void CodePatcher::PatchInstanceCallAt(uword return_address, | 15 void CodePatcher::PatchInstanceCallAt(uword return_address, |
16 const Code& code, | 16 const Code& code, |
17 uword new_target) { | 17 const Code& target) { |
18 ASSERT(code.ContainsInstructionAt(return_address)); | 18 ASSERT(code.ContainsInstructionAt(return_address)); |
19 CallPattern call(return_address, code); | 19 CallPattern call(return_address, code); |
20 call.SetTargetAddress(new_target); | 20 call.SetTargetCode(target); |
21 } | 21 } |
22 | 22 |
23 | 23 |
24 class PoolPointerCall : public ValueObject { | 24 class PoolPointerCall : public ValueObject { |
25 public: | 25 public: |
26 PoolPointerCall(uword pc, const Code& code) | 26 PoolPointerCall(uword pc, const Code& code) |
27 : end_(pc), | 27 : end_(pc), |
28 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 28 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
29 // Last instruction: blr ip0. | 29 // Last instruction: blr ip0. |
30 ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200); | 30 ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200); |
31 InstructionPattern::DecodeLoadWordFromPool( | 31 InstructionPattern::DecodeLoadWordFromPool( |
32 end_ - Instr::kInstrSize, ®_, &index_); | 32 end_ - 2 * Instr::kInstrSize, ®_, &index_); |
33 } | 33 } |
34 | 34 |
35 intptr_t pp_index() const { | 35 intptr_t pp_index() const { |
36 return index_; | 36 return index_; |
37 } | 37 } |
38 | 38 |
39 uword Target() const { | 39 RawCode* Target() const { |
40 return object_pool_.RawValueAt(pp_index()); | 40 return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(pp_index())); |
41 } | 41 } |
42 | 42 |
43 void SetTarget(uword target) const { | 43 void SetTarget(const Code& target) const { |
44 object_pool_.SetRawValueAt(pp_index(), target); | 44 object_pool_.SetObjectAt(pp_index(), target); |
45 // No need to flush the instruction cache, since the code is not modified. | 45 // No need to flush the instruction cache, since the code is not modified. |
46 } | 46 } |
47 | 47 |
48 private: | 48 private: |
49 static const int kCallPatternSize = 3 * Instr::kInstrSize; | 49 static const int kCallPatternSize = 3 * Instr::kInstrSize; |
50 uword end_; | 50 uword end_; |
51 const ObjectPool& object_pool_; | 51 const ObjectPool& object_pool_; |
52 Register reg_; | 52 Register reg_; |
53 intptr_t index_; | 53 intptr_t index_; |
54 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 54 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
55 }; | 55 }; |
56 | 56 |
57 | 57 |
58 uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 58 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, |
59 const Code& code) { | 59 const Code& code) { |
60 ASSERT(code.ContainsInstructionAt(return_address)); | 60 ASSERT(code.ContainsInstructionAt(return_address)); |
61 PoolPointerCall call(return_address, code); | 61 PoolPointerCall call(return_address, code); |
62 return call.Target(); | 62 return call.Target(); |
63 } | 63 } |
64 | 64 |
65 | 65 |
66 void CodePatcher::PatchStaticCallAt(uword return_address, | 66 void CodePatcher::PatchStaticCallAt(uword return_address, |
67 const Code& code, | 67 const Code& code, |
68 uword new_target) { | 68 const Code& new_target) { |
69 PatchPoolPointerCallAt(return_address, code, new_target); | 69 PatchPoolPointerCallAt(return_address, code, new_target); |
70 } | 70 } |
71 | 71 |
72 | 72 |
73 void CodePatcher::PatchPoolPointerCallAt(uword return_address, | 73 void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
74 const Code& code, | 74 const Code& code, |
75 uword new_target) { | 75 const Code& new_target) { |
76 ASSERT(code.ContainsInstructionAt(return_address)); | 76 ASSERT(code.ContainsInstructionAt(return_address)); |
77 PoolPointerCall call(return_address, code); | 77 PoolPointerCall call(return_address, code); |
78 call.SetTarget(new_target); | 78 call.SetTarget(new_target); |
79 } | 79 } |
80 | 80 |
81 | 81 |
82 void CodePatcher::InsertCallAt(uword start, uword target) { | 82 void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) { |
83 // The inserted call should not overlap the lazy deopt jump code. | 83 // The inserted call should not overlap the lazy deopt jump code. |
84 ASSERT(start + CallPattern::kLengthInBytes <= target); | 84 ASSERT(start + CallPattern::kDeoptCallLengthInBytes <= target); |
85 CallPattern::InsertAt(start, target); | 85 CallPattern::InsertDeoptCallAt(start, target); |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 uword CodePatcher::GetInstanceCallAt(uword return_address, | 89 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, |
90 const Code& code, | 90 const Code& code, |
91 ICData* ic_data) { | 91 ICData* ic_data) { |
92 ASSERT(code.ContainsInstructionAt(return_address)); | 92 ASSERT(code.ContainsInstructionAt(return_address)); |
93 CallPattern call(return_address, code); | 93 CallPattern call(return_address, code); |
94 if (ic_data != NULL) { | 94 if (ic_data != NULL) { |
95 *ic_data = call.IcData(); | 95 *ic_data = call.IcData(); |
96 } | 96 } |
97 return call.TargetAddress(); | 97 return call.TargetCode(); |
98 } | 98 } |
99 | 99 |
100 | 100 |
101 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 101 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
102 // The instance call instruction sequence has a variable size on ARM64. | 102 // The instance call instruction sequence has a variable size on ARM64. |
103 UNREACHABLE(); | 103 UNREACHABLE(); |
104 return 0; | 104 return 0; |
105 } | 105 } |
106 | 106 |
107 | 107 |
108 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( | 108 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( |
109 uword return_address, const Code& code, ICData* ic_data_result) { | 109 uword return_address, const Code& code, ICData* ic_data_result) { |
110 ASSERT(code.ContainsInstructionAt(return_address)); | 110 ASSERT(code.ContainsInstructionAt(return_address)); |
111 CallPattern static_call(return_address, code); | 111 CallPattern static_call(return_address, code); |
112 ICData& ic_data = ICData::Handle(); | 112 ICData& ic_data = ICData::Handle(); |
113 ic_data ^= static_call.IcData(); | 113 ic_data ^= static_call.IcData(); |
114 if (ic_data_result != NULL) { | 114 if (ic_data_result != NULL) { |
115 *ic_data_result = ic_data.raw(); | 115 *ic_data_result = ic_data.raw(); |
116 } | 116 } |
117 return ic_data.GetTargetAt(0); | 117 return ic_data.GetTargetAt(0); |
118 } | 118 } |
119 | 119 |
120 | 120 |
121 void CodePatcher::PatchNativeCallAt(uword return_address, | 121 void CodePatcher::PatchNativeCallAt(uword return_address, |
122 const Code& code, | 122 const Code& code, |
123 NativeFunction target, | 123 NativeFunction target, |
124 const Code& trampoline) { | 124 const Code& trampoline) { |
125 ASSERT(code.ContainsInstructionAt(return_address)); | 125 ASSERT(code.ContainsInstructionAt(return_address)); |
126 NativeCallPattern call(return_address, code); | 126 NativeCallPattern call(return_address, code); |
127 call.set_target(trampoline.EntryPoint()); | 127 call.set_target(trampoline); |
128 call.set_native_function(target); | 128 call.set_native_function(target); |
129 } | 129 } |
130 | 130 |
131 | 131 |
132 uword CodePatcher::GetNativeCallAt(uword return_address, | 132 RawCode* CodePatcher::GetNativeCallAt(uword return_address, |
133 const Code& code, | 133 const Code& code, |
134 NativeFunction* target) { | 134 NativeFunction* target) { |
135 ASSERT(code.ContainsInstructionAt(return_address)); | 135 ASSERT(code.ContainsInstructionAt(return_address)); |
136 NativeCallPattern call(return_address, code); | 136 NativeCallPattern call(return_address, code); |
137 *target = call.native_function(); | 137 *target = call.native_function(); |
138 return call.target(); | 138 return call.target(); |
139 } | 139 } |
140 | 140 |
141 | 141 |
142 // This class pattern matches on a load from the object pool. Loading on | 142 // This class pattern matches on a load from the object pool. Loading on |
143 // ARM64 is complicated because it can take more than one form. We | 143 // ARM64 is complicated because it can take more than one form. We |
144 // match backwards from the end of the sequence so we can reuse the code for | 144 // match backwards from the end of the sequence so we can reuse the code for |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 | 176 |
177 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 177 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
178 ASSERT(code.ContainsInstructionAt(pc)); | 178 ASSERT(code.ContainsInstructionAt(pc)); |
179 EdgeCounter counter(pc, code); | 179 EdgeCounter counter(pc, code); |
180 return counter.edge_counter(); | 180 return counter.edge_counter(); |
181 } | 181 } |
182 | 182 |
183 } // namespace dart | 183 } // namespace dart |
184 | 184 |
185 #endif // defined TARGET_ARCH_ARM64 | 185 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |