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 5364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5375 void PatchClass::set_source_class(const Class& value) const { | 5375 void PatchClass::set_source_class(const Class& value) const { |
5376 StorePointer(&raw_ptr()->source_class_, value.raw()); | 5376 StorePointer(&raw_ptr()->source_class_, value.raw()); |
5377 } | 5377 } |
5378 | 5378 |
5379 | 5379 |
5380 bool Function::HasBreakpoint() const { | 5380 bool Function::HasBreakpoint() const { |
5381 return Isolate::Current()->debugger()->HasBreakpoint(*this); | 5381 return Isolate::Current()->debugger()->HasBreakpoint(*this); |
5382 } | 5382 } |
5383 | 5383 |
5384 | 5384 |
| 5385 void Function::InstallOptimizedCode(const Code& code, bool is_osr) const { |
| 5386 // We may not have previous code if 'always_optimize' is set. |
| 5387 if (!is_osr && HasCode()) { |
| 5388 Code::Handle(CurrentCode()).DisableDartCode(); |
| 5389 } |
| 5390 AttachCode(code); |
| 5391 } |
| 5392 |
| 5393 |
5385 void Function::SetInstructions(const Code& value) const { | 5394 void Function::SetInstructions(const Code& value) const { |
| 5395 ASSERT(Thread::Current()->IsMutatorThread()); |
| 5396 SetInstructionsSafe(value); |
| 5397 } |
| 5398 |
| 5399 |
| 5400 void Function::SetInstructionsSafe(const Code& value) const { |
5386 StorePointer(&raw_ptr()->code_, value.raw()); | 5401 StorePointer(&raw_ptr()->code_, value.raw()); |
5387 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); | 5402 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); |
5388 } | 5403 } |
5389 | 5404 |
| 5405 |
5390 void Function::AttachCode(const Code& value) const { | 5406 void Function::AttachCode(const Code& value) const { |
5391 // Finish setting up code before activating it. | 5407 // Finish setting up code before activating it. |
5392 value.set_owner(*this); | 5408 value.set_owner(*this); |
5393 SetInstructions(value); | 5409 SetInstructions(value); |
5394 ASSERT(Function::Handle(value.function()).IsNull() || | 5410 ASSERT(Function::Handle(value.function()).IsNull() || |
5395 (value.function() == this->raw())); | 5411 (value.function() == this->raw())); |
5396 } | 5412 } |
5397 | 5413 |
5398 | 5414 |
5399 bool Function::HasCode() const { | 5415 bool Function::HasCode() const { |
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6485 result.set_num_fixed_parameters(0); | 6501 result.set_num_fixed_parameters(0); |
6486 result.set_num_optional_parameters(0); | 6502 result.set_num_optional_parameters(0); |
6487 result.set_usage_counter(0); | 6503 result.set_usage_counter(0); |
6488 result.set_deoptimization_counter(0); | 6504 result.set_deoptimization_counter(0); |
6489 result.set_optimized_instruction_count(0); | 6505 result.set_optimized_instruction_count(0); |
6490 result.set_optimized_call_site_count(0); | 6506 result.set_optimized_call_site_count(0); |
6491 result.set_is_optimizable(is_native ? false : true); | 6507 result.set_is_optimizable(is_native ? false : true); |
6492 result.set_is_inlinable(true); | 6508 result.set_is_inlinable(true); |
6493 result.set_allows_hoisting_check_class(true); | 6509 result.set_allows_hoisting_check_class(true); |
6494 result.set_allows_bounds_check_generalization(true); | 6510 result.set_allows_bounds_check_generalization(true); |
6495 result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); | 6511 result.SetInstructionsSafe( |
| 6512 Code::Handle(StubCode::LazyCompile_entry()->code())); |
6496 if (kind == RawFunction::kClosureFunction) { | 6513 if (kind == RawFunction::kClosureFunction) { |
6497 const ClosureData& data = ClosureData::Handle(ClosureData::New()); | 6514 const ClosureData& data = ClosureData::Handle(ClosureData::New()); |
6498 result.set_data(data); | 6515 result.set_data(data); |
6499 } | 6516 } |
6500 return result.raw(); | 6517 return result.raw(); |
6501 } | 6518 } |
6502 | 6519 |
6503 | 6520 |
6504 RawFunction* Function::Clone(const Class& new_owner) const { | 6521 RawFunction* Function::Clone(const Class& new_owner) const { |
6505 ASSERT(!IsGenerativeConstructor()); | 6522 ASSERT(!IsGenerativeConstructor()); |
(...skipping 5571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12077 ASSERT(!value.IsNull()); | 12094 ASSERT(!value.IsNull()); |
12078 StorePointer(&raw_ptr()->args_descriptor_, value.raw()); | 12095 StorePointer(&raw_ptr()->args_descriptor_, value.raw()); |
12079 } | 12096 } |
12080 | 12097 |
12081 void ICData::set_deopt_id(intptr_t value) const { | 12098 void ICData::set_deopt_id(intptr_t value) const { |
12082 ASSERT(value <= kMaxInt32); | 12099 ASSERT(value <= kMaxInt32); |
12083 StoreNonPointer(&raw_ptr()->deopt_id_, value); | 12100 StoreNonPointer(&raw_ptr()->deopt_id_, value); |
12084 } | 12101 } |
12085 | 12102 |
12086 | 12103 |
12087 void ICData::set_ic_data(const Array& value) const { | 12104 void ICData::set_ic_data_array(const Array& value) const { |
12088 ASSERT(!value.IsNull()); | 12105 ASSERT(!value.IsNull()); |
12089 StorePointer(&raw_ptr()->ic_data_, value.raw()); | 12106 StorePointer(&raw_ptr()->ic_data_, value.raw()); |
12090 } | 12107 } |
12091 | 12108 |
12092 | 12109 |
12093 intptr_t ICData::NumArgsTested() const { | 12110 intptr_t ICData::NumArgsTested() const { |
12094 return NumArgsTestedBits::decode(raw_ptr()->state_bits_); | 12111 return NumArgsTestedBits::decode(raw_ptr()->state_bits_); |
12095 } | 12112 } |
12096 | 12113 |
12097 | 12114 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12185 intptr_t count = 0; | 12202 intptr_t count = 0; |
12186 for (intptr_t i = 0; i < n; i++) { | 12203 for (intptr_t i = 0; i < n; i++) { |
12187 if (GetCountAt(i) > 0) { | 12204 if (GetCountAt(i) > 0) { |
12188 count++; | 12205 count++; |
12189 } | 12206 } |
12190 } | 12207 } |
12191 return count; | 12208 return count; |
12192 } | 12209 } |
12193 | 12210 |
12194 | 12211 |
12195 void ICData::WriteSentinel(const Array& data) const { | 12212 void ICData::WriteSentinel(const Array& data, intptr_t test_entry_length) { |
12196 ASSERT(!data.IsNull()); | 12213 ASSERT(!data.IsNull()); |
12197 for (intptr_t i = 1; i <= TestEntryLength(); i++) { | 12214 for (intptr_t i = 1; i <= test_entry_length; i++) { |
12198 data.SetAt(data.Length() - i, smi_illegal_cid()); | 12215 data.SetAt(data.Length() - i, smi_illegal_cid()); |
12199 } | 12216 } |
12200 } | 12217 } |
12201 | 12218 |
12202 | 12219 |
12203 #if defined(DEBUG) | 12220 #if defined(DEBUG) |
12204 // Used in asserts to verify that a check is not added twice. | 12221 // Used in asserts to verify that a check is not added twice. |
12205 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { | 12222 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { |
12206 const intptr_t len = NumberOfChecks(); | 12223 const intptr_t len = NumberOfChecks(); |
12207 for (intptr_t i = 0; i < len; i++) { | 12224 for (intptr_t i = 0; i < len; i++) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12240 } | 12257 } |
12241 return; | 12258 return; |
12242 } | 12259 } |
12243 ASSERT(NumArgsTested() == 0); | 12260 ASSERT(NumArgsTested() == 0); |
12244 // Can add only once. | 12261 // Can add only once. |
12245 const intptr_t old_num = NumberOfChecks(); | 12262 const intptr_t old_num = NumberOfChecks(); |
12246 ASSERT(old_num == 0); | 12263 ASSERT(old_num == 0); |
12247 Array& data = Array::Handle(ic_data()); | 12264 Array& data = Array::Handle(ic_data()); |
12248 const intptr_t new_len = data.Length() + TestEntryLength(); | 12265 const intptr_t new_len = data.Length() + TestEntryLength(); |
12249 data = Array::Grow(data, new_len, Heap::kOld); | 12266 data = Array::Grow(data, new_len, Heap::kOld); |
12250 set_ic_data(data); | 12267 WriteSentinel(data, TestEntryLength()); |
12251 WriteSentinel(data); | |
12252 intptr_t data_pos = old_num * TestEntryLength(); | 12268 intptr_t data_pos = old_num * TestEntryLength(); |
12253 ASSERT(!target.IsNull()); | 12269 ASSERT(!target.IsNull()); |
12254 data.SetAt(data_pos++, target); | 12270 data.SetAt(data_pos++, target); |
12255 // Set count to 0 as this is called during compilation, before the | 12271 // Set count to 0 as this is called during compilation, before the |
12256 // call has been executed. | 12272 // call has been executed. |
12257 const Smi& value = Smi::Handle(Smi::New(0)); | 12273 const Smi& value = Smi::Handle(Smi::New(0)); |
12258 data.SetAt(data_pos, value); | 12274 data.SetAt(data_pos, value); |
| 12275 // Multithreaded access to ICData requires setting of array to be the last |
| 12276 // operation. |
| 12277 set_ic_data_array(data); |
12259 } | 12278 } |
12260 | 12279 |
12261 | 12280 |
12262 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 12281 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
12263 const Function& target) const { | 12282 const Function& target) const { |
12264 ASSERT(!target.IsNull()); | 12283 ASSERT(!target.IsNull()); |
12265 ASSERT(target.name() == target_name()); | 12284 ASSERT(target.name() == target_name()); |
12266 DEBUG_ASSERT(!HasCheck(class_ids)); | 12285 DEBUG_ASSERT(!HasCheck(class_ids)); |
12267 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. | 12286 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. |
12268 ASSERT(class_ids.length() == NumArgsTested()); | 12287 ASSERT(class_ids.length() == NumArgsTested()); |
(...skipping 17 matching lines...) Expand all Loading... |
12286 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 12305 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12287 ASSERT(class_ids[i] != kIllegalCid); | 12306 ASSERT(class_ids[i] != kIllegalCid); |
12288 value = Smi::New(class_ids[i]); | 12307 value = Smi::New(class_ids[i]); |
12289 data.SetAt(i, value); | 12308 data.SetAt(i, value); |
12290 } | 12309 } |
12291 return; | 12310 return; |
12292 } | 12311 } |
12293 } | 12312 } |
12294 const intptr_t new_len = data.Length() + TestEntryLength(); | 12313 const intptr_t new_len = data.Length() + TestEntryLength(); |
12295 data = Array::Grow(data, new_len, Heap::kOld); | 12314 data = Array::Grow(data, new_len, Heap::kOld); |
12296 set_ic_data(data); | 12315 WriteSentinel(data, TestEntryLength()); |
12297 WriteSentinel(data); | |
12298 intptr_t data_pos = old_num * TestEntryLength(); | 12316 intptr_t data_pos = old_num * TestEntryLength(); |
12299 Smi& value = Smi::Handle(); | 12317 Smi& value = Smi::Handle(); |
12300 for (intptr_t i = 0; i < class_ids.length(); i++) { | 12318 for (intptr_t i = 0; i < class_ids.length(); i++) { |
12301 // kIllegalCid is used as terminating value, do not add it. | 12319 // kIllegalCid is used as terminating value, do not add it. |
12302 ASSERT(class_ids[i] != kIllegalCid); | 12320 ASSERT(class_ids[i] != kIllegalCid); |
12303 value = Smi::New(class_ids[i]); | 12321 value = Smi::New(class_ids[i]); |
12304 data.SetAt(data_pos++, value); | 12322 data.SetAt(data_pos++, value); |
12305 } | 12323 } |
12306 ASSERT(!target.IsNull()); | 12324 ASSERT(!target.IsNull()); |
12307 data.SetAt(data_pos++, target); | 12325 data.SetAt(data_pos++, target); |
12308 value = Smi::New(1); | 12326 value = Smi::New(1); |
12309 data.SetAt(data_pos, value); | 12327 data.SetAt(data_pos, value); |
| 12328 // Multithreaded access to ICData requires setting of array to be the last |
| 12329 // operation. |
| 12330 set_ic_data_array(data); |
12310 } | 12331 } |
12311 | 12332 |
12312 | 12333 |
12313 void ICData::AddReceiverCheck(intptr_t receiver_class_id, | 12334 void ICData::AddReceiverCheck(intptr_t receiver_class_id, |
12314 const Function& target, | 12335 const Function& target, |
12315 intptr_t count) const { | 12336 intptr_t count) const { |
12316 #if defined(DEBUG) | 12337 #if defined(DEBUG) |
12317 GrowableArray<intptr_t> class_ids(1); | 12338 GrowableArray<intptr_t> class_ids(1); |
12318 class_ids.Add(receiver_class_id); | 12339 class_ids.Add(receiver_class_id); |
12319 ASSERT(!HasCheck(class_ids)); | 12340 ASSERT(!HasCheck(class_ids)); |
12320 #endif // DEBUG | 12341 #endif // DEBUG |
12321 ASSERT(!target.IsNull()); | 12342 ASSERT(!target.IsNull()); |
12322 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. | 12343 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. |
12323 ASSERT(receiver_class_id != kIllegalCid); | 12344 ASSERT(receiver_class_id != kIllegalCid); |
12324 | 12345 |
12325 const intptr_t old_num = NumberOfChecks(); | 12346 const intptr_t old_num = NumberOfChecks(); |
12326 Array& data = Array::Handle(ic_data()); | 12347 Array& data = Array::Handle(ic_data()); |
12327 const intptr_t new_len = data.Length() + TestEntryLength(); | 12348 const intptr_t new_len = data.Length() + TestEntryLength(); |
12328 data = Array::Grow(data, new_len, Heap::kOld); | 12349 data = Array::Grow(data, new_len, Heap::kOld); |
12329 set_ic_data(data); | 12350 WriteSentinel(data, TestEntryLength()); |
12330 WriteSentinel(data); | |
12331 intptr_t data_pos = old_num * TestEntryLength(); | 12351 intptr_t data_pos = old_num * TestEntryLength(); |
12332 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { | 12352 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { |
12333 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); | 12353 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); |
12334 // Move class occupying position 0 to the data_pos. | 12354 // Move class occupying position 0 to the data_pos. |
12335 for (intptr_t i = 0; i < TestEntryLength(); i++) { | 12355 for (intptr_t i = 0; i < TestEntryLength(); i++) { |
12336 data.SetAt(data_pos + i, Object::Handle(data.At(i))); | 12356 data.SetAt(data_pos + i, Object::Handle(data.At(i))); |
12337 } | 12357 } |
12338 // Insert kSmiCid in position 0. | 12358 // Insert kSmiCid in position 0. |
12339 data_pos = 0; | 12359 data_pos = 0; |
12340 } | 12360 } |
12341 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); | 12361 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); |
12342 data.SetAt(data_pos + 1, target); | 12362 data.SetAt(data_pos + 1, target); |
12343 data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count))); | 12363 data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count))); |
| 12364 // Multithreaded access to ICData requires setting of array to be the last |
| 12365 // operation. |
| 12366 set_ic_data_array(data); |
12344 } | 12367 } |
12345 | 12368 |
12346 | 12369 |
12347 void ICData::GetCheckAt(intptr_t index, | 12370 void ICData::GetCheckAt(intptr_t index, |
12348 GrowableArray<intptr_t>* class_ids, | 12371 GrowableArray<intptr_t>* class_ids, |
12349 Function* target) const { | 12372 Function* target) const { |
12350 ASSERT(index < NumberOfChecks()); | 12373 ASSERT(index < NumberOfChecks()); |
12351 ASSERT(class_ids != NULL); | 12374 ASSERT(class_ids != NULL); |
12352 ASSERT(target != NULL); | 12375 ASSERT(target != NULL); |
12353 class_ids->Clear(); | 12376 class_ids->Clear(); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12629 result.set_owner(owner); | 12652 result.set_owner(owner); |
12630 result.set_target_name(target_name); | 12653 result.set_target_name(target_name); |
12631 result.set_arguments_descriptor(arguments_descriptor); | 12654 result.set_arguments_descriptor(arguments_descriptor); |
12632 result.set_deopt_id(deopt_id); | 12655 result.set_deopt_id(deopt_id); |
12633 result.set_state_bits(0); | 12656 result.set_state_bits(0); |
12634 result.SetNumArgsTested(num_args_tested); | 12657 result.SetNumArgsTested(num_args_tested); |
12635 // Number of array elements in one test entry. | 12658 // Number of array elements in one test entry. |
12636 intptr_t len = result.TestEntryLength(); | 12659 intptr_t len = result.TestEntryLength(); |
12637 // IC data array must be null terminated (sentinel entry). | 12660 // IC data array must be null terminated (sentinel entry). |
12638 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); | 12661 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); |
12639 result.set_ic_data(ic_data); | 12662 WriteSentinel(ic_data, result.TestEntryLength()); |
12640 result.WriteSentinel(ic_data); | 12663 result.set_ic_data_array(ic_data); |
12641 return result.raw(); | 12664 return result.raw(); |
12642 } | 12665 } |
12643 | 12666 |
12644 | 12667 |
12645 RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) { | 12668 RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) { |
12646 const ICData& result = ICData::Handle(ICData::New( | 12669 const ICData& result = ICData::Handle(ICData::New( |
12647 Function::Handle(from.owner()), | 12670 Function::Handle(from.owner()), |
12648 String::Handle(from.target_name()), | 12671 String::Handle(from.target_name()), |
12649 Array::Handle(from.arguments_descriptor()), | 12672 Array::Handle(from.arguments_descriptor()), |
12650 from.deopt_id(), | 12673 from.deopt_id(), |
(...skipping 9105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21756 return tag_label.ToCString(); | 21779 return tag_label.ToCString(); |
21757 } | 21780 } |
21758 | 21781 |
21759 | 21782 |
21760 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 21783 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
21761 Instance::PrintJSONImpl(stream, ref); | 21784 Instance::PrintJSONImpl(stream, ref); |
21762 } | 21785 } |
21763 | 21786 |
21764 | 21787 |
21765 } // namespace dart | 21788 } // namespace dart |
OLD | NEW |