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/instructions.h" | 8 #include "vm/instructions.h" |
9 #include "vm/instructions_mips.h" | 9 #include "vm/instructions_mips.h" |
10 | 10 |
11 #include "vm/constants_mips.h" | 11 #include "vm/constants_mips.h" |
12 #include "vm/cpu.h" | 12 #include "vm/cpu.h" |
13 #include "vm/object.h" | 13 #include "vm/object.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 CallPattern::CallPattern(uword pc, const Code& code) | 17 CallPattern::CallPattern(uword pc, const Code& code) |
18 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 18 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
19 end_(pc), | 19 end_(pc), |
20 ic_data_load_end_(0), | 20 ic_data_load_end_(0), |
21 target_code_pool_index_(-1), | 21 target_code_pool_index_(-1), |
22 ic_data_(ICData::Handle()) { | 22 ic_data_(ICData::Handle()) { |
23 ASSERT(code.ContainsInstructionAt(pc)); | 23 ASSERT(code.ContainsInstructionAt(pc)); |
24 // Last instruction: jalr RA, T9(=R25). | 24 // Last instruction: jalr RA, T9(=R25). |
25 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); | 25 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); |
26 Register reg; | 26 Register reg; |
27 // The end of the pattern is the instruction after the delay slot of the jalr. | 27 // The end of the pattern is the instruction after the delay slot of the jalr. |
28 ic_data_load_end_ = | 28 ic_data_load_end_ = InstructionPattern::DecodeLoadWordFromPool( |
29 InstructionPattern::DecodeLoadWordFromPool(end_ - (3 * Instr::kInstrSize), | 29 end_ - (3 * Instr::kInstrSize), ®, &target_code_pool_index_); |
30 ®, | |
31 &target_code_pool_index_); | |
32 ASSERT(reg == CODE_REG); | 30 ASSERT(reg == CODE_REG); |
33 } | 31 } |
34 | 32 |
35 | 33 |
36 // 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 |
37 // 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 |
38 // the first instruction in the sequence. Returns the register being loaded | 36 // the first instruction in the sequence. Returns the register being loaded |
39 // and the loaded object in the output parameters 'reg' and 'obj' | 37 // and the loaded object in the output parameters 'reg' and 'obj' |
40 // respectively. | 38 // respectively. |
41 uword InstructionPattern::DecodeLoadObject(uword end, | 39 uword InstructionPattern::DecodeLoadObject(uword end, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 ASSERT(instr->OpcodeField() == LUI); | 114 ASSERT(instr->OpcodeField() == LUI); |
117 ASSERT(instr->RtField() == *reg); | 115 ASSERT(instr->RtField() == *reg); |
118 // Offset is signed, so add the upper 16 bits. | 116 // Offset is signed, so add the upper 16 bits. |
119 offset += (instr->UImmField() << 16); | 117 offset += (instr->UImmField() << 16); |
120 } | 118 } |
121 *index = ObjectPool::IndexFromOffset(offset); | 119 *index = ObjectPool::IndexFromOffset(offset); |
122 return start; | 120 return start; |
123 } | 121 } |
124 | 122 |
125 | 123 |
126 bool DecodeLoadObjectFromPoolOrThread(uword pc, | 124 bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { |
127 const Code& code, | |
128 Object* obj) { | |
129 ASSERT(code.ContainsInstructionAt(pc)); | 125 ASSERT(code.ContainsInstructionAt(pc)); |
130 | 126 |
131 Instr* instr = Instr::At(pc); | 127 Instr* instr = Instr::At(pc); |
132 if ((instr->OpcodeField() == LW)) { | 128 if ((instr->OpcodeField() == LW)) { |
133 intptr_t offset = instr->SImmField(); | 129 intptr_t offset = instr->SImmField(); |
134 if (instr->RsField() == PP) { | 130 if (instr->RsField() == PP) { |
135 intptr_t index = ObjectPool::IndexFromOffset(offset); | 131 intptr_t index = ObjectPool::IndexFromOffset(offset); |
136 const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); | 132 const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); |
137 if (pool.InfoAt(index) == ObjectPool::kTaggedObject) { | 133 if (pool.InfoAt(index) == ObjectPool::kTaggedObject) { |
138 *obj = pool.ObjectAt(index); | 134 *obj = pool.ObjectAt(index); |
139 return true; | 135 return true; |
140 } | 136 } |
141 } else if (instr->RsField() == THR) { | 137 } else if (instr->RsField() == THR) { |
142 return Thread::ObjectAtOffset(offset, obj); | 138 return Thread::ObjectAtOffset(offset, obj); |
143 } | 139 } |
144 } | 140 } |
145 // TODO(rmacnak): Sequence for loads beyond 16 bits. | 141 // TODO(rmacnak): Sequence for loads beyond 16 bits. |
146 | 142 |
147 return false; | 143 return false; |
148 } | 144 } |
149 | 145 |
150 | 146 |
151 RawICData* CallPattern::IcData() { | 147 RawICData* CallPattern::IcData() { |
152 if (ic_data_.IsNull()) { | 148 if (ic_data_.IsNull()) { |
153 Register reg; | 149 Register reg; |
154 InstructionPattern::DecodeLoadObject(ic_data_load_end_, | 150 InstructionPattern::DecodeLoadObject(ic_data_load_end_, object_pool_, ®, |
155 object_pool_, | |
156 ®, | |
157 &ic_data_); | 151 &ic_data_); |
158 ASSERT(reg == S5); | 152 ASSERT(reg == S5); |
159 } | 153 } |
160 return ic_data_.raw(); | 154 return ic_data_.raw(); |
161 } | 155 } |
162 | 156 |
163 | 157 |
164 RawCode* CallPattern::TargetCode() const { | 158 RawCode* CallPattern::TargetCode() const { |
165 return reinterpret_cast<RawCode*>( | 159 return reinterpret_cast<RawCode*>( |
166 object_pool_.ObjectAt(target_code_pool_index_)); | 160 object_pool_.ObjectAt(target_code_pool_index_)); |
167 } | 161 } |
168 | 162 |
169 | 163 |
170 void CallPattern::SetTargetCode(const Code& target) const { | 164 void CallPattern::SetTargetCode(const Code& target) const { |
171 object_pool_.SetObjectAt(target_code_pool_index_, target); | 165 object_pool_.SetObjectAt(target_code_pool_index_, target); |
172 // No need to flush the instruction cache, since the code is not modified. | 166 // No need to flush the instruction cache, since the code is not modified. |
173 } | 167 } |
174 | 168 |
175 | 169 |
176 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) | 170 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) |
177 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 171 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
178 end_(pc), | 172 end_(pc), |
179 native_function_pool_index_(-1), | 173 native_function_pool_index_(-1), |
180 target_code_pool_index_(-1) { | 174 target_code_pool_index_(-1) { |
181 ASSERT(code.ContainsInstructionAt(pc)); | 175 ASSERT(code.ContainsInstructionAt(pc)); |
182 // Last instruction: jalr RA, T9(=R25). | 176 // Last instruction: jalr RA, T9(=R25). |
183 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); | 177 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); |
184 | 178 |
185 Register reg; | 179 Register reg; |
186 uword native_function_load_end = | 180 uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool( |
187 InstructionPattern::DecodeLoadWordFromPool(end_ - 3 * Instr::kInstrSize, | 181 end_ - 3 * Instr::kInstrSize, ®, &target_code_pool_index_); |
188 ®, | |
189 &target_code_pool_index_); | |
190 ASSERT(reg == CODE_REG); | 182 ASSERT(reg == CODE_REG); |
191 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, | 183 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, ®, |
192 ®, | |
193 &native_function_pool_index_); | 184 &native_function_pool_index_); |
194 ASSERT(reg == T5); | 185 ASSERT(reg == T5); |
195 } | 186 } |
196 | 187 |
197 | 188 |
198 RawCode* NativeCallPattern::target() const { | 189 RawCode* NativeCallPattern::target() const { |
199 return reinterpret_cast<RawCode*>( | 190 return reinterpret_cast<RawCode*>( |
200 object_pool_.ObjectAt(target_code_pool_index_)); | 191 object_pool_.ObjectAt(target_code_pool_index_)); |
201 } | 192 } |
202 | 193 |
203 | 194 |
204 void NativeCallPattern::set_target(const Code& target) const { | 195 void NativeCallPattern::set_target(const Code& target) const { |
205 object_pool_.SetObjectAt(target_code_pool_index_, target); | 196 object_pool_.SetObjectAt(target_code_pool_index_, target); |
206 // No need to flush the instruction cache, since the code is not modified. | 197 // No need to flush the instruction cache, since the code is not modified. |
207 } | 198 } |
208 | 199 |
209 | 200 |
210 NativeFunction NativeCallPattern::native_function() const { | 201 NativeFunction NativeCallPattern::native_function() const { |
211 return reinterpret_cast<NativeFunction>( | 202 return reinterpret_cast<NativeFunction>( |
212 object_pool_.RawValueAt(native_function_pool_index_)); | 203 object_pool_.RawValueAt(native_function_pool_index_)); |
213 } | 204 } |
214 | 205 |
215 | 206 |
216 void NativeCallPattern::set_native_function(NativeFunction func) const { | 207 void NativeCallPattern::set_native_function(NativeFunction func) const { |
217 object_pool_.SetRawValueAt(native_function_pool_index_, | 208 object_pool_.SetRawValueAt(native_function_pool_index_, |
218 reinterpret_cast<uword>(func)); | 209 reinterpret_cast<uword>(func)); |
219 } | 210 } |
220 | 211 |
221 | 212 |
222 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) | 213 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) |
223 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 214 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
224 data_pool_index_(-1), | 215 data_pool_index_(-1), |
225 target_pool_index_(-1) { | 216 target_pool_index_(-1) { |
226 ASSERT(code.ContainsInstructionAt(pc)); | 217 ASSERT(code.ContainsInstructionAt(pc)); |
227 // Last instruction: jalr t9. | 218 // Last instruction: jalr t9. |
228 ASSERT(*(reinterpret_cast<uword*>(pc) - 1) == 0); // Delay slot. | 219 ASSERT(*(reinterpret_cast<uword*>(pc) - 1) == 0); // Delay slot. |
229 ASSERT(*(reinterpret_cast<uword*>(pc) - 2) == 0x0320f809); | 220 ASSERT(*(reinterpret_cast<uword*>(pc) - 2) == 0x0320f809); |
230 | 221 |
231 Register reg; | 222 Register reg; |
232 uword data_load_end = | 223 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool( |
233 InstructionPattern::DecodeLoadWordFromPool(pc - 2 * Instr::kInstrSize, | 224 pc - 2 * Instr::kInstrSize, ®, &data_pool_index_); |
234 ®, | |
235 &data_pool_index_); | |
236 ASSERT(reg == S5); | 225 ASSERT(reg == S5); |
237 InstructionPattern::DecodeLoadWordFromPool(data_load_end - Instr::kInstrSize, | 226 InstructionPattern::DecodeLoadWordFromPool(data_load_end - Instr::kInstrSize, |
238 ®, | 227 ®, &target_pool_index_); |
239 &target_pool_index_); | |
240 ASSERT(reg == CODE_REG); | 228 ASSERT(reg == CODE_REG); |
241 } | 229 } |
242 | 230 |
243 | 231 |
244 RawObject* SwitchableCallPattern::data() const { | 232 RawObject* SwitchableCallPattern::data() const { |
245 return object_pool_.ObjectAt(data_pool_index_); | 233 return object_pool_.ObjectAt(data_pool_index_); |
246 } | 234 } |
247 | 235 |
248 | 236 |
249 RawCode* SwitchableCallPattern::target() const { | 237 RawCode* SwitchableCallPattern::target() const { |
250 return reinterpret_cast<RawCode*>( | 238 return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_pool_index_)); |
251 object_pool_.ObjectAt(target_pool_index_)); | |
252 } | 239 } |
253 | 240 |
254 | 241 |
255 void SwitchableCallPattern::SetData(const Object& data) const { | 242 void SwitchableCallPattern::SetData(const Object& data) const { |
256 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode()); | 243 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode()); |
257 object_pool_.SetObjectAt(data_pool_index_, data); | 244 object_pool_.SetObjectAt(data_pool_index_, data); |
258 } | 245 } |
259 | 246 |
260 | 247 |
261 void SwitchableCallPattern::SetTarget(const Code& target) const { | 248 void SwitchableCallPattern::SetTarget(const Code& target) const { |
262 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode()); | 249 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode()); |
263 object_pool_.SetObjectAt(target_pool_index_, target); | 250 object_pool_.SetObjectAt(target_pool_index_, target); |
264 } | 251 } |
265 | 252 |
266 | 253 |
267 ReturnPattern::ReturnPattern(uword pc) | 254 ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {} |
268 : pc_(pc) { | |
269 } | |
270 | 255 |
271 | 256 |
272 bool ReturnPattern::IsValid() const { | 257 bool ReturnPattern::IsValid() const { |
273 Instr* jr = Instr::At(pc_); | 258 Instr* jr = Instr::At(pc_); |
274 return (jr->OpcodeField() == SPECIAL) && | 259 return (jr->OpcodeField() == SPECIAL) && (jr->FunctionField() == JR) && |
275 (jr->FunctionField() == JR) && | |
276 (jr->RsField() == RA); | 260 (jr->RsField() == RA); |
277 } | 261 } |
278 | 262 |
279 } // namespace dart | 263 } // namespace dart |
280 | 264 |
281 #endif // defined TARGET_ARCH_MIPS | 265 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |