Chromium Code Reviews| 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/bigint_operations.h" | 10 #include "vm/bigint_operations.h" |
| (...skipping 7361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7372 | 7372 |
| 7373 void ICData::WriteSentinel() const { | 7373 void ICData::WriteSentinel() const { |
| 7374 const Smi& sentinel_value = Smi::Handle(Smi::New(kIllegalCid)); | 7374 const Smi& sentinel_value = Smi::Handle(Smi::New(kIllegalCid)); |
| 7375 const Array& data = Array::Handle(ic_data()); | 7375 const Array& data = Array::Handle(ic_data()); |
| 7376 for (intptr_t i = 1; i <= TestEntryLength(); i++) { | 7376 for (intptr_t i = 1; i <= TestEntryLength(); i++) { |
| 7377 data.SetAt(data.Length() - i, sentinel_value); | 7377 data.SetAt(data.Length() - i, sentinel_value); |
| 7378 } | 7378 } |
| 7379 } | 7379 } |
| 7380 | 7380 |
| 7381 | 7381 |
| 7382 // Used in asserts to verify that a check is not added twice. | |
| 7383 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { | |
|
Florian Schneider
2012/10/05 09:17:35
Do we want this inside #ifdef DEBUG as well to avo
srdjan
2012/10/09 18:06:03
#if defined(DEBUG)
| |
| 7384 for (intptr_t i = 0; i < NumberOfChecks(); i++) { | |
| 7385 GrowableArray<intptr_t> class_ids; | |
| 7386 Function& target = Function::Handle(); | |
| 7387 GetCheckAt(i, &class_ids, &target); | |
| 7388 bool matches = true; | |
| 7389 for (intptr_t k = 0; k < class_ids.length(); k++) { | |
| 7390 if (class_ids[k] != cids[k]) { | |
| 7391 matches = false; | |
| 7392 break; | |
| 7393 } | |
| 7394 } | |
| 7395 if (matches) { | |
| 7396 return true; | |
| 7397 } | |
| 7398 } | |
| 7399 return false; | |
| 7400 } | |
| 7401 | |
| 7402 | |
| 7382 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 7403 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
| 7383 const Function& target) const { | 7404 const Function& target) const { |
| 7405 ASSERT(!HasCheck(class_ids)); | |
|
Florian Schneider
2012/10/05 09:17:35
Maybe DEBUG_ASSERT?
srdjan
2012/10/09 18:06:03
Done.
| |
| 7384 ASSERT(num_args_tested() > 1); // Otherwise use 'AddReceiverCheck'. | 7406 ASSERT(num_args_tested() > 1); // Otherwise use 'AddReceiverCheck'. |
| 7385 ASSERT(class_ids.length() == num_args_tested()); | 7407 ASSERT(class_ids.length() == num_args_tested()); |
| 7386 const intptr_t old_num = NumberOfChecks(); | 7408 const intptr_t old_num = NumberOfChecks(); |
| 7387 Array& data = Array::Handle(ic_data()); | 7409 Array& data = Array::Handle(ic_data()); |
| 7388 const intptr_t new_len = data.Length() + TestEntryLength(); | 7410 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 7389 data = Array::Grow(data, new_len, Heap::kOld); | 7411 data = Array::Grow(data, new_len, Heap::kOld); |
| 7390 set_ic_data(data); | 7412 set_ic_data(data); |
| 7391 WriteSentinel(); | 7413 WriteSentinel(); |
| 7392 intptr_t data_pos = old_num * TestEntryLength(); | 7414 intptr_t data_pos = old_num * TestEntryLength(); |
| 7393 for (intptr_t i = 0; i < class_ids.length(); i++) { | 7415 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 7394 // kIllegalCid is used as terminating value, do not add it. | 7416 // kIllegalCid is used as terminating value, do not add it. |
| 7395 ASSERT(class_ids[i] != kIllegalCid); | 7417 ASSERT(class_ids[i] != kIllegalCid); |
| 7396 data.SetAt(data_pos++, Smi::Handle(Smi::New(class_ids[i]))); | 7418 data.SetAt(data_pos++, Smi::Handle(Smi::New(class_ids[i]))); |
| 7397 } | 7419 } |
| 7398 ASSERT(!target.IsNull()); | 7420 ASSERT(!target.IsNull()); |
| 7399 data.SetAt(data_pos, target); | 7421 data.SetAt(data_pos, target); |
| 7400 } | 7422 } |
| 7401 | 7423 |
| 7402 | 7424 |
| 7403 void ICData::AddReceiverCheck(intptr_t receiver_class_id, | 7425 void ICData::AddReceiverCheck(intptr_t receiver_class_id, |
| 7404 const Function& target) const { | 7426 const Function& target) const { |
| 7427 #if defined(DEBUG) | |
| 7428 GrowableArray<intptr_t> class_ids(1); | |
| 7429 class_ids.Add(receiver_class_id); | |
| 7430 ASSERT(!HasCheck(class_ids)); | |
| 7431 #endif // DEBUG | |
| 7405 ASSERT(num_args_tested() == 1); // Otherwise use 'AddCheck'. | 7432 ASSERT(num_args_tested() == 1); // Otherwise use 'AddCheck'. |
| 7406 ASSERT(receiver_class_id != kIllegalCid); | 7433 ASSERT(receiver_class_id != kIllegalCid); |
| 7407 ASSERT(!target.IsNull()); | 7434 ASSERT(!target.IsNull()); |
| 7408 | 7435 |
| 7409 const intptr_t old_num = NumberOfChecks(); | 7436 const intptr_t old_num = NumberOfChecks(); |
| 7410 Array& data = Array::Handle(ic_data()); | 7437 Array& data = Array::Handle(ic_data()); |
| 7411 const intptr_t new_len = data.Length() + TestEntryLength(); | 7438 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 7412 data = Array::Grow(data, new_len, Heap::kOld); | 7439 data = Array::Grow(data, new_len, Heap::kOld); |
| 7413 set_ic_data(data); | 7440 set_ic_data(data); |
| 7414 WriteSentinel(); | 7441 WriteSentinel(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 7425 } else { | 7452 } else { |
| 7426 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); | 7453 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); |
| 7427 data.SetAt(data_pos + 1, target); | 7454 data.SetAt(data_pos + 1, target); |
| 7428 } | 7455 } |
| 7429 } | 7456 } |
| 7430 | 7457 |
| 7431 | 7458 |
| 7432 void ICData::GetCheckAt(intptr_t index, | 7459 void ICData::GetCheckAt(intptr_t index, |
| 7433 GrowableArray<intptr_t>* class_ids, | 7460 GrowableArray<intptr_t>* class_ids, |
| 7434 Function* target) const { | 7461 Function* target) const { |
| 7462 ASSERT(index < NumberOfChecks()); | |
| 7435 ASSERT(class_ids != NULL); | 7463 ASSERT(class_ids != NULL); |
| 7436 ASSERT(target != NULL); | 7464 ASSERT(target != NULL); |
| 7437 class_ids->Clear(); | 7465 class_ids->Clear(); |
| 7438 const Array& data = Array::Handle(ic_data()); | 7466 const Array& data = Array::Handle(ic_data()); |
| 7439 intptr_t data_pos = index * TestEntryLength(); | 7467 intptr_t data_pos = index * TestEntryLength(); |
| 7440 Smi& smi = Smi::Handle(); | 7468 Smi& smi = Smi::Handle(); |
| 7441 for (intptr_t i = 0; i < num_args_tested(); i++) { | 7469 for (intptr_t i = 0; i < num_args_tested(); i++) { |
| 7442 smi ^= data.At(data_pos++); | 7470 smi ^= data.At(data_pos++); |
| 7443 class_ids->Add(smi.Value()); | 7471 class_ids->Add(smi.Value()); |
| 7444 } | 7472 } |
| 7445 (*target) ^= data.At(data_pos); | 7473 (*target) ^= data.At(data_pos); |
| 7446 } | 7474 } |
| 7447 | 7475 |
| 7448 | 7476 |
| 7449 void ICData::GetOneClassCheckAt( | 7477 void ICData::GetOneClassCheckAt(intptr_t index, |
| 7450 int index, intptr_t* class_id, Function* target) const { | 7478 intptr_t* class_id, |
| 7479 Function* target) const { | |
| 7451 ASSERT(class_id != NULL); | 7480 ASSERT(class_id != NULL); |
| 7452 ASSERT(target != NULL); | 7481 ASSERT(target != NULL); |
| 7453 ASSERT(num_args_tested() == 1); | 7482 ASSERT(num_args_tested() == 1); |
| 7454 const Array& data = Array::Handle(ic_data()); | 7483 const Array& data = Array::Handle(ic_data()); |
| 7455 intptr_t data_pos = index * TestEntryLength(); | 7484 intptr_t data_pos = index * TestEntryLength(); |
| 7456 Smi& smi = Smi::Handle(); | 7485 Smi& smi = Smi::Handle(); |
| 7457 smi ^= data.At(data_pos); | 7486 smi ^= data.At(data_pos); |
| 7458 *class_id = smi.Value(); | 7487 *class_id = smi.Value(); |
| 7459 *target ^= data.At(data_pos + 1); | 7488 *target ^= data.At(data_pos + 1); |
| 7460 } | 7489 } |
| 7461 | 7490 |
| 7462 | 7491 |
| 7492 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { | |
| 7493 GrowableArray<intptr_t> class_ids; | |
| 7494 Function& target = Function::Handle(); | |
| 7495 GetCheckAt(index, &class_ids, &target); | |
| 7496 return class_ids[arg_nr]; | |
| 7497 } | |
| 7498 | |
| 7499 | |
| 7463 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { | 7500 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { |
| 7464 ASSERT(index < NumberOfChecks()); | 7501 ASSERT(index < NumberOfChecks()); |
| 7465 const Array& data = Array::Handle(ic_data()); | 7502 const Array& data = Array::Handle(ic_data()); |
| 7466 const intptr_t data_pos = index * TestEntryLength(); | 7503 const intptr_t data_pos = index * TestEntryLength(); |
| 7467 Smi& smi = Smi::Handle(); | 7504 Smi& smi = Smi::Handle(); |
| 7468 smi ^= data.At(data_pos); | 7505 smi ^= data.At(data_pos); |
| 7469 return smi.Value(); | 7506 return smi.Value(); |
| 7470 } | 7507 } |
| 7471 | 7508 |
| 7472 | 7509 |
| 7473 RawFunction* ICData::GetTargetAt(intptr_t index) const { | 7510 RawFunction* ICData::GetTargetAt(intptr_t index) const { |
| 7474 const Array& data = Array::Handle(ic_data()); | 7511 const Array& data = Array::Handle(ic_data()); |
| 7475 const intptr_t data_pos = index * TestEntryLength() + num_args_tested(); | 7512 const intptr_t data_pos = index * TestEntryLength() + num_args_tested(); |
| 7476 Function& target = Function::Handle(); | 7513 Function& target = Function::Handle(); |
| 7477 target ^= data.At(data_pos); | 7514 target ^= data.At(data_pos); |
| 7478 return target.raw(); | 7515 return target.raw(); |
| 7479 } | 7516 } |
| 7480 | 7517 |
| 7481 | 7518 |
| 7482 RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const { | 7519 RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const { |
| 7483 for (intptr_t i = 0; i < NumberOfChecks(); i++) { | 7520 for (intptr_t i = 0; i < NumberOfChecks(); i++) { |
| 7484 if (GetReceiverClassIdAt(i) == class_id) { | 7521 if (GetReceiverClassIdAt(i) == class_id) { |
| 7485 return GetTargetAt(i); | 7522 return GetTargetAt(i); |
| 7486 } | 7523 } |
| 7487 } | 7524 } |
| 7488 return Function::null(); | 7525 return Function::null(); |
| 7489 } | 7526 } |
| 7490 | 7527 |
| 7491 | 7528 |
| 7492 RawICData* ICData::AsUnaryClassChecks() const { | 7529 RawICData* ICData::AsUnaryClassChecksForArgNr(intptr_t arg_nr) const { |
| 7493 ASSERT(!IsNull()); | 7530 ASSERT(!IsNull()); |
| 7494 ASSERT(num_args_tested() > 0); | 7531 ASSERT(num_args_tested() > arg_nr); |
| 7495 if (num_args_tested() == 1) return raw(); | 7532 if ((arg_nr == 0) && (num_args_tested() == 1)) { |
| 7533 // Frequent case. | |
| 7534 return raw(); | |
| 7535 } | |
| 7496 const intptr_t kNumArgsTested = 1; | 7536 const intptr_t kNumArgsTested = 1; |
| 7497 ICData& result = ICData::Handle(ICData::New( | 7537 ICData& result = ICData::Handle(ICData::New( |
| 7498 Function::Handle(function()), | 7538 Function::Handle(function()), |
| 7499 String::Handle(target_name()), | 7539 String::Handle(target_name()), |
| 7500 deopt_id(), | 7540 deopt_id(), |
| 7501 kNumArgsTested)); | 7541 kNumArgsTested)); |
| 7502 for (intptr_t i = 0; i < NumberOfChecks(); i++) { | 7542 for (intptr_t i = 0; i < NumberOfChecks(); i++) { |
| 7503 const intptr_t class_id = GetReceiverClassIdAt(i); | 7543 const intptr_t class_id = GetClassIdAt(i, arg_nr); |
| 7504 intptr_t duplicate_class_id = -1; | 7544 intptr_t duplicate_class_id = -1; |
| 7505 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) { | 7545 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) { |
| 7506 if (class_id == result.GetReceiverClassIdAt(k)) { | 7546 if (class_id == result.GetReceiverClassIdAt(k)) { |
| 7507 duplicate_class_id = k; | 7547 duplicate_class_id = k; |
| 7508 break; | 7548 break; |
| 7509 } | 7549 } |
| 7510 } | 7550 } |
| 7511 if (duplicate_class_id >= 0) { | 7551 if (duplicate_class_id >= 0) { |
| 7512 ASSERT(result.GetTargetAt(duplicate_class_id) == GetTargetAt(i)); | 7552 // This check is valid only when checking the receiver. |
| 7553 ASSERT((arg_nr != 0) || | |
| 7554 (result.GetTargetAt(duplicate_class_id) == GetTargetAt(i))); | |
| 7513 } else { | 7555 } else { |
| 7514 // This will make sure that Smi is first if it exists. | 7556 // This will make sure that Smi is first if it exists. |
| 7515 result.AddReceiverCheck(class_id, | 7557 result.AddReceiverCheck(class_id, |
| 7516 Function::Handle(GetTargetAt(i))); | 7558 Function::Handle(GetTargetAt(i))); |
| 7517 } | 7559 } |
| 7518 } | 7560 } |
| 7519 return result.raw(); | 7561 return result.raw(); |
| 7520 } | 7562 } |
| 7521 | 7563 |
| 7522 | 7564 |
| (...skipping 4609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12132 } | 12174 } |
| 12133 return result.raw(); | 12175 return result.raw(); |
| 12134 } | 12176 } |
| 12135 | 12177 |
| 12136 | 12178 |
| 12137 const char* WeakProperty::ToCString() const { | 12179 const char* WeakProperty::ToCString() const { |
| 12138 return "_WeakProperty"; | 12180 return "_WeakProperty"; |
| 12139 } | 12181 } |
| 12140 | 12182 |
| 12141 } // namespace dart | 12183 } // namespace dart |
| OLD | NEW |