Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 const GrowableArray<const Function*>& inline_id_to_function, | 96 const GrowableArray<const Function*>& inline_id_to_function, |
| 97 const GrowableArray<intptr_t>& caller_inline_id) | 97 const GrowableArray<intptr_t>& caller_inline_id) |
| 98 : isolate_(Isolate::Current()), | 98 : isolate_(Isolate::Current()), |
| 99 assembler_(assembler), | 99 assembler_(assembler), |
| 100 parsed_function_(parsed_function), | 100 parsed_function_(parsed_function), |
| 101 flow_graph_(*flow_graph), | 101 flow_graph_(*flow_graph), |
| 102 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), | 102 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), |
| 103 current_block_(NULL), | 103 current_block_(NULL), |
| 104 exception_handlers_list_(NULL), | 104 exception_handlers_list_(NULL), |
| 105 pc_descriptors_list_(NULL), | 105 pc_descriptors_list_(NULL), |
| 106 stackmap_table_builder_( | 106 stackmap_table_builder_(NULL), |
| 107 is_optimizing ? new StackmapTableBuilder() : NULL), | |
| 108 block_info_(block_order_.length()), | 107 block_info_(block_order_.length()), |
| 109 deopt_infos_(), | 108 deopt_infos_(), |
| 110 static_calls_target_table_(GrowableObjectArray::ZoneHandle( | 109 static_calls_target_table_(GrowableObjectArray::ZoneHandle( |
| 111 GrowableObjectArray::New())), | 110 GrowableObjectArray::New())), |
| 112 is_optimizing_(is_optimizing), | 111 is_optimizing_(is_optimizing), |
| 113 may_reoptimize_(false), | 112 may_reoptimize_(false), |
| 114 intrinsic_mode_(false), | 113 intrinsic_mode_(false), |
| 115 double_class_(Class::ZoneHandle( | 114 double_class_(Class::ZoneHandle( |
| 116 isolate_->object_store()->double_class())), | 115 isolate_->object_store()->double_class())), |
| 117 mint_class_(Class::ZoneHandle( | 116 mint_class_(Class::ZoneHandle( |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 ICData::kDeoptAtCall, | 660 ICData::kDeoptAtCall, |
| 662 0, // No flags. | 661 0, // No flags. |
| 663 pending_deoptimization_env_); | 662 pending_deoptimization_env_); |
| 664 info->set_pc_offset(assembler()->CodeSize()); | 663 info->set_pc_offset(assembler()->CodeSize()); |
| 665 deopt_infos_.Add(info); | 664 deopt_infos_.Add(info); |
| 666 } | 665 } |
| 667 | 666 |
| 668 | 667 |
| 669 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters | 668 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters |
| 670 // and FlowGraphCompiler::SlowPathEnvironmentFor. | 669 // and FlowGraphCompiler::SlowPathEnvironmentFor. |
| 670 // See StackFrame::VisitObjectPointers for the details of how stack map is | |
| 671 // interpreted. | |
| 671 void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs) { | 672 void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs) { |
| 672 if (is_optimizing()) { | 673 if (is_optimizing() || locs->live_registers()->HasUntaggedValues()) { |
| 674 const intptr_t spill_area_size = is_optimizing() ? | |
| 675 flow_graph_.graph_entry()->spill_slot_count() : 0; | |
| 676 | |
| 673 RegisterSet* registers = locs->live_registers(); | 677 RegisterSet* registers = locs->live_registers(); |
| 674 ASSERT(registers != NULL); | 678 ASSERT(registers != NULL); |
| 675 const intptr_t kFpuRegisterSpillFactor = | 679 const intptr_t kFpuRegisterSpillFactor = |
| 676 kFpuRegisterSize / kWordSize; | 680 kFpuRegisterSize / kWordSize; |
| 677 const intptr_t live_registers_size = registers->CpuRegisterCount() + | 681 const intptr_t live_registers_size = registers->CpuRegisterCount() + |
| 678 (registers->FpuRegisterCount() * kFpuRegisterSpillFactor); | 682 (registers->FpuRegisterCount() * kFpuRegisterSpillFactor); |
| 683 | |
| 679 BitmapBuilder* bitmap = locs->stack_bitmap(); | 684 BitmapBuilder* bitmap = locs->stack_bitmap(); |
| 680 ASSERT(bitmap != NULL); | 685 |
| 681 // An instruction may have two safepoints in deferred code. The | 686 // An instruction may have two safepoints in deferred code. The |
| 682 // call to RecordSafepoint has the side-effect of appending the live | 687 // call to RecordSafepoint has the side-effect of appending the live |
| 683 // registers to the bitmap. This is why the second call to RecordSafepoint | 688 // registers to the bitmap. This is why the second call to RecordSafepoint |
| 684 // with the same instruction (and same location summary) sees a bitmap that | 689 // with the same instruction (and same location summary) sees a bitmap that |
| 685 // is larger that StackSize(). It will never be larger than StackSize() + | 690 // is larger that StackSize(). It will never be larger than StackSize() + |
| 686 // live_registers_size. | 691 // live_registers_size. |
| 687 ASSERT(bitmap->Length() <= (StackSize() + live_registers_size)); | 692 ASSERT(bitmap->Length() <= (spill_area_size + live_registers_size)); |
| 688 // The first safepoint will grow the bitmap to be the size of StackSize() | 693 // The first safepoint will grow the bitmap to be the size of |
| 689 // but the second safepoint will truncate the bitmap and append the | 694 // spill_area_size but the second safepoint will truncate the bitmap and |
| 690 // live registers to it again. The bitmap produced by both calls will | 695 // append the live registers to it again. The bitmap produced by both calls |
| 691 // be the same. | 696 // will be the same. |
| 692 bitmap->SetLength(StackSize()); | 697 bitmap->SetLength(spill_area_size); |
| 693 | 698 |
| 694 // Mark the bits in the stack map in the same order we push registers in | 699 // Mark the bits in the stack map in the same order we push registers in |
| 695 // slow path code (see FlowGraphCompiler::SaveLiveRegisters). | 700 // slow path code (see FlowGraphCompiler::SaveLiveRegisters). |
| 696 // | 701 // |
| 697 // Slow path code can have registers at the safepoint. | 702 // Slow path code can have registers at the safepoint. |
| 698 if (!locs->always_calls()) { | 703 if (!locs->always_calls()) { |
| 699 RegisterSet* regs = locs->live_registers(); | 704 RegisterSet* regs = locs->live_registers(); |
| 700 if (regs->FpuRegisterCount() > 0) { | 705 if (regs->FpuRegisterCount() > 0) { |
| 701 // Denote FPU registers with 0 bits in the stackmap. Based on the | 706 // Denote FPU registers with 0 bits in the stackmap. Based on the |
| 702 // assumption that there are normally few live FPU registers, this | 707 // assumption that there are normally few live FPU registers, this |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 717 // General purpose registers have the lowest register number at the | 722 // General purpose registers have the lowest register number at the |
| 718 // highest address (i.e., first in the stackmap). | 723 // highest address (i.e., first in the stackmap). |
| 719 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) { | 724 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) { |
| 720 Register reg = static_cast<Register>(i); | 725 Register reg = static_cast<Register>(i); |
| 721 if (locs->live_registers()->ContainsRegister(reg)) { | 726 if (locs->live_registers()->ContainsRegister(reg)) { |
| 722 bitmap->Set(bitmap->Length(), locs->live_registers()->IsTagged(reg)); | 727 bitmap->Set(bitmap->Length(), locs->live_registers()->IsTagged(reg)); |
| 723 } | 728 } |
| 724 } | 729 } |
| 725 } | 730 } |
| 726 | 731 |
| 727 intptr_t register_bit_count = bitmap->Length() - StackSize(); | 732 intptr_t register_bit_count = bitmap->Length() - spill_area_size; |
| 728 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 733 stackmap_table_builder()->AddEntry(assembler()->CodeSize(), |
| 729 bitmap, | 734 bitmap, |
| 730 register_bit_count); | 735 register_bit_count); |
| 731 } | 736 } |
| 732 } | 737 } |
| 733 | 738 |
| 734 | 739 |
| 735 // This function must be kept in sync with: | 740 // This function must be kept in sync with: |
| 736 // | 741 // |
| 737 // FlowGraphCompiler::RecordSafepoint | 742 // FlowGraphCompiler::RecordSafepoint |
| 738 // FlowGraphCompiler::SaveLiveRegisters | 743 // FlowGraphCompiler::SaveLiveRegisters |
| 739 // MaterializeObjectInstr::RemapRegisters | 744 // MaterializeObjectInstr::RemapRegisters |
| 740 // | 745 // |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 857 const Array& object_array = | 862 const Array& object_array = |
| 858 Array::Handle(Array::MakeArray(builder.object_table())); | 863 Array::Handle(Array::MakeArray(builder.object_table())); |
| 859 ASSERT(code.object_table() == Array::null()); | 864 ASSERT(code.object_table() == Array::null()); |
| 860 code.set_object_table(object_array); | 865 code.set_object_table(object_array); |
| 861 } | 866 } |
| 862 } | 867 } |
| 863 | 868 |
| 864 | 869 |
| 865 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { | 870 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { |
| 866 if (stackmap_table_builder_ == NULL) { | 871 if (stackmap_table_builder_ == NULL) { |
| 867 // The unoptimizing compiler has no stack maps. | 872 // The unoptimizing compiler has no stack maps. |
|
koda
2015/03/03 17:57:48
Update comment.
Vyacheslav Egorov (Google)
2015/03/03 18:01:06
Acknowledged.
| |
| 868 code.set_stackmaps(Object::null_array()); | 873 code.set_stackmaps(Object::null_array()); |
| 869 } else { | 874 } else { |
| 870 // Finalize the stack map array and add it to the code object. | 875 // Finalize the stack map array and add it to the code object. |
| 871 ASSERT(is_optimizing()); | |
| 872 code.set_stackmaps( | 876 code.set_stackmaps( |
| 873 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code))); | 877 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code))); |
| 874 } | 878 } |
| 875 } | 879 } |
| 876 | 880 |
| 877 | 881 |
| 878 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { | 882 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { |
| 879 LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle(); | 883 LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle(); |
| 880 if (parsed_function().node_sequence() == NULL) { | 884 if (parsed_function().node_sequence() == NULL) { |
| 881 ASSERT(flow_graph().IsIrregexpFunction()); | 885 ASSERT(flow_graph().IsIrregexpFunction()); |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1588 const Array& res = Array::Handle( | 1592 const Array& res = Array::Handle( |
| 1589 Array::New(inline_id_to_function_.length(), Heap::kOld)); | 1593 Array::New(inline_id_to_function_.length(), Heap::kOld)); |
| 1590 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { | 1594 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
| 1591 res.SetAt(i, *inline_id_to_function_[i]); | 1595 res.SetAt(i, *inline_id_to_function_[i]); |
| 1592 } | 1596 } |
| 1593 return res.raw(); | 1597 return res.raw(); |
| 1594 } | 1598 } |
| 1595 | 1599 |
| 1596 | 1600 |
| 1597 } // namespace dart | 1601 } // namespace dart |
| OLD | NEW |