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, |
| 16 const Code& code, |
| 17 uword new_target) { |
| 18 ASSERT(code.ContainsInstructionAt(return_address)); |
| 19 CallPattern call(return_address, code); |
| 20 call.SetTargetAddress(new_target); |
| 21 } |
| 22 |
| 23 |
15 class PoolPointerCall : public ValueObject { | 24 class PoolPointerCall : public ValueObject { |
16 public: | 25 public: |
17 PoolPointerCall(uword pc, const Code& code) | 26 PoolPointerCall(uword pc, const Code& code) |
18 : end_(pc), | 27 : end_(pc), |
19 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 28 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
20 // Last instruction: blr ip0. | 29 // Last instruction: blr ip0. |
21 ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200); | 30 ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200); |
22 InstructionPattern::DecodeLoadWordFromPool( | 31 InstructionPattern::DecodeLoadWordFromPool( |
23 end_ - 2 * Instr::kInstrSize, ®_, &index_); | 32 end_ - Instr::kInstrSize, ®_, &index_); |
24 } | 33 } |
25 | 34 |
26 intptr_t pp_index() const { | 35 intptr_t pp_index() const { |
27 return index_; | 36 return index_; |
28 } | 37 } |
29 | 38 |
30 RawCode* Target() const { | 39 uword Target() const { |
31 return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(pp_index())); | 40 return object_pool_.RawValueAt(pp_index()); |
32 } | 41 } |
33 | 42 |
34 void SetTarget(const Code& target) const { | 43 void SetTarget(uword target) const { |
35 object_pool_.SetObjectAt(pp_index(), target); | 44 object_pool_.SetRawValueAt(pp_index(), target); |
36 // 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. |
37 } | 46 } |
38 | 47 |
39 private: | 48 private: |
40 static const int kCallPatternSize = 3 * Instr::kInstrSize; | 49 static const int kCallPatternSize = 3 * Instr::kInstrSize; |
41 uword end_; | 50 uword end_; |
42 const ObjectPool& object_pool_; | 51 const ObjectPool& object_pool_; |
43 Register reg_; | 52 Register reg_; |
44 intptr_t index_; | 53 intptr_t index_; |
45 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 54 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
46 }; | 55 }; |
47 | 56 |
48 | 57 |
49 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, | 58 uword CodePatcher::GetStaticCallTargetAt(uword return_address, |
50 const Code& code) { | 59 const Code& code) { |
51 ASSERT(code.ContainsInstructionAt(return_address)); | 60 ASSERT(code.ContainsInstructionAt(return_address)); |
52 PoolPointerCall call(return_address, code); | 61 PoolPointerCall call(return_address, code); |
53 return call.Target(); | 62 return call.Target(); |
54 } | 63 } |
55 | 64 |
56 | 65 |
57 void CodePatcher::PatchStaticCallAt(uword return_address, | 66 void CodePatcher::PatchStaticCallAt(uword return_address, |
58 const Code& code, | 67 const Code& code, |
59 const Code& new_target) { | 68 uword new_target) { |
60 PatchPoolPointerCallAt(return_address, code, new_target); | 69 PatchPoolPointerCallAt(return_address, code, new_target); |
61 } | 70 } |
62 | 71 |
63 | 72 |
64 void CodePatcher::PatchPoolPointerCallAt(uword return_address, | 73 void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
65 const Code& code, | 74 const Code& code, |
66 const Code& new_target) { | 75 uword new_target) { |
67 ASSERT(code.ContainsInstructionAt(return_address)); | 76 ASSERT(code.ContainsInstructionAt(return_address)); |
68 PoolPointerCall call(return_address, code); | 77 PoolPointerCall call(return_address, code); |
69 call.SetTarget(new_target); | 78 call.SetTarget(new_target); |
70 } | 79 } |
71 | 80 |
72 | 81 |
73 void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) { | 82 void CodePatcher::InsertCallAt(uword start, uword target) { |
74 // The inserted call should not overlap the lazy deopt jump code. | 83 // The inserted call should not overlap the lazy deopt jump code. |
75 ASSERT(start + CallPattern::kDeoptCallLengthInBytes <= target); | 84 ASSERT(start + CallPattern::kLengthInBytes <= target); |
76 CallPattern::InsertDeoptCallAt(start, target); | 85 CallPattern::InsertAt(start, target); |
77 } | 86 } |
78 | 87 |
79 | 88 |
80 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, | 89 uword CodePatcher::GetInstanceCallAt(uword return_address, |
81 const Code& code, | 90 const Code& code, |
82 ICData* ic_data) { | 91 ICData* ic_data) { |
83 ASSERT(code.ContainsInstructionAt(return_address)); | 92 ASSERT(code.ContainsInstructionAt(return_address)); |
84 CallPattern call(return_address, code); | 93 CallPattern call(return_address, code); |
85 if (ic_data != NULL) { | 94 if (ic_data != NULL) { |
86 *ic_data = call.IcData(); | 95 *ic_data = call.IcData(); |
87 } | 96 } |
88 return call.TargetCode(); | 97 return call.TargetAddress(); |
89 } | 98 } |
90 | 99 |
91 | 100 |
92 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 101 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
93 // The instance call instruction sequence has a variable size on ARM64. | 102 // The instance call instruction sequence has a variable size on ARM64. |
94 UNREACHABLE(); | 103 UNREACHABLE(); |
95 return 0; | 104 return 0; |
96 } | 105 } |
97 | 106 |
98 | 107 |
99 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( | 108 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( |
100 uword return_address, const Code& code, ICData* ic_data_result) { | 109 uword return_address, const Code& code, ICData* ic_data_result) { |
101 ASSERT(code.ContainsInstructionAt(return_address)); | 110 ASSERT(code.ContainsInstructionAt(return_address)); |
102 CallPattern static_call(return_address, code); | 111 CallPattern static_call(return_address, code); |
103 ICData& ic_data = ICData::Handle(); | 112 ICData& ic_data = ICData::Handle(); |
104 ic_data ^= static_call.IcData(); | 113 ic_data ^= static_call.IcData(); |
105 if (ic_data_result != NULL) { | 114 if (ic_data_result != NULL) { |
106 *ic_data_result = ic_data.raw(); | 115 *ic_data_result = ic_data.raw(); |
107 } | 116 } |
108 return ic_data.GetTargetAt(0); | 117 return ic_data.GetTargetAt(0); |
109 } | 118 } |
110 | 119 |
111 | 120 |
112 void CodePatcher::PatchNativeCallAt(uword return_address, | 121 void CodePatcher::PatchNativeCallAt(uword return_address, |
113 const Code& code, | 122 const Code& code, |
114 NativeFunction target, | 123 NativeFunction target, |
115 const Code& trampoline) { | 124 const Code& trampoline) { |
116 ASSERT(code.ContainsInstructionAt(return_address)); | 125 ASSERT(code.ContainsInstructionAt(return_address)); |
117 NativeCallPattern call(return_address, code); | 126 NativeCallPattern call(return_address, code); |
118 call.set_target(trampoline); | 127 call.set_target(trampoline.EntryPoint()); |
119 call.set_native_function(target); | 128 call.set_native_function(target); |
120 } | 129 } |
121 | 130 |
122 | 131 |
123 RawCode* CodePatcher::GetNativeCallAt(uword return_address, | 132 uword CodePatcher::GetNativeCallAt(uword return_address, |
124 const Code& code, | 133 const Code& code, |
125 NativeFunction* target) { | 134 NativeFunction* target) { |
126 ASSERT(code.ContainsInstructionAt(return_address)); | 135 ASSERT(code.ContainsInstructionAt(return_address)); |
127 NativeCallPattern call(return_address, code); | 136 NativeCallPattern call(return_address, code); |
128 *target = call.native_function(); | 137 *target = call.native_function(); |
129 return call.target(); | 138 return call.target(); |
130 } | 139 } |
131 | 140 |
132 | 141 |
133 // 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 |
134 // 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 |
135 // 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... |
167 | 176 |
168 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 177 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
169 ASSERT(code.ContainsInstructionAt(pc)); | 178 ASSERT(code.ContainsInstructionAt(pc)); |
170 EdgeCounter counter(pc, code); | 179 EdgeCounter counter(pc, code); |
171 return counter.edge_counter(); | 180 return counter.edge_counter(); |
172 } | 181 } |
173 | 182 |
174 } // namespace dart | 183 } // namespace dart |
175 | 184 |
176 #endif // defined TARGET_ARCH_ARM64 | 185 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |