| 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 12268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12279 } | 12279 } |
| 12280 } | 12280 } |
| 12281 | 12281 |
| 12282 | 12282 |
| 12283 #if defined(DEBUG) | 12283 #if defined(DEBUG) |
| 12284 // Used in asserts to verify that a check is not added twice. | 12284 // Used in asserts to verify that a check is not added twice. |
| 12285 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { | 12285 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { |
| 12286 const intptr_t len = NumberOfChecks(); | 12286 const intptr_t len = NumberOfChecks(); |
| 12287 for (intptr_t i = 0; i < len; i++) { | 12287 for (intptr_t i = 0; i < len; i++) { |
| 12288 GrowableArray<intptr_t> class_ids; | 12288 GrowableArray<intptr_t> class_ids; |
| 12289 Function& target = Function::Handle(); | 12289 GetClassIdsAt(i, &class_ids); |
| 12290 GetCheckAt(i, &class_ids, &target); | |
| 12291 bool matches = true; | 12290 bool matches = true; |
| 12292 for (intptr_t k = 0; k < class_ids.length(); k++) { | 12291 for (intptr_t k = 0; k < class_ids.length(); k++) { |
| 12293 if (class_ids[k] != cids[k]) { | 12292 if (class_ids[k] != cids[k]) { |
| 12294 matches = false; | 12293 matches = false; |
| 12295 break; | 12294 break; |
| 12296 } | 12295 } |
| 12297 } | 12296 } |
| 12298 if (matches) { | 12297 if (matches) { |
| 12299 return true; | 12298 return true; |
| 12300 } | 12299 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12439 class_ids->Clear(); | 12438 class_ids->Clear(); |
| 12440 const Array& data = Array::Handle(ic_data()); | 12439 const Array& data = Array::Handle(ic_data()); |
| 12441 intptr_t data_pos = index * TestEntryLength(); | 12440 intptr_t data_pos = index * TestEntryLength(); |
| 12442 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 12441 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 12443 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 12442 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
| 12444 } | 12443 } |
| 12445 (*target) ^= data.At(data_pos++); | 12444 (*target) ^= data.At(data_pos++); |
| 12446 } | 12445 } |
| 12447 | 12446 |
| 12448 | 12447 |
| 12448 void ICData::GetClassIdsAt(intptr_t index, |
| 12449 GrowableArray<intptr_t>* class_ids) const { |
| 12450 ASSERT(index < NumberOfChecks()); |
| 12451 ASSERT(class_ids != NULL); |
| 12452 class_ids->Clear(); |
| 12453 const Array& data = Array::Handle(ic_data()); |
| 12454 intptr_t data_pos = index * TestEntryLength(); |
| 12455 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 12456 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
| 12457 } |
| 12458 } |
| 12459 |
| 12460 |
| 12449 void ICData::GetOneClassCheckAt(intptr_t index, | 12461 void ICData::GetOneClassCheckAt(intptr_t index, |
| 12450 intptr_t* class_id, | 12462 intptr_t* class_id, |
| 12451 Function* target) const { | 12463 Function* target) const { |
| 12452 ASSERT(class_id != NULL); | 12464 ASSERT(class_id != NULL); |
| 12453 ASSERT(target != NULL); | 12465 ASSERT(target != NULL); |
| 12454 ASSERT(NumArgsTested() == 1); | 12466 ASSERT(NumArgsTested() == 1); |
| 12455 const Array& data = Array::Handle(ic_data()); | 12467 const Array& data = Array::Handle(ic_data()); |
| 12456 const intptr_t data_pos = index * TestEntryLength(); | 12468 const intptr_t data_pos = index * TestEntryLength(); |
| 12457 *class_id = Smi::Value(Smi::RawCast(data.At(data_pos))); | 12469 *class_id = Smi::Value(Smi::RawCast(data.At(data_pos))); |
| 12458 *target ^= data.At(data_pos + 1); | 12470 *target ^= data.At(data_pos + 1); |
| 12459 } | 12471 } |
| 12460 | 12472 |
| 12461 | 12473 |
| 12462 intptr_t ICData::GetCidAt(intptr_t index) const { | 12474 intptr_t ICData::GetCidAt(intptr_t index) const { |
| 12463 ASSERT(NumArgsTested() == 1); | 12475 ASSERT(NumArgsTested() == 1); |
| 12464 const Array& data = Array::Handle(ic_data()); | 12476 const Array& data = Array::Handle(ic_data()); |
| 12465 const intptr_t data_pos = index * TestEntryLength(); | 12477 const intptr_t data_pos = index * TestEntryLength(); |
| 12466 return Smi::Value(Smi::RawCast(data.At(data_pos))); | 12478 return Smi::Value(Smi::RawCast(data.At(data_pos))); |
| 12467 } | 12479 } |
| 12468 | 12480 |
| 12469 | 12481 |
| 12470 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { | 12482 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { |
| 12471 GrowableArray<intptr_t> class_ids; | 12483 GrowableArray<intptr_t> class_ids; |
| 12472 Function& target = Function::Handle(); | 12484 GetClassIdsAt(index, &class_ids); |
| 12473 GetCheckAt(index, &class_ids, &target); | |
| 12474 return class_ids[arg_nr]; | 12485 return class_ids[arg_nr]; |
| 12475 } | 12486 } |
| 12476 | 12487 |
| 12477 | 12488 |
| 12478 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { | 12489 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { |
| 12479 ASSERT(index < NumberOfChecks()); | 12490 ASSERT(index < NumberOfChecks()); |
| 12480 const intptr_t data_pos = index * TestEntryLength(); | 12491 const intptr_t data_pos = index * TestEntryLength(); |
| 12481 NoSafepointScope no_safepoint; | 12492 NoSafepointScope no_safepoint; |
| 12482 RawArray* raw_data = ic_data(); | 12493 RawArray* raw_data = ic_data(); |
| 12483 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); | 12494 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12639 } | 12650 } |
| 12640 return true; | 12651 return true; |
| 12641 } | 12652 } |
| 12642 | 12653 |
| 12643 | 12654 |
| 12644 void ICData::GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, | 12655 void ICData::GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, |
| 12645 GrowableArray<intptr_t>* second) const { | 12656 GrowableArray<intptr_t>* second) const { |
| 12646 ASSERT(NumArgsTested() == 2); | 12657 ASSERT(NumArgsTested() == 2); |
| 12647 first->Clear(); | 12658 first->Clear(); |
| 12648 second->Clear(); | 12659 second->Clear(); |
| 12649 Function& target = Function::Handle(); | |
| 12650 GrowableArray<intptr_t> class_ids; | 12660 GrowableArray<intptr_t> class_ids; |
| 12651 const intptr_t len = NumberOfChecks(); | 12661 const intptr_t len = NumberOfChecks(); |
| 12652 for (intptr_t i = 0; i < len; i++) { | 12662 for (intptr_t i = 0; i < len; i++) { |
| 12653 if (GetCountAt(i) > 0) { | 12663 if (GetCountAt(i) > 0) { |
| 12654 GetCheckAt(i, &class_ids, &target); | 12664 GetClassIdsAt(i, &class_ids); |
| 12655 ASSERT(class_ids.length() == 2); | 12665 ASSERT(class_ids.length() == 2); |
| 12656 first->Add(class_ids[0]); | 12666 first->Add(class_ids[0]); |
| 12657 second->Add(class_ids[1]); | 12667 second->Add(class_ids[1]); |
| 12658 } | 12668 } |
| 12659 } | 12669 } |
| 12660 } | 12670 } |
| 12661 | 12671 |
| 12662 | 12672 |
| 12663 bool ICData::IsUsedAt(intptr_t i) const { | 12673 bool ICData::IsUsedAt(intptr_t i) const { |
| 12664 if (GetCountAt(i) <= 0) { | 12674 if (GetCountAt(i) <= 0) { |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12887 | 12897 |
| 12888 bool ICData::HasRangeFeedback() const { | 12898 bool ICData::HasRangeFeedback() const { |
| 12889 const String& target = String::Handle(target_name()); | 12899 const String& target = String::Handle(target_name()); |
| 12890 const Token::Kind token_kind = RecognizeArithmeticOp(target); | 12900 const Token::Kind token_kind = RecognizeArithmeticOp(target); |
| 12891 if (!Token::IsBinaryArithmeticOperator(token_kind) && | 12901 if (!Token::IsBinaryArithmeticOperator(token_kind) && |
| 12892 !Token::IsUnaryArithmeticOperator(token_kind)) { | 12902 !Token::IsUnaryArithmeticOperator(token_kind)) { |
| 12893 return false; | 12903 return false; |
| 12894 } | 12904 } |
| 12895 | 12905 |
| 12896 bool initialized = false; | 12906 bool initialized = false; |
| 12897 Function& t = Function::Handle(); | |
| 12898 const intptr_t len = NumberOfChecks(); | 12907 const intptr_t len = NumberOfChecks(); |
| 12899 GrowableArray<intptr_t> class_ids; | 12908 GrowableArray<intptr_t> class_ids; |
| 12900 for (intptr_t i = 0; i < len; i++) { | 12909 for (intptr_t i = 0; i < len; i++) { |
| 12901 if (IsUsedAt(i)) { | 12910 if (IsUsedAt(i)) { |
| 12902 initialized = true; | 12911 initialized = true; |
| 12903 GetCheckAt(i, &class_ids, &t); | 12912 GetClassIdsAt(i, &class_ids); |
| 12904 for (intptr_t j = 0; j < class_ids.length(); j++) { | 12913 for (intptr_t j = 0; j < class_ids.length(); j++) { |
| 12905 const intptr_t cid = class_ids[j]; | 12914 const intptr_t cid = class_ids[j]; |
| 12906 if ((cid != kSmiCid) && (cid != kMintCid)) { | 12915 if ((cid != kSmiCid) && (cid != kMintCid)) { |
| 12907 return false; | 12916 return false; |
| 12908 } | 12917 } |
| 12909 } | 12918 } |
| 12910 } | 12919 } |
| 12911 } | 12920 } |
| 12912 | 12921 |
| 12913 return initialized; | 12922 return initialized; |
| (...skipping 4378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17292 const int64_t right_value = other.AsInt64Value(); | 17301 const int64_t right_value = other.AsInt64Value(); |
| 17293 switch (operation) { | 17302 switch (operation) { |
| 17294 case Token::kADD: { | 17303 case Token::kADD: { |
| 17295 if (((left_value < 0) != (right_value < 0)) || | 17304 if (((left_value < 0) != (right_value < 0)) || |
| 17296 ((left_value + right_value) < 0) == (left_value < 0)) { | 17305 ((left_value + right_value) < 0) == (left_value < 0)) { |
| 17297 return Integer::New(left_value + right_value, space); | 17306 return Integer::New(left_value + right_value, space); |
| 17298 } | 17307 } |
| 17299 break; | 17308 break; |
| 17300 } | 17309 } |
| 17301 case Token::kSUB: { | 17310 case Token::kSUB: { |
| 17302 // TODO(srdjan): Investigate why XCode 7 produces wrong code | 17311 // TODO(srdjan): XCode 7 produces different code in -O0 than in -O2 for |
| 17303 // if the comparison is inlined as in above (Token::kADD). | 17312 // following code when 'left_value - right_value' overflows into a |
| 17313 // positive number (left negative, right positive): |
| 17314 // if (((left_value < 0) == (right_value < 0)) || |
| 17315 // ((left_value - right_value) < 0) == (left_value < 0)) { |
| 17316 // |
| 17317 // Restructuring code using temporary variables is a workaround. |
| 17304 const bool both_same_sign = (left_value < 0) == (right_value < 0); | 17318 const bool both_same_sign = (left_value < 0) == (right_value < 0); |
| 17305 const bool result_same_sign_as_left = | 17319 const bool result_same_sign_as_left = |
| 17306 ((left_value - right_value) < 0) == (left_value < 0); | 17320 ((left_value - right_value) < 0) == (left_value < 0); |
| 17307 if (both_same_sign || result_same_sign_as_left) { | 17321 if (both_same_sign || result_same_sign_as_left) { |
| 17308 return Integer::New(left_value - right_value, space); | 17322 return Integer::New(left_value - right_value, space); |
| 17309 } | 17323 } |
| 17310 break; | 17324 break; |
| 17311 } | 17325 } |
| 17312 case Token::kMUL: { | 17326 case Token::kMUL: { |
| 17313 if ((Utils::HighestBit(left_value) + | 17327 if ((Utils::HighestBit(left_value) + |
| (...skipping 4604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21918 return tag_label.ToCString(); | 21932 return tag_label.ToCString(); |
| 21919 } | 21933 } |
| 21920 | 21934 |
| 21921 | 21935 |
| 21922 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 21936 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 21923 Instance::PrintJSONImpl(stream, ref); | 21937 Instance::PrintJSONImpl(stream, ref); |
| 21924 } | 21938 } |
| 21925 | 21939 |
| 21926 | 21940 |
| 21927 } // namespace dart | 21941 } // namespace dart |
| OLD | NEW |