OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 #include "vm/optimizer.h" |
| 6 |
| 7 #include "vm/intermediate_language.h" |
| 8 #include "vm/object.h" |
| 9 |
| 10 namespace dart { |
| 11 |
| 12 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results, |
| 13 intptr_t test_cid) { |
| 14 for (intptr_t i = 0; i < results.length(); i += 2) { |
| 15 if (results[i] == test_cid) return true; |
| 16 } |
| 17 return false; |
| 18 } |
| 19 |
| 20 |
| 21 static void TryAddTest(ZoneGrowableArray<intptr_t>* results, |
| 22 intptr_t test_cid, |
| 23 bool result) { |
| 24 if (!CidTestResultsContains(*results, test_cid)) { |
| 25 results->Add(test_cid); |
| 26 results->Add(result); |
| 27 } |
| 28 } |
| 29 |
| 30 |
| 31 // Used when we only need the positive result because we return false by |
| 32 // default. |
| 33 static void PurgeNegativeTestCidsEntries(ZoneGrowableArray<intptr_t>* results) { |
| 34 // We can't purge the Smi entry at the beginning since it is used in the |
| 35 // Smi check before the Cid is loaded. |
| 36 int dest = 2; |
| 37 for (intptr_t i = 2; i < results->length(); i += 2) { |
| 38 if (results->At(i + 1) != 0) { |
| 39 (*results)[dest++] = results->At(i); |
| 40 (*results)[dest++] = results->At(i + 1); |
| 41 } |
| 42 } |
| 43 results->SetLength(dest); |
| 44 } |
| 45 |
| 46 |
| 47 bool Optimizer::SpecializeTestCidsForNumericTypes( |
| 48 ZoneGrowableArray<intptr_t>* results, |
| 49 const AbstractType& type) { |
| 50 ASSERT(results->length() >= 2); // At least on entry. |
| 51 const ClassTable& class_table = *Isolate::Current()->class_table(); |
| 52 if ((*results)[0] != kSmiCid) { |
| 53 const Class& cls = Class::Handle(class_table.At(kSmiCid)); |
| 54 const Class& type_class = Class::Handle(type.type_class()); |
| 55 const bool smi_is_subtype = |
| 56 cls.IsSubtypeOf(Object::null_type_arguments(), type_class, |
| 57 Object::null_type_arguments(), NULL, NULL, Heap::kOld); |
| 58 results->Add((*results)[results->length() - 2]); |
| 59 results->Add((*results)[results->length() - 2]); |
| 60 for (intptr_t i = results->length() - 3; i > 1; --i) { |
| 61 (*results)[i] = (*results)[i - 2]; |
| 62 } |
| 63 (*results)[0] = kSmiCid; |
| 64 (*results)[1] = smi_is_subtype; |
| 65 } |
| 66 |
| 67 ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); |
| 68 ASSERT(results->length() >= 2); |
| 69 if (type.IsSmiType()) { |
| 70 ASSERT((*results)[0] == kSmiCid); |
| 71 PurgeNegativeTestCidsEntries(results); |
| 72 return false; |
| 73 } else if (type.IsIntType()) { |
| 74 ASSERT((*results)[0] == kSmiCid); |
| 75 TryAddTest(results, kMintCid, true); |
| 76 TryAddTest(results, kBigintCid, true); |
| 77 // Cannot deoptimize since all tests returning true have been added. |
| 78 PurgeNegativeTestCidsEntries(results); |
| 79 return false; |
| 80 } else if (type.IsNumberType()) { |
| 81 ASSERT((*results)[0] == kSmiCid); |
| 82 TryAddTest(results, kMintCid, true); |
| 83 TryAddTest(results, kBigintCid, true); |
| 84 TryAddTest(results, kDoubleCid, true); |
| 85 PurgeNegativeTestCidsEntries(results); |
| 86 return false; |
| 87 } else if (type.IsDoubleType()) { |
| 88 ASSERT((*results)[0] == kSmiCid); |
| 89 TryAddTest(results, kDoubleCid, true); |
| 90 PurgeNegativeTestCidsEntries(results); |
| 91 return false; |
| 92 } |
| 93 return true; // May deoptimize since we have not identified all 'true' tests. |
| 94 } |
| 95 |
| 96 } // namespace dart |
OLD | NEW |