| 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 #ifndef VM_DEOPT_INSTRUCTIONS_H_ | 5 #ifndef VM_DEOPT_INSTRUCTIONS_H_ |
| 6 #define VM_DEOPT_INSTRUCTIONS_H_ | 6 #define VM_DEOPT_INSTRUCTIONS_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| 11 #include "vm/deferred_objects.h" | 11 #include "vm/deferred_objects.h" |
| 12 #include "vm/growable_array.h" | 12 #include "vm/growable_array.h" |
| 13 #include "vm/locations.h" |
| 13 #include "vm/object.h" | 14 #include "vm/object.h" |
| 14 | 15 |
| 15 namespace dart { | 16 namespace dart { |
| 16 | 17 |
| 17 class Location; | 18 class Location; |
| 18 class Value; | 19 class Value; |
| 19 class MaterializeObjectInstr; | 20 class MaterializeObjectInstr; |
| 20 class StackFrame; | 21 class StackFrame; |
| 21 | 22 |
| 22 // Holds all data relevant for execution of deoptimization instructions. | 23 // Holds all data relevant for execution of deoptimization instructions. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 return cpu_registers_[reg]; | 64 return cpu_registers_[reg]; |
| 64 } | 65 } |
| 65 | 66 |
| 66 double FpuRegisterValue(FpuRegister reg) const { | 67 double FpuRegisterValue(FpuRegister reg) const { |
| 67 ASSERT(fpu_registers_ != NULL); | 68 ASSERT(fpu_registers_ != NULL); |
| 68 ASSERT(reg >= 0); | 69 ASSERT(reg >= 0); |
| 69 ASSERT(reg < kNumberOfFpuRegisters); | 70 ASSERT(reg < kNumberOfFpuRegisters); |
| 70 return *reinterpret_cast<double*>(&fpu_registers_[reg]); | 71 return *reinterpret_cast<double*>(&fpu_registers_[reg]); |
| 71 } | 72 } |
| 72 | 73 |
| 73 int64_t FpuRegisterValueAsInt64(FpuRegister reg) const { | |
| 74 ASSERT(fpu_registers_ != NULL); | |
| 75 ASSERT(reg >= 0); | |
| 76 ASSERT(reg < kNumberOfFpuRegisters); | |
| 77 return *reinterpret_cast<int64_t*>(&fpu_registers_[reg]); | |
| 78 } | |
| 79 | |
| 80 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { | 74 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { |
| 81 ASSERT(fpu_registers_ != NULL); | 75 ASSERT(fpu_registers_ != NULL); |
| 82 ASSERT(reg >= 0); | 76 ASSERT(reg >= 0); |
| 83 ASSERT(reg < kNumberOfFpuRegisters); | 77 ASSERT(reg < kNumberOfFpuRegisters); |
| 84 const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); | 78 const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); |
| 85 return simd128_value_t().readFrom(address); | 79 return simd128_value_t().readFrom(address); |
| 86 } | 80 } |
| 87 | 81 |
| 88 void set_dest_frame(intptr_t* dest_frame) { | 82 void set_dest_frame(intptr_t* dest_frame) { |
| 89 ASSERT(dest_frame != NULL && dest_frame_ == NULL); | 83 ASSERT(dest_frame != NULL && dest_frame_ == NULL); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 113 | 107 |
| 114 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 108 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 115 | 109 |
| 116 void DeferMaterializedObjectRef(intptr_t idx, intptr_t* slot) { | 110 void DeferMaterializedObjectRef(intptr_t idx, intptr_t* slot) { |
| 117 deferred_slots_ = new DeferredObjectRef( | 111 deferred_slots_ = new DeferredObjectRef( |
| 118 idx, | 112 idx, |
| 119 reinterpret_cast<RawInstance**>(slot), | 113 reinterpret_cast<RawInstance**>(slot), |
| 120 deferred_slots_); | 114 deferred_slots_); |
| 121 } | 115 } |
| 122 | 116 |
| 123 void DeferDoubleMaterialization(double value, RawDouble** slot) { | 117 void DeferMaterialization(double value, RawDouble** slot) { |
| 124 deferred_slots_ = new DeferredDouble( | 118 deferred_slots_ = new DeferredDouble( |
| 125 value, | 119 value, |
| 126 reinterpret_cast<RawInstance**>(slot), | 120 reinterpret_cast<RawInstance**>(slot), |
| 127 deferred_slots_); | 121 deferred_slots_); |
| 128 } | 122 } |
| 129 | 123 |
| 130 void DeferMintMaterialization(int64_t value, RawMint** slot) { | 124 void DeferMintMaterialization(int64_t value, RawMint** slot) { |
| 131 deferred_slots_ = new DeferredMint( | 125 deferred_slots_ = new DeferredMint( |
| 132 value, | 126 value, |
| 133 reinterpret_cast<RawInstance**>(slot), | 127 reinterpret_cast<RawInstance**>(slot), |
| 134 deferred_slots_); | 128 deferred_slots_); |
| 135 } | 129 } |
| 136 | 130 |
| 137 void DeferFloat32x4Materialization(simd128_value_t value, | 131 void DeferMaterialization(simd128_value_t value, RawFloat32x4** slot) { |
| 138 RawFloat32x4** slot) { | |
| 139 deferred_slots_ = new DeferredFloat32x4( | 132 deferred_slots_ = new DeferredFloat32x4( |
| 140 value, | 133 value, |
| 141 reinterpret_cast<RawInstance**>(slot), | 134 reinterpret_cast<RawInstance**>(slot), |
| 142 deferred_slots_); | 135 deferred_slots_); |
| 143 } | 136 } |
| 144 | 137 |
| 145 void DeferFloat64x2Materialization(simd128_value_t value, | 138 void DeferMaterialization(simd128_value_t value, RawFloat64x2** slot) { |
| 146 RawFloat64x2** slot) { | |
| 147 deferred_slots_ = new DeferredFloat64x2( | 139 deferred_slots_ = new DeferredFloat64x2( |
| 148 value, | 140 value, |
| 149 reinterpret_cast<RawInstance**>(slot), | 141 reinterpret_cast<RawInstance**>(slot), |
| 150 deferred_slots_); | 142 deferred_slots_); |
| 151 } | 143 } |
| 152 | 144 |
| 153 void DeferInt32x4Materialization(simd128_value_t value, | 145 void DeferMaterialization(simd128_value_t value, RawInt32x4** slot) { |
| 154 RawInt32x4** slot) { | |
| 155 deferred_slots_ = new DeferredInt32x4( | 146 deferred_slots_ = new DeferredInt32x4( |
| 156 value, | 147 value, |
| 157 reinterpret_cast<RawInstance**>(slot), | 148 reinterpret_cast<RawInstance**>(slot), |
| 158 deferred_slots_); | 149 deferred_slots_); |
| 159 } | 150 } |
| 160 | 151 |
| 161 DeferredObject* GetDeferredObject(intptr_t idx) const { | 152 DeferredObject* GetDeferredObject(intptr_t idx) const { |
| 162 return deferred_objects_[idx]; | 153 return deferred_objects_[idx]; |
| 163 } | 154 } |
| 164 | 155 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 | 205 |
| 215 | 206 |
| 216 // Represents one deopt instruction, e.g, setup return address, store object, | 207 // Represents one deopt instruction, e.g, setup return address, store object, |
| 217 // store register, etc. The target is defined by instruction's position in | 208 // store register, etc. The target is defined by instruction's position in |
| 218 // the deopt-info array. | 209 // the deopt-info array. |
| 219 class DeoptInstr : public ZoneAllocated { | 210 class DeoptInstr : public ZoneAllocated { |
| 220 public: | 211 public: |
| 221 enum Kind { | 212 enum Kind { |
| 222 kRetAddress, | 213 kRetAddress, |
| 223 kConstant, | 214 kConstant, |
| 224 kRegister, | 215 kWord, |
| 225 kFpuRegister, | 216 kDouble, |
| 226 kFloat32x4FpuRegister, | 217 kFloat32x4, |
| 227 kFloat64x2FpuRegister, | 218 kFloat64x2, |
| 228 kInt32x4FpuRegister, | 219 kInt32x4, |
| 229 kStackSlot, | |
| 230 kDoubleStackSlot, | |
| 231 kFloat32x4StackSlot, | |
| 232 kFloat64x2StackSlot, | |
| 233 kInt32x4StackSlot, | |
| 234 // Mints are split into low and high words. Each word can be in a register | 220 // Mints are split into low and high words. Each word can be in a register |
| 235 // or stack slot. Note Mints are only used on 32-bit architectures. | 221 // or stack slot. Note Mints are only used on 32-bit architectures. |
| 236 kMintRegisterPair, | 222 kMintPair, |
| 237 kMintStackSlotPair, | 223 kUint32, |
| 238 kMintStackSlotRegister, | |
| 239 kUint32Register, | |
| 240 kUint32StackSlot, | |
| 241 kPcMarker, | 224 kPcMarker, |
| 242 kPp, | 225 kPp, |
| 243 kCallerFp, | 226 kCallerFp, |
| 244 kCallerPp, | 227 kCallerPp, |
| 245 kCallerPc, | 228 kCallerPc, |
| 246 kSuffix, | 229 kSuffix, |
| 247 kMaterializedObjectRef, | 230 kMaterializedObjectRef, |
| 248 kMaterializeObject | 231 kMaterializeObject |
| 249 }; | 232 }; |
| 250 | 233 |
| 251 static DeoptInstr* Create(intptr_t kind_as_int, intptr_t source_index); | 234 static DeoptInstr* Create(intptr_t kind_as_int, intptr_t source_index); |
| 252 | 235 |
| 253 DeoptInstr() {} | 236 DeoptInstr() {} |
| 254 virtual ~DeoptInstr() {} | 237 virtual ~DeoptInstr() {} |
| 255 | 238 |
| 256 virtual const char* ToCString() const = 0; | 239 virtual const char* ToCString() const { |
| 240 const char* args = ArgumentsToCString(); |
| 241 if (args != NULL) { |
| 242 return Isolate::Current()->current_zone()->PrintToString( |
| 243 "%s(%s)", KindToCString(kind()), args); |
| 244 } else { |
| 245 return KindToCString(kind()); |
| 246 } |
| 247 } |
| 257 | 248 |
| 258 virtual void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) = 0; | 249 virtual void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) = 0; |
| 259 | 250 |
| 260 virtual DeoptInstr::Kind kind() const = 0; | 251 virtual DeoptInstr::Kind kind() const = 0; |
| 261 | 252 |
| 262 bool Equals(const DeoptInstr& other) const { | 253 bool Equals(const DeoptInstr& other) const { |
| 263 return (kind() == other.kind()) && (source_index() == other.source_index()); | 254 return (kind() == other.kind()) && (source_index() == other.source_index()); |
| 264 } | 255 } |
| 265 | 256 |
| 266 // Decode the payload of a suffix command. Return the suffix length and | 257 // Decode the payload of a suffix command. Return the suffix length and |
| (...skipping 11 matching lines...) Expand all Loading... |
| 278 static intptr_t GetFieldCount(DeoptInstr* instr) { | 269 static intptr_t GetFieldCount(DeoptInstr* instr) { |
| 279 ASSERT(instr->kind() == DeoptInstr::kMaterializeObject); | 270 ASSERT(instr->kind() == DeoptInstr::kMaterializeObject); |
| 280 return instr->source_index(); | 271 return instr->source_index(); |
| 281 } | 272 } |
| 282 | 273 |
| 283 protected: | 274 protected: |
| 284 friend class DeoptInfoBuilder; | 275 friend class DeoptInfoBuilder; |
| 285 | 276 |
| 286 virtual intptr_t source_index() const = 0; | 277 virtual intptr_t source_index() const = 0; |
| 287 | 278 |
| 279 virtual const char* ArgumentsToCString() const { |
| 280 return NULL; |
| 281 } |
| 282 |
| 288 private: | 283 private: |
| 284 static const char* KindToCString(Kind kind); |
| 285 |
| 289 DISALLOW_COPY_AND_ASSIGN(DeoptInstr); | 286 DISALLOW_COPY_AND_ASSIGN(DeoptInstr); |
| 290 }; | 287 }; |
| 291 | 288 |
| 292 | 289 |
| 290 // Helper class that allows to read a value of the given register from |
| 291 // the DeoptContext as the specified type. |
| 292 // It calls different method depending on which kind of register (cpu/fpu) and |
| 293 // destination types are specified. |
| 294 template<typename RegisterType, typename DestinationType> |
| 295 struct RegisterReader; |
| 296 |
| 297 template<typename T> |
| 298 struct RegisterReader<Register, T> { |
| 299 static intptr_t Read(DeoptContext* context, Register reg) { |
| 300 return context->RegisterValue(reg); |
| 301 } |
| 302 }; |
| 303 |
| 304 template<> |
| 305 struct RegisterReader<FpuRegister, double> { |
| 306 static double Read(DeoptContext* context, FpuRegister reg) { |
| 307 return context->FpuRegisterValue(reg); |
| 308 } |
| 309 }; |
| 310 |
| 311 |
| 312 template<> |
| 313 struct RegisterReader<FpuRegister, simd128_value_t> { |
| 314 static simd128_value_t Read(DeoptContext* context, FpuRegister reg) { |
| 315 return context->FpuRegisterValueAsSimd128(reg); |
| 316 } |
| 317 }; |
| 318 |
| 319 |
| 320 // Class that encapsulates reading and writing of values that were either in |
| 321 // the registers in the optimized code or were spilled from those registers |
| 322 // to the stack. |
| 323 template<typename RegisterType> |
| 324 class RegisterSource { |
| 325 public: |
| 326 enum Kind { |
| 327 // Spilled register source represented as its spill slot. |
| 328 kStackSlot = 0, |
| 329 // Register source represented as its register index. |
| 330 kRegister = 1 |
| 331 }; |
| 332 |
| 333 explicit RegisterSource(intptr_t source_index) |
| 334 : source_index_(source_index) { } |
| 335 |
| 336 RegisterSource(Kind kind, intptr_t index) |
| 337 : source_index_(KindField::encode(kind) | RawIndexField::encode(index)) { |
| 338 } |
| 339 |
| 340 template<typename T> |
| 341 T Value(DeoptContext* context) const { |
| 342 if (is_register()) { |
| 343 return static_cast<T>(RegisterReader<RegisterType, T>::Read( |
| 344 context, reg())); |
| 345 } else { |
| 346 return *reinterpret_cast<T*>(context->GetSourceFrameAddressAt( |
| 347 context->source_frame_size() - raw_index() - 1)); |
| 348 } |
| 349 } |
| 350 |
| 351 intptr_t source_index() const { return source_index_; } |
| 352 |
| 353 const char* ToCString() const { |
| 354 if (is_register()) { |
| 355 return Name(reg()); |
| 356 } else { |
| 357 return Isolate::Current()->current_zone()->PrintToString( |
| 358 "s%" Pd "", raw_index()); |
| 359 } |
| 360 } |
| 361 |
| 362 private: |
| 363 class KindField : public BitField<intptr_t, 0, 1> { }; |
| 364 class RawIndexField : public BitField<intptr_t, 1, kBitsPerWord - 1> { }; |
| 365 |
| 366 bool is_register() const { |
| 367 return KindField::decode(source_index_) == kRegister; |
| 368 } |
| 369 intptr_t raw_index() const { return RawIndexField::decode(source_index_); } |
| 370 |
| 371 RegisterType reg() const { return static_cast<RegisterType>(raw_index()); } |
| 372 |
| 373 static const char* Name(Register reg) { |
| 374 return Assembler::RegisterName(reg); |
| 375 } |
| 376 |
| 377 static const char* Name(FpuRegister fpu_reg) { |
| 378 return Assembler::FpuRegisterName(fpu_reg); |
| 379 } |
| 380 |
| 381 const intptr_t source_index_; |
| 382 }; |
| 383 |
| 384 |
| 385 typedef RegisterSource<Register> CpuRegisterSource; |
| 386 typedef RegisterSource<FpuRegister> FpuRegisterSource; |
| 387 |
| 388 |
| 293 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX | 389 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX |
| 294 // methods in the order of their target, starting wih deoptimized code | 390 // methods in the order of their target, starting wih deoptimized code |
| 295 // continuation pc and ending with the first argument of the deoptimized | 391 // continuation pc and ending with the first argument of the deoptimized |
| 296 // code. Call CreateDeoptInfo to write the accumulated instructions into | 392 // code. Call CreateDeoptInfo to write the accumulated instructions into |
| 297 // the heap and reset the builder's internal state for the next DeoptInfo. | 393 // the heap and reset the builder's internal state for the next DeoptInfo. |
| 298 class DeoptInfoBuilder : public ValueObject { | 394 class DeoptInfoBuilder : public ValueObject { |
| 299 public: | 395 public: |
| 300 DeoptInfoBuilder(Isolate* isolate, const intptr_t num_args); | 396 DeoptInfoBuilder(Isolate* isolate, const intptr_t num_args); |
| 301 | 397 |
| 302 // 'object_table' holds all objects referred to by DeoptInstr in | 398 // 'object_table' holds all objects referred to by DeoptInstr in |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 // Mark the actual start of the frame description after all materialization | 431 // Mark the actual start of the frame description after all materialization |
| 336 // instructions were emitted. Used for verification purposes. | 432 // instructions were emitted. Used for verification purposes. |
| 337 void MarkFrameStart() { | 433 void MarkFrameStart() { |
| 338 ASSERT(frame_start_ == -1); | 434 ASSERT(frame_start_ == -1); |
| 339 frame_start_ = instructions_.length(); | 435 frame_start_ = instructions_.length(); |
| 340 } | 436 } |
| 341 | 437 |
| 342 private: | 438 private: |
| 343 class TrieNode; | 439 class TrieNode; |
| 344 | 440 |
| 441 CpuRegisterSource ToCpuRegisterSource(const Location& loc); |
| 442 FpuRegisterSource ToFpuRegisterSource(const Location& loc, |
| 443 Location::Kind expected_stack_slot_kind); |
| 444 |
| 345 intptr_t FindOrAddObjectInTable(const Object& obj) const; | 445 intptr_t FindOrAddObjectInTable(const Object& obj) const; |
| 346 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; | 446 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; |
| 347 intptr_t CalculateStackIndex(const Location& source_loc) const; | 447 intptr_t CalculateStackIndex(const Location& source_loc) const; |
| 348 | 448 |
| 349 intptr_t FrameSize() const { | 449 intptr_t FrameSize() const { |
| 350 return instructions_.length() - frame_start_; | 450 return instructions_.length() - frame_start_; |
| 351 } | 451 } |
| 352 | 452 |
| 353 void AddConstant(const Object& obj, intptr_t dest_index); | 453 void AddConstant(const Object& obj, intptr_t dest_index); |
| 354 | 454 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 DeoptInfo* info, | 498 DeoptInfo* info, |
| 399 Smi* reason); | 499 Smi* reason); |
| 400 | 500 |
| 401 private: | 501 private: |
| 402 static const intptr_t kEntrySize = 3; | 502 static const intptr_t kEntrySize = 3; |
| 403 }; | 503 }; |
| 404 | 504 |
| 405 } // namespace dart | 505 } // namespace dart |
| 406 | 506 |
| 407 #endif // VM_DEOPT_INSTRUCTIONS_H_ | 507 #endif // VM_DEOPT_INSTRUCTIONS_H_ |
| OLD | NEW |