OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/constants_mips.h" | 8 #include "vm/constants_mips.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 CallPattern::CallPattern(uword pc, const Code& code) | 15 CallPattern::CallPattern(uword pc, const Code& code) |
16 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 16 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
17 end_(pc), | 17 end_(pc), |
18 ic_data_load_end_(0), | 18 ic_data_load_end_(0), |
19 target_address_pool_index_(-1), | 19 target_code_pool_index_(-1), |
20 ic_data_(ICData::Handle()) { | 20 ic_data_(ICData::Handle()) { |
21 ASSERT(code.ContainsInstructionAt(pc)); | 21 ASSERT(code.ContainsInstructionAt(pc)); |
22 // Last instruction: jalr RA, T9(=R25). | 22 // Last instruction: jalr RA, T9(=R25). |
23 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); | 23 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); |
24 Register reg; | 24 Register reg; |
25 // The end of the pattern is the instruction after the delay slot of the jalr. | 25 // The end of the pattern is the instruction after the delay slot of the jalr. |
26 ic_data_load_end_ = | 26 ic_data_load_end_ = |
27 InstructionPattern::DecodeLoadWordFromPool(end_ - (2 * Instr::kInstrSize), | 27 InstructionPattern::DecodeLoadWordFromPool(end_ - (3 * Instr::kInstrSize), |
28 ®, | 28 ®, |
29 &target_address_pool_index_); | 29 &target_code_pool_index_); |
30 ASSERT(reg == T9); | 30 ASSERT(reg == CODE_REG); |
31 } | 31 } |
32 | 32 |
33 | 33 |
34 // Decodes a load sequence ending at 'end' (the last instruction of the load | 34 // Decodes a load sequence ending at 'end' (the last instruction of the load |
35 // sequence is the instruction before the one at end). Returns a pointer to | 35 // sequence is the instruction before the one at end). Returns a pointer to |
36 // the first instruction in the sequence. Returns the register being loaded | 36 // the first instruction in the sequence. Returns the register being loaded |
37 // and the loaded object in the output parameters 'reg' and 'obj' | 37 // and the loaded object in the output parameters 'reg' and 'obj' |
38 // respectively. | 38 // respectively. |
39 uword InstructionPattern::DecodeLoadObject(uword end, | 39 uword InstructionPattern::DecodeLoadObject(uword end, |
40 const ObjectPool& object_pool, | 40 const ObjectPool& object_pool, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 InstructionPattern::DecodeLoadObject(ic_data_load_end_, | 127 InstructionPattern::DecodeLoadObject(ic_data_load_end_, |
128 object_pool_, | 128 object_pool_, |
129 ®, | 129 ®, |
130 &ic_data_); | 130 &ic_data_); |
131 ASSERT(reg == S5); | 131 ASSERT(reg == S5); |
132 } | 132 } |
133 return ic_data_.raw(); | 133 return ic_data_.raw(); |
134 } | 134 } |
135 | 135 |
136 | 136 |
137 uword CallPattern::TargetAddress() const { | 137 RawCode* CallPattern::TargetCode() const { |
138 return object_pool_.RawValueAt(target_address_pool_index_); | 138 return reinterpret_cast<RawCode*>( |
| 139 object_pool_.ObjectAt(target_code_pool_index_)); |
139 } | 140 } |
140 | 141 |
141 | 142 |
142 void CallPattern::SetTargetAddress(uword target_address) const { | 143 void CallPattern::SetTargetCode(const Code& target) const { |
143 object_pool_.SetRawValueAt(target_address_pool_index_, target_address); | 144 object_pool_.SetObjectAt(target_code_pool_index_, target); |
144 // No need to flush the instruction cache, since the code is not modified. | 145 // No need to flush the instruction cache, since the code is not modified. |
145 } | 146 } |
146 | 147 |
147 | 148 |
148 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) | 149 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) |
149 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 150 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
150 end_(pc), | 151 end_(pc), |
151 native_function_pool_index_(-1), | 152 native_function_pool_index_(-1), |
152 target_address_pool_index_(-1) { | 153 target_code_pool_index_(-1) { |
153 ASSERT(code.ContainsInstructionAt(pc)); | 154 ASSERT(code.ContainsInstructionAt(pc)); |
154 // Last instruction: jalr RA, T9(=R25). | 155 // Last instruction: jalr RA, T9(=R25). |
155 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); | 156 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); |
156 | 157 |
157 Register reg; | 158 Register reg; |
158 uword native_function_load_end = | 159 uword native_function_load_end = |
159 InstructionPattern::DecodeLoadWordFromPool(end_ - 2 * Instr::kInstrSize, | 160 InstructionPattern::DecodeLoadWordFromPool(end_ - 3 * Instr::kInstrSize, |
160 ®, | 161 ®, |
161 &target_address_pool_index_); | 162 &target_code_pool_index_); |
162 ASSERT(reg == T9); | 163 ASSERT(reg == CODE_REG); |
163 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, | 164 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, |
164 ®, | 165 ®, |
165 &native_function_pool_index_); | 166 &native_function_pool_index_); |
166 ASSERT(reg == T5); | 167 ASSERT(reg == T5); |
167 } | 168 } |
168 | 169 |
169 | 170 |
170 uword NativeCallPattern::target() const { | 171 RawCode* NativeCallPattern::target() const { |
171 return object_pool_.RawValueAt(target_address_pool_index_); | 172 return reinterpret_cast<RawCode*>( |
| 173 object_pool_.ObjectAt(target_code_pool_index_)); |
172 } | 174 } |
173 | 175 |
174 | 176 |
175 void NativeCallPattern::set_target(uword target_address) const { | 177 void NativeCallPattern::set_target(const Code& target) const { |
176 object_pool_.SetRawValueAt(target_address_pool_index_, target_address); | 178 object_pool_.SetObjectAt(target_code_pool_index_, target); |
177 // No need to flush the instruction cache, since the code is not modified. | 179 // No need to flush the instruction cache, since the code is not modified. |
178 } | 180 } |
179 | 181 |
180 | 182 |
181 NativeFunction NativeCallPattern::native_function() const { | 183 NativeFunction NativeCallPattern::native_function() const { |
182 return reinterpret_cast<NativeFunction>( | 184 return reinterpret_cast<NativeFunction>( |
183 object_pool_.RawValueAt(native_function_pool_index_)); | 185 object_pool_.RawValueAt(native_function_pool_index_)); |
184 } | 186 } |
185 | 187 |
186 | 188 |
187 void NativeCallPattern::set_native_function(NativeFunction func) const { | 189 void NativeCallPattern::set_native_function(NativeFunction func) const { |
188 object_pool_.SetRawValueAt(native_function_pool_index_, | 190 object_pool_.SetRawValueAt(native_function_pool_index_, |
189 reinterpret_cast<uword>(func)); | 191 reinterpret_cast<uword>(func)); |
190 } | 192 } |
191 | 193 |
192 | 194 |
193 void CallPattern::InsertAt(uword pc, uword target_address) { | 195 void CallPattern::InsertDeoptCallAt(uword pc, uword target_address) { |
194 Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize)); | 196 Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize)); |
195 Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize)); | 197 Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize)); |
196 Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize)); | 198 Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize)); |
197 Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize)); | 199 Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize)); |
198 uint16_t target_lo = target_address & 0xffff; | 200 uint16_t target_lo = target_address & 0xffff; |
199 uint16_t target_hi = target_address >> 16; | 201 uint16_t target_hi = target_address >> 16; |
200 | 202 |
201 lui->SetImmInstrBits(LUI, ZR, T9, target_hi); | 203 lui->SetImmInstrBits(LUI, ZR, T9, target_hi); |
202 ori->SetImmInstrBits(ORI, T9, T9, target_lo); | 204 ori->SetImmInstrBits(ORI, T9, T9, target_lo); |
203 jr->SetSpecialInstrBits(JALR, T9, ZR, RA); | 205 jr->SetSpecialInstrBits(JALR, T9, ZR, RA); |
204 nop->SetInstructionBits(Instr::kNopInstruction); | 206 nop->SetInstructionBits(Instr::kNopInstruction); |
205 | 207 |
206 ASSERT(kFixedLengthInBytes == 4 * Instr::kInstrSize); | 208 ASSERT(kDeoptCallLengthInBytes == 4 * Instr::kInstrSize); |
207 CPU::FlushICache(pc, kFixedLengthInBytes); | 209 CPU::FlushICache(pc, kDeoptCallLengthInBytes); |
208 } | 210 } |
209 | 211 |
210 | 212 |
211 JumpPattern::JumpPattern(uword pc, const Code& code) : pc_(pc) { } | |
212 | |
213 | |
214 bool JumpPattern::IsValid() const { | |
215 Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize)); | |
216 Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize)); | |
217 Instr* jr = Instr::At(pc_ + (2 * Instr::kInstrSize)); | |
218 Instr* nop = Instr::At(pc_ + (3 * Instr::kInstrSize)); | |
219 return (lui->OpcodeField() == LUI) && | |
220 (ori->OpcodeField() == ORI) && | |
221 (jr->OpcodeField() == SPECIAL) && | |
222 (jr->FunctionField() == JR) && | |
223 (nop->InstructionBits() == Instr::kNopInstruction); | |
224 } | |
225 | |
226 | |
227 uword JumpPattern::TargetAddress() const { | |
228 Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize)); | |
229 Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize)); | |
230 const uint16_t target_lo = ori->UImmField(); | |
231 const uint16_t target_hi = lui->UImmField(); | |
232 return (target_hi << 16) | target_lo; | |
233 } | |
234 | |
235 | |
236 void JumpPattern::SetTargetAddress(uword target_address) const { | |
237 Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize)); | |
238 Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize)); | |
239 const int32_t lui_bits = lui->InstructionBits(); | |
240 const int32_t ori_bits = ori->InstructionBits(); | |
241 const uint16_t target_lo = target_address & 0xffff; | |
242 const uint16_t target_hi = target_address >> 16; | |
243 | |
244 lui->SetInstructionBits((lui_bits & 0xffff0000) | target_hi); | |
245 ori->SetInstructionBits((ori_bits & 0xffff0000) | target_lo); | |
246 } | |
247 | |
248 | |
249 ReturnPattern::ReturnPattern(uword pc) | 213 ReturnPattern::ReturnPattern(uword pc) |
250 : pc_(pc) { | 214 : pc_(pc) { |
251 } | 215 } |
252 | 216 |
253 | 217 |
254 bool ReturnPattern::IsValid() const { | 218 bool ReturnPattern::IsValid() const { |
255 Instr* jr = Instr::At(pc_); | 219 Instr* jr = Instr::At(pc_); |
256 return (jr->OpcodeField() == SPECIAL) && | 220 return (jr->OpcodeField() == SPECIAL) && |
257 (jr->FunctionField() == JR) && | 221 (jr->FunctionField() == JR) && |
258 (jr->RsField() == RA); | 222 (jr->RsField() == RA); |
259 } | 223 } |
260 | 224 |
261 } // namespace dart | 225 } // namespace dart |
262 | 226 |
263 #endif // defined TARGET_ARCH_MIPS | 227 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |