OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 5410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5421 void Function::set_kind(RawFunction::Kind value) const { | 5421 void Function::set_kind(RawFunction::Kind value) const { |
5422 set_kind_tag(KindBits::update(value, raw_ptr()->kind_tag_)); | 5422 set_kind_tag(KindBits::update(value, raw_ptr()->kind_tag_)); |
5423 } | 5423 } |
5424 | 5424 |
5425 | 5425 |
5426 void Function::set_modifier(RawFunction::AsyncModifier value) const { | 5426 void Function::set_modifier(RawFunction::AsyncModifier value) const { |
5427 set_kind_tag(ModifierBits::update(value, raw_ptr()->kind_tag_)); | 5427 set_kind_tag(ModifierBits::update(value, raw_ptr()->kind_tag_)); |
5428 } | 5428 } |
5429 | 5429 |
5430 | 5430 |
5431 void Function::set_is_intrinsic(bool value) const { | |
5432 set_kind_tag(IntrinsicBit::update(value, raw_ptr()->kind_tag_)); | |
5433 } | |
5434 | |
5435 | |
5436 void Function::set_recognized_kind(MethodRecognizer::Kind value) const { | 5431 void Function::set_recognized_kind(MethodRecognizer::Kind value) const { |
5437 // Prevent multiple settings of kind. | 5432 // Prevent multiple settings of kind. |
5438 ASSERT((value == MethodRecognizer::kUnknown) || !IsRecognized()); | 5433 ASSERT((value == MethodRecognizer::kUnknown) || !IsRecognized()); |
5439 set_kind_tag(RecognizedBits::update(value, raw_ptr()->kind_tag_)); | 5434 set_kind_tag(RecognizedBits::update(value, raw_ptr()->kind_tag_)); |
5440 } | 5435 } |
5441 | 5436 |
5442 | 5437 |
5443 void Function::set_is_redirecting(bool value) const { | |
5444 set_kind_tag(RedirectingBit::update(value, raw_ptr()->kind_tag_)); | |
5445 } | |
5446 | |
5447 | |
5448 void Function::set_is_static(bool value) const { | |
5449 set_kind_tag(StaticBit::update(value, raw_ptr()->kind_tag_)); | |
5450 } | |
5451 | |
5452 | |
5453 void Function::set_is_const(bool value) const { | |
5454 set_kind_tag(ConstBit::update(value, raw_ptr()->kind_tag_)); | |
5455 } | |
5456 | |
5457 | |
5458 void Function::set_is_external(bool value) const { | |
5459 set_kind_tag(ExternalBit::update(value, raw_ptr()->kind_tag_)); | |
5460 } | |
5461 | |
5462 | |
5463 void Function::set_is_async_closure(bool value) const { | |
5464 set_kind_tag(AsyncClosureBit::update(value, raw_ptr()->kind_tag_)); | |
5465 // Prohibit inlining as the closure is used for implementing a continuation. | |
5466 set_is_inlinable(false); | |
5467 } | |
5468 | |
5469 | |
5470 void Function::set_token_pos(intptr_t value) const { | 5438 void Function::set_token_pos(intptr_t value) const { |
5471 ASSERT(value >= 0); | 5439 ASSERT(value >= 0); |
5472 StoreNonPointer(&raw_ptr()->token_pos_, value); | 5440 StoreNonPointer(&raw_ptr()->token_pos_, value); |
5473 } | 5441 } |
5474 | 5442 |
5475 | 5443 |
5476 void Function::set_kind_tag(intptr_t value) const { | 5444 void Function::set_kind_tag(intptr_t value) const { |
5477 StoreNonPointer(&raw_ptr()->kind_tag_, static_cast<uint32_t>(value)); | 5445 StoreNonPointer(&raw_ptr()->kind_tag_, static_cast<uint32_t>(value)); |
5478 } | 5446 } |
5479 | 5447 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5540 } | 5508 } |
5541 } | 5509 } |
5542 | 5510 |
5543 | 5511 |
5544 void Function::SetIsNativeAutoSetupScope(bool value) const { | 5512 void Function::SetIsNativeAutoSetupScope(bool value) const { |
5545 ASSERT(is_native()); | 5513 ASSERT(is_native()); |
5546 set_is_optimizable(value); | 5514 set_is_optimizable(value); |
5547 } | 5515 } |
5548 | 5516 |
5549 | 5517 |
5550 void Function::set_is_optimizable(bool value) const { | 5518 bool Function::CanBeInlined() const { |
5551 set_kind_tag(OptimizableBit::update(value, raw_ptr()->kind_tag_)); | 5519 return is_inlinable() && |
| 5520 !is_async_closure() && |
| 5521 HasCode() && |
| 5522 !Isolate::Current()->debugger()->HasBreakpoint(*this); |
5552 } | 5523 } |
5553 | 5524 |
5554 | 5525 |
5555 void Function::set_allows_hoisting_check_class(bool value) const { | |
5556 set_kind_tag( | |
5557 AllowsHoistingCheckClassBit::update(value, raw_ptr()->kind_tag_)); | |
5558 } | |
5559 | |
5560 | |
5561 void Function::set_is_native(bool value) const { | |
5562 set_kind_tag(NativeBit::update(value, raw_ptr()->kind_tag_)); | |
5563 } | |
5564 | |
5565 | |
5566 void Function::set_is_abstract(bool value) const { | |
5567 set_kind_tag(AbstractBit::update(value, raw_ptr()->kind_tag_)); | |
5568 } | |
5569 | |
5570 | |
5571 void Function::set_is_inlinable(bool value) const { | |
5572 set_kind_tag(InlinableBit::update(value, raw_ptr()->kind_tag_)); | |
5573 } | |
5574 | |
5575 | |
5576 bool Function::IsInlineable() const { | |
5577 return (InlinableBit::decode(raw_ptr()->kind_tag_) && | |
5578 HasCode() && | |
5579 !Isolate::Current()->debugger()->HasBreakpoint(*this)); | |
5580 } | |
5581 | |
5582 | |
5583 void Function::set_is_visible(bool value) const { | |
5584 set_kind_tag(VisibleBit::update(value, raw_ptr()->kind_tag_)); | |
5585 } | |
5586 | |
5587 | |
5588 intptr_t Function::NumParameters() const { | 5526 intptr_t Function::NumParameters() const { |
5589 return num_fixed_parameters() + NumOptionalParameters(); | 5527 return num_fixed_parameters() + NumOptionalParameters(); |
5590 } | 5528 } |
5591 | 5529 |
5592 | 5530 |
5593 intptr_t Function::NumImplicitParameters() const { | 5531 intptr_t Function::NumImplicitParameters() const { |
5594 if (kind() == RawFunction::kConstructor) { | 5532 if (kind() == RawFunction::kConstructor) { |
5595 if (is_static()) { | 5533 if (is_static()) { |
5596 ASSERT(IsFactory()); | 5534 ASSERT(IsFactory()); |
5597 return 1; // Type arguments. | 5535 return 1; // Type arguments. |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6113 result.set_end_token_pos(token_pos); | 6051 result.set_end_token_pos(token_pos); |
6114 result.set_num_fixed_parameters(0); | 6052 result.set_num_fixed_parameters(0); |
6115 result.set_num_optional_parameters(0); | 6053 result.set_num_optional_parameters(0); |
6116 result.set_usage_counter(0); | 6054 result.set_usage_counter(0); |
6117 result.set_deoptimization_counter(0); | 6055 result.set_deoptimization_counter(0); |
6118 result.set_optimized_instruction_count(0); | 6056 result.set_optimized_instruction_count(0); |
6119 result.set_optimized_call_site_count(0); | 6057 result.set_optimized_call_site_count(0); |
6120 result.set_is_optimizable(is_native ? false : true); | 6058 result.set_is_optimizable(is_native ? false : true); |
6121 result.set_is_inlinable(true); | 6059 result.set_is_inlinable(true); |
6122 result.set_allows_hoisting_check_class(true); | 6060 result.set_allows_hoisting_check_class(true); |
| 6061 result.set_allows_bounds_check_generalization(true); |
6123 result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); | 6062 result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); |
6124 if (kind == RawFunction::kClosureFunction) { | 6063 if (kind == RawFunction::kClosureFunction) { |
6125 const ClosureData& data = ClosureData::Handle(ClosureData::New()); | 6064 const ClosureData& data = ClosureData::Handle(ClosureData::New()); |
6126 result.set_data(data); | 6065 result.set_data(data); |
6127 } | 6066 } |
6128 | 6067 |
6129 return result.raw(); | 6068 return result.raw(); |
6130 } | 6069 } |
6131 | 6070 |
6132 | 6071 |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6766 jsobj.AddProperty("parent", parent); | 6705 jsobj.AddProperty("parent", parent); |
6767 } | 6706 } |
6768 const char* kind_string = Function::KindToCString(kind()); | 6707 const char* kind_string = Function::KindToCString(kind()); |
6769 jsobj.AddProperty("kind", kind_string); | 6708 jsobj.AddProperty("kind", kind_string); |
6770 if (ref) { | 6709 if (ref) { |
6771 return; | 6710 return; |
6772 } | 6711 } |
6773 jsobj.AddProperty("static", is_static()); | 6712 jsobj.AddProperty("static", is_static()); |
6774 jsobj.AddProperty("const", is_const()); | 6713 jsobj.AddProperty("const", is_const()); |
6775 jsobj.AddProperty("optimizable", is_optimizable()); | 6714 jsobj.AddProperty("optimizable", is_optimizable()); |
6776 jsobj.AddProperty("inlinable", IsInlineable()); | 6715 jsobj.AddProperty("inlinable", CanBeInlined()); |
6777 jsobj.AddProperty("unoptimizedCode", Object::Handle(unoptimized_code())); | 6716 jsobj.AddProperty("unoptimizedCode", Object::Handle(unoptimized_code())); |
6778 jsobj.AddProperty("usageCounter", usage_counter()); | 6717 jsobj.AddProperty("usageCounter", usage_counter()); |
6779 jsobj.AddProperty("optimizedCallSiteCount", optimized_call_site_count()); | 6718 jsobj.AddProperty("optimizedCallSiteCount", optimized_call_site_count()); |
6780 jsobj.AddProperty("code", Object::Handle(CurrentCode())); | 6719 jsobj.AddProperty("code", Object::Handle(CurrentCode())); |
6781 jsobj.AddProperty("deoptimizations", | 6720 jsobj.AddProperty("deoptimizations", |
6782 static_cast<intptr_t>(deoptimization_counter())); | 6721 static_cast<intptr_t>(deoptimization_counter())); |
6783 | 6722 |
6784 const Script& script = Script::Handle(this->script()); | 6723 const Script& script = Script::Handle(this->script()); |
6785 if (!script.IsNull()) { | 6724 if (!script.IsNull()) { |
6786 jsobj.AddProperty("script", script); | 6725 jsobj.AddProperty("script", script); |
(...skipping 4343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11130 } | 11069 } |
11131 return pos; | 11070 return pos; |
11132 } | 11071 } |
11133 | 11072 |
11134 | 11073 |
11135 void DeoptInfo::ToInstructions(const Array& table, | 11074 void DeoptInfo::ToInstructions(const Array& table, |
11136 GrowableArray<DeoptInstr*>* instructions) const { | 11075 GrowableArray<DeoptInstr*>* instructions) const { |
11137 ASSERT(instructions->is_empty()); | 11076 ASSERT(instructions->is_empty()); |
11138 Smi& offset = Smi::Handle(); | 11077 Smi& offset = Smi::Handle(); |
11139 DeoptInfo& info = DeoptInfo::Handle(raw()); | 11078 DeoptInfo& info = DeoptInfo::Handle(raw()); |
11140 Smi& reason = Smi::Handle(); | 11079 Smi& reason_and_flags = Smi::Handle(); |
11141 intptr_t index = 0; | 11080 intptr_t index = 0; |
11142 intptr_t length = TranslationLength(); | 11081 intptr_t length = TranslationLength(); |
11143 while (index < length) { | 11082 while (index < length) { |
11144 intptr_t instruction = info.Instruction(index); | 11083 intptr_t instruction = info.Instruction(index); |
11145 intptr_t from_index = info.FromIndex(index); | 11084 intptr_t from_index = info.FromIndex(index); |
11146 if (instruction == DeoptInstr::kSuffix) { | 11085 if (instruction == DeoptInstr::kSuffix) { |
11147 // Suffix instructions cause us to 'jump' to another translation, | 11086 // Suffix instructions cause us to 'jump' to another translation, |
11148 // changing info, length and index. | 11087 // changing info, length and index. |
11149 intptr_t info_number = 0; | 11088 intptr_t info_number = 0; |
11150 intptr_t suffix_length = | 11089 intptr_t suffix_length = |
11151 DeoptInstr::DecodeSuffix(from_index, &info_number); | 11090 DeoptInstr::DecodeSuffix(from_index, &info_number); |
11152 DeoptTable::GetEntry(table, info_number, &offset, &info, &reason); | 11091 DeoptTable::GetEntry( |
| 11092 table, info_number, &offset, &info, &reason_and_flags); |
11153 length = info.TranslationLength(); | 11093 length = info.TranslationLength(); |
11154 index = length - suffix_length; | 11094 index = length - suffix_length; |
11155 } else { | 11095 } else { |
11156 instructions->Add(DeoptInstr::Create(instruction, from_index)); | 11096 instructions->Add(DeoptInstr::Create(instruction, from_index)); |
11157 ++index; | 11097 ++index; |
11158 } | 11098 } |
11159 } | 11099 } |
11160 } | 11100 } |
11161 | 11101 |
11162 | 11102 |
(...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11918 } | 11858 } |
11919 #endif // DEBUG | 11859 #endif // DEBUG |
11920 } | 11860 } |
11921 | 11861 |
11922 | 11862 |
11923 bool Code::HasBreakpoint() const { | 11863 bool Code::HasBreakpoint() const { |
11924 return Isolate::Current()->debugger()->HasBreakpoint(*this); | 11864 return Isolate::Current()->debugger()->HasBreakpoint(*this); |
11925 } | 11865 } |
11926 | 11866 |
11927 | 11867 |
11928 RawDeoptInfo* Code::GetDeoptInfoAtPc( | 11868 RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc, |
11929 uword pc, ICData::DeoptReasonId* deopt_reason) const { | 11869 ICData::DeoptReasonId* deopt_reason, |
| 11870 uint32_t* deopt_flags) const { |
11930 ASSERT(is_optimized()); | 11871 ASSERT(is_optimized()); |
11931 const Instructions& instrs = Instructions::Handle(instructions()); | 11872 const Instructions& instrs = Instructions::Handle(instructions()); |
11932 uword code_entry = instrs.EntryPoint(); | 11873 uword code_entry = instrs.EntryPoint(); |
11933 const Array& table = Array::Handle(deopt_info_array()); | 11874 const Array& table = Array::Handle(deopt_info_array()); |
11934 ASSERT(!table.IsNull()); | 11875 ASSERT(!table.IsNull()); |
11935 // Linear search for the PC offset matching the target PC. | 11876 // Linear search for the PC offset matching the target PC. |
11936 intptr_t length = DeoptTable::GetLength(table); | 11877 intptr_t length = DeoptTable::GetLength(table); |
11937 Smi& offset = Smi::Handle(); | 11878 Smi& offset = Smi::Handle(); |
11938 Smi& reason = Smi::Handle(); | 11879 Smi& reason_and_flags = Smi::Handle(); |
11939 DeoptInfo& info = DeoptInfo::Handle(); | 11880 DeoptInfo& info = DeoptInfo::Handle(); |
11940 for (intptr_t i = 0; i < length; ++i) { | 11881 for (intptr_t i = 0; i < length; ++i) { |
11941 DeoptTable::GetEntry(table, i, &offset, &info, &reason); | 11882 DeoptTable::GetEntry(table, i, &offset, &info, &reason_and_flags); |
11942 if (pc == (code_entry + offset.Value())) { | 11883 if (pc == (code_entry + offset.Value())) { |
11943 ASSERT(!info.IsNull()); | 11884 ASSERT(!info.IsNull()); |
11944 ASSERT((0 <= reason.Value()) && | 11885 *deopt_reason = DeoptTable::ReasonField::decode(reason_and_flags.Value()); |
11945 (reason.Value() < ICData::kDeoptNumReasons)); | 11886 *deopt_flags = DeoptTable::FlagsField::decode(reason_and_flags.Value()); |
11946 *deopt_reason = static_cast<ICData::DeoptReasonId>(reason.Value()); | |
11947 return info.raw(); | 11887 return info.raw(); |
11948 } | 11888 } |
11949 } | 11889 } |
11950 *deopt_reason = ICData::kDeoptUnknown; | 11890 *deopt_reason = ICData::kDeoptUnknown; |
11951 return DeoptInfo::null(); | 11891 return DeoptInfo::null(); |
11952 } | 11892 } |
11953 | 11893 |
11954 | 11894 |
11955 intptr_t Code::BinarySearchInSCallTable(uword pc) const { | 11895 intptr_t Code::BinarySearchInSCallTable(uword pc) const { |
11956 NoGCScope no_gc; | 11896 NoGCScope no_gc; |
(...skipping 8350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20307 return tag_label.ToCString(); | 20247 return tag_label.ToCString(); |
20308 } | 20248 } |
20309 | 20249 |
20310 | 20250 |
20311 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 20251 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
20312 Instance::PrintJSONImpl(stream, ref); | 20252 Instance::PrintJSONImpl(stream, ref); |
20313 } | 20253 } |
20314 | 20254 |
20315 | 20255 |
20316 } // namespace dart | 20256 } // namespace dart |
OLD | NEW |