| 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/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/locations.h" | 10 #include "vm/locations.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 public: | 65 public: |
| 66 explicit DeoptStackSlotInstr(intptr_t from_index) | 66 explicit DeoptStackSlotInstr(intptr_t from_index) |
| 67 : stack_slot_index_(from_index) { | 67 : stack_slot_index_(from_index) { |
| 68 ASSERT(stack_slot_index_ >= 0); | 68 ASSERT(stack_slot_index_ >= 0); |
| 69 } | 69 } |
| 70 | 70 |
| 71 virtual intptr_t from_index() const { return stack_slot_index_; } | 71 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 72 virtual DeoptInstr::Kind kind() const { return kStackSlot; } | 72 virtual DeoptInstr::Kind kind() const { return kStackSlot; } |
| 73 | 73 |
| 74 virtual const char* ToCString() const { | 74 virtual const char* ToCString() const { |
| 75 const char* format = "s%"Pd""; | 75 return Isolate::Current()->current_zone()->PrintToString( |
| 76 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 76 "s%"Pd"", stack_slot_index_); |
| 77 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 78 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | |
| 79 return chars; | |
| 80 } | 77 } |
| 81 | 78 |
| 82 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 79 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 83 intptr_t from_index = | 80 intptr_t from_index = |
| 84 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 81 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 85 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); | 82 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); |
| 86 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 87 *to_addr = *from_addr; | 83 *to_addr = *from_addr; |
| 88 } | 84 } |
| 89 | 85 |
| 90 private: | 86 private: |
| 91 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 87 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 92 | 88 |
| 93 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | 89 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); |
| 94 }; | 90 }; |
| 95 | 91 |
| 96 | 92 |
| 97 class DeoptDoubleStackSlotInstr : public DeoptInstr { | 93 class DeoptDoubleStackSlotInstr : public DeoptInstr { |
| 98 public: | 94 public: |
| 99 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) | 95 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) |
| 100 : stack_slot_index_(from_index) { | 96 : stack_slot_index_(from_index) { |
| 101 ASSERT(stack_slot_index_ >= 0); | 97 ASSERT(stack_slot_index_ >= 0); |
| 102 } | 98 } |
| 103 | 99 |
| 104 virtual intptr_t from_index() const { return stack_slot_index_; } | 100 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 105 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } | 101 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } |
| 106 | 102 |
| 107 virtual const char* ToCString() const { | 103 virtual const char* ToCString() const { |
| 108 const char* format = "ds%"Pd""; | 104 return Isolate::Current()->current_zone()->PrintToString( |
| 109 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 105 "ds%"Pd"", stack_slot_index_); |
| 110 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 111 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | |
| 112 return chars; | |
| 113 } | 106 } |
| 114 | 107 |
| 115 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 108 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 116 intptr_t from_index = | 109 intptr_t from_index = |
| 117 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 110 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 118 double* from_addr = reinterpret_cast<double*>( | 111 double* from_addr = reinterpret_cast<double*>( |
| 119 deopt_context->GetFromFrameAddressAt(from_index)); | 112 deopt_context->GetFromFrameAddressAt(from_index)); |
| 120 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 121 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 113 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 122 Isolate::Current()->DeferDoubleMaterialization( | 114 Isolate::Current()->DeferDoubleMaterialization( |
| 123 *from_addr, reinterpret_cast<RawDouble**>(to_addr)); | 115 *from_addr, reinterpret_cast<RawDouble**>(to_addr)); |
| 124 } | 116 } |
| 125 | 117 |
| 126 private: | 118 private: |
| 127 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 119 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 128 | 120 |
| 129 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); | 121 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); |
| 130 }; | 122 }; |
| 131 | 123 |
| 132 | 124 |
| 133 class DeoptInt64StackSlotInstr : public DeoptInstr { | 125 class DeoptInt64StackSlotInstr : public DeoptInstr { |
| 134 public: | 126 public: |
| 135 explicit DeoptInt64StackSlotInstr(intptr_t from_index) | 127 explicit DeoptInt64StackSlotInstr(intptr_t from_index) |
| 136 : stack_slot_index_(from_index) { | 128 : stack_slot_index_(from_index) { |
| 137 ASSERT(stack_slot_index_ >= 0); | 129 ASSERT(stack_slot_index_ >= 0); |
| 138 } | 130 } |
| 139 | 131 |
| 140 virtual intptr_t from_index() const { return stack_slot_index_; } | 132 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 141 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } | 133 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } |
| 142 | 134 |
| 143 virtual const char* ToCString() const { | 135 virtual const char* ToCString() const { |
| 144 const char* format = "ms%"Pd""; | 136 return Isolate::Current()->current_zone()->PrintToString( |
| 145 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 137 "ms%"Pd"", stack_slot_index_); |
| 146 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 147 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | |
| 148 return chars; | |
| 149 } | 138 } |
| 150 | 139 |
| 151 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 140 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 152 intptr_t from_index = | 141 intptr_t from_index = |
| 153 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 142 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 154 int64_t* from_addr = reinterpret_cast<int64_t*>( | 143 int64_t* from_addr = reinterpret_cast<int64_t*>( |
| 155 deopt_context->GetFromFrameAddressAt(from_index)); | 144 deopt_context->GetFromFrameAddressAt(from_index)); |
| 156 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 157 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 145 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 158 if (Smi::IsValid64(*from_addr)) { | 146 if (Smi::IsValid64(*from_addr)) { |
| 159 *to_addr = reinterpret_cast<intptr_t>( | 147 *to_addr = reinterpret_cast<intptr_t>( |
| 160 Smi::New(static_cast<intptr_t>(*from_addr))); | 148 Smi::New(static_cast<intptr_t>(*from_addr))); |
| 161 } else { | 149 } else { |
| 162 Isolate::Current()->DeferMintMaterialization( | 150 Isolate::Current()->DeferMintMaterialization( |
| 163 *from_addr, reinterpret_cast<RawMint**>(to_addr)); | 151 *from_addr, reinterpret_cast<RawMint**>(to_addr)); |
| 164 } | 152 } |
| 165 } | 153 } |
| 166 | 154 |
| 167 private: | 155 private: |
| 168 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 156 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 169 | 157 |
| 170 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); | 158 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); |
| 171 }; | 159 }; |
| 172 | 160 |
| 173 | 161 |
| 174 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { | 162 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { |
| 175 public: | 163 public: |
| 176 explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index) | 164 explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index) |
| 177 : stack_slot_index_(from_index) { | 165 : stack_slot_index_(from_index) { |
| 178 ASSERT(stack_slot_index_ >= 0); | 166 ASSERT(stack_slot_index_ >= 0); |
| 179 } | 167 } |
| 180 | 168 |
| 181 virtual intptr_t from_index() const { return stack_slot_index_; } | 169 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 182 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } | 170 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } |
| 183 | 171 |
| 184 virtual const char* ToCString() const { | 172 virtual const char* ToCString() const { |
| 185 const char* format = "f32x4s%"Pd""; | 173 return Isolate::Current()->current_zone()->PrintToString( |
| 186 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 174 "f32x4s%"Pd"", stack_slot_index_); |
| 187 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 188 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | |
| 189 return chars; | |
| 190 } | 175 } |
| 191 | 176 |
| 192 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 177 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 193 intptr_t from_index = | 178 intptr_t from_index = |
| 194 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 179 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 195 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( | 180 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( |
| 196 deopt_context->GetFromFrameAddressAt(from_index)); | 181 deopt_context->GetFromFrameAddressAt(from_index)); |
| 197 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 198 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 182 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 199 Isolate::Current()->DeferFloat32x4Materialization( | 183 Isolate::Current()->DeferFloat32x4Materialization( |
| 200 *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); | 184 *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); |
| 201 } | 185 } |
| 202 | 186 |
| 203 private: | 187 private: |
| 204 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 188 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 205 | 189 |
| 206 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); | 190 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); |
| 207 }; | 191 }; |
| 208 | 192 |
| 209 | 193 |
| 210 class DeoptUint32x4StackSlotInstr : public DeoptInstr { | 194 class DeoptUint32x4StackSlotInstr : public DeoptInstr { |
| 211 public: | 195 public: |
| 212 explicit DeoptUint32x4StackSlotInstr(intptr_t from_index) | 196 explicit DeoptUint32x4StackSlotInstr(intptr_t from_index) |
| 213 : stack_slot_index_(from_index) { | 197 : stack_slot_index_(from_index) { |
| 214 ASSERT(stack_slot_index_ >= 0); | 198 ASSERT(stack_slot_index_ >= 0); |
| 215 } | 199 } |
| 216 | 200 |
| 217 virtual intptr_t from_index() const { return stack_slot_index_; } | 201 virtual intptr_t from_index() const { return stack_slot_index_; } |
| 218 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } | 202 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } |
| 219 | 203 |
| 220 virtual const char* ToCString() const { | 204 virtual const char* ToCString() const { |
| 221 const char* format = "ui32x4s%"Pd""; | 205 return Isolate::Current()->current_zone()->PrintToString( |
| 222 intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_); | 206 "ui32x4s%"Pd"", stack_slot_index_); |
| 223 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 224 OS::SNPrint(chars, len + 1, format, stack_slot_index_); | |
| 225 return chars; | |
| 226 } | 207 } |
| 227 | 208 |
| 228 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 209 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 229 intptr_t from_index = | 210 intptr_t from_index = |
| 230 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 211 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 231 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( | 212 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( |
| 232 deopt_context->GetFromFrameAddressAt(from_index)); | 213 deopt_context->GetFromFrameAddressAt(from_index)); |
| 233 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 234 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 214 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 235 Isolate::Current()->DeferUint32x4Materialization( | 215 Isolate::Current()->DeferUint32x4Materialization( |
| 236 *from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); | 216 *from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); |
| 237 } | 217 } |
| 238 | 218 |
| 239 private: | 219 private: |
| 240 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 220 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 241 | 221 |
| 242 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); | 222 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); |
| 243 }; | 223 }; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 263 DeoptId::encode(deopt_id_); | 243 DeoptId::encode(deopt_id_); |
| 264 } | 244 } |
| 265 | 245 |
| 266 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 246 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 267 | 247 |
| 268 virtual const char* ToCString() const { | 248 virtual const char* ToCString() const { |
| 269 return Isolate::Current()->current_zone()->PrintToString( | 249 return Isolate::Current()->current_zone()->PrintToString( |
| 270 "ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_); | 250 "ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_); |
| 271 } | 251 } |
| 272 | 252 |
| 273 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 253 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 274 Function& function = Function::Handle(deopt_context->isolate()); | 254 Function& function = Function::Handle(deopt_context->isolate()); |
| 275 function ^= deopt_context->ObjectAt(object_table_index_); | 255 function ^= deopt_context->ObjectAt(object_table_index_); |
| 276 const Code& code = | 256 const Code& code = |
| 277 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 257 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 278 ASSERT(!code.IsNull()); | 258 ASSERT(!code.IsNull()); |
| 279 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 259 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
| 280 PcDescriptors::kDeopt); | 260 PcDescriptors::kDeopt); |
| 281 ASSERT(continue_at_pc != 0); | 261 ASSERT(continue_at_pc != 0); |
| 282 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 283 *to_addr = continue_at_pc; | 262 *to_addr = continue_at_pc; |
| 284 | 263 |
| 285 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); | 264 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); |
| 286 if (pc != 0) { | 265 if (pc != 0) { |
| 287 // If the deoptimization happened at an IC call, update the IC data | 266 // If the deoptimization happened at an IC call, update the IC data |
| 288 // to avoid repeated deoptimization at the same site next time around. | 267 // to avoid repeated deoptimization at the same site next time around. |
| 289 ICData& ic_data = ICData::Handle(); | 268 ICData& ic_data = ICData::Handle(); |
| 290 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL); | 269 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL); |
| 291 if (!ic_data.IsNull()) { | 270 if (!ic_data.IsNull()) { |
| 292 ic_data.set_deopt_reason(deopt_context->deopt_reason()); | 271 ic_data.set_deopt_reason(deopt_context->deopt_reason()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 314 public: | 293 public: |
| 315 explicit DeoptConstantInstr(intptr_t object_table_index) | 294 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 316 : object_table_index_(object_table_index) { | 295 : object_table_index_(object_table_index) { |
| 317 ASSERT(object_table_index >= 0); | 296 ASSERT(object_table_index >= 0); |
| 318 } | 297 } |
| 319 | 298 |
| 320 virtual intptr_t from_index() const { return object_table_index_; } | 299 virtual intptr_t from_index() const { return object_table_index_; } |
| 321 virtual DeoptInstr::Kind kind() const { return kConstant; } | 300 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| 322 | 301 |
| 323 virtual const char* ToCString() const { | 302 virtual const char* ToCString() const { |
| 324 const char* format = "const oti:%"Pd""; | 303 return Isolate::Current()->current_zone()->PrintToString( |
| 325 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); | 304 "const oti:%"Pd"", object_table_index_); |
| 326 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 327 OS::SNPrint(chars, len + 1, format, object_table_index_); | |
| 328 return chars; | |
| 329 } | 305 } |
| 330 | 306 |
| 331 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 307 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 332 const Object& obj = Object::Handle( | 308 const Object& obj = Object::Handle( |
| 333 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); | 309 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); |
| 334 RawObject** to_addr = reinterpret_cast<RawObject**>( | 310 *reinterpret_cast<RawObject**>(to_addr) = obj.raw(); |
| 335 deopt_context->GetToFrameAddressAt(to_index)); | |
| 336 *to_addr = obj.raw(); | |
| 337 } | 311 } |
| 338 | 312 |
| 339 private: | 313 private: |
| 340 const intptr_t object_table_index_; | 314 const intptr_t object_table_index_; |
| 341 | 315 |
| 342 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 316 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 343 }; | 317 }; |
| 344 | 318 |
| 345 | 319 |
| 346 // Deoptimization instruction moving a CPU register. | 320 // Deoptimization instruction moving a CPU register. |
| 347 class DeoptRegisterInstr: public DeoptInstr { | 321 class DeoptRegisterInstr: public DeoptInstr { |
| 348 public: | 322 public: |
| 349 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 323 explicit DeoptRegisterInstr(intptr_t reg_as_int) |
| 350 : reg_(static_cast<Register>(reg_as_int)) {} | 324 : reg_(static_cast<Register>(reg_as_int)) {} |
| 351 | 325 |
| 352 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 326 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 353 virtual DeoptInstr::Kind kind() const { return kRegister; } | 327 virtual DeoptInstr::Kind kind() const { return kRegister; } |
| 354 | 328 |
| 355 virtual const char* ToCString() const { | 329 virtual const char* ToCString() const { |
| 356 return Assembler::RegisterName(reg_); | 330 return Assembler::RegisterName(reg_); |
| 357 } | 331 } |
| 358 | 332 |
| 359 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 333 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 360 intptr_t value = deopt_context->RegisterValue(reg_); | 334 *to_addr = deopt_context->RegisterValue(reg_); |
| 361 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 362 *to_addr = value; | |
| 363 } | 335 } |
| 364 | 336 |
| 365 private: | 337 private: |
| 366 const Register reg_; | 338 const Register reg_; |
| 367 | 339 |
| 368 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 340 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); |
| 369 }; | 341 }; |
| 370 | 342 |
| 371 | 343 |
| 372 // Deoptimization instruction moving an XMM register. | 344 // Deoptimization instruction moving an XMM register. |
| 373 class DeoptFpuRegisterInstr: public DeoptInstr { | 345 class DeoptFpuRegisterInstr: public DeoptInstr { |
| 374 public: | 346 public: |
| 375 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) | 347 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) |
| 376 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 348 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 377 | 349 |
| 378 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 350 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 379 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } | 351 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } |
| 380 | 352 |
| 381 virtual const char* ToCString() const { | 353 virtual const char* ToCString() const { |
| 382 return Assembler::FpuRegisterName(reg_); | 354 return Assembler::FpuRegisterName(reg_); |
| 383 } | 355 } |
| 384 | 356 |
| 385 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 357 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 386 double value = deopt_context->FpuRegisterValue(reg_); | 358 double value = deopt_context->FpuRegisterValue(reg_); |
| 387 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 388 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 359 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 389 Isolate::Current()->DeferDoubleMaterialization( | 360 Isolate::Current()->DeferDoubleMaterialization( |
| 390 value, reinterpret_cast<RawDouble**>(to_addr)); | 361 value, reinterpret_cast<RawDouble**>(to_addr)); |
| 391 } | 362 } |
| 392 | 363 |
| 393 private: | 364 private: |
| 394 const FpuRegister reg_; | 365 const FpuRegister reg_; |
| 395 | 366 |
| 396 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); | 367 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); |
| 397 }; | 368 }; |
| 398 | 369 |
| 399 | 370 |
| 400 class DeoptInt64FpuRegisterInstr: public DeoptInstr { | 371 class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
| 401 public: | 372 public: |
| 402 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) | 373 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) |
| 403 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 374 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 404 | 375 |
| 405 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 376 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 406 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } | 377 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } |
| 407 | 378 |
| 408 virtual const char* ToCString() const { | 379 virtual const char* ToCString() const { |
| 409 const char* format = "%s(m)"; | 380 return Isolate::Current()->current_zone()->PrintToString( |
| 410 intptr_t len = | 381 "%s(m)", Assembler::FpuRegisterName(reg_)); |
| 411 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); | |
| 412 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 413 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); | |
| 414 return chars; | |
| 415 } | 382 } |
| 416 | 383 |
| 417 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 384 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 418 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); | 385 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); |
| 419 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 420 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 386 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 421 if (Smi::IsValid64(value)) { | 387 if (Smi::IsValid64(value)) { |
| 422 *to_addr = reinterpret_cast<intptr_t>( | 388 *to_addr = reinterpret_cast<intptr_t>( |
| 423 Smi::New(static_cast<intptr_t>(value))); | 389 Smi::New(static_cast<intptr_t>(value))); |
| 424 } else { | 390 } else { |
| 425 Isolate::Current()->DeferMintMaterialization( | 391 Isolate::Current()->DeferMintMaterialization( |
| 426 value, reinterpret_cast<RawMint**>(to_addr)); | 392 value, reinterpret_cast<RawMint**>(to_addr)); |
| 427 } | 393 } |
| 428 } | 394 } |
| 429 | 395 |
| 430 private: | 396 private: |
| 431 const FpuRegister reg_; | 397 const FpuRegister reg_; |
| 432 | 398 |
| 433 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); | 399 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); |
| 434 }; | 400 }; |
| 435 | 401 |
| 436 | 402 |
| 437 // Deoptimization instruction moving an XMM register. | 403 // Deoptimization instruction moving an XMM register. |
| 438 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { | 404 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { |
| 439 public: | 405 public: |
| 440 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) | 406 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) |
| 441 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 407 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 442 | 408 |
| 443 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 409 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 444 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } | 410 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } |
| 445 | 411 |
| 446 virtual const char* ToCString() const { | 412 virtual const char* ToCString() const { |
| 447 const char* format = "%s(f32x4)"; | 413 return Isolate::Current()->current_zone()->PrintToString( |
| 448 intptr_t len = | 414 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
| 449 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); | |
| 450 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 451 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); | |
| 452 return chars; | |
| 453 } | 415 } |
| 454 | 416 |
| 455 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 417 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 456 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | 418 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
| 457 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 458 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 419 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 459 Isolate::Current()->DeferFloat32x4Materialization( | 420 Isolate::Current()->DeferFloat32x4Materialization( |
| 460 value, reinterpret_cast<RawFloat32x4**>(to_addr)); | 421 value, reinterpret_cast<RawFloat32x4**>(to_addr)); |
| 461 } | 422 } |
| 462 | 423 |
| 463 private: | 424 private: |
| 464 const FpuRegister reg_; | 425 const FpuRegister reg_; |
| 465 | 426 |
| 466 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); | 427 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); |
| 467 }; | 428 }; |
| 468 | 429 |
| 469 | 430 |
| 470 // Deoptimization instruction moving an XMM register. | 431 // Deoptimization instruction moving an XMM register. |
| 471 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { | 432 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { |
| 472 public: | 433 public: |
| 473 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) | 434 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) |
| 474 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 435 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 475 | 436 |
| 476 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 437 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
| 477 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } | 438 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } |
| 478 | 439 |
| 479 virtual const char* ToCString() const { | 440 virtual const char* ToCString() const { |
| 480 const char* format = "%s(f32x4)"; | 441 return Isolate::Current()->current_zone()->PrintToString( |
| 481 intptr_t len = | 442 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
| 482 OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_)); | |
| 483 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 484 OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_)); | |
| 485 return chars; | |
| 486 } | 443 } |
| 487 | 444 |
| 488 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 445 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 489 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | 446 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
| 490 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 491 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 447 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 492 Isolate::Current()->DeferUint32x4Materialization( | 448 Isolate::Current()->DeferUint32x4Materialization( |
| 493 value, reinterpret_cast<RawUint32x4**>(to_addr)); | 449 value, reinterpret_cast<RawUint32x4**>(to_addr)); |
| 494 } | 450 } |
| 495 | 451 |
| 496 private: | 452 private: |
| 497 const FpuRegister reg_; | 453 const FpuRegister reg_; |
| 498 | 454 |
| 499 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); | 455 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); |
| 500 }; | 456 }; |
| 501 | 457 |
| 502 | 458 |
| 503 // Deoptimization instruction creating a PC marker for the code of | 459 // Deoptimization instruction creating a PC marker for the code of |
| 504 // function at 'object_table_index'. | 460 // function at 'object_table_index'. |
| 505 class DeoptPcMarkerInstr : public DeoptInstr { | 461 class DeoptPcMarkerInstr : public DeoptInstr { |
| 506 public: | 462 public: |
| 507 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 463 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 508 : object_table_index_(object_table_index) { | 464 : object_table_index_(object_table_index) { |
| 509 ASSERT(object_table_index >= 0); | 465 ASSERT(object_table_index >= 0); |
| 510 } | 466 } |
| 511 | 467 |
| 512 virtual intptr_t from_index() const { return object_table_index_; } | 468 virtual intptr_t from_index() const { return object_table_index_; } |
| 513 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 469 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 514 | 470 |
| 515 virtual const char* ToCString() const { | 471 virtual const char* ToCString() const { |
| 516 const char* format = "pcmark oti:%"Pd""; | 472 return Isolate::Current()->current_zone()->PrintToString( |
| 517 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_); | 473 "pcmark oti:%"Pd"", object_table_index_); |
| 518 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 519 OS::SNPrint(chars, len + 1, format, object_table_index_); | |
| 520 return chars; | |
| 521 } | 474 } |
| 522 | 475 |
| 523 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 476 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 524 Function& function = Function::Handle(deopt_context->isolate()); | 477 Function& function = Function::Handle(deopt_context->isolate()); |
| 525 function ^= deopt_context->ObjectAt(object_table_index_); | 478 function ^= deopt_context->ObjectAt(object_table_index_); |
| 526 const Code& code = | 479 const Code& code = |
| 527 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 480 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 528 ASSERT(!code.IsNull()); | 481 ASSERT(!code.IsNull()); |
| 529 intptr_t pc_marker = code.EntryPoint() + | 482 intptr_t pc_marker = code.EntryPoint() + |
| 530 Assembler::kOffsetOfSavedPCfromEntrypoint; | 483 Assembler::kOffsetOfSavedPCfromEntrypoint; |
| 531 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 532 *to_addr = pc_marker; | 484 *to_addr = pc_marker; |
| 533 // Increment the deoptimization counter. This effectively increments each | 485 // Increment the deoptimization counter. This effectively increments each |
| 534 // function occurring in the optimized frame. | 486 // function occurring in the optimized frame. |
| 535 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 487 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 536 if (FLAG_trace_deoptimization) { | 488 if (FLAG_trace_deoptimization) { |
| 537 OS::PrintErr("Deoptimizing %s (count %d)\n", | 489 OS::PrintErr("Deoptimizing %s (count %d)\n", |
| 538 function.ToFullyQualifiedCString(), | 490 function.ToFullyQualifiedCString(), |
| 539 function.deoptimization_counter()); | 491 function.deoptimization_counter()); |
| 540 } | 492 } |
| 541 // Clear invocation counter so that hopefully the function gets reoptimized | 493 // Clear invocation counter so that hopefully the function gets reoptimized |
| (...skipping 14 matching lines...) Expand all Loading... |
| 556 public: | 508 public: |
| 557 DeoptCallerFpInstr() {} | 509 DeoptCallerFpInstr() {} |
| 558 | 510 |
| 559 virtual intptr_t from_index() const { return 0; } | 511 virtual intptr_t from_index() const { return 0; } |
| 560 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 512 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 561 | 513 |
| 562 virtual const char* ToCString() const { | 514 virtual const char* ToCString() const { |
| 563 return "callerfp"; | 515 return "callerfp"; |
| 564 } | 516 } |
| 565 | 517 |
| 566 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 518 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 567 intptr_t from = deopt_context->GetCallerFp(); | 519 *to_addr = deopt_context->GetCallerFp(); |
| 568 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 569 *to_addr = from; | |
| 570 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); | 520 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(to_addr)); |
| 571 } | 521 } |
| 572 | 522 |
| 573 private: | 523 private: |
| 574 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 524 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 575 }; | 525 }; |
| 576 | 526 |
| 577 | 527 |
| 578 // Deoptimization instruction copying the caller return address from optimized | 528 // Deoptimization instruction copying the caller return address from optimized |
| 579 // frame. | 529 // frame. |
| 580 class DeoptCallerPcInstr : public DeoptInstr { | 530 class DeoptCallerPcInstr : public DeoptInstr { |
| 581 public: | 531 public: |
| 582 DeoptCallerPcInstr() {} | 532 DeoptCallerPcInstr() {} |
| 583 | 533 |
| 584 virtual intptr_t from_index() const { return 0; } | 534 virtual intptr_t from_index() const { return 0; } |
| 585 virtual DeoptInstr::Kind kind() const { return kCallerPc; } | 535 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
| 586 | 536 |
| 587 virtual const char* ToCString() const { | 537 virtual const char* ToCString() const { |
| 588 return "callerpc"; | 538 return "callerpc"; |
| 589 } | 539 } |
| 590 | 540 |
| 591 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 541 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 592 intptr_t from = deopt_context->GetFromPc(); | 542 *to_addr = deopt_context->GetFromPc(); |
| 593 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); | |
| 594 *to_addr = from; | |
| 595 } | 543 } |
| 596 | 544 |
| 597 private: | 545 private: |
| 598 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 546 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 599 }; | 547 }; |
| 600 | 548 |
| 601 | 549 |
| 602 // Deoptimization instruction that indicates the rest of this DeoptInfo is a | 550 // Deoptimization instruction that indicates the rest of this DeoptInfo is a |
| 603 // suffix of another one. The suffix contains the info number (0 based | 551 // suffix of another one. The suffix contains the info number (0 based |
| 604 // index in the deopt table of the DeoptInfo to share) and the length of the | 552 // index in the deopt table of the DeoptInfo to share) and the length of the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 616 suffix_length_(SuffixLength::decode(from_index)) { | 564 suffix_length_(SuffixLength::decode(from_index)) { |
| 617 } | 565 } |
| 618 | 566 |
| 619 virtual intptr_t from_index() const { | 567 virtual intptr_t from_index() const { |
| 620 return InfoNumber::encode(info_number_) | | 568 return InfoNumber::encode(info_number_) | |
| 621 SuffixLength::encode(suffix_length_); | 569 SuffixLength::encode(suffix_length_); |
| 622 } | 570 } |
| 623 virtual DeoptInstr::Kind kind() const { return kSuffix; } | 571 virtual DeoptInstr::Kind kind() const { return kSuffix; } |
| 624 | 572 |
| 625 virtual const char* ToCString() const { | 573 virtual const char* ToCString() const { |
| 626 const char* format = "suffix %"Pd":%"Pd; | 574 return Isolate::Current()->current_zone()->PrintToString( |
| 627 intptr_t len = OS::SNPrint(NULL, 0, format, info_number_, suffix_length_); | 575 "suffix %"Pd":%"Pd, info_number_, suffix_length_); |
| 628 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
| 629 OS::SNPrint(chars, len + 1, format, info_number_, suffix_length_); | |
| 630 return chars; | |
| 631 } | 576 } |
| 632 | 577 |
| 633 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { | 578 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 634 // The deoptimization info is uncompressed by translating away suffixes | 579 // The deoptimization info is uncompressed by translating away suffixes |
| 635 // before executing the instructions. | 580 // before executing the instructions. |
| 636 UNREACHABLE(); | 581 UNREACHABLE(); |
| 637 } | 582 } |
| 638 | 583 |
| 639 private: | 584 private: |
| 640 // Static decoder functions in DeoptInstr have access to the bitfield | 585 // Static decoder functions in DeoptInstr have access to the bitfield |
| 641 // definitions. | 586 // definitions. |
| 642 friend class DeoptInstr; | 587 friend class DeoptInstr; |
| 643 | 588 |
| 644 static const intptr_t kFieldWidth = kBitsPerWord / 2; | 589 static const intptr_t kFieldWidth = kBitsPerWord / 2; |
| 645 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { }; | 590 class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { }; |
| 646 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; | 591 class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; |
| 647 | 592 |
| 648 const intptr_t info_number_; | 593 const intptr_t info_number_; |
| 649 const intptr_t suffix_length_; | 594 const intptr_t suffix_length_; |
| 650 | 595 |
| 651 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); | 596 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); |
| 652 }; | 597 }; |
| 653 | 598 |
| 654 | 599 |
| 600 // Write reference to a materialized object with the given index into the |
| 601 // stack slot. |
| 602 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 603 public: |
| 604 explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
| 605 : index_(index) { |
| 606 ASSERT(index >= 0); |
| 607 } |
| 608 |
| 609 virtual intptr_t from_index() const { return index_; } |
| 610 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 611 |
| 612 virtual const char* ToCString() const { |
| 613 return Isolate::Current()->current_zone()->PrintToString( |
| 614 "mat ref #%"Pd"", index_); |
| 615 } |
| 616 |
| 617 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 618 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); |
| 619 Isolate::Current()->DeferMaterializedObjectRef( |
| 620 index_, to_addr); |
| 621 } |
| 622 |
| 623 private: |
| 624 intptr_t index_; |
| 625 |
| 626 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
| 627 }; |
| 628 |
| 629 |
| 630 // Materialize object with the given number of fields. |
| 631 // Arguments for materialization (class and field-value pairs) are pushed |
| 632 // to the expression stack of the bottom-most frame. |
| 633 class DeoptMaterializeObjectInstr : public DeoptInstr { |
| 634 public: |
| 635 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 636 : field_count_(field_count) { |
| 637 ASSERT(field_count >= 0); |
| 638 } |
| 639 |
| 640 virtual intptr_t from_index() const { return field_count_; } |
| 641 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 642 |
| 643 virtual const char* ToCString() const { |
| 644 return Isolate::Current()->current_zone()->PrintToString( |
| 645 "mat obj len:%"Pd"", field_count_); |
| 646 } |
| 647 |
| 648 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { |
| 649 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 650 UNREACHABLE(); |
| 651 } |
| 652 |
| 653 private: |
| 654 intptr_t field_count_; |
| 655 |
| 656 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
| 657 }; |
| 658 |
| 659 |
| 655 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { | 660 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { |
| 656 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); | 661 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); |
| 657 return DeoptSuffixInstr::SuffixLength::decode(from_index); | 662 return DeoptSuffixInstr::SuffixLength::decode(from_index); |
| 658 } | 663 } |
| 659 | 664 |
| 660 | 665 |
| 661 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 666 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
| 662 const Array& object_table, | 667 const Array& object_table, |
| 663 Function* func) { | 668 Function* func) { |
| 664 ASSERT(instr->kind() == kRetAddress); | 669 ASSERT(instr->kind() == kRetAddress); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 693 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); | 698 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); |
| 694 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); | 699 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); |
| 695 case kFloat32x4FpuRegister: | 700 case kFloat32x4FpuRegister: |
| 696 return new DeoptFloat32x4FpuRegisterInstr(from_index); | 701 return new DeoptFloat32x4FpuRegisterInstr(from_index); |
| 697 case kUint32x4FpuRegister: | 702 case kUint32x4FpuRegister: |
| 698 return new DeoptUint32x4FpuRegisterInstr(from_index); | 703 return new DeoptUint32x4FpuRegisterInstr(from_index); |
| 699 case kPcMarker: return new DeoptPcMarkerInstr(from_index); | 704 case kPcMarker: return new DeoptPcMarkerInstr(from_index); |
| 700 case kCallerFp: return new DeoptCallerFpInstr(); | 705 case kCallerFp: return new DeoptCallerFpInstr(); |
| 701 case kCallerPc: return new DeoptCallerPcInstr(); | 706 case kCallerPc: return new DeoptCallerPcInstr(); |
| 702 case kSuffix: return new DeoptSuffixInstr(from_index); | 707 case kSuffix: return new DeoptSuffixInstr(from_index); |
| 708 case kMaterializedObjectRef: |
| 709 return new DeoptMaterializedObjectRefInstr(from_index); |
| 710 case kMaterializeObject: return new DeoptMaterializeObjectInstr(from_index); |
| 703 } | 711 } |
| 704 UNREACHABLE(); | 712 UNREACHABLE(); |
| 705 return NULL; | 713 return NULL; |
| 706 } | 714 } |
| 707 | 715 |
| 708 | 716 |
| 709 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 717 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
| 710 public: | 718 public: |
| 711 // Construct the root node representing the implicit "shared" terminator | 719 // Construct the root node representing the implicit "shared" terminator |
| 712 // at the end of each deopt info. | 720 // at the end of each deopt info. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 736 | 744 |
| 737 GrowableArray<TrieNode*> children_; | 745 GrowableArray<TrieNode*> children_; |
| 738 }; | 746 }; |
| 739 | 747 |
| 740 | 748 |
| 741 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args) | 749 DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args) |
| 742 : instructions_(), | 750 : instructions_(), |
| 743 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), | 751 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), |
| 744 num_args_(num_args), | 752 num_args_(num_args), |
| 745 trie_root_(new TrieNode()), | 753 trie_root_(new TrieNode()), |
| 746 current_info_number_(0) { | 754 current_info_number_(0), |
| 755 frame_start_(-1), |
| 756 materializations_() { |
| 747 } | 757 } |
| 748 | 758 |
| 749 | 759 |
| 750 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | 760 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { |
| 751 for (intptr_t i = 0; i < object_table_.Length(); i++) { | 761 for (intptr_t i = 0; i < object_table_.Length(); i++) { |
| 752 if (object_table_.At(i) == obj.raw()) { | 762 if (object_table_.At(i) == obj.raw()) { |
| 753 return i; | 763 return i; |
| 754 } | 764 } |
| 755 } | 765 } |
| 756 // Add object. | 766 // Add object. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 771 intptr_t deopt_id, | 781 intptr_t deopt_id, |
| 772 intptr_t to_index) { | 782 intptr_t to_index) { |
| 773 // Check that deopt_id exists. | 783 // Check that deopt_id exists. |
| 774 // TODO(vegorov): verify after deoptimization targets as well. | 784 // TODO(vegorov): verify after deoptimization targets as well. |
| 775 #ifdef DEBUG | 785 #ifdef DEBUG |
| 776 const Code& code = Code::Handle(function.unoptimized_code()); | 786 const Code& code = Code::Handle(function.unoptimized_code()); |
| 777 ASSERT(Isolate::IsDeoptAfter(deopt_id) || | 787 ASSERT(Isolate::IsDeoptAfter(deopt_id) || |
| 778 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); | 788 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); |
| 779 #endif | 789 #endif |
| 780 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 790 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 781 ASSERT(to_index == instructions_.length()); | 791 ASSERT(to_index == FrameSize()); |
| 782 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); | 792 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 783 } | 793 } |
| 784 | 794 |
| 785 | 795 |
| 786 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 796 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
| 787 intptr_t to_index) { | 797 intptr_t to_index) { |
| 788 // Function object was already added by AddReturnAddress, find it. | 798 // Function object was already added by AddReturnAddress, find it. |
| 789 intptr_t from_index = FindOrAddObjectInTable(function); | 799 intptr_t from_index = FindOrAddObjectInTable(function); |
| 790 ASSERT(to_index == instructions_.length()); | 800 ASSERT(to_index == FrameSize()); |
| 791 instructions_.Add(new DeoptPcMarkerInstr(from_index)); | 801 instructions_.Add(new DeoptPcMarkerInstr(from_index)); |
| 792 } | 802 } |
| 793 | 803 |
| 794 | 804 |
| 795 void DeoptInfoBuilder::AddCopy(Value* value, | 805 void DeoptInfoBuilder::AddCopy(Value* value, |
| 796 const Location& from_loc, | 806 const Location& from_loc, |
| 797 const intptr_t to_index) { | 807 const intptr_t to_index) { |
| 798 DeoptInstr* deopt_instr = NULL; | 808 DeoptInstr* deopt_instr = NULL; |
| 799 if (from_loc.IsConstant()) { | 809 if (from_loc.IsConstant()) { |
| 800 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); | 810 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 826 deopt_instr = new DeoptInt64StackSlotInstr(from_index); | 836 deopt_instr = new DeoptInt64StackSlotInstr(from_index); |
| 827 } | 837 } |
| 828 } else if (from_loc.IsQuadStackSlot()) { | 838 } else if (from_loc.IsQuadStackSlot()) { |
| 829 intptr_t from_index = CalculateStackIndex(from_loc); | 839 intptr_t from_index = CalculateStackIndex(from_loc); |
| 830 if (value->definition()->representation() == kUnboxedFloat32x4) { | 840 if (value->definition()->representation() == kUnboxedFloat32x4) { |
| 831 deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index); | 841 deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index); |
| 832 } else { | 842 } else { |
| 833 ASSERT(value->definition()->representation() == kUnboxedUint32x4); | 843 ASSERT(value->definition()->representation() == kUnboxedUint32x4); |
| 834 deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); | 844 deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); |
| 835 } | 845 } |
| 846 } else if (from_loc.IsInvalid() && |
| 847 value->definition()->IsMaterializeObject()) { |
| 848 const intptr_t index = FindMaterialization( |
| 849 value->definition()->AsMaterializeObject()); |
| 850 ASSERT(index >= 0); |
| 851 deopt_instr = new DeoptMaterializedObjectRefInstr(index); |
| 836 } else { | 852 } else { |
| 837 UNREACHABLE(); | 853 UNREACHABLE(); |
| 838 } | 854 } |
| 839 ASSERT(to_index == instructions_.length()); | 855 ASSERT(to_index == FrameSize()); |
| 840 ASSERT(deopt_instr != NULL); | 856 ASSERT(deopt_instr != NULL); |
| 841 instructions_.Add(deopt_instr); | 857 instructions_.Add(deopt_instr); |
| 842 } | 858 } |
| 843 | 859 |
| 844 | 860 |
| 845 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { | 861 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { |
| 846 ASSERT(to_index == instructions_.length()); | 862 ASSERT(to_index == FrameSize()); |
| 847 instructions_.Add(new DeoptCallerFpInstr()); | 863 instructions_.Add(new DeoptCallerFpInstr()); |
| 848 } | 864 } |
| 849 | 865 |
| 850 | 866 |
| 851 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { | 867 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { |
| 852 ASSERT(to_index == instructions_.length()); | 868 ASSERT(to_index == FrameSize()); |
| 853 instructions_.Add(new DeoptCallerPcInstr()); | 869 instructions_.Add(new DeoptCallerPcInstr()); |
| 854 } | 870 } |
| 855 | 871 |
| 856 | 872 |
| 873 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t to_index) { |
| 874 ASSERT(to_index == FrameSize()); |
| 875 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
| 876 instructions_.Add(new DeoptConstantInstr(object_table_index)); |
| 877 } |
| 878 |
| 879 |
| 880 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
| 881 const intptr_t index = FindMaterialization(mat); |
| 882 if (index >= 0) { |
| 883 return; // Already added. |
| 884 } |
| 885 materializations_.Add(mat); |
| 886 |
| 887 // Count initialized fields and emit kMaterializeObject instruction. |
| 888 // There is no need to write nulls into fields because object is null |
| 889 // initialized by default. |
| 890 intptr_t non_null_fields = 0; |
| 891 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 892 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 893 non_null_fields++; |
| 894 } |
| 895 } |
| 896 |
| 897 instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields)); |
| 898 } |
| 899 |
| 900 |
| 901 intptr_t DeoptInfoBuilder::EmitMaterializationArguments() { |
| 902 intptr_t slot_idx = 1; // Return address is emitted at 0. |
| 903 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 904 MaterializeObjectInstr* mat = materializations_[i]; |
| 905 AddConstant(mat->cls(), slot_idx++); // Class of the instance to allocate. |
| 906 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 907 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 908 // Emit field-value pair. |
| 909 AddConstant(mat->FieldAt(i), slot_idx++); |
| 910 AddCopy(mat->InputAt(i), mat->LocationAt(i), slot_idx++); |
| 911 } |
| 912 } |
| 913 } |
| 914 return slot_idx; |
| 915 } |
| 916 |
| 917 |
| 918 intptr_t DeoptInfoBuilder::FindMaterialization( |
| 919 MaterializeObjectInstr* mat) const { |
| 920 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 921 if (materializations_[i] == mat) { |
| 922 return i; |
| 923 } |
| 924 } |
| 925 return -1; |
| 926 } |
| 927 |
| 928 |
| 857 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { | 929 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { |
| 930 // TODO(vegorov): enable compression of deoptimization info containing object |
| 931 // materialization instructions. |
| 932 const bool disable_compression = |
| 933 (instructions_[0]->kind() == DeoptInstr::kMaterializeObject); |
| 934 |
| 858 intptr_t length = instructions_.length(); | 935 intptr_t length = instructions_.length(); |
| 859 | 936 |
| 860 // Count the number of instructions that are a shared suffix of some deopt | 937 // Count the number of instructions that are a shared suffix of some deopt |
| 861 // info already written. | 938 // info already written. |
| 862 TrieNode* suffix = trie_root_; | 939 TrieNode* suffix = trie_root_; |
| 863 intptr_t suffix_length = 0; | 940 intptr_t suffix_length = 0; |
| 864 if (FLAG_compress_deopt_info) { | 941 if (FLAG_compress_deopt_info && !disable_compression) { |
| 865 for (intptr_t i = length - 1; i >= 0; --i) { | 942 for (intptr_t i = length - 1; i >= 0; --i) { |
| 866 TrieNode* node = suffix->FindChild(*instructions_[i]); | 943 TrieNode* node = suffix->FindChild(*instructions_[i]); |
| 867 if (node == NULL) break; | 944 if (node == NULL) break; |
| 868 suffix = node; | 945 suffix = node; |
| 869 ++suffix_length; | 946 ++suffix_length; |
| 870 } | 947 } |
| 871 } | 948 } |
| 872 | 949 |
| 873 // Allocate space for the translation. If the shared suffix is longer | 950 // Allocate space for the translation. If the shared suffix is longer |
| 874 // than one instruction, we replace it with a single suffix instruction. | 951 // than one instruction, we replace it with a single suffix instruction. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 887 } | 964 } |
| 888 suffix->AddChild(node); | 965 suffix->AddChild(node); |
| 889 | 966 |
| 890 if (suffix_length > 1) { | 967 if (suffix_length > 1) { |
| 891 DeoptInstr* instr = | 968 DeoptInstr* instr = |
| 892 new DeoptSuffixInstr(suffix->info_number(), suffix_length); | 969 new DeoptSuffixInstr(suffix->info_number(), suffix_length); |
| 893 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); | 970 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); |
| 894 } | 971 } |
| 895 | 972 |
| 896 instructions_.Clear(); | 973 instructions_.Clear(); |
| 974 materializations_.Clear(); |
| 975 frame_start_ = -1; |
| 976 |
| 897 ++current_info_number_; | 977 ++current_info_number_; |
| 898 return deopt_info.raw(); | 978 return deopt_info.raw(); |
| 899 } | 979 } |
| 900 | 980 |
| 901 | 981 |
| 902 intptr_t DeoptTable::SizeFor(intptr_t length) { | 982 intptr_t DeoptTable::SizeFor(intptr_t length) { |
| 903 return length * kEntrySize; | 983 return length * kEntrySize; |
| 904 } | 984 } |
| 905 | 985 |
| 906 void DeoptTable::SetEntry(const Array& table, | 986 void DeoptTable::SetEntry(const Array& table, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 927 Smi* offset, | 1007 Smi* offset, |
| 928 DeoptInfo* info, | 1008 DeoptInfo* info, |
| 929 Smi* reason) { | 1009 Smi* reason) { |
| 930 intptr_t i = index * kEntrySize; | 1010 intptr_t i = index * kEntrySize; |
| 931 *offset ^= table.At(i); | 1011 *offset ^= table.At(i); |
| 932 *info ^= table.At(i + 1); | 1012 *info ^= table.At(i + 1); |
| 933 *reason ^= table.At(i + 2); | 1013 *reason ^= table.At(i + 2); |
| 934 } | 1014 } |
| 935 | 1015 |
| 936 } // namespace dart | 1016 } // namespace dart |
| OLD | NEW |