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 |