| 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" |
| 11 #include "vm/parser.h" | 11 #include "vm/parser.h" |
| 12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, compress_deopt_info, true, | 16 DEFINE_FLAG(bool, compress_deopt_info, true, |
| 17 "Compress the size of the deoptimization info for optimized code."); | 17 "Compress the size of the deoptimization info for optimized code."); |
| 18 DECLARE_FLAG(bool, trace_deoptimization); | 18 DECLARE_FLAG(bool, trace_deoptimization); |
| 19 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 19 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 20 | 20 |
| 21 DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, | 21 DeoptContext::DeoptContext(const Array& object_table, |
| 22 intptr_t to_frame_size, | 22 intptr_t num_args, |
| 23 const Array& object_table, | 23 DeoptReasonId deopt_reason) |
| 24 intptr_t num_args, | 24 : object_table_(object_table.raw()), |
| 25 DeoptReasonId deopt_reason) | 25 dest_frame_(NULL), |
| 26 : object_table_(object_table), | 26 dest_frame_size_(0), |
| 27 to_frame_(to_frame_start), | 27 source_frame_is_copy_(false), |
| 28 to_frame_size_(to_frame_size), | 28 source_frame_(NULL), |
| 29 from_frame_(NULL), | 29 source_frame_size_(0), |
| 30 from_frame_size_(0), | 30 cpu_registers_(NULL), |
| 31 registers_copy_(NULL), | 31 fpu_registers_(NULL), |
| 32 fpu_registers_copy_(NULL), | |
| 33 num_args_(num_args), | 32 num_args_(num_args), |
| 34 deopt_reason_(deopt_reason), | 33 deopt_reason_(deopt_reason), |
| 35 isolate_(Isolate::Current()) { | 34 isolate_(Isolate::Current()), |
| 36 from_frame_ = isolate_->deopt_frame_copy(); | 35 deferred_boxes_(NULL), |
| 37 from_frame_size_ = isolate_->deopt_frame_copy_size(); | 36 deferred_object_refs_(NULL), |
| 38 registers_copy_ = isolate_->deopt_cpu_registers_copy(); | 37 deferred_objects_count_(0), |
| 39 fpu_registers_copy_ = isolate_->deopt_fpu_registers_copy(); | 38 deferred_objects_(NULL) { |
| 40 // The deoptimized frame is filled starting just below the sp of its caller | |
| 41 // down to kDartFrameFixedSize words below its own sp. | |
| 42 // The chain of frame pointers is recreated from the fp of the caller. | |
| 43 caller_fp_ = GetFromFp(); | |
| 44 } | 39 } |
| 45 | 40 |
| 46 | 41 |
| 47 intptr_t DeoptimizationContext::GetFromFp() const { | 42 DeoptContext::~DeoptContext() { |
| 48 return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp]; | 43 // Delete memory for source frame and registers. |
| 44 if (source_frame_is_copy_) { |
| 45 delete[] source_frame_; |
| 46 } |
| 47 source_frame_ = NULL; |
| 48 delete[] fpu_registers_; |
| 49 delete[] cpu_registers_; |
| 50 fpu_registers_ = NULL; |
| 51 cpu_registers_ = NULL; |
| 52 |
| 53 // Delete all deferred objects. |
| 54 for (intptr_t i = 0; i < deferred_objects_count_; i++) { |
| 55 delete deferred_objects_[i]; |
| 56 } |
| 57 delete[] deferred_objects_; |
| 58 deferred_objects_ = NULL; |
| 59 deferred_objects_count_ = 0; |
| 49 } | 60 } |
| 50 | 61 |
| 51 | 62 |
| 52 intptr_t DeoptimizationContext::GetFromPp() const { | 63 void DeoptContext::SetSourceArgs(intptr_t* frame_start, |
| 53 return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp + | 64 intptr_t frame_size, |
| 54 StackFrame::SavedCallerPpSlotFromFp()]; | 65 fpu_register_t* fpu_registers, |
| 66 intptr_t* cpu_registers, |
| 67 bool source_frame_is_copy) { |
| 68 ASSERT(frame_start != NULL); |
| 69 ASSERT(frame_size >= 0); |
| 70 ASSERT(source_frame_ == NULL); |
| 71 ASSERT(cpu_registers_ == NULL && fpu_registers_ == NULL); |
| 72 source_frame_ = frame_start; |
| 73 source_frame_size_ = frame_size; |
| 74 caller_fp_ = GetSourceFp(); |
| 75 cpu_registers_ = cpu_registers; |
| 76 fpu_registers_ = fpu_registers; |
| 77 source_frame_is_copy_ = source_frame_is_copy; |
| 55 } | 78 } |
| 56 | 79 |
| 57 | 80 |
| 58 intptr_t DeoptimizationContext::GetFromPc() const { | 81 void DeoptContext::SetDestArgs(intptr_t* frame_start, |
| 59 return from_frame_[from_frame_size_ - num_args_ + kSavedPcSlotFromSp]; | 82 intptr_t frame_size) { |
| 83 ASSERT(frame_start != NULL); |
| 84 ASSERT(frame_size >= 0); |
| 85 ASSERT(dest_frame_ == NULL); |
| 86 dest_frame_ = frame_start; |
| 87 dest_frame_size_ = frame_size; |
| 60 } | 88 } |
| 61 | 89 |
| 62 | 90 |
| 63 intptr_t DeoptimizationContext::GetCallerFp() const { | 91 void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 92 visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_table_)); |
| 93 } |
| 94 |
| 95 |
| 96 intptr_t DeoptContext::GetSourceFp() const { |
| 97 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 98 kParamEndSlotFromFp]; |
| 99 } |
| 100 |
| 101 |
| 102 intptr_t DeoptContext::GetSourcePp() const { |
| 103 return source_frame_[source_frame_size_ - 1 - num_args_ - |
| 104 kParamEndSlotFromFp + |
| 105 StackFrame::SavedCallerPpSlotFromFp()]; |
| 106 } |
| 107 |
| 108 |
| 109 intptr_t DeoptContext::GetSourcePc() const { |
| 110 return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; |
| 111 } |
| 112 |
| 113 |
| 114 intptr_t DeoptContext::GetCallerFp() const { |
| 64 return caller_fp_; | 115 return caller_fp_; |
| 65 } | 116 } |
| 66 | 117 |
| 67 | 118 |
| 68 void DeoptimizationContext::SetCallerFp(intptr_t caller_fp) { | 119 void DeoptContext::SetCallerFp(intptr_t caller_fp) { |
| 69 caller_fp_ = caller_fp; | 120 caller_fp_ = caller_fp; |
| 70 } | 121 } |
| 71 | 122 |
| 72 | 123 |
| 124 static void FillDeferredSlots(DeferredSlot** slot_list) { |
| 125 DeferredSlot* slot = *slot_list; |
| 126 *slot_list = NULL; |
| 127 |
| 128 while (slot != NULL) { |
| 129 DeferredSlot* current = slot; |
| 130 slot = slot->next(); |
| 131 |
| 132 current->Materialize(); |
| 133 |
| 134 delete current; |
| 135 } |
| 136 } |
| 137 |
| 138 |
| 139 // Materializes all deferred objects. Returns the total number of |
| 140 // artificial arguments used during deoptimization. |
| 141 intptr_t DeoptContext::MaterializeDeferredObjects() { |
| 142 // First materialize all unboxed "primitive" values (doubles, mints, simd) |
| 143 // then materialize objects. The order is important: objects might be |
| 144 // referencing boxes allocated on the first step. At the same time |
| 145 // objects can't be referencing other deferred objects because storing |
| 146 // an object into a field is always conservatively treated as escaping by |
| 147 // allocation sinking and load forwarding. |
| 148 FillDeferredSlots(&deferred_boxes_); |
| 149 FillDeferredSlots(&deferred_object_refs_); |
| 150 |
| 151 // Compute total number of artificial arguments used during deoptimization. |
| 152 intptr_t deopt_arguments = 0; |
| 153 for (intptr_t i = 0; i < DeferredObjectsCount(); i++) { |
| 154 deopt_arguments += GetDeferredObject(i)->ArgumentCount(); |
| 155 } |
| 156 return deopt_arguments; |
| 157 } |
| 158 |
| 159 |
| 73 // Deoptimization instruction moving value from optimized frame at | 160 // Deoptimization instruction moving value from optimized frame at |
| 74 // 'from_index' to specified slots in the unoptimized frame. | 161 // 'source_index' to specified slots in the unoptimized frame. |
| 75 // 'from_index' represents the slot index of the frame (0 being first argument) | 162 // 'source_index' represents the slot index of the frame (0 being |
| 76 // and accounts for saved return address, frame pointer, pool pointer and pc | 163 // first argument) and accounts for saved return address, frame |
| 77 // marker. | 164 // pointer, pool pointer and pc marker. |
| 78 class DeoptStackSlotInstr : public DeoptInstr { | 165 class DeoptStackSlotInstr : public DeoptInstr { |
| 79 public: | 166 public: |
| 80 explicit DeoptStackSlotInstr(intptr_t from_index) | 167 explicit DeoptStackSlotInstr(intptr_t source_index) |
| 81 : stack_slot_index_(from_index) { | 168 : stack_slot_index_(source_index) { |
| 82 ASSERT(stack_slot_index_ >= 0); | 169 ASSERT(stack_slot_index_ >= 0); |
| 83 } | 170 } |
| 84 | 171 |
| 85 virtual intptr_t from_index() const { return stack_slot_index_; } | 172 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 86 virtual DeoptInstr::Kind kind() const { return kStackSlot; } | 173 virtual DeoptInstr::Kind kind() const { return kStackSlot; } |
| 87 | 174 |
| 88 virtual const char* ToCString() const { | 175 virtual const char* ToCString() const { |
| 89 return Isolate::Current()->current_zone()->PrintToString( | 176 return Isolate::Current()->current_zone()->PrintToString( |
| 90 "s%" Pd "", stack_slot_index_); | 177 "s%" Pd "", stack_slot_index_); |
| 91 } | 178 } |
| 92 | 179 |
| 93 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 180 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 94 intptr_t from_index = | 181 intptr_t source_index = |
| 95 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 182 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 96 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); | 183 intptr_t* source_addr = |
| 97 *to_addr = *from_addr; | 184 deopt_context->GetSourceFrameAddressAt(source_index); |
| 185 *dest_addr = *source_addr; |
| 98 } | 186 } |
| 99 | 187 |
| 100 private: | 188 private: |
| 101 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 189 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 102 | 190 |
| 103 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | 191 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); |
| 104 }; | 192 }; |
| 105 | 193 |
| 106 | 194 |
| 107 class DeoptDoubleStackSlotInstr : public DeoptInstr { | 195 class DeoptDoubleStackSlotInstr : public DeoptInstr { |
| 108 public: | 196 public: |
| 109 explicit DeoptDoubleStackSlotInstr(intptr_t from_index) | 197 explicit DeoptDoubleStackSlotInstr(intptr_t source_index) |
| 110 : stack_slot_index_(from_index) { | 198 : stack_slot_index_(source_index) { |
| 111 ASSERT(stack_slot_index_ >= 0); | 199 ASSERT(stack_slot_index_ >= 0); |
| 112 } | 200 } |
| 113 | 201 |
| 114 virtual intptr_t from_index() const { return stack_slot_index_; } | 202 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 115 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } | 203 virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } |
| 116 | 204 |
| 117 virtual const char* ToCString() const { | 205 virtual const char* ToCString() const { |
| 118 return Isolate::Current()->current_zone()->PrintToString( | 206 return Isolate::Current()->current_zone()->PrintToString( |
| 119 "ds%" Pd "", stack_slot_index_); | 207 "ds%" Pd "", stack_slot_index_); |
| 120 } | 208 } |
| 121 | 209 |
| 122 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 210 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 123 intptr_t from_index = | 211 intptr_t source_index = |
| 124 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 212 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 125 double* from_addr = reinterpret_cast<double*>( | 213 double* source_addr = reinterpret_cast<double*>( |
| 126 deopt_context->GetFromFrameAddressAt(from_index)); | 214 deopt_context->GetSourceFrameAddressAt(source_index)); |
| 127 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 215 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 128 Isolate::Current()->DeferDoubleMaterialization( | 216 deopt_context->DeferDoubleMaterialization( |
| 129 *from_addr, reinterpret_cast<RawDouble**>(to_addr)); | 217 *source_addr, reinterpret_cast<RawDouble**>(dest_addr)); |
| 130 } | 218 } |
| 131 | 219 |
| 132 private: | 220 private: |
| 133 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 221 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 134 | 222 |
| 135 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); | 223 DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr); |
| 136 }; | 224 }; |
| 137 | 225 |
| 138 | 226 |
| 139 class DeoptInt64StackSlotInstr : public DeoptInstr { | 227 class DeoptInt64StackSlotInstr : public DeoptInstr { |
| 140 public: | 228 public: |
| 141 explicit DeoptInt64StackSlotInstr(intptr_t from_index) | 229 explicit DeoptInt64StackSlotInstr(intptr_t source_index) |
| 142 : stack_slot_index_(from_index) { | 230 : stack_slot_index_(source_index) { |
| 143 ASSERT(stack_slot_index_ >= 0); | 231 ASSERT(stack_slot_index_ >= 0); |
| 144 } | 232 } |
| 145 | 233 |
| 146 virtual intptr_t from_index() const { return stack_slot_index_; } | 234 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 147 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } | 235 virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } |
| 148 | 236 |
| 149 virtual const char* ToCString() const { | 237 virtual const char* ToCString() const { |
| 150 return Isolate::Current()->current_zone()->PrintToString( | 238 return Isolate::Current()->current_zone()->PrintToString( |
| 151 "ms%" Pd "", stack_slot_index_); | 239 "ms%" Pd "", stack_slot_index_); |
| 152 } | 240 } |
| 153 | 241 |
| 154 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 242 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 155 intptr_t from_index = | 243 intptr_t source_index = |
| 156 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 244 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 157 int64_t* from_addr = reinterpret_cast<int64_t*>( | 245 int64_t* source_addr = reinterpret_cast<int64_t*>( |
| 158 deopt_context->GetFromFrameAddressAt(from_index)); | 246 deopt_context->GetSourceFrameAddressAt(source_index)); |
| 159 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 247 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 160 if (Smi::IsValid64(*from_addr)) { | 248 if (Smi::IsValid64(*source_addr)) { |
| 161 *to_addr = reinterpret_cast<intptr_t>( | 249 *dest_addr = reinterpret_cast<intptr_t>( |
| 162 Smi::New(static_cast<intptr_t>(*from_addr))); | 250 Smi::New(static_cast<intptr_t>(*source_addr))); |
| 163 } else { | 251 } else { |
| 164 Isolate::Current()->DeferMintMaterialization( | 252 deopt_context->DeferMintMaterialization( |
| 165 *from_addr, reinterpret_cast<RawMint**>(to_addr)); | 253 *source_addr, reinterpret_cast<RawMint**>(dest_addr)); |
| 166 } | 254 } |
| 167 } | 255 } |
| 168 | 256 |
| 169 private: | 257 private: |
| 170 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 258 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 171 | 259 |
| 172 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); | 260 DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr); |
| 173 }; | 261 }; |
| 174 | 262 |
| 175 | 263 |
| 176 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { | 264 class DeoptFloat32x4StackSlotInstr : public DeoptInstr { |
| 177 public: | 265 public: |
| 178 explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index) | 266 explicit DeoptFloat32x4StackSlotInstr(intptr_t source_index) |
| 179 : stack_slot_index_(from_index) { | 267 : stack_slot_index_(source_index) { |
| 180 ASSERT(stack_slot_index_ >= 0); | 268 ASSERT(stack_slot_index_ >= 0); |
| 181 } | 269 } |
| 182 | 270 |
| 183 virtual intptr_t from_index() const { return stack_slot_index_; } | 271 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 184 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } | 272 virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } |
| 185 | 273 |
| 186 virtual const char* ToCString() const { | 274 virtual const char* ToCString() const { |
| 187 return Isolate::Current()->current_zone()->PrintToString( | 275 return Isolate::Current()->current_zone()->PrintToString( |
| 188 "f32x4s%" Pd "", stack_slot_index_); | 276 "f32x4s%" Pd "", stack_slot_index_); |
| 189 } | 277 } |
| 190 | 278 |
| 191 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 279 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 192 intptr_t from_index = | 280 intptr_t source_index = |
| 193 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 281 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 194 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( | 282 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( |
| 195 deopt_context->GetFromFrameAddressAt(from_index)); | 283 deopt_context->GetSourceFrameAddressAt(source_index)); |
| 196 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 284 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 197 Isolate::Current()->DeferFloat32x4Materialization( | 285 deopt_context->DeferFloat32x4Materialization( |
| 198 *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); | 286 *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr)); |
| 199 } | 287 } |
| 200 | 288 |
| 201 private: | 289 private: |
| 202 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 290 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 203 | 291 |
| 204 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); | 292 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr); |
| 205 }; | 293 }; |
| 206 | 294 |
| 207 | 295 |
| 208 class DeoptUint32x4StackSlotInstr : public DeoptInstr { | 296 class DeoptUint32x4StackSlotInstr : public DeoptInstr { |
| 209 public: | 297 public: |
| 210 explicit DeoptUint32x4StackSlotInstr(intptr_t from_index) | 298 explicit DeoptUint32x4StackSlotInstr(intptr_t source_index) |
| 211 : stack_slot_index_(from_index) { | 299 : stack_slot_index_(source_index) { |
| 212 ASSERT(stack_slot_index_ >= 0); | 300 ASSERT(stack_slot_index_ >= 0); |
| 213 } | 301 } |
| 214 | 302 |
| 215 virtual intptr_t from_index() const { return stack_slot_index_; } | 303 virtual intptr_t source_index() const { return stack_slot_index_; } |
| 216 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } | 304 virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } |
| 217 | 305 |
| 218 virtual const char* ToCString() const { | 306 virtual const char* ToCString() const { |
| 219 return Isolate::Current()->current_zone()->PrintToString( | 307 return Isolate::Current()->current_zone()->PrintToString( |
| 220 "ui32x4s%" Pd "", stack_slot_index_); | 308 "ui32x4s%" Pd "", stack_slot_index_); |
| 221 } | 309 } |
| 222 | 310 |
| 223 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 311 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 224 intptr_t from_index = | 312 intptr_t source_index = |
| 225 deopt_context->from_frame_size() - stack_slot_index_ - 1; | 313 deopt_context->source_frame_size() - stack_slot_index_ - 1; |
| 226 simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( | 314 simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( |
| 227 deopt_context->GetFromFrameAddressAt(from_index)); | 315 deopt_context->GetSourceFrameAddressAt(source_index)); |
| 228 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 316 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 229 Isolate::Current()->DeferUint32x4Materialization( | 317 deopt_context->DeferUint32x4Materialization( |
| 230 *from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); | 318 *source_addr, reinterpret_cast<RawUint32x4**>(dest_addr)); |
| 231 } | 319 } |
| 232 | 320 |
| 233 private: | 321 private: |
| 234 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 322 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
| 235 | 323 |
| 236 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); | 324 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); |
| 237 }; | 325 }; |
| 238 | 326 |
| 239 | 327 |
| 240 // Deoptimization instruction creating return address using function and | 328 // Deoptimization instruction creating return address using function and |
| 241 // deopt-id stored at 'object_table_index'. | 329 // deopt-id stored at 'object_table_index'. |
| 242 class DeoptRetAddressInstr : public DeoptInstr { | 330 class DeoptRetAddressInstr : public DeoptInstr { |
| 243 public: | 331 public: |
| 244 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) | 332 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id) |
| 245 : object_table_index_(object_table_index), deopt_id_(deopt_id) { | 333 : object_table_index_(object_table_index), deopt_id_(deopt_id) { |
| 246 ASSERT(object_table_index >= 0); | 334 ASSERT(object_table_index >= 0); |
| 247 ASSERT(deopt_id >= 0); | 335 ASSERT(deopt_id >= 0); |
| 248 } | 336 } |
| 249 | 337 |
| 250 explicit DeoptRetAddressInstr(intptr_t from_index) | 338 explicit DeoptRetAddressInstr(intptr_t source_index) |
| 251 : object_table_index_(ObjectTableIndex::decode(from_index)), | 339 : object_table_index_(ObjectTableIndex::decode(source_index)), |
| 252 deopt_id_(DeoptId::decode(from_index)) { | 340 deopt_id_(DeoptId::decode(source_index)) { |
| 253 } | 341 } |
| 254 | 342 |
| 255 virtual intptr_t from_index() const { | 343 virtual intptr_t source_index() const { |
| 256 return ObjectTableIndex::encode(object_table_index_) | | 344 return ObjectTableIndex::encode(object_table_index_) | |
| 257 DeoptId::encode(deopt_id_); | 345 DeoptId::encode(deopt_id_); |
| 258 } | 346 } |
| 259 | 347 |
| 260 virtual DeoptInstr::Kind kind() const { return kRetAddress; } | 348 virtual DeoptInstr::Kind kind() const { return kRetAddress; } |
| 261 | 349 |
| 262 virtual const char* ToCString() const { | 350 virtual const char* ToCString() const { |
| 263 return Isolate::Current()->current_zone()->PrintToString( | 351 return Isolate::Current()->current_zone()->PrintToString( |
| 264 "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); | 352 "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); |
| 265 } | 353 } |
| 266 | 354 |
| 267 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 355 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 268 Function& function = Function::Handle(deopt_context->isolate()); | 356 Function& function = Function::Handle(deopt_context->isolate()); |
| 269 function ^= deopt_context->ObjectAt(object_table_index_); | 357 function ^= deopt_context->ObjectAt(object_table_index_); |
| 270 const Code& code = | 358 const Code& code = |
| 271 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 359 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 272 ASSERT(!code.IsNull()); | 360 ASSERT(!code.IsNull()); |
| 273 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, | 361 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, |
| 274 PcDescriptors::kDeopt); | 362 PcDescriptors::kDeopt); |
| 275 ASSERT(continue_at_pc != 0); | 363 ASSERT(continue_at_pc != 0); |
| 276 *to_addr = continue_at_pc; | 364 *dest_addr = continue_at_pc; |
| 277 | 365 |
| 278 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); | 366 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); |
| 279 if (pc != 0) { | 367 if (pc != 0) { |
| 280 // If the deoptimization happened at an IC call, update the IC data | 368 // If the deoptimization happened at an IC call, update the IC data |
| 281 // to avoid repeated deoptimization at the same site next time around. | 369 // to avoid repeated deoptimization at the same site next time around. |
| 282 ICData& ic_data = ICData::Handle(); | 370 ICData& ic_data = ICData::Handle(); |
| 283 CodePatcher::GetInstanceCallAt(pc, code, &ic_data); | 371 CodePatcher::GetInstanceCallAt(pc, code, &ic_data); |
| 284 if (!ic_data.IsNull()) { | 372 if (!ic_data.IsNull()) { |
| 285 ic_data.set_deopt_reason(deopt_context->deopt_reason()); | 373 ic_data.set_deopt_reason(deopt_context->deopt_reason()); |
| 286 } | 374 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 303 | 391 |
| 304 | 392 |
| 305 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 393 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
| 306 class DeoptConstantInstr : public DeoptInstr { | 394 class DeoptConstantInstr : public DeoptInstr { |
| 307 public: | 395 public: |
| 308 explicit DeoptConstantInstr(intptr_t object_table_index) | 396 explicit DeoptConstantInstr(intptr_t object_table_index) |
| 309 : object_table_index_(object_table_index) { | 397 : object_table_index_(object_table_index) { |
| 310 ASSERT(object_table_index >= 0); | 398 ASSERT(object_table_index >= 0); |
| 311 } | 399 } |
| 312 | 400 |
| 313 virtual intptr_t from_index() const { return object_table_index_; } | 401 virtual intptr_t source_index() const { return object_table_index_; } |
| 314 virtual DeoptInstr::Kind kind() const { return kConstant; } | 402 virtual DeoptInstr::Kind kind() const { return kConstant; } |
| 315 | 403 |
| 316 virtual const char* ToCString() const { | 404 virtual const char* ToCString() const { |
| 317 return Isolate::Current()->current_zone()->PrintToString( | 405 return Isolate::Current()->current_zone()->PrintToString( |
| 318 "const oti:%" Pd "", object_table_index_); | 406 "const oti:%" Pd "", object_table_index_); |
| 319 } | 407 } |
| 320 | 408 |
| 321 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 409 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 322 const Object& obj = Object::Handle( | 410 const Object& obj = Object::Handle( |
| 323 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); | 411 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); |
| 324 *reinterpret_cast<RawObject**>(to_addr) = obj.raw(); | 412 *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); |
| 325 } | 413 } |
| 326 | 414 |
| 327 private: | 415 private: |
| 328 const intptr_t object_table_index_; | 416 const intptr_t object_table_index_; |
| 329 | 417 |
| 330 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 418 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
| 331 }; | 419 }; |
| 332 | 420 |
| 333 | 421 |
| 334 // Deoptimization instruction moving a CPU register. | 422 // Deoptimization instruction moving a CPU register. |
| 335 class DeoptRegisterInstr: public DeoptInstr { | 423 class DeoptRegisterInstr: public DeoptInstr { |
| 336 public: | 424 public: |
| 337 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 425 explicit DeoptRegisterInstr(intptr_t reg_as_int) |
| 338 : reg_(static_cast<Register>(reg_as_int)) {} | 426 : reg_(static_cast<Register>(reg_as_int)) {} |
| 339 | 427 |
| 340 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 428 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 341 virtual DeoptInstr::Kind kind() const { return kRegister; } | 429 virtual DeoptInstr::Kind kind() const { return kRegister; } |
| 342 | 430 |
| 343 virtual const char* ToCString() const { | 431 virtual const char* ToCString() const { |
| 344 return Assembler::RegisterName(reg_); | 432 return Assembler::RegisterName(reg_); |
| 345 } | 433 } |
| 346 | 434 |
| 347 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 435 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 348 *to_addr = deopt_context->RegisterValue(reg_); | 436 *dest_addr = deopt_context->RegisterValue(reg_); |
| 349 } | 437 } |
| 350 | 438 |
| 351 private: | 439 private: |
| 352 const Register reg_; | 440 const Register reg_; |
| 353 | 441 |
| 354 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 442 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); |
| 355 }; | 443 }; |
| 356 | 444 |
| 357 | 445 |
| 358 // Deoptimization instruction moving an XMM register. | 446 // Deoptimization instruction moving an XMM register. |
| 359 class DeoptFpuRegisterInstr: public DeoptInstr { | 447 class DeoptFpuRegisterInstr: public DeoptInstr { |
| 360 public: | 448 public: |
| 361 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) | 449 explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) |
| 362 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 450 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 363 | 451 |
| 364 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 452 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 365 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } | 453 virtual DeoptInstr::Kind kind() const { return kFpuRegister; } |
| 366 | 454 |
| 367 virtual const char* ToCString() const { | 455 virtual const char* ToCString() const { |
| 368 return Assembler::FpuRegisterName(reg_); | 456 return Assembler::FpuRegisterName(reg_); |
| 369 } | 457 } |
| 370 | 458 |
| 371 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 459 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 372 double value = deopt_context->FpuRegisterValue(reg_); | 460 double value = deopt_context->FpuRegisterValue(reg_); |
| 373 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 461 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 374 Isolate::Current()->DeferDoubleMaterialization( | 462 deopt_context->DeferDoubleMaterialization( |
| 375 value, reinterpret_cast<RawDouble**>(to_addr)); | 463 value, reinterpret_cast<RawDouble**>(dest_addr)); |
| 376 } | 464 } |
| 377 | 465 |
| 378 private: | 466 private: |
| 379 const FpuRegister reg_; | 467 const FpuRegister reg_; |
| 380 | 468 |
| 381 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); | 469 DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr); |
| 382 }; | 470 }; |
| 383 | 471 |
| 384 | 472 |
| 385 class DeoptInt64FpuRegisterInstr: public DeoptInstr { | 473 class DeoptInt64FpuRegisterInstr: public DeoptInstr { |
| 386 public: | 474 public: |
| 387 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) | 475 explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) |
| 388 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 476 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 389 | 477 |
| 390 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 478 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 391 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } | 479 virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } |
| 392 | 480 |
| 393 virtual const char* ToCString() const { | 481 virtual const char* ToCString() const { |
| 394 return Isolate::Current()->current_zone()->PrintToString( | 482 return Isolate::Current()->current_zone()->PrintToString( |
| 395 "%s(m)", Assembler::FpuRegisterName(reg_)); | 483 "%s(m)", Assembler::FpuRegisterName(reg_)); |
| 396 } | 484 } |
| 397 | 485 |
| 398 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 486 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 399 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); | 487 int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); |
| 400 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 488 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 401 if (Smi::IsValid64(value)) { | 489 if (Smi::IsValid64(value)) { |
| 402 *to_addr = reinterpret_cast<intptr_t>( | 490 *dest_addr = reinterpret_cast<intptr_t>( |
| 403 Smi::New(static_cast<intptr_t>(value))); | 491 Smi::New(static_cast<intptr_t>(value))); |
| 404 } else { | 492 } else { |
| 405 Isolate::Current()->DeferMintMaterialization( | 493 deopt_context->DeferMintMaterialization( |
| 406 value, reinterpret_cast<RawMint**>(to_addr)); | 494 value, reinterpret_cast<RawMint**>(dest_addr)); |
| 407 } | 495 } |
| 408 } | 496 } |
| 409 | 497 |
| 410 private: | 498 private: |
| 411 const FpuRegister reg_; | 499 const FpuRegister reg_; |
| 412 | 500 |
| 413 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); | 501 DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr); |
| 414 }; | 502 }; |
| 415 | 503 |
| 416 | 504 |
| 417 // Deoptimization instruction moving an XMM register. | 505 // Deoptimization instruction moving an XMM register. |
| 418 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { | 506 class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr { |
| 419 public: | 507 public: |
| 420 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) | 508 explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) |
| 421 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 509 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 422 | 510 |
| 423 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 511 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 424 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } | 512 virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } |
| 425 | 513 |
| 426 virtual const char* ToCString() const { | 514 virtual const char* ToCString() const { |
| 427 return Isolate::Current()->current_zone()->PrintToString( | 515 return Isolate::Current()->current_zone()->PrintToString( |
| 428 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); | 516 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
| 429 } | 517 } |
| 430 | 518 |
| 431 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 519 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 432 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | 520 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
| 433 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 521 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 434 Isolate::Current()->DeferFloat32x4Materialization( | 522 deopt_context->DeferFloat32x4Materialization( |
| 435 value, reinterpret_cast<RawFloat32x4**>(to_addr)); | 523 value, reinterpret_cast<RawFloat32x4**>(dest_addr)); |
| 436 } | 524 } |
| 437 | 525 |
| 438 private: | 526 private: |
| 439 const FpuRegister reg_; | 527 const FpuRegister reg_; |
| 440 | 528 |
| 441 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); | 529 DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr); |
| 442 }; | 530 }; |
| 443 | 531 |
| 444 | 532 |
| 445 // Deoptimization instruction moving an XMM register. | 533 // Deoptimization instruction moving an XMM register. |
| 446 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { | 534 class DeoptUint32x4FpuRegisterInstr: public DeoptInstr { |
| 447 public: | 535 public: |
| 448 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) | 536 explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) |
| 449 : reg_(static_cast<FpuRegister>(reg_as_int)) {} | 537 : reg_(static_cast<FpuRegister>(reg_as_int)) {} |
| 450 | 538 |
| 451 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 539 virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } |
| 452 virtual DeoptInstr::Kind kind() const { return kUint32x4FpuRegister; } | 540 virtual DeoptInstr::Kind kind() const { return kUint32x4FpuRegister; } |
| 453 | 541 |
| 454 virtual const char* ToCString() const { | 542 virtual const char* ToCString() const { |
| 455 return Isolate::Current()->current_zone()->PrintToString( | 543 return Isolate::Current()->current_zone()->PrintToString( |
| 456 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); | 544 "%s(f32x4)", Assembler::FpuRegisterName(reg_)); |
| 457 } | 545 } |
| 458 | 546 |
| 459 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 547 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 460 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); | 548 simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); |
| 461 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 549 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 462 Isolate::Current()->DeferUint32x4Materialization( | 550 deopt_context->DeferUint32x4Materialization( |
| 463 value, reinterpret_cast<RawUint32x4**>(to_addr)); | 551 value, reinterpret_cast<RawUint32x4**>(dest_addr)); |
| 464 } | 552 } |
| 465 | 553 |
| 466 private: | 554 private: |
| 467 const FpuRegister reg_; | 555 const FpuRegister reg_; |
| 468 | 556 |
| 469 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); | 557 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr); |
| 470 }; | 558 }; |
| 471 | 559 |
| 472 | 560 |
| 473 // Deoptimization instruction creating a PC marker for the code of | 561 // Deoptimization instruction creating a PC marker for the code of |
| 474 // function at 'object_table_index'. | 562 // function at 'object_table_index'. |
| 475 class DeoptPcMarkerInstr : public DeoptInstr { | 563 class DeoptPcMarkerInstr : public DeoptInstr { |
| 476 public: | 564 public: |
| 477 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 565 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
| 478 : object_table_index_(object_table_index) { | 566 : object_table_index_(object_table_index) { |
| 479 ASSERT(object_table_index >= 0); | 567 ASSERT(object_table_index >= 0); |
| 480 } | 568 } |
| 481 | 569 |
| 482 virtual intptr_t from_index() const { return object_table_index_; } | 570 virtual intptr_t source_index() const { return object_table_index_; } |
| 483 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | 571 virtual DeoptInstr::Kind kind() const { return kPcMarker; } |
| 484 | 572 |
| 485 virtual const char* ToCString() const { | 573 virtual const char* ToCString() const { |
| 486 return Isolate::Current()->current_zone()->PrintToString( | 574 return Isolate::Current()->current_zone()->PrintToString( |
| 487 "pcmark oti:%" Pd "", object_table_index_); | 575 "pcmark oti:%" Pd "", object_table_index_); |
| 488 } | 576 } |
| 489 | 577 |
| 490 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 578 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 491 Function& function = Function::Handle(deopt_context->isolate()); | 579 Function& function = Function::Handle(deopt_context->isolate()); |
| 492 function ^= deopt_context->ObjectAt(object_table_index_); | 580 function ^= deopt_context->ObjectAt(object_table_index_); |
| 493 if (function.IsNull()) { | 581 if (function.IsNull()) { |
| 494 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. | 582 // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. |
| 495 *to_addr = 0; | 583 *dest_addr = 0; |
| 496 return; | 584 return; |
| 497 } | 585 } |
| 498 const Code& code = | 586 const Code& code = |
| 499 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 587 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 500 ASSERT(!code.IsNull()); | 588 ASSERT(!code.IsNull()); |
| 501 const intptr_t pc_marker = | 589 const intptr_t pc_marker = |
| 502 code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset; | 590 code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset; |
| 503 *to_addr = pc_marker; | 591 *dest_addr = pc_marker; |
| 504 // Increment the deoptimization counter. This effectively increments each | 592 // Increment the deoptimization counter. This effectively increments each |
| 505 // function occurring in the optimized frame. | 593 // function occurring in the optimized frame. |
| 506 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 594 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
| 507 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 595 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 508 OS::PrintErr("Deoptimizing %s (count %d)\n", | 596 OS::PrintErr("Deoptimizing %s (count %d)\n", |
| 509 function.ToFullyQualifiedCString(), | 597 function.ToFullyQualifiedCString(), |
| 510 function.deoptimization_counter()); | 598 function.deoptimization_counter()); |
| 511 } | 599 } |
| 512 // Clear invocation counter so that hopefully the function gets reoptimized | 600 // Clear invocation counter so that hopefully the function gets reoptimized |
| 513 // only after more feedback has been collected. | 601 // only after more feedback has been collected. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 524 | 612 |
| 525 // Deoptimization instruction creating a pool pointer for the code of | 613 // Deoptimization instruction creating a pool pointer for the code of |
| 526 // function at 'object_table_index'. | 614 // function at 'object_table_index'. |
| 527 class DeoptPpInstr : public DeoptInstr { | 615 class DeoptPpInstr : public DeoptInstr { |
| 528 public: | 616 public: |
| 529 explicit DeoptPpInstr(intptr_t object_table_index) | 617 explicit DeoptPpInstr(intptr_t object_table_index) |
| 530 : object_table_index_(object_table_index) { | 618 : object_table_index_(object_table_index) { |
| 531 ASSERT(object_table_index >= 0); | 619 ASSERT(object_table_index >= 0); |
| 532 } | 620 } |
| 533 | 621 |
| 534 virtual intptr_t from_index() const { return object_table_index_; } | 622 virtual intptr_t source_index() const { return object_table_index_; } |
| 535 virtual DeoptInstr::Kind kind() const { return kPp; } | 623 virtual DeoptInstr::Kind kind() const { return kPp; } |
| 536 | 624 |
| 537 virtual const char* ToCString() const { | 625 virtual const char* ToCString() const { |
| 538 return Isolate::Current()->current_zone()->PrintToString( | 626 return Isolate::Current()->current_zone()->PrintToString( |
| 539 "pp oti:%" Pd "", object_table_index_); | 627 "pp oti:%" Pd "", object_table_index_); |
| 540 } | 628 } |
| 541 | 629 |
| 542 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 630 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 543 Function& function = Function::Handle(deopt_context->isolate()); | 631 Function& function = Function::Handle(deopt_context->isolate()); |
| 544 function ^= deopt_context->ObjectAt(object_table_index_); | 632 function ^= deopt_context->ObjectAt(object_table_index_); |
| 545 const Code& code = | 633 const Code& code = |
| 546 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); | 634 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 547 ASSERT(!code.IsNull()); | 635 ASSERT(!code.IsNull()); |
| 548 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); | 636 const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); |
| 549 *to_addr = pp; | 637 *dest_addr = pp; |
| 550 } | 638 } |
| 551 | 639 |
| 552 private: | 640 private: |
| 553 intptr_t object_table_index_; | 641 intptr_t object_table_index_; |
| 554 | 642 |
| 555 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); | 643 DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr); |
| 556 }; | 644 }; |
| 557 | 645 |
| 558 | 646 |
| 559 // Deoptimization instruction copying the caller saved FP from optimized frame. | 647 // Deoptimization instruction copying the caller saved FP from optimized frame. |
| 560 class DeoptCallerFpInstr : public DeoptInstr { | 648 class DeoptCallerFpInstr : public DeoptInstr { |
| 561 public: | 649 public: |
| 562 DeoptCallerFpInstr() {} | 650 DeoptCallerFpInstr() {} |
| 563 | 651 |
| 564 virtual intptr_t from_index() const { return 0; } | 652 virtual intptr_t source_index() const { return 0; } |
| 565 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | 653 virtual DeoptInstr::Kind kind() const { return kCallerFp; } |
| 566 | 654 |
| 567 virtual const char* ToCString() const { | 655 virtual const char* ToCString() const { |
| 568 return "callerfp"; | 656 return "callerfp"; |
| 569 } | 657 } |
| 570 | 658 |
| 571 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 659 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 572 *to_addr = deopt_context->GetCallerFp(); | 660 *dest_addr = deopt_context->GetCallerFp(); |
| 573 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( | 661 deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( |
| 574 to_addr - (kSavedCallerFpSlotFromFp * kWordSize))); | 662 dest_addr - (kSavedCallerFpSlotFromFp * kWordSize))); |
| 575 } | 663 } |
| 576 | 664 |
| 577 private: | 665 private: |
| 578 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 666 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
| 579 }; | 667 }; |
| 580 | 668 |
| 581 | 669 |
| 582 // Deoptimization instruction copying the caller saved PP from optimized frame. | 670 // Deoptimization instruction copying the caller saved PP from optimized frame. |
| 583 class DeoptCallerPpInstr : public DeoptInstr { | 671 class DeoptCallerPpInstr : public DeoptInstr { |
| 584 public: | 672 public: |
| 585 DeoptCallerPpInstr() {} | 673 DeoptCallerPpInstr() {} |
| 586 | 674 |
| 587 virtual intptr_t from_index() const { return 0; } | 675 virtual intptr_t source_index() const { return 0; } |
| 588 virtual DeoptInstr::Kind kind() const { return kCallerPp; } | 676 virtual DeoptInstr::Kind kind() const { return kCallerPp; } |
| 589 | 677 |
| 590 virtual const char* ToCString() const { | 678 virtual const char* ToCString() const { |
| 591 return "callerpp"; | 679 return "callerpp"; |
| 592 } | 680 } |
| 593 | 681 |
| 594 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 682 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 595 *to_addr = deopt_context->GetFromPp(); | 683 *dest_addr = deopt_context->GetSourcePp(); |
| 596 } | 684 } |
| 597 | 685 |
| 598 private: | 686 private: |
| 599 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); | 687 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr); |
| 600 }; | 688 }; |
| 601 | 689 |
| 602 | 690 |
| 603 // Deoptimization instruction copying the caller return address from optimized | 691 // Deoptimization instruction copying the caller return address from optimized |
| 604 // frame. | 692 // frame. |
| 605 class DeoptCallerPcInstr : public DeoptInstr { | 693 class DeoptCallerPcInstr : public DeoptInstr { |
| 606 public: | 694 public: |
| 607 DeoptCallerPcInstr() {} | 695 DeoptCallerPcInstr() {} |
| 608 | 696 |
| 609 virtual intptr_t from_index() const { return 0; } | 697 virtual intptr_t source_index() const { return 0; } |
| 610 virtual DeoptInstr::Kind kind() const { return kCallerPc; } | 698 virtual DeoptInstr::Kind kind() const { return kCallerPc; } |
| 611 | 699 |
| 612 virtual const char* ToCString() const { | 700 virtual const char* ToCString() const { |
| 613 return "callerpc"; | 701 return "callerpc"; |
| 614 } | 702 } |
| 615 | 703 |
| 616 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 704 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 617 *to_addr = deopt_context->GetFromPc(); | 705 *dest_addr = deopt_context->GetSourcePc(); |
| 618 } | 706 } |
| 619 | 707 |
| 620 private: | 708 private: |
| 621 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 709 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
| 622 }; | 710 }; |
| 623 | 711 |
| 624 | 712 |
| 625 // Deoptimization instruction that indicates the rest of this DeoptInfo is a | 713 // Deoptimization instruction that indicates the rest of this DeoptInfo is a |
| 626 // suffix of another one. The suffix contains the info number (0 based | 714 // suffix of another one. The suffix contains the info number (0 based |
| 627 // index in the deopt table of the DeoptInfo to share) and the length of the | 715 // index in the deopt table of the DeoptInfo to share) and the length of the |
| 628 // suffix. | 716 // suffix. |
| 629 class DeoptSuffixInstr : public DeoptInstr { | 717 class DeoptSuffixInstr : public DeoptInstr { |
| 630 public: | 718 public: |
| 631 DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length) | 719 DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length) |
| 632 : info_number_(info_number), suffix_length_(suffix_length) { | 720 : info_number_(info_number), suffix_length_(suffix_length) { |
| 633 ASSERT(info_number >= 0); | 721 ASSERT(info_number >= 0); |
| 634 ASSERT(suffix_length >= 0); | 722 ASSERT(suffix_length >= 0); |
| 635 } | 723 } |
| 636 | 724 |
| 637 explicit DeoptSuffixInstr(intptr_t from_index) | 725 explicit DeoptSuffixInstr(intptr_t source_index) |
| 638 : info_number_(InfoNumber::decode(from_index)), | 726 : info_number_(InfoNumber::decode(source_index)), |
| 639 suffix_length_(SuffixLength::decode(from_index)) { | 727 suffix_length_(SuffixLength::decode(source_index)) { |
| 640 } | 728 } |
| 641 | 729 |
| 642 virtual intptr_t from_index() const { | 730 virtual intptr_t source_index() const { |
| 643 return InfoNumber::encode(info_number_) | | 731 return InfoNumber::encode(info_number_) | |
| 644 SuffixLength::encode(suffix_length_); | 732 SuffixLength::encode(suffix_length_); |
| 645 } | 733 } |
| 646 virtual DeoptInstr::Kind kind() const { return kSuffix; } | 734 virtual DeoptInstr::Kind kind() const { return kSuffix; } |
| 647 | 735 |
| 648 virtual const char* ToCString() const { | 736 virtual const char* ToCString() const { |
| 649 return Isolate::Current()->current_zone()->PrintToString( | 737 return Isolate::Current()->current_zone()->PrintToString( |
| 650 "suffix %" Pd ":%" Pd, info_number_, suffix_length_); | 738 "suffix %" Pd ":%" Pd, info_number_, suffix_length_); |
| 651 } | 739 } |
| 652 | 740 |
| 653 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 741 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 654 // The deoptimization info is uncompressed by translating away suffixes | 742 // The deoptimization info is uncompressed by translating away suffixes |
| 655 // before executing the instructions. | 743 // before executing the instructions. |
| 656 UNREACHABLE(); | 744 UNREACHABLE(); |
| 657 } | 745 } |
| 658 | 746 |
| 659 private: | 747 private: |
| 660 // Static decoder functions in DeoptInstr have access to the bitfield | 748 // Static decoder functions in DeoptInstr have access to the bitfield |
| 661 // definitions. | 749 // definitions. |
| 662 friend class DeoptInstr; | 750 friend class DeoptInstr; |
| 663 | 751 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 674 | 762 |
| 675 // Write reference to a materialized object with the given index into the | 763 // Write reference to a materialized object with the given index into the |
| 676 // stack slot. | 764 // stack slot. |
| 677 class DeoptMaterializedObjectRefInstr : public DeoptInstr { | 765 class DeoptMaterializedObjectRefInstr : public DeoptInstr { |
| 678 public: | 766 public: |
| 679 explicit DeoptMaterializedObjectRefInstr(intptr_t index) | 767 explicit DeoptMaterializedObjectRefInstr(intptr_t index) |
| 680 : index_(index) { | 768 : index_(index) { |
| 681 ASSERT(index >= 0); | 769 ASSERT(index >= 0); |
| 682 } | 770 } |
| 683 | 771 |
| 684 virtual intptr_t from_index() const { return index_; } | 772 virtual intptr_t source_index() const { return index_; } |
| 685 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } | 773 virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } |
| 686 | 774 |
| 687 virtual const char* ToCString() const { | 775 virtual const char* ToCString() const { |
| 688 return Isolate::Current()->current_zone()->PrintToString( | 776 return Isolate::Current()->current_zone()->PrintToString( |
| 689 "mat ref #%" Pd "", index_); | 777 "mat ref #%" Pd "", index_); |
| 690 } | 778 } |
| 691 | 779 |
| 692 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 780 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 693 *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); | 781 *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); |
| 694 Isolate::Current()->DeferMaterializedObjectRef( | 782 deopt_context->DeferMaterializedObjectRef( |
| 695 index_, to_addr); | 783 index_, dest_addr); |
| 696 } | 784 } |
| 697 | 785 |
| 698 private: | 786 private: |
| 699 intptr_t index_; | 787 intptr_t index_; |
| 700 | 788 |
| 701 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); | 789 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr); |
| 702 }; | 790 }; |
| 703 | 791 |
| 704 | 792 |
| 705 // Materialize object with the given number of fields. | 793 // Materialize object with the given number of fields. |
| 706 // Arguments for materialization (class and field-value pairs) are pushed | 794 // Arguments for materialization (class and field-value pairs) are pushed |
| 707 // to the expression stack of the bottom-most frame. | 795 // to the expression stack of the bottom-most frame. |
| 708 class DeoptMaterializeObjectInstr : public DeoptInstr { | 796 class DeoptMaterializeObjectInstr : public DeoptInstr { |
| 709 public: | 797 public: |
| 710 explicit DeoptMaterializeObjectInstr(intptr_t field_count) | 798 explicit DeoptMaterializeObjectInstr(intptr_t field_count) |
| 711 : field_count_(field_count) { | 799 : field_count_(field_count) { |
| 712 ASSERT(field_count >= 0); | 800 ASSERT(field_count >= 0); |
| 713 } | 801 } |
| 714 | 802 |
| 715 virtual intptr_t from_index() const { return field_count_; } | 803 virtual intptr_t source_index() const { return field_count_; } |
| 716 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } | 804 virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } |
| 717 | 805 |
| 718 virtual const char* ToCString() const { | 806 virtual const char* ToCString() const { |
| 719 return Isolate::Current()->current_zone()->PrintToString( | 807 return Isolate::Current()->current_zone()->PrintToString( |
| 720 "mat obj len:%" Pd "", field_count_); | 808 "mat obj len:%" Pd "", field_count_); |
| 721 } | 809 } |
| 722 | 810 |
| 723 void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { | 811 void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { |
| 724 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. | 812 // This instructions are executed manually by the DeoptimizeWithDeoptInfo. |
| 725 UNREACHABLE(); | 813 UNREACHABLE(); |
| 726 } | 814 } |
| 727 | 815 |
| 728 private: | 816 private: |
| 729 intptr_t field_count_; | 817 intptr_t field_count_; |
| 730 | 818 |
| 731 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); | 819 DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr); |
| 732 }; | 820 }; |
| 733 | 821 |
| 734 | 822 |
| 735 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { | 823 intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index, |
| 736 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); | 824 intptr_t* info_number) { |
| 737 return DeoptSuffixInstr::SuffixLength::decode(from_index); | 825 *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index); |
| 826 return DeoptSuffixInstr::SuffixLength::decode(source_index); |
| 738 } | 827 } |
| 739 | 828 |
| 740 | 829 |
| 741 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, | 830 uword DeoptInstr::GetRetAddress(DeoptInstr* instr, |
| 742 const Array& object_table, | 831 const Array& object_table, |
| 743 Function* func) { | 832 Function* func) { |
| 744 ASSERT(instr->kind() == kRetAddress); | 833 ASSERT(instr->kind() == kRetAddress); |
| 745 DeoptRetAddressInstr* ret_address_instr = | 834 DeoptRetAddressInstr* ret_address_instr = |
| 746 static_cast<DeoptRetAddressInstr*>(instr); | 835 static_cast<DeoptRetAddressInstr*>(instr); |
| 747 // The following assert may trigger when displaying a backtrace | 836 // The following assert may trigger when displaying a backtrace |
| 748 // from the simulator. | 837 // from the simulator. |
| 749 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); | 838 ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id())); |
| 750 ASSERT(!object_table.IsNull()); | 839 ASSERT(!object_table.IsNull()); |
| 751 ASSERT(func != NULL); | 840 ASSERT(func != NULL); |
| 752 *func ^= object_table.At(ret_address_instr->object_table_index()); | 841 *func ^= object_table.At(ret_address_instr->object_table_index()); |
| 753 const Code& code = Code::Handle(func->unoptimized_code()); | 842 const Code& code = Code::Handle(func->unoptimized_code()); |
| 754 ASSERT(!code.IsNull()); | 843 ASSERT(!code.IsNull()); |
| 755 uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(), | 844 uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(), |
| 756 PcDescriptors::kDeopt); | 845 PcDescriptors::kDeopt); |
| 757 ASSERT(res != 0); | 846 ASSERT(res != 0); |
| 758 return res; | 847 return res; |
| 759 } | 848 } |
| 760 | 849 |
| 761 | 850 |
| 762 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | 851 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { |
| 763 Kind kind = static_cast<Kind>(kind_as_int); | 852 Kind kind = static_cast<Kind>(kind_as_int); |
| 764 switch (kind) { | 853 switch (kind) { |
| 765 case kStackSlot: return new DeoptStackSlotInstr(from_index); | 854 case kStackSlot: return new DeoptStackSlotInstr(source_index); |
| 766 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); | 855 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index); |
| 767 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); | 856 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index); |
| 768 case kFloat32x4StackSlot: | 857 case kFloat32x4StackSlot: |
| 769 return new DeoptFloat32x4StackSlotInstr(from_index); | 858 return new DeoptFloat32x4StackSlotInstr(source_index); |
| 770 case kUint32x4StackSlot: | 859 case kUint32x4StackSlot: |
| 771 return new DeoptUint32x4StackSlotInstr(from_index); | 860 return new DeoptUint32x4StackSlotInstr(source_index); |
| 772 case kRetAddress: return new DeoptRetAddressInstr(from_index); | 861 case kRetAddress: return new DeoptRetAddressInstr(source_index); |
| 773 case kConstant: return new DeoptConstantInstr(from_index); | 862 case kConstant: return new DeoptConstantInstr(source_index); |
| 774 case kRegister: return new DeoptRegisterInstr(from_index); | 863 case kRegister: return new DeoptRegisterInstr(source_index); |
| 775 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); | 864 case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); |
| 776 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); | 865 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index); |
| 777 case kFloat32x4FpuRegister: | 866 case kFloat32x4FpuRegister: |
| 778 return new DeoptFloat32x4FpuRegisterInstr(from_index); | 867 return new DeoptFloat32x4FpuRegisterInstr(source_index); |
| 779 case kUint32x4FpuRegister: | 868 case kUint32x4FpuRegister: |
| 780 return new DeoptUint32x4FpuRegisterInstr(from_index); | 869 return new DeoptUint32x4FpuRegisterInstr(source_index); |
| 781 case kPcMarker: return new DeoptPcMarkerInstr(from_index); | 870 case kPcMarker: return new DeoptPcMarkerInstr(source_index); |
| 782 case kPp: return new DeoptPpInstr(from_index); | 871 case kPp: return new DeoptPpInstr(source_index); |
| 783 case kCallerFp: return new DeoptCallerFpInstr(); | 872 case kCallerFp: return new DeoptCallerFpInstr(); |
| 784 case kCallerPp: return new DeoptCallerPpInstr(); | 873 case kCallerPp: return new DeoptCallerPpInstr(); |
| 785 case kCallerPc: return new DeoptCallerPcInstr(); | 874 case kCallerPc: return new DeoptCallerPcInstr(); |
| 786 case kSuffix: return new DeoptSuffixInstr(from_index); | 875 case kSuffix: return new DeoptSuffixInstr(source_index); |
| 787 case kMaterializedObjectRef: | 876 case kMaterializedObjectRef: |
| 788 return new DeoptMaterializedObjectRefInstr(from_index); | 877 return new DeoptMaterializedObjectRefInstr(source_index); |
| 789 case kMaterializeObject: return new DeoptMaterializeObjectInstr(from_index); | 878 case kMaterializeObject: |
| 879 return new DeoptMaterializeObjectInstr(source_index); |
| 790 } | 880 } |
| 791 UNREACHABLE(); | 881 UNREACHABLE(); |
| 792 return NULL; | 882 return NULL; |
| 793 } | 883 } |
| 794 | 884 |
| 795 | 885 |
| 796 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { | 886 class DeoptInfoBuilder::TrieNode : public ZoneAllocated { |
| 797 public: | 887 public: |
| 798 // Construct the root node representing the implicit "shared" terminator | 888 // Construct the root node representing the implicit "shared" terminator |
| 799 // at the end of each deopt info. | 889 // at the end of each deopt info. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 return i; | 933 return i; |
| 844 } | 934 } |
| 845 } | 935 } |
| 846 // Add object. | 936 // Add object. |
| 847 const intptr_t result = object_table_.Length(); | 937 const intptr_t result = object_table_.Length(); |
| 848 object_table_.Add(obj, Heap::kOld); | 938 object_table_.Add(obj, Heap::kOld); |
| 849 return result; | 939 return result; |
| 850 } | 940 } |
| 851 | 941 |
| 852 | 942 |
| 853 intptr_t DeoptInfoBuilder::CalculateStackIndex(const Location& from_loc) const { | 943 intptr_t DeoptInfoBuilder::CalculateStackIndex( |
| 854 return from_loc.stack_index() < 0 ? | 944 const Location& source_loc) const { |
| 855 from_loc.stack_index() + num_args_ : | 945 return source_loc.stack_index() < 0 ? |
| 856 from_loc.stack_index() + num_args_ + kDartFrameFixedSize; | 946 source_loc.stack_index() + num_args_ : |
| 947 source_loc.stack_index() + num_args_ + kDartFrameFixedSize; |
| 857 } | 948 } |
| 858 | 949 |
| 859 | 950 |
| 860 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | 951 void DeoptInfoBuilder::AddReturnAddress(const Function& function, |
| 861 intptr_t deopt_id, | 952 intptr_t deopt_id, |
| 862 intptr_t to_index) { | 953 intptr_t dest_index) { |
| 863 // Check that deopt_id exists. | 954 // Check that deopt_id exists. |
| 864 // TODO(vegorov): verify after deoptimization targets as well. | 955 // TODO(vegorov): verify after deoptimization targets as well. |
| 865 #ifdef DEBUG | 956 #ifdef DEBUG |
| 866 const Code& code = Code::Handle(function.unoptimized_code()); | 957 const Code& code = Code::Handle(function.unoptimized_code()); |
| 867 ASSERT(Isolate::IsDeoptAfter(deopt_id) || | 958 ASSERT(Isolate::IsDeoptAfter(deopt_id) || |
| 868 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); | 959 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); |
| 869 #endif | 960 #endif |
| 870 const intptr_t object_table_index = FindOrAddObjectInTable(function); | 961 const intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 871 ASSERT(to_index == FrameSize()); | 962 ASSERT(dest_index == FrameSize()); |
| 872 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); | 963 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); |
| 873 } | 964 } |
| 874 | 965 |
| 875 | 966 |
| 876 void DeoptInfoBuilder::AddPcMarker(const Function& function, | 967 void DeoptInfoBuilder::AddPcMarker(const Function& function, |
| 877 intptr_t to_index) { | 968 intptr_t dest_index) { |
| 878 intptr_t object_table_index = FindOrAddObjectInTable(function); | 969 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 879 ASSERT(to_index == FrameSize()); | 970 ASSERT(dest_index == FrameSize()); |
| 880 instructions_.Add(new DeoptPcMarkerInstr(object_table_index)); | 971 instructions_.Add(new DeoptPcMarkerInstr(object_table_index)); |
| 881 } | 972 } |
| 882 | 973 |
| 883 | 974 |
| 884 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t to_index) { | 975 void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { |
| 885 intptr_t object_table_index = FindOrAddObjectInTable(function); | 976 intptr_t object_table_index = FindOrAddObjectInTable(function); |
| 886 ASSERT(to_index == FrameSize()); | 977 ASSERT(dest_index == FrameSize()); |
| 887 instructions_.Add(new DeoptPpInstr(object_table_index)); | 978 instructions_.Add(new DeoptPpInstr(object_table_index)); |
| 888 } | 979 } |
| 889 | 980 |
| 890 | 981 |
| 891 void DeoptInfoBuilder::AddCopy(Value* value, | 982 void DeoptInfoBuilder::AddCopy(Value* value, |
| 892 const Location& from_loc, | 983 const Location& source_loc, |
| 893 const intptr_t to_index) { | 984 const intptr_t dest_index) { |
| 894 DeoptInstr* deopt_instr = NULL; | 985 DeoptInstr* deopt_instr = NULL; |
| 895 if (from_loc.IsConstant()) { | 986 if (source_loc.IsConstant()) { |
| 896 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); | 987 intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); |
| 897 deopt_instr = new DeoptConstantInstr(object_table_index); | 988 deopt_instr = new DeoptConstantInstr(object_table_index); |
| 898 } else if (from_loc.IsRegister()) { | 989 } else if (source_loc.IsRegister()) { |
| 899 ASSERT(value->definition()->representation() == kTagged); | 990 ASSERT(value->definition()->representation() == kTagged); |
| 900 deopt_instr = new DeoptRegisterInstr(from_loc.reg()); | 991 deopt_instr = new DeoptRegisterInstr(source_loc.reg()); |
| 901 } else if (from_loc.IsFpuRegister()) { | 992 } else if (source_loc.IsFpuRegister()) { |
| 902 if (value->definition()->representation() == kUnboxedDouble) { | 993 if (value->definition()->representation() == kUnboxedDouble) { |
| 903 deopt_instr = new DeoptFpuRegisterInstr(from_loc.fpu_reg()); | 994 deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg()); |
| 904 } else if (value->definition()->representation() == kUnboxedMint) { | 995 } else if (value->definition()->representation() == kUnboxedMint) { |
| 905 deopt_instr = new DeoptInt64FpuRegisterInstr(from_loc.fpu_reg()); | 996 deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg()); |
| 906 } else if (value->definition()->representation() == kUnboxedFloat32x4) { | 997 } else if (value->definition()->representation() == kUnboxedFloat32x4) { |
| 907 deopt_instr = new DeoptFloat32x4FpuRegisterInstr(from_loc.fpu_reg()); | 998 deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); |
| 908 } else { | 999 } else { |
| 909 ASSERT(value->definition()->representation() == kUnboxedUint32x4); | 1000 ASSERT(value->definition()->representation() == kUnboxedUint32x4); |
| 910 deopt_instr = new DeoptUint32x4FpuRegisterInstr(from_loc.fpu_reg()); | 1001 deopt_instr = new DeoptUint32x4FpuRegisterInstr(source_loc.fpu_reg()); |
| 911 } | 1002 } |
| 912 } else if (from_loc.IsStackSlot()) { | 1003 } else if (source_loc.IsStackSlot()) { |
| 913 ASSERT(value->definition()->representation() == kTagged); | 1004 ASSERT(value->definition()->representation() == kTagged); |
| 914 intptr_t from_index = CalculateStackIndex(from_loc); | 1005 intptr_t source_index = CalculateStackIndex(source_loc); |
| 915 deopt_instr = new DeoptStackSlotInstr(from_index); | 1006 deopt_instr = new DeoptStackSlotInstr(source_index); |
| 916 } else if (from_loc.IsDoubleStackSlot()) { | 1007 } else if (source_loc.IsDoubleStackSlot()) { |
| 917 intptr_t from_index = CalculateStackIndex(from_loc); | 1008 intptr_t source_index = CalculateStackIndex(source_loc); |
| 918 if (value->definition()->representation() == kUnboxedDouble) { | 1009 if (value->definition()->representation() == kUnboxedDouble) { |
| 919 deopt_instr = new DeoptDoubleStackSlotInstr(from_index); | 1010 deopt_instr = new DeoptDoubleStackSlotInstr(source_index); |
| 920 } else { | 1011 } else { |
| 921 ASSERT(value->definition()->representation() == kUnboxedMint); | 1012 ASSERT(value->definition()->representation() == kUnboxedMint); |
| 922 deopt_instr = new DeoptInt64StackSlotInstr(from_index); | 1013 deopt_instr = new DeoptInt64StackSlotInstr(source_index); |
| 923 } | 1014 } |
| 924 } else if (from_loc.IsQuadStackSlot()) { | 1015 } else if (source_loc.IsQuadStackSlot()) { |
| 925 intptr_t from_index = CalculateStackIndex(from_loc); | 1016 intptr_t source_index = CalculateStackIndex(source_loc); |
| 926 if (value->definition()->representation() == kUnboxedFloat32x4) { | 1017 if (value->definition()->representation() == kUnboxedFloat32x4) { |
| 927 deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index); | 1018 deopt_instr = new DeoptFloat32x4StackSlotInstr(source_index); |
| 928 } else { | 1019 } else { |
| 929 ASSERT(value->definition()->representation() == kUnboxedUint32x4); | 1020 ASSERT(value->definition()->representation() == kUnboxedUint32x4); |
| 930 deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); | 1021 deopt_instr = new DeoptUint32x4StackSlotInstr(source_index); |
| 931 } | 1022 } |
| 932 } else if (from_loc.IsInvalid() && | 1023 } else if (source_loc.IsInvalid() && |
| 933 value->definition()->IsMaterializeObject()) { | 1024 value->definition()->IsMaterializeObject()) { |
| 934 const intptr_t index = FindMaterialization( | 1025 const intptr_t index = FindMaterialization( |
| 935 value->definition()->AsMaterializeObject()); | 1026 value->definition()->AsMaterializeObject()); |
| 936 ASSERT(index >= 0); | 1027 ASSERT(index >= 0); |
| 937 deopt_instr = new DeoptMaterializedObjectRefInstr(index); | 1028 deopt_instr = new DeoptMaterializedObjectRefInstr(index); |
| 938 } else { | 1029 } else { |
| 939 UNREACHABLE(); | 1030 UNREACHABLE(); |
| 940 } | 1031 } |
| 941 ASSERT(to_index == FrameSize()); | 1032 ASSERT(dest_index == FrameSize()); |
| 942 ASSERT(deopt_instr != NULL); | 1033 ASSERT(deopt_instr != NULL); |
| 943 instructions_.Add(deopt_instr); | 1034 instructions_.Add(deopt_instr); |
| 944 } | 1035 } |
| 945 | 1036 |
| 946 | 1037 |
| 947 void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { | 1038 void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { |
| 948 ASSERT(to_index == FrameSize()); | 1039 ASSERT(dest_index == FrameSize()); |
| 949 instructions_.Add(new DeoptCallerFpInstr()); | 1040 instructions_.Add(new DeoptCallerFpInstr()); |
| 950 } | 1041 } |
| 951 | 1042 |
| 952 | 1043 |
| 953 void DeoptInfoBuilder::AddCallerPp(intptr_t to_index) { | 1044 void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { |
| 954 ASSERT(to_index == FrameSize()); | 1045 ASSERT(dest_index == FrameSize()); |
| 955 instructions_.Add(new DeoptCallerPpInstr()); | 1046 instructions_.Add(new DeoptCallerPpInstr()); |
| 956 } | 1047 } |
| 957 | 1048 |
| 958 | 1049 |
| 959 void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { | 1050 void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { |
| 960 ASSERT(to_index == FrameSize()); | 1051 ASSERT(dest_index == FrameSize()); |
| 961 instructions_.Add(new DeoptCallerPcInstr()); | 1052 instructions_.Add(new DeoptCallerPcInstr()); |
| 962 } | 1053 } |
| 963 | 1054 |
| 964 | 1055 |
| 965 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t to_index) { | 1056 void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { |
| 966 ASSERT(to_index == FrameSize()); | 1057 ASSERT(dest_index == FrameSize()); |
| 967 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 1058 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
| 968 instructions_.Add(new DeoptConstantInstr(object_table_index)); | 1059 instructions_.Add(new DeoptConstantInstr(object_table_index)); |
| 969 } | 1060 } |
| 970 | 1061 |
| 971 | 1062 |
| 972 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { | 1063 void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) { |
| 973 const intptr_t index = FindMaterialization(mat); | 1064 const intptr_t index = FindMaterialization(mat); |
| 974 if (index >= 0) { | 1065 if (index >= 0) { |
| 975 return; // Already added. | 1066 return; // Already added. |
| 976 } | 1067 } |
| 977 materializations_.Add(mat); | 1068 materializations_.Add(mat); |
| 978 | 1069 |
| 979 // Count initialized fields and emit kMaterializeObject instruction. | 1070 // Count initialized fields and emit kMaterializeObject instruction. |
| 980 // There is no need to write nulls into fields because object is null | 1071 // There is no need to write nulls into fields because object is null |
| 981 // initialized by default. | 1072 // initialized by default. |
| 982 intptr_t non_null_fields = 0; | 1073 intptr_t non_null_fields = 0; |
| 983 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1074 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 984 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1075 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 985 non_null_fields++; | 1076 non_null_fields++; |
| 986 } | 1077 } |
| 987 } | 1078 } |
| 988 | 1079 |
| 989 instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields)); | 1080 instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields)); |
| 990 } | 1081 } |
| 991 | 1082 |
| 992 | 1083 |
| 993 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t to_index) { | 1084 intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { |
| 994 ASSERT(to_index == kDartFrameFixedSize); | 1085 ASSERT(dest_index == kDartFrameFixedSize); |
| 995 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1086 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 996 MaterializeObjectInstr* mat = materializations_[i]; | 1087 MaterializeObjectInstr* mat = materializations_[i]; |
| 997 AddConstant(mat->cls(), to_index++); // Class of the instance to allocate. | 1088 // Class of the instance to allocate. |
| 1089 AddConstant(mat->cls(), dest_index++); |
| 998 for (intptr_t i = 0; i < mat->InputCount(); i++) { | 1090 for (intptr_t i = 0; i < mat->InputCount(); i++) { |
| 999 if (!mat->InputAt(i)->BindsToConstantNull()) { | 1091 if (!mat->InputAt(i)->BindsToConstantNull()) { |
| 1000 // Emit field-value pair. | 1092 // Emit field-value pair. |
| 1001 AddConstant(mat->FieldAt(i), to_index++); | 1093 AddConstant(mat->FieldAt(i), dest_index++); |
| 1002 AddCopy(mat->InputAt(i), mat->LocationAt(i), to_index++); | 1094 AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); |
| 1003 } | 1095 } |
| 1004 } | 1096 } |
| 1005 } | 1097 } |
| 1006 return to_index; | 1098 return dest_index; |
| 1007 } | 1099 } |
| 1008 | 1100 |
| 1009 | 1101 |
| 1010 intptr_t DeoptInfoBuilder::FindMaterialization( | 1102 intptr_t DeoptInfoBuilder::FindMaterialization( |
| 1011 MaterializeObjectInstr* mat) const { | 1103 MaterializeObjectInstr* mat) const { |
| 1012 for (intptr_t i = 0; i < materializations_.length(); i++) { | 1104 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 1013 if (materializations_[i] == mat) { | 1105 if (materializations_[i] == mat) { |
| 1014 return i; | 1106 return i; |
| 1015 } | 1107 } |
| 1016 } | 1108 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1042 // Allocate space for the translation. If the shared suffix is longer | 1134 // Allocate space for the translation. If the shared suffix is longer |
| 1043 // than one instruction, we replace it with a single suffix instruction. | 1135 // than one instruction, we replace it with a single suffix instruction. |
| 1044 if (suffix_length > 1) length -= (suffix_length - 1); | 1136 if (suffix_length > 1) length -= (suffix_length - 1); |
| 1045 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(length)); | 1137 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(length)); |
| 1046 | 1138 |
| 1047 // Write the unshared instructions and build their sub-tree. | 1139 // Write the unshared instructions and build their sub-tree. |
| 1048 TrieNode* node = NULL; | 1140 TrieNode* node = NULL; |
| 1049 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; | 1141 intptr_t write_count = (suffix_length > 1) ? length - 1 : length; |
| 1050 for (intptr_t i = 0; i < write_count; ++i) { | 1142 for (intptr_t i = 0; i < write_count; ++i) { |
| 1051 DeoptInstr* instr = instructions_[i]; | 1143 DeoptInstr* instr = instructions_[i]; |
| 1052 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | 1144 deopt_info.SetAt(i, instr->kind(), instr->source_index()); |
| 1053 TrieNode* child = node; | 1145 TrieNode* child = node; |
| 1054 node = new TrieNode(instr, current_info_number_); | 1146 node = new TrieNode(instr, current_info_number_); |
| 1055 node->AddChild(child); | 1147 node->AddChild(child); |
| 1056 } | 1148 } |
| 1057 | 1149 |
| 1058 if (suffix_length > 1) { | 1150 if (suffix_length > 1) { |
| 1059 suffix->AddChild(node); | 1151 suffix->AddChild(node); |
| 1060 DeoptInstr* instr = | 1152 DeoptInstr* instr = |
| 1061 new DeoptSuffixInstr(suffix->info_number(), suffix_length); | 1153 new DeoptSuffixInstr(suffix->info_number(), suffix_length); |
| 1062 deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); | 1154 deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); |
| 1063 } else { | 1155 } else { |
| 1064 trie_root_->AddChild(node); | 1156 trie_root_->AddChild(node); |
| 1065 } | 1157 } |
| 1066 | 1158 |
| 1067 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); | 1159 ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table)); |
| 1068 instructions_.Clear(); | 1160 instructions_.Clear(); |
| 1069 materializations_.Clear(); | 1161 materializations_.Clear(); |
| 1070 frame_start_ = -1; | 1162 frame_start_ = -1; |
| 1071 | 1163 |
| 1072 ++current_info_number_; | 1164 ++current_info_number_; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1102 Smi* offset, | 1194 Smi* offset, |
| 1103 DeoptInfo* info, | 1195 DeoptInfo* info, |
| 1104 Smi* reason) { | 1196 Smi* reason) { |
| 1105 intptr_t i = index * kEntrySize; | 1197 intptr_t i = index * kEntrySize; |
| 1106 *offset ^= table.At(i); | 1198 *offset ^= table.At(i); |
| 1107 *info ^= table.At(i + 1); | 1199 *info ^= table.At(i + 1); |
| 1108 *reason ^= table.At(i + 2); | 1200 *reason ^= table.At(i + 2); |
| 1109 } | 1201 } |
| 1110 | 1202 |
| 1111 } // namespace dart | 1203 } // namespace dart |
| OLD | NEW |