Chromium Code Reviews| 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 template<typename RegisterType, typename DestinationType> struct SourceReader; | |
| 291 | |
| 292 template<typename T> | |
| 293 struct SourceReader<Register, T> { | |
| 294 static intptr_t Read(DeoptContext* context, Register reg) { | |
| 295 return context->RegisterValue(reg); | |
| 296 } | |
| 297 }; | |
| 298 | |
| 299 template<> | |
| 300 struct SourceReader<FpuRegister, double> { | |
| 301 static double Read(DeoptContext* context, FpuRegister reg) { | |
| 302 return context->FpuRegisterValue(reg); | |
| 303 } | |
| 304 }; | |
| 305 | |
| 306 | |
| 307 template<> | |
| 308 struct SourceReader<FpuRegister, simd128_value_t> { | |
| 309 static simd128_value_t Read(DeoptContext* context, FpuRegister reg) { | |
| 310 return context->FpuRegisterValueAsSimd128(reg); | |
| 311 } | |
| 312 }; | |
| 313 | |
| 314 | |
| 315 template<typename RegisterType> | |
| 316 class GenericDeoptSource { | |
| 317 public: | |
| 318 enum Kind { | |
| 319 kStackSlot = 0, | |
| 320 kRegister = 1 | |
| 321 }; | |
| 322 | |
| 323 explicit GenericDeoptSource(intptr_t source_index) | |
|
Florian Schneider
2014/08/22 17:05:45
Is this constructor used at all, or is is dead cod
Vyacheslav Egorov (Google)
2014/08/23 00:26:45
It is used when deserializing deopt instructions.
| |
| 324 : source_index_(source_index) { } | |
| 325 | |
| 326 GenericDeoptSource(Kind kind, intptr_t index) | |
| 327 : source_index_(IsRegister::encode(kind) | RawIndex::encode(index)) { | |
| 328 } | |
| 329 | |
| 330 template<typename T> | |
| 331 T Value(DeoptContext* context) const { | |
| 332 if (is_register()) { | |
| 333 return static_cast<T>(SourceReader<RegisterType, T>::Read( | |
| 334 context, reg())); | |
| 335 } else { | |
| 336 return *reinterpret_cast<T*>(context->GetSourceFrameAddressAt( | |
| 337 context->source_frame_size() - raw_index() - 1)); | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 intptr_t source_index() const { return source_index_; } | |
| 342 | |
| 343 const char* ToCString() const { | |
| 344 if (is_register()) { | |
| 345 return Name(reg()); | |
| 346 } else { | |
| 347 return Isolate::Current()->current_zone()->PrintToString( | |
| 348 "s%" Pd "", raw_index()); | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 private: | |
| 353 class IsRegister : public BitField<intptr_t, 0, 1> { }; | |
| 354 class RawIndex : public BitField<intptr_t, 1, kBitsPerWord - 1> { }; | |
| 355 | |
| 356 bool is_register() const { | |
| 357 return IsRegister::decode(source_index_) == kRegister; | |
| 358 } | |
| 359 intptr_t raw_index() const { return RawIndex::decode(source_index_); } | |
| 360 | |
| 361 RegisterType reg() const { return static_cast<RegisterType>(raw_index()); } | |
| 362 | |
| 363 static const char* Name(Register reg) { | |
| 364 return Assembler::RegisterName(reg); | |
| 365 } | |
| 366 | |
| 367 static const char* Name(FpuRegister fpu_reg) { | |
| 368 return Assembler::FpuRegisterName(fpu_reg); | |
| 369 } | |
| 370 | |
| 371 const intptr_t source_index_; | |
| 372 }; | |
| 373 | |
| 374 | |
| 375 typedef GenericDeoptSource<Register> MachineWordSource; | |
| 376 typedef GenericDeoptSource<FpuRegister> MachineFpuSource; | |
| 377 | |
| 378 | |
| 293 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX | 379 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX |
| 294 // methods in the order of their target, starting wih deoptimized code | 380 // methods in the order of their target, starting wih deoptimized code |
| 295 // continuation pc and ending with the first argument of the deoptimized | 381 // continuation pc and ending with the first argument of the deoptimized |
| 296 // code. Call CreateDeoptInfo to write the accumulated instructions into | 382 // code. Call CreateDeoptInfo to write the accumulated instructions into |
| 297 // the heap and reset the builder's internal state for the next DeoptInfo. | 383 // the heap and reset the builder's internal state for the next DeoptInfo. |
| 298 class DeoptInfoBuilder : public ValueObject { | 384 class DeoptInfoBuilder : public ValueObject { |
| 299 public: | 385 public: |
| 300 DeoptInfoBuilder(Isolate* isolate, const intptr_t num_args); | 386 DeoptInfoBuilder(Isolate* isolate, const intptr_t num_args); |
| 301 | 387 |
| 302 // 'object_table' holds all objects referred to by DeoptInstr in | 388 // '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 | 421 // Mark the actual start of the frame description after all materialization |
| 336 // instructions were emitted. Used for verification purposes. | 422 // instructions were emitted. Used for verification purposes. |
| 337 void MarkFrameStart() { | 423 void MarkFrameStart() { |
| 338 ASSERT(frame_start_ == -1); | 424 ASSERT(frame_start_ == -1); |
| 339 frame_start_ = instructions_.length(); | 425 frame_start_ = instructions_.length(); |
| 340 } | 426 } |
| 341 | 427 |
| 342 private: | 428 private: |
| 343 class TrieNode; | 429 class TrieNode; |
| 344 | 430 |
| 431 MachineWordSource ToMachineWordSource(const Location& loc); | |
| 432 MachineFpuSource ToMachineFpuSource(const Location& loc, | |
| 433 Location::Kind expected_stack_slot_kind); | |
| 434 | |
| 345 intptr_t FindOrAddObjectInTable(const Object& obj) const; | 435 intptr_t FindOrAddObjectInTable(const Object& obj) const; |
| 346 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; | 436 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; |
| 347 intptr_t CalculateStackIndex(const Location& source_loc) const; | 437 intptr_t CalculateStackIndex(const Location& source_loc) const; |
| 348 | 438 |
| 349 intptr_t FrameSize() const { | 439 intptr_t FrameSize() const { |
| 350 return instructions_.length() - frame_start_; | 440 return instructions_.length() - frame_start_; |
| 351 } | 441 } |
| 352 | 442 |
| 353 void AddConstant(const Object& obj, intptr_t dest_index); | 443 void AddConstant(const Object& obj, intptr_t dest_index); |
| 354 | 444 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 DeoptInfo* info, | 488 DeoptInfo* info, |
| 399 Smi* reason); | 489 Smi* reason); |
| 400 | 490 |
| 401 private: | 491 private: |
| 402 static const intptr_t kEntrySize = 3; | 492 static const intptr_t kEntrySize = 3; |
| 403 }; | 493 }; |
| 404 | 494 |
| 405 } // namespace dart | 495 } // namespace dart |
| 406 | 496 |
| 407 #endif // VM_DEOPT_INSTRUCTIONS_H_ | 497 #endif // VM_DEOPT_INSTRUCTIONS_H_ |
| OLD | NEW |