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

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

Issue 11048032: Support for mixed null/smi equality: do not deoptimize, emit same optimized code as if that was smi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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) 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698