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_code_pool_index_(-1), | 19 target_address_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_ - (3 * Instr::kInstrSize), | 27 InstructionPattern::DecodeLoadWordFromPool(end_ - (2 * Instr::kInstrSize), |
28 ®, | 28 ®, |
29 &target_code_pool_index_); | 29 &target_address_pool_index_); |
30 ASSERT(reg == CODE_REG); | 30 ASSERT(reg == T9); |
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 RawCode* CallPattern::TargetCode() const { | 137 uword CallPattern::TargetAddress() const { |
138 return reinterpret_cast<RawCode*>( | 138 return object_pool_.RawValueAt(target_address_pool_index_); |
139 object_pool_.ObjectAt(target_code_pool_index_)); | |
140 } | 139 } |
141 | 140 |
142 | 141 |
143 void CallPattern::SetTargetCode(const Code& target) const { | 142 void CallPattern::SetTargetAddress(uword target_address) const { |
144 object_pool_.SetObjectAt(target_code_pool_index_, target); | 143 object_pool_.SetRawValueAt(target_address_pool_index_, target_address); |
145 // No need to flush the instruction cache, since the code is not modified. | 144 // No need to flush the instruction cache, since the code is not modified. |
146 } | 145 } |
147 | 146 |
148 | 147 |
149 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) | 148 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) |
150 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 149 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
151 end_(pc), | 150 end_(pc), |
152 native_function_pool_index_(-1), | 151 native_function_pool_index_(-1), |
153 target_code_pool_index_(-1) { | 152 target_address_pool_index_(-1) { |
154 ASSERT(code.ContainsInstructionAt(pc)); | 153 ASSERT(code.ContainsInstructionAt(pc)); |
155 // Last instruction: jalr RA, T9(=R25). | 154 // Last instruction: jalr RA, T9(=R25). |
156 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); | 155 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0320f809); |
157 | 156 |
158 Register reg; | 157 Register reg; |
159 uword native_function_load_end = | 158 uword native_function_load_end = |
160 InstructionPattern::DecodeLoadWordFromPool(end_ - 3 * Instr::kInstrSize, | 159 InstructionPattern::DecodeLoadWordFromPool(end_ - 2 * Instr::kInstrSize, |
161 ®, | 160 ®, |
162 &target_code_pool_index_); | 161 &target_address_pool_index_); |
163 ASSERT(reg == CODE_REG); | 162 ASSERT(reg == T9); |
164 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, | 163 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, |
165 ®, | 164 ®, |
166 &native_function_pool_index_); | 165 &native_function_pool_index_); |
167 ASSERT(reg == T5); | 166 ASSERT(reg == T5); |
168 } | 167 } |
169 | 168 |
170 | 169 |
171 RawCode* NativeCallPattern::target() const { | 170 uword NativeCallPattern::target() const { |
172 return reinterpret_cast<RawCode*>( | 171 return object_pool_.RawValueAt(target_address_pool_index_); |
173 object_pool_.ObjectAt(target_code_pool_index_)); | |
174 } | 172 } |
175 | 173 |
176 | 174 |
177 void NativeCallPattern::set_target(const Code& target) const { | 175 void NativeCallPattern::set_target(uword target_address) const { |
178 object_pool_.SetObjectAt(target_code_pool_index_, target); | 176 object_pool_.SetRawValueAt(target_address_pool_index_, target_address); |
179 // No need to flush the instruction cache, since the code is not modified. | 177 // No need to flush the instruction cache, since the code is not modified. |
180 } | 178 } |
181 | 179 |
182 | 180 |
183 NativeFunction NativeCallPattern::native_function() const { | 181 NativeFunction NativeCallPattern::native_function() const { |
184 return reinterpret_cast<NativeFunction>( | 182 return reinterpret_cast<NativeFunction>( |
185 object_pool_.RawValueAt(native_function_pool_index_)); | 183 object_pool_.RawValueAt(native_function_pool_index_)); |
186 } | 184 } |
187 | 185 |
188 | 186 |
189 void NativeCallPattern::set_native_function(NativeFunction func) const { | 187 void NativeCallPattern::set_native_function(NativeFunction func) const { |
190 object_pool_.SetRawValueAt(native_function_pool_index_, | 188 object_pool_.SetRawValueAt(native_function_pool_index_, |
191 reinterpret_cast<uword>(func)); | 189 reinterpret_cast<uword>(func)); |
192 } | 190 } |
193 | 191 |
194 | 192 |
195 void CallPattern::InsertDeoptCallAt(uword pc, uword target_address) { | 193 void CallPattern::InsertAt(uword pc, uword target_address) { |
196 Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize)); | 194 Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize)); |
197 Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize)); | 195 Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize)); |
198 Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize)); | 196 Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize)); |
199 Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize)); | 197 Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize)); |
200 uint16_t target_lo = target_address & 0xffff; | 198 uint16_t target_lo = target_address & 0xffff; |
201 uint16_t target_hi = target_address >> 16; | 199 uint16_t target_hi = target_address >> 16; |
202 | 200 |
203 lui->SetImmInstrBits(LUI, ZR, T9, target_hi); | 201 lui->SetImmInstrBits(LUI, ZR, T9, target_hi); |
204 ori->SetImmInstrBits(ORI, T9, T9, target_lo); | 202 ori->SetImmInstrBits(ORI, T9, T9, target_lo); |
205 jr->SetSpecialInstrBits(JALR, T9, ZR, RA); | 203 jr->SetSpecialInstrBits(JALR, T9, ZR, RA); |
206 nop->SetInstructionBits(Instr::kNopInstruction); | 204 nop->SetInstructionBits(Instr::kNopInstruction); |
207 | 205 |
208 ASSERT(kDeoptCallLengthInBytes == 4 * Instr::kInstrSize); | 206 ASSERT(kFixedLengthInBytes == 4 * Instr::kInstrSize); |
209 CPU::FlushICache(pc, kDeoptCallLengthInBytes); | 207 CPU::FlushICache(pc, kFixedLengthInBytes); |
210 } | 208 } |
211 | 209 |
212 | 210 |
| 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 |
213 ReturnPattern::ReturnPattern(uword pc) | 249 ReturnPattern::ReturnPattern(uword pc) |
214 : pc_(pc) { | 250 : pc_(pc) { |
215 } | 251 } |
216 | 252 |
217 | 253 |
218 bool ReturnPattern::IsValid() const { | 254 bool ReturnPattern::IsValid() const { |
219 Instr* jr = Instr::At(pc_); | 255 Instr* jr = Instr::At(pc_); |
220 return (jr->OpcodeField() == SPECIAL) && | 256 return (jr->OpcodeField() == SPECIAL) && |
221 (jr->FunctionField() == JR) && | 257 (jr->FunctionField() == JR) && |
222 (jr->RsField() == RA); | 258 (jr->RsField() == RA); |
223 } | 259 } |
224 | 260 |
225 } // namespace dart | 261 } // namespace dart |
226 | 262 |
227 #endif // defined TARGET_ARCH_MIPS | 263 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |