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/locations.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/stack_frame.h" | |
| 15 #include "vm/thread.h" | 16 #include "vm/thread.h" |
| 16 | 17 |
| 17 namespace dart { | 18 namespace dart { |
| 18 | 19 |
| 19 class Location; | 20 class Location; |
| 20 class Value; | 21 class Value; |
| 21 class MaterializeObjectInstr; | 22 class MaterializeObjectInstr; |
| 22 class StackFrame; | 23 class StackFrame; |
| 23 class TimelineEvent; | 24 class TimelineEvent; |
| 24 | 25 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 41 bool deoptimizing_code); | 42 bool deoptimizing_code); |
| 42 virtual ~DeoptContext(); | 43 virtual ~DeoptContext(); |
| 43 | 44 |
| 44 // Returns the offset of the dest fp from the dest sp. Used in | 45 // Returns the offset of the dest fp from the dest sp. Used in |
| 45 // runtime code to adjust the stack size before deoptimization. | 46 // runtime code to adjust the stack size before deoptimization. |
| 46 intptr_t DestStackAdjustment() const; | 47 intptr_t DestStackAdjustment() const; |
| 47 | 48 |
| 48 intptr_t* GetSourceFrameAddressAt(intptr_t index) const { | 49 intptr_t* GetSourceFrameAddressAt(intptr_t index) const { |
| 49 ASSERT(source_frame_ != NULL); | 50 ASSERT(source_frame_ != NULL); |
| 50 ASSERT((0 <= index) && (index < source_frame_size_)); | 51 ASSERT((0 <= index) && (index < source_frame_size_)); |
| 52 #if !defined(TARGET_ARCH_DBC) | |
| 53 // Convert FP relative index to SP relative one. | |
| 54 index = source_frame_size_ - 1 - index; | |
| 55 #endif // !defined(TARGET_ARCH_DBC) | |
| 51 return &source_frame_[index]; | 56 return &source_frame_[index]; |
| 52 } | 57 } |
| 53 | 58 |
| 54 intptr_t GetSourceFp() const; | 59 intptr_t GetSourceFp() const; |
| 55 intptr_t GetSourcePp() const; | 60 intptr_t GetSourcePp() const; |
| 56 intptr_t GetSourcePc() const; | 61 intptr_t GetSourcePc() const; |
| 57 | 62 |
| 58 intptr_t GetCallerFp() const; | 63 intptr_t GetCallerFp() const; |
| 59 void SetCallerFp(intptr_t callers_fp); | 64 void SetCallerFp(intptr_t callers_fp); |
| 60 | 65 |
| 61 RawObject* ObjectAt(intptr_t index) const { | 66 RawObject* ObjectAt(intptr_t index) const { |
| 62 const ObjectPool& object_pool = ObjectPool::Handle(object_pool_); | 67 const ObjectPool& object_pool = ObjectPool::Handle(object_pool_); |
| 63 return object_pool.ObjectAt(index); | 68 return object_pool.ObjectAt(index); |
| 64 } | 69 } |
| 65 | 70 |
| 66 intptr_t RegisterValue(Register reg) const { | 71 intptr_t RegisterValue(Register reg) const { |
| 72 #if !defined(TARGET_ARCH_DBC) | |
| 67 ASSERT(cpu_registers_ != NULL); | 73 ASSERT(cpu_registers_ != NULL); |
|
zra
2016/05/20 16:56:05
Would it make sense to keep any of these asserts?
Vyacheslav Egorov (Google)
2016/05/24 12:42:20
Done.
| |
| 68 ASSERT(reg >= 0); | 74 ASSERT(reg >= 0); |
| 69 ASSERT(reg < kNumberOfCpuRegisters); | 75 ASSERT(reg < kNumberOfCpuRegisters); |
| 70 return cpu_registers_[reg]; | 76 return cpu_registers_[reg]; |
| 77 #else | |
| 78 // On DBC registers and stack slots are the same. | |
| 79 const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg; | |
| 80 return *GetSourceFrameAddressAt(stack_index); | |
| 81 #endif // !defined(TARGET_ARCH_DBC) | |
| 71 } | 82 } |
| 72 | 83 |
| 73 double FpuRegisterValue(FpuRegister reg) const { | 84 double FpuRegisterValue(FpuRegister reg) const { |
| 85 #if !defined(TARGET_ARCH_DBC) | |
| 74 ASSERT(fpu_registers_ != NULL); | 86 ASSERT(fpu_registers_ != NULL); |
| 75 ASSERT(reg >= 0); | 87 ASSERT(reg >= 0); |
| 76 ASSERT(reg < kNumberOfFpuRegisters); | 88 ASSERT(reg < kNumberOfFpuRegisters); |
| 77 return *reinterpret_cast<double*>(&fpu_registers_[reg]); | 89 return *reinterpret_cast<double*>(&fpu_registers_[reg]); |
| 90 #else | |
| 91 UNREACHABLE(); | |
|
zra
2016/05/20 16:56:05
Maybe instead of this #ifdef do ASSERT(FlowGraphCo
Vyacheslav Egorov (Google)
2016/05/24 12:42:20
Done.
| |
| 92 return 0.0; | |
| 93 #endif // !defined(TARGET_ARCH_DBC) | |
| 78 } | 94 } |
| 79 | 95 |
| 80 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { | 96 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { |
| 97 #if !defined(TARGET_ARCH_DBC) | |
| 81 ASSERT(fpu_registers_ != NULL); | 98 ASSERT(fpu_registers_ != NULL); |
| 82 ASSERT(reg >= 0); | 99 ASSERT(reg >= 0); |
| 83 ASSERT(reg < kNumberOfFpuRegisters); | 100 ASSERT(reg < kNumberOfFpuRegisters); |
| 84 const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); | 101 const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); |
| 85 return simd128_value_t().readFrom(address); | 102 return simd128_value_t().readFrom(address); |
| 103 #else | |
| 104 UNREACHABLE(); | |
|
zra
2016/05/20 16:56:05
ditto with FlowGraphCompiler::SupportsUnboxedSimd1
Vyacheslav Egorov (Google)
2016/05/24 12:42:20
Done.
| |
| 105 return simd128_value_t(); | |
| 106 #endif | |
| 86 } | 107 } |
| 87 | 108 |
| 88 void set_dest_frame(intptr_t* dest_frame) { | 109 // Return base pointer for the given frame (either source or destination). |
| 89 ASSERT(dest_frame != NULL && dest_frame_ == NULL); | 110 // Base pointer points to the slot with the lowest address in the frame |
| 90 dest_frame_ = dest_frame; | 111 // including incoming arguments and artificial deoptimization frame |
| 112 // on top of it. | |
| 113 // Note: artificial frame created by the deoptimization stub is considered | |
| 114 // part of the frame because it contains saved caller PC and FP that | |
| 115 // deoptimization will fill in. | |
| 116 intptr_t* FrameBase(const StackFrame* frame) { | |
|
Florian Schneider
2016/05/25 11:28:40
static?
Florian Schneider
2016/05/25 11:29:46
Never mind... num_args_ is used.
| |
| 117 #if !defined(TARGET_ARCH_DBC) | |
| 118 // SP of the deoptimization frame is the lowest slot because | |
| 119 // stack is growing downwards. | |
| 120 return reinterpret_cast<intptr_t*>( | |
| 121 frame->sp() - (kDartFrameFixedSize * kWordSize)); | |
| 122 #else | |
| 123 // First argument is the lowest slot because stack is growing upwards. | |
| 124 return reinterpret_cast<intptr_t*>( | |
| 125 frame->fp() - (kDartFrameFixedSize + num_args_) * kWordSize); | |
| 126 #endif // !defined(TARGET_ARCH_DBC) | |
| 127 } | |
| 128 | |
| 129 void set_dest_frame(const StackFrame* frame) { | |
| 130 ASSERT(frame != NULL && dest_frame_ == NULL); | |
| 131 dest_frame_ = FrameBase(frame); | |
| 91 } | 132 } |
| 92 | 133 |
| 93 Thread* thread() const { return thread_; } | 134 Thread* thread() const { return thread_; } |
| 94 Zone* zone() const { return thread_->zone(); } | 135 Zone* zone() const { return thread_->zone(); } |
| 95 | 136 |
| 96 intptr_t source_frame_size() const { return source_frame_size_; } | 137 intptr_t source_frame_size() const { return source_frame_size_; } |
| 97 intptr_t dest_frame_size() const { return dest_frame_size_; } | 138 intptr_t dest_frame_size() const { return dest_frame_size_; } |
| 98 | 139 |
| 99 RawCode* code() const { return code_; } | 140 RawCode* code() const { return code_; } |
| 100 | 141 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 } | 222 } |
| 182 | 223 |
| 183 void DeferPpMaterialization(intptr_t index, RawObject** slot) { | 224 void DeferPpMaterialization(intptr_t index, RawObject** slot) { |
| 184 deferred_slots_ = new DeferredPp(index, slot, deferred_slots_); | 225 deferred_slots_ = new DeferredPp(index, slot, deferred_slots_); |
| 185 } | 226 } |
| 186 | 227 |
| 187 DeferredObject* GetDeferredObject(intptr_t idx) const { | 228 DeferredObject* GetDeferredObject(intptr_t idx) const { |
| 188 return deferred_objects_[idx]; | 229 return deferred_objects_[idx]; |
| 189 } | 230 } |
| 190 | 231 |
| 232 intptr_t num_args() const { return num_args_; } | |
| 233 | |
| 191 private: | 234 private: |
| 192 intptr_t* GetDestFrameAddressAt(intptr_t index) const { | 235 intptr_t* GetDestFrameAddressAt(intptr_t index) const { |
| 193 ASSERT(dest_frame_ != NULL); | 236 ASSERT(dest_frame_ != NULL); |
| 194 ASSERT((0 <= index) && (index < dest_frame_size_)); | 237 ASSERT((0 <= index) && (index < dest_frame_size_)); |
| 238 #if defined(TARGET_ARCH_DBC) | |
| 239 // Stack on DBC is growing upwards but we record deopt commands | |
| 240 // in the same order we record them on other architectures as if | |
| 241 // the stack was growing downwards. | |
| 242 index = dest_frame_size_ - 1 - index; | |
| 243 #endif // defined(TARGET_ARCH_DBC) | |
| 195 return &dest_frame_[index]; | 244 return &dest_frame_[index]; |
| 196 } | 245 } |
| 197 | 246 |
| 198 void PrepareForDeferredMaterialization(intptr_t count) { | 247 void PrepareForDeferredMaterialization(intptr_t count) { |
| 199 if (count > 0) { | 248 if (count > 0) { |
| 200 deferred_objects_ = new DeferredObject*[count]; | 249 deferred_objects_ = new DeferredObject*[count]; |
| 201 deferred_objects_count_ = count; | 250 deferred_objects_count_ = count; |
| 202 } | 251 } |
| 203 } | 252 } |
| 204 | 253 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 376 : source_index_(KindField::encode(kind) | RawIndexField::encode(index)) { | 425 : source_index_(KindField::encode(kind) | RawIndexField::encode(index)) { |
| 377 } | 426 } |
| 378 | 427 |
| 379 template<typename T> | 428 template<typename T> |
| 380 T Value(DeoptContext* context) const { | 429 T Value(DeoptContext* context) const { |
| 381 if (is_register()) { | 430 if (is_register()) { |
| 382 return static_cast<T>(RegisterReader<RegisterType, T>::Read( | 431 return static_cast<T>(RegisterReader<RegisterType, T>::Read( |
| 383 context, reg())); | 432 context, reg())); |
| 384 } else { | 433 } else { |
| 385 return *reinterpret_cast<T*>(context->GetSourceFrameAddressAt( | 434 return *reinterpret_cast<T*>(context->GetSourceFrameAddressAt( |
| 386 context->source_frame_size() - raw_index() - 1)); | 435 raw_index())); |
| 387 } | 436 } |
| 388 } | 437 } |
| 389 | 438 |
| 390 intptr_t source_index() const { return source_index_; } | 439 intptr_t source_index() const { return source_index_; } |
| 391 | 440 |
| 392 const char* ToCString() const { | 441 const char* ToCString() const { |
| 393 if (is_register()) { | 442 if (is_register()) { |
| 394 return Name(reg()); | 443 return Name(reg()); |
| 395 } else { | 444 } else { |
| 396 return Thread::Current()->zone()->PrintToString( | 445 return Thread::Current()->zone()->PrintToString( |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 public BitField<intptr_t, ICData::DeoptReasonId, 0, 8> { }; | 600 public BitField<intptr_t, ICData::DeoptReasonId, 0, 8> { }; |
| 552 class FlagsField : public BitField<intptr_t, uint32_t, 8, 8> { }; | 601 class FlagsField : public BitField<intptr_t, uint32_t, 8, 8> { }; |
| 553 | 602 |
| 554 private: | 603 private: |
| 555 static const intptr_t kEntrySize = 3; | 604 static const intptr_t kEntrySize = 3; |
| 556 }; | 605 }; |
| 557 | 606 |
| 558 } // namespace dart | 607 } // namespace dart |
| 559 | 608 |
| 560 #endif // VM_DEOPT_INSTRUCTIONS_H_ | 609 #endif // VM_DEOPT_INSTRUCTIONS_H_ |
| OLD | NEW |