Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Side by Side Diff: runtime/vm/deopt_instructions.cc

Issue 12457034: Ensure that all goto instructions have deoptimization target. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 } 236 }
237 237
238 private: 238 private:
239 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. 239 const intptr_t stack_slot_index_; // First argument is 0, always >= 0.
240 240
241 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr); 241 DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr);
242 }; 242 };
243 243
244 244
245 // Deoptimization instruction creating return address using function and 245 // Deoptimization instruction creating return address using function and
246 // deopt-id stored at 'object_table_index'. Uses the deopt-after 246 // deopt-id stored at 'object_table_index'.
247 // continuation point. 247 class DeoptRetAddressInstr : public DeoptInstr {
248 class DeoptRetAfterAddressInstr : public DeoptInstr {
249 public: 248 public:
250 DeoptRetAfterAddressInstr(intptr_t object_table_index, intptr_t deopt_id) 249 DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id)
251 : object_table_index_(object_table_index), deopt_id_(deopt_id) { 250 : object_table_index_(object_table_index), deopt_id_(deopt_id) {
252 ASSERT(object_table_index >= 0); 251 ASSERT(object_table_index >= 0);
253 ASSERT(deopt_id >= 0); 252 ASSERT(deopt_id >= 0);
254 } 253 }
255 254
256 explicit DeoptRetAfterAddressInstr(intptr_t from_index) 255 explicit DeoptRetAddressInstr(intptr_t from_index)
257 : object_table_index_(ObjectTableIndex::decode(from_index)), 256 : object_table_index_(ObjectTableIndex::decode(from_index)),
258 deopt_id_(DeoptId::decode(from_index)) { 257 deopt_id_(DeoptId::decode(from_index)) {
259 } 258 }
260 259
261 virtual intptr_t from_index() const { 260 virtual intptr_t from_index() const {
262 return ObjectTableIndex::encode(object_table_index_) | 261 return ObjectTableIndex::encode(object_table_index_) |
263 DeoptId::encode(deopt_id_); 262 DeoptId::encode(deopt_id_);
264 } 263 }
265 virtual DeoptInstr::Kind kind() const { return kRetAfterAddress; } 264
265 virtual DeoptInstr::Kind kind() const { return kRetAddress; }
266 266
267 virtual const char* ToCString() const { 267 virtual const char* ToCString() const {
268 const char* format = "ret aft oti:%"Pd"(%"Pd")"; 268 return Isolate::Current()->current_zone()->PrintToString(
269 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_); 269 "ret oti:%"Pd"(%"Pd")", object_table_index_, deopt_id_);
270 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
271 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_);
272 return chars;
273 } 270 }
274 271
275 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { 272 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
276 Function& function = Function::Handle(deopt_context->isolate());
277 function ^= deopt_context->ObjectAt(object_table_index_);
278 const Code& code =
279 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
280 ASSERT(!code.IsNull());
281 uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_);
282 ASSERT(continue_at_pc != 0);
283 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
284 *to_addr = continue_at_pc;
285 }
286
287 intptr_t object_table_index() const { return object_table_index_; }
288 intptr_t deopt_id() const { return deopt_id_; }
289
290 private:
291 static const intptr_t kFieldWidth = kBitsPerWord / 2;
292 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { };
293 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
294
295 const intptr_t object_table_index_;
296 const intptr_t deopt_id_;
297
298 DISALLOW_COPY_AND_ASSIGN(DeoptRetAfterAddressInstr);
299 };
300
301
302 // Deoptimization instruction creating return address using function and
303 // deopt-id stored at 'object_table_index'. Uses the deopt-before
304 // continuation point.
305 class DeoptRetBeforeAddressInstr : public DeoptInstr {
306 public:
307 DeoptRetBeforeAddressInstr(intptr_t object_table_index, intptr_t deopt_id)
308 : object_table_index_(object_table_index), deopt_id_(deopt_id) {
309 ASSERT(object_table_index >= 0);
310 ASSERT(deopt_id >= 0);
311 }
312
313 explicit DeoptRetBeforeAddressInstr(intptr_t from_index)
314 : object_table_index_(ObjectTableIndex::decode(from_index)),
315 deopt_id_(DeoptId::decode(from_index)) {
316 }
317
318 virtual intptr_t from_index() const {
319 return ObjectTableIndex::encode(object_table_index_) |
320 DeoptId::encode(deopt_id_);
321 }
322 virtual DeoptInstr::Kind kind() const { return kRetBeforeAddress; }
323
324 virtual const char* ToCString() const {
325 const char* format = "ret bef oti:%"Pd"(%"Pd")";
326 intptr_t len = OS::SNPrint(NULL, 0, format, object_table_index_, deopt_id_);
327 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
328 OS::SNPrint(chars, len + 1, format, object_table_index_, deopt_id_);
329 return chars;
330 }
331
332 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
333 Function& function = Function::Handle(deopt_context->isolate()); 273 Function& function = Function::Handle(deopt_context->isolate());
334 function ^= deopt_context->ObjectAt(object_table_index_); 274 function ^= deopt_context->ObjectAt(object_table_index_);
335 const Code& code = 275 const Code& code =
336 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); 276 Code::Handle(deopt_context->isolate(), function.unoptimized_code());
337 ASSERT(!code.IsNull()); 277 ASSERT(!code.IsNull());
338 uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_); 278 uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
279 PcDescriptors::kDeopt);
339 ASSERT(continue_at_pc != 0); 280 ASSERT(continue_at_pc != 0);
340 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); 281 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
341 *to_addr = continue_at_pc; 282 *to_addr = continue_at_pc;
342 283
343 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); 284 uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall);
344 if (pc != 0) { 285 if (pc != 0) {
345 // If the deoptimization happened at an IC call, update the IC data 286 // If the deoptimization happened at an IC call, update the IC data
346 // to avoid repeated deoptimization at the same site next time around. 287 // to avoid repeated deoptimization at the same site next time around.
347 ICData& ic_data = ICData::Handle(); 288 ICData& ic_data = ICData::Handle();
348 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL); 289 CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL);
349 if (!ic_data.IsNull()) { 290 if (!ic_data.IsNull()) {
350 ic_data.set_deopt_reason(deopt_context->deopt_reason()); 291 ic_data.set_deopt_reason(deopt_context->deopt_reason());
351 } 292 }
352 } 293 }
353 } 294 }
354 295
296 intptr_t object_table_index() const { return object_table_index_; }
297 intptr_t deopt_id() const { return deopt_id_; }
298
355 private: 299 private:
356 static const intptr_t kFieldWidth = kBitsPerWord / 2; 300 static const intptr_t kFieldWidth = kBitsPerWord / 2;
357 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { }; 301 class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { };
358 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { }; 302 class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
359 303
360 const intptr_t object_table_index_; 304 const intptr_t object_table_index_;
361 const intptr_t deopt_id_; 305 const intptr_t deopt_id_;
362 306
363 DISALLOW_COPY_AND_ASSIGN(DeoptRetBeforeAddressInstr); 307 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr);
364 }; 308 };
365 309
366 310
367 // Deoptimization instruction moving a constant stored at 'object_table_index'. 311 // Deoptimization instruction moving a constant stored at 'object_table_index'.
368 class DeoptConstantInstr : public DeoptInstr { 312 class DeoptConstantInstr : public DeoptInstr {
369 public: 313 public:
370 explicit DeoptConstantInstr(intptr_t object_table_index) 314 explicit DeoptConstantInstr(intptr_t object_table_index)
371 : object_table_index_(object_table_index) { 315 : object_table_index_(object_table_index) {
372 ASSERT(object_table_index >= 0); 316 ASSERT(object_table_index >= 0);
373 } 317 }
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr); 650 DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
707 }; 651 };
708 652
709 653
710 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { 654 intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) {
711 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); 655 *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index);
712 return DeoptSuffixInstr::SuffixLength::decode(from_index); 656 return DeoptSuffixInstr::SuffixLength::decode(from_index);
713 } 657 }
714 658
715 659
716 uword DeoptInstr::GetRetAfterAddress(DeoptInstr* instr, 660 uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
717 const Array& object_table, 661 const Array& object_table,
718 Function* func) { 662 Function* func) {
719 ASSERT(instr->kind() == kRetAfterAddress); 663 ASSERT(instr->kind() == kRetAddress);
720 DeoptRetAfterAddressInstr* ret_after_instr = 664 DeoptRetAddressInstr* ret_address_instr =
721 static_cast<DeoptRetAfterAddressInstr*>(instr); 665 static_cast<DeoptRetAddressInstr*>(instr);
Florian Schneider 2013/04/12 09:23:55 check that deopt_id is a lazy-deopt: ASSERT((ret_
Vyacheslav Egorov (Google) 2013/04/12 10:57:06 Done.
722 ASSERT(!object_table.IsNull()); 666 ASSERT(!object_table.IsNull());
723 ASSERT(func != NULL); 667 ASSERT(func != NULL);
724 *func ^= object_table.At(ret_after_instr->object_table_index()); 668 *func ^= object_table.At(ret_address_instr->object_table_index());
725 const Code& code = Code::Handle(func->unoptimized_code()); 669 const Code& code = Code::Handle(func->unoptimized_code());
726 ASSERT(!code.IsNull()); 670 ASSERT(!code.IsNull());
727 uword res = code.GetDeoptAfterPcAtDeoptId(ret_after_instr->deopt_id()); 671 uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(),
672 PcDescriptors::kDeopt);
728 ASSERT(res != 0); 673 ASSERT(res != 0);
729 return res; 674 return res;
730 } 675 }
731 676
732 677
733 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { 678 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) {
734 Kind kind = static_cast<Kind>(kind_as_int); 679 Kind kind = static_cast<Kind>(kind_as_int);
735 switch (kind) { 680 switch (kind) {
736 case kStackSlot: return new DeoptStackSlotInstr(from_index); 681 case kStackSlot: return new DeoptStackSlotInstr(from_index);
737 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); 682 case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index);
738 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); 683 case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index);
739 case kFloat32x4StackSlot: 684 case kFloat32x4StackSlot:
740 return new DeoptFloat32x4StackSlotInstr(from_index); 685 return new DeoptFloat32x4StackSlotInstr(from_index);
741 case kUint32x4StackSlot: 686 case kUint32x4StackSlot:
742 return new DeoptUint32x4StackSlotInstr(from_index); 687 return new DeoptUint32x4StackSlotInstr(from_index);
743 case kRetAfterAddress: return new DeoptRetAfterAddressInstr(from_index); 688 case kRetAddress: return new DeoptRetAddressInstr(from_index);
744 case kRetBeforeAddress: return new DeoptRetBeforeAddressInstr(from_index);
745 case kConstant: return new DeoptConstantInstr(from_index); 689 case kConstant: return new DeoptConstantInstr(from_index);
746 case kRegister: return new DeoptRegisterInstr(from_index); 690 case kRegister: return new DeoptRegisterInstr(from_index);
747 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); 691 case kFpuRegister: return new DeoptFpuRegisterInstr(from_index);
748 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); 692 case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index);
749 case kFloat32x4FpuRegister: 693 case kFloat32x4FpuRegister:
750 return new DeoptFloat32x4FpuRegisterInstr(from_index); 694 return new DeoptFloat32x4FpuRegisterInstr(from_index);
751 case kUint32x4FpuRegister: 695 case kUint32x4FpuRegister:
752 return new DeoptUint32x4FpuRegisterInstr(from_index); 696 return new DeoptUint32x4FpuRegisterInstr(from_index);
753 case kPcMarker: return new DeoptPcMarkerInstr(from_index); 697 case kPcMarker: return new DeoptPcMarkerInstr(from_index);
754 case kCallerFp: return new DeoptCallerFpInstr(); 698 case kCallerFp: return new DeoptCallerFpInstr();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 return i; 751 return i;
808 } 752 }
809 } 753 }
810 // Add object. 754 // Add object.
811 const intptr_t result = object_table_.Length(); 755 const intptr_t result = object_table_.Length();
812 object_table_.Add(obj); 756 object_table_.Add(obj);
813 return result; 757 return result;
814 } 758 }
815 759
816 760
817 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function, 761 void DeoptInfoBuilder::AddReturnAddress(const Function& function,
818 intptr_t deopt_id, 762 intptr_t deopt_id,
819 intptr_t to_index) { 763 intptr_t to_index) {
820 // Check that deopt_id exists. 764 // Check that deopt_id exists.
821 ASSERT(Code::Handle(function.unoptimized_code()). 765 // TODO(vegorov): verify after deoptimization targets as well.
822 GetDeoptBeforePcAtDeoptId(deopt_id) != 0); 766 #ifdef DEBUG
767 const Code& code = Code::Handle(function.unoptimized_code());
768 ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
769 (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
770 #endif
823 const intptr_t object_table_index = FindOrAddObjectInTable(function); 771 const intptr_t object_table_index = FindOrAddObjectInTable(function);
824 ASSERT(to_index == instructions_.length()); 772 ASSERT(to_index == instructions_.length());
825 instructions_.Add(new DeoptRetBeforeAddressInstr(object_table_index, 773 instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id));
826 deopt_id));
827 } 774 }
828 775
829 776
830 void DeoptInfoBuilder::AddReturnAddressAfter(const Function& function,
831 intptr_t deopt_id,
832 intptr_t to_index) {
833 const intptr_t object_table_index = FindOrAddObjectInTable(function);
834 ASSERT(to_index == instructions_.length());
835 instructions_.Add(new DeoptRetAfterAddressInstr(object_table_index,
836 deopt_id));
837 }
838
839
840 void DeoptInfoBuilder::AddPcMarker(const Function& function, 777 void DeoptInfoBuilder::AddPcMarker(const Function& function,
841 intptr_t to_index) { 778 intptr_t to_index) {
842 // Function object was already added by AddReturnAddress, find it. 779 // Function object was already added by AddReturnAddress, find it.
843 intptr_t from_index = FindOrAddObjectInTable(function); 780 intptr_t from_index = FindOrAddObjectInTable(function);
844 ASSERT(to_index == instructions_.length()); 781 ASSERT(to_index == instructions_.length());
845 instructions_.Add(new DeoptPcMarkerInstr(from_index)); 782 instructions_.Add(new DeoptPcMarkerInstr(from_index));
846 } 783 }
847 784
848 785
849 void DeoptInfoBuilder::AddCopy(const Location& from_loc, 786 void DeoptInfoBuilder::AddCopy(const Location& from_loc,
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 Smi* offset, 909 Smi* offset,
973 DeoptInfo* info, 910 DeoptInfo* info,
974 Smi* reason) { 911 Smi* reason) {
975 intptr_t i = index * kEntrySize; 912 intptr_t i = index * kEntrySize;
976 *offset ^= table.At(i); 913 *offset ^= table.At(i);
977 *info ^= table.At(i + 1); 914 *info ^= table.At(i + 1);
978 *reason ^= table.At(i + 2); 915 *reason ^= table.At(i + 2);
979 } 916 }
980 917
981 } // namespace dart 918 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698