Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 5 | #include "src/type-feedback-vector.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 6 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 7 | #include "src/code-stubs.h" |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 8 | #include "src/ic/ic.h" |
| 9 | #include "src/ic/ic-state.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 10 | #include "src/objects.h" |
| 11 | #include "src/type-feedback-vector-inl.h" |
| 12 | |
| 13 | namespace v8 { |
| 14 | namespace internal { |
| 15 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 16 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 17 | static bool IsPropertyNameFeedback(Object* feedback) { |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 18 | if (feedback->IsString()) return true; |
| 19 | if (!feedback->IsSymbol()) return false; |
| 20 | Symbol* symbol = Symbol::cast(feedback); |
| 21 | Heap* heap = symbol->GetHeap(); |
| 22 | return symbol != heap->uninitialized_symbol() && |
| 23 | symbol != heap->premonomorphic_symbol() && |
| 24 | symbol != heap->megamorphic_symbol(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 28 | std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) { |
| 29 | return os << TypeFeedbackMetadata::Kind2String(kind); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 30 | } |
| 31 | |
| 32 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 33 | FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( |
| 34 | FeedbackVectorSlot slot) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 35 | int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 36 | int data = Smi::cast(get(index))->value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 37 | return VectorICComputer::decode(data, slot.ToInt()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 38 | } |
| 39 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 40 | String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const { |
| 41 | DCHECK(SlotRequiresName(GetKind(slot))); |
| 42 | FixedArray* names = FixedArray::cast(get(kNamesTableIndex)); |
| 43 | // TODO(ishell): consider using binary search here or even Dictionary when we |
| 44 | // have more ICs with names. |
| 45 | Smi* key = Smi::FromInt(slot.ToInt()); |
| 46 | for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) { |
| 47 | Object* current_key = names->get(entry + kNameTableSlotIndex); |
| 48 | if (current_key == key) { |
| 49 | Object* name = names->get(entry + kNameTableNameIndex); |
| 50 | DCHECK(name->IsString()); |
| 51 | return String::cast(name); |
| 52 | } |
| 53 | } |
| 54 | UNREACHABLE(); |
| 55 | return nullptr; |
| 56 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 57 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 58 | void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, |
| 59 | FeedbackVectorSlotKind kind) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 60 | int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 61 | int data = Smi::cast(get(index))->value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 62 | int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 63 | set(index, Smi::FromInt(new_data)); |
| 64 | } |
| 65 | |
| 66 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 67 | template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
| 68 | Isolate* isolate, const StaticFeedbackVectorSpec* spec); |
| 69 | template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
| 70 | Isolate* isolate, const FeedbackVectorSpec* spec); |
| 71 | |
| 72 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 73 | // static |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 74 | template <typename Spec> |
| 75 | Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate, |
| 76 | const Spec* spec) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 77 | Factory* factory = isolate->factory(); |
| 78 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 79 | const int slot_count = spec->slots(); |
| 80 | const int slot_kinds_length = VectorICComputer::word_count(slot_count); |
| 81 | const int length = slot_kinds_length + kReservedIndexCount; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 82 | if (length == kReservedIndexCount) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 83 | return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 84 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 85 | #ifdef DEBUG |
| 86 | for (int i = 0; i < slot_count;) { |
| 87 | FeedbackVectorSlotKind kind = spec->GetKind(i); |
| 88 | int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
| 89 | for (int j = 1; j < entry_size; j++) { |
| 90 | FeedbackVectorSlotKind kind = spec->GetKind(i + j); |
| 91 | DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind); |
| 92 | } |
| 93 | i += entry_size; |
| 94 | } |
| 95 | #endif |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 96 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 97 | Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 98 | array->set(kSlotsCountIndex, Smi::FromInt(slot_count)); |
| 99 | // Fill the bit-vector part with zeros. |
| 100 | for (int i = 0; i < slot_kinds_length; i++) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 101 | array->set(kReservedIndexCount + i, Smi::FromInt(0)); |
| 102 | } |
| 103 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 104 | Handle<TypeFeedbackMetadata> metadata = |
| 105 | Handle<TypeFeedbackMetadata>::cast(array); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 106 | |
| 107 | // Add names to NamesTable. |
| 108 | const int name_count = spec->name_count(); |
| 109 | |
| 110 | Handle<FixedArray> names = |
| 111 | name_count == 0 |
| 112 | ? factory->empty_fixed_array() |
| 113 | : factory->NewFixedArray(name_count * kNameTableEntrySize); |
| 114 | int name_index = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 115 | for (int i = 0; i < slot_count; i++) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 116 | FeedbackVectorSlotKind kind = spec->GetKind(i); |
| 117 | metadata->SetKind(FeedbackVectorSlot(i), kind); |
| 118 | if (SlotRequiresName(kind)) { |
| 119 | Handle<String> name = spec->GetName(name_index); |
| 120 | DCHECK(!name.is_null()); |
| 121 | int entry = name_index * kNameTableEntrySize; |
| 122 | names->set(entry + kNameTableSlotIndex, Smi::FromInt(i)); |
| 123 | names->set(entry + kNameTableNameIndex, *name); |
| 124 | name_index++; |
| 125 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 126 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 127 | DCHECK_EQ(name_count, name_index); |
| 128 | metadata->set(kNamesTableIndex, *names); |
| 129 | |
| 130 | // It's important that the TypeFeedbackMetadata have a COW map, since it's |
| 131 | // pointed to by both a SharedFunctionInfo and indirectly by closures through |
| 132 | // the TypeFeedbackVector. The serializer uses the COW map type to decide |
| 133 | // this object belongs in the startup snapshot and not the partial |
| 134 | // snapshot(s). |
| 135 | metadata->set_map(isolate->heap()->fixed_cow_array_map()); |
| 136 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 137 | return metadata; |
| 138 | } |
| 139 | |
| 140 | |
| 141 | bool TypeFeedbackMetadata::SpecDiffersFrom( |
| 142 | const FeedbackVectorSpec* other_spec) const { |
| 143 | if (other_spec->slots() != slot_count()) { |
| 144 | return true; |
| 145 | } |
| 146 | |
| 147 | int slots = slot_count(); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 148 | int name_index = 0; |
| 149 | for (int i = 0; i < slots;) { |
| 150 | FeedbackVectorSlot slot(i); |
| 151 | FeedbackVectorSlotKind kind = GetKind(slot); |
| 152 | int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
| 153 | |
| 154 | if (kind != other_spec->GetKind(i)) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 155 | return true; |
| 156 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 157 | if (SlotRequiresName(kind)) { |
| 158 | String* name = GetName(slot); |
| 159 | DCHECK(name != GetHeap()->empty_string()); |
| 160 | String* other_name = *other_spec->GetName(name_index++); |
| 161 | if (name != other_name) { |
| 162 | return true; |
| 163 | } |
| 164 | } |
| 165 | i += entry_size; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 166 | } |
| 167 | return false; |
| 168 | } |
| 169 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 170 | bool TypeFeedbackMetadata::DiffersFrom( |
| 171 | const TypeFeedbackMetadata* other_metadata) const { |
| 172 | if (other_metadata->slot_count() != slot_count()) { |
| 173 | return true; |
| 174 | } |
| 175 | |
| 176 | int slots = slot_count(); |
| 177 | for (int i = 0; i < slots;) { |
| 178 | FeedbackVectorSlot slot(i); |
| 179 | FeedbackVectorSlotKind kind = GetKind(slot); |
| 180 | int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
| 181 | if (GetKind(slot) != other_metadata->GetKind(slot)) { |
| 182 | return true; |
| 183 | } |
| 184 | if (SlotRequiresName(kind)) { |
| 185 | if (GetName(slot) != other_metadata->GetName(slot)) { |
| 186 | return true; |
| 187 | } |
| 188 | } |
| 189 | i += entry_size; |
| 190 | } |
| 191 | return false; |
| 192 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 193 | |
| 194 | const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { |
| 195 | switch (kind) { |
| 196 | case FeedbackVectorSlotKind::INVALID: |
| 197 | return "INVALID"; |
| 198 | case FeedbackVectorSlotKind::CALL_IC: |
| 199 | return "CALL_IC"; |
| 200 | case FeedbackVectorSlotKind::LOAD_IC: |
| 201 | return "LOAD_IC"; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 202 | case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: |
| 203 | return "LOAD_GLOBAL_IC"; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 204 | case FeedbackVectorSlotKind::KEYED_LOAD_IC: |
| 205 | return "KEYED_LOAD_IC"; |
| 206 | case FeedbackVectorSlotKind::STORE_IC: |
| 207 | return "STORE_IC"; |
| 208 | case FeedbackVectorSlotKind::KEYED_STORE_IC: |
| 209 | return "KEYED_STORE_IC"; |
| 210 | case FeedbackVectorSlotKind::GENERAL: |
| 211 | return "STUB"; |
| 212 | case FeedbackVectorSlotKind::KINDS_NUMBER: |
| 213 | break; |
| 214 | } |
| 215 | UNREACHABLE(); |
| 216 | return "?"; |
| 217 | } |
| 218 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 219 | FeedbackVectorSlotKind TypeFeedbackVector::GetKind( |
| 220 | FeedbackVectorSlot slot) const { |
| 221 | DCHECK(!is_empty()); |
| 222 | return metadata()->GetKind(slot); |
| 223 | } |
| 224 | |
| 225 | String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const { |
| 226 | DCHECK(!is_empty()); |
| 227 | return metadata()->GetName(slot); |
| 228 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 229 | |
| 230 | // static |
| 231 | Handle<TypeFeedbackVector> TypeFeedbackVector::New( |
| 232 | Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) { |
| 233 | Factory* factory = isolate->factory(); |
| 234 | |
| 235 | const int slot_count = metadata->slot_count(); |
| 236 | const int length = slot_count + kReservedIndexCount; |
| 237 | if (length == kReservedIndexCount) { |
| 238 | return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array()); |
| 239 | } |
| 240 | |
| 241 | Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); |
| 242 | array->set(kMetadataIndex, *metadata); |
| 243 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 244 | DisallowHeapAllocation no_gc; |
| 245 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 246 | // Ensure we can skip the write barrier |
| 247 | Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 248 | DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 249 | for (int i = 0; i < slot_count;) { |
| 250 | FeedbackVectorSlot slot(i); |
| 251 | FeedbackVectorSlotKind kind = metadata->GetKind(slot); |
| 252 | int index = TypeFeedbackVector::GetIndex(slot); |
| 253 | int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 254 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 255 | Object* value; |
| 256 | if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) { |
| 257 | value = *factory->empty_weak_cell(); |
| 258 | } else { |
| 259 | value = *uninitialized_sentinel; |
| 260 | } |
| 261 | array->set(index, value, SKIP_WRITE_BARRIER); |
| 262 | for (int j = 1; j < entry_size; j++) { |
| 263 | array->set(index + j, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
| 264 | } |
| 265 | i += entry_size; |
| 266 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 267 | return Handle<TypeFeedbackVector>::cast(array); |
| 268 | } |
| 269 | |
| 270 | |
| 271 | // static |
| 272 | int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, |
| 273 | FeedbackVectorSlot slot) { |
| 274 | return kReservedIndexCount + slot.ToInt(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 275 | } |
| 276 | |
| 277 | |
| 278 | // static |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 279 | Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
| 280 | Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
| 281 | Handle<TypeFeedbackVector> result; |
| 282 | result = Handle<TypeFeedbackVector>::cast( |
| 283 | isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); |
| 284 | return result; |
| 285 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 286 | |
| 287 | |
| 288 | // This logic is copied from |
| 289 | // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 290 | static bool ClearLogic(Isolate* isolate) { |
| 291 | return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 295 | void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, |
| 296 | bool force_clear) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 297 | Isolate* isolate = GetIsolate(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 298 | |
| 299 | if (!force_clear && !ClearLogic(isolate)) return; |
| 300 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 301 | Object* uninitialized_sentinel = |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 302 | TypeFeedbackVector::RawUninitializedSentinel(isolate); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 303 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 304 | TypeFeedbackMetadataIterator iter(metadata()); |
| 305 | while (iter.HasNext()) { |
| 306 | FeedbackVectorSlot slot = iter.Next(); |
| 307 | FeedbackVectorSlotKind kind = iter.kind(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 308 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 309 | Object* obj = Get(slot); |
| 310 | if (obj != uninitialized_sentinel) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 311 | switch (kind) { |
| 312 | case FeedbackVectorSlotKind::CALL_IC: { |
| 313 | CallICNexus nexus(this, slot); |
| 314 | nexus.Clear(shared->code()); |
| 315 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 316 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 317 | case FeedbackVectorSlotKind::LOAD_IC: { |
| 318 | LoadICNexus nexus(this, slot); |
| 319 | nexus.Clear(shared->code()); |
| 320 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 321 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 322 | case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: { |
| 323 | LoadGlobalICNexus nexus(this, slot); |
| 324 | nexus.Clear(shared->code()); |
| 325 | break; |
| 326 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 327 | case FeedbackVectorSlotKind::KEYED_LOAD_IC: { |
| 328 | KeyedLoadICNexus nexus(this, slot); |
| 329 | nexus.Clear(shared->code()); |
| 330 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 331 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 332 | case FeedbackVectorSlotKind::STORE_IC: { |
| 333 | StoreICNexus nexus(this, slot); |
| 334 | nexus.Clear(shared->code()); |
| 335 | break; |
| 336 | } |
| 337 | case FeedbackVectorSlotKind::KEYED_STORE_IC: { |
| 338 | KeyedStoreICNexus nexus(this, slot); |
| 339 | nexus.Clear(shared->code()); |
| 340 | break; |
| 341 | } |
| 342 | case FeedbackVectorSlotKind::GENERAL: { |
| 343 | if (obj->IsHeapObject()) { |
| 344 | InstanceType instance_type = |
| 345 | HeapObject::cast(obj)->map()->instance_type(); |
| 346 | // AllocationSites are exempt from clearing. They don't store Maps |
| 347 | // or Code pointers which can cause memory leaks if not cleared |
| 348 | // regularly. |
| 349 | if (instance_type != ALLOCATION_SITE_TYPE) { |
| 350 | Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); |
| 351 | } |
| 352 | } |
| 353 | break; |
| 354 | } |
| 355 | case FeedbackVectorSlotKind::INVALID: |
| 356 | case FeedbackVectorSlotKind::KINDS_NUMBER: |
| 357 | UNREACHABLE(); |
| 358 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 359 | } |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 365 | // static |
| 366 | void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) { |
| 367 | SharedFunctionInfo::Iterator iterator(isolate); |
| 368 | SharedFunctionInfo* shared; |
| 369 | while ((shared = iterator.Next())) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 370 | if (!shared->OptimizedCodeMapIsCleared()) { |
| 371 | FixedArray* optimized_code_map = shared->optimized_code_map(); |
| 372 | int length = optimized_code_map->length(); |
| 373 | for (int i = SharedFunctionInfo::kEntriesStart; i < length; |
| 374 | i += SharedFunctionInfo::kEntryLength) { |
| 375 | Object* lits = |
| 376 | optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset); |
| 377 | TypeFeedbackVector* vector = nullptr; |
| 378 | if (lits->IsWeakCell()) { |
| 379 | WeakCell* cell = WeakCell::cast(lits); |
| 380 | if (cell->value()->IsLiteralsArray()) { |
| 381 | vector = LiteralsArray::cast(cell->value())->feedback_vector(); |
| 382 | } |
| 383 | } else { |
| 384 | DCHECK(lits->IsLiteralsArray()); |
| 385 | vector = LiteralsArray::cast(lits)->feedback_vector(); |
| 386 | } |
| 387 | if (vector != nullptr) { |
| 388 | vector->ClearKeyedStoreICs(shared); |
| 389 | } |
| 390 | } |
| 391 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 392 | } |
| 393 | } |
| 394 | |
| 395 | |
| 396 | void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) { |
| 397 | Isolate* isolate = GetIsolate(); |
| 398 | |
| 399 | Code* host = shared->code(); |
| 400 | Object* uninitialized_sentinel = |
| 401 | TypeFeedbackVector::RawUninitializedSentinel(isolate); |
| 402 | |
| 403 | TypeFeedbackMetadataIterator iter(metadata()); |
| 404 | while (iter.HasNext()) { |
| 405 | FeedbackVectorSlot slot = iter.Next(); |
| 406 | FeedbackVectorSlotKind kind = iter.kind(); |
| 407 | if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue; |
| 408 | Object* obj = Get(slot); |
| 409 | if (obj != uninitialized_sentinel) { |
| 410 | KeyedStoreICNexus nexus(this, slot); |
| 411 | nexus.Clear(host); |
| 412 | } |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | |
| 417 | // static |
| 418 | Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) { |
| 419 | return isolate->factory()->dummy_vector(); |
| 420 | } |
| 421 | |
| 422 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 423 | Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
| 424 | Isolate* isolate = GetIsolate(); |
| 425 | Handle<Object> feedback = handle(GetFeedback(), isolate); |
| 426 | if (!feedback->IsFixedArray() || |
| 427 | FixedArray::cast(*feedback)->length() != length) { |
| 428 | Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
| 429 | SetFeedback(*array); |
| 430 | return array; |
| 431 | } |
| 432 | return Handle<FixedArray>::cast(feedback); |
| 433 | } |
| 434 | |
| 435 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 436 | Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 437 | Isolate* isolate = GetIsolate(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 438 | Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate); |
| 439 | if (!feedback_extra->IsFixedArray() || |
| 440 | FixedArray::cast(*feedback_extra)->length() != length) { |
| 441 | Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
| 442 | SetFeedbackExtra(*array); |
| 443 | return array; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 444 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 445 | return Handle<FixedArray>::cast(feedback_extra); |
| 446 | } |
| 447 | |
| 448 | |
| 449 | void FeedbackNexus::InstallHandlers(Handle<FixedArray> array, |
| 450 | MapHandleList* maps, |
| 451 | CodeHandleList* handlers) { |
| 452 | int receiver_count = maps->length(); |
| 453 | for (int current = 0; current < receiver_count; ++current) { |
| 454 | Handle<Map> map = maps->at(current); |
| 455 | Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 456 | array->set(current * 2, *cell); |
| 457 | array->set(current * 2 + 1, *handlers->at(current)); |
| 458 | } |
| 459 | } |
| 460 | |
| 461 | |
| 462 | void FeedbackNexus::ConfigureUninitialized() { |
| 463 | SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 464 | SKIP_WRITE_BARRIER); |
| 465 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 466 | SKIP_WRITE_BARRIER); |
| 467 | } |
| 468 | |
| 469 | |
| 470 | void FeedbackNexus::ConfigurePremonomorphic() { |
| 471 | SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()), |
| 472 | SKIP_WRITE_BARRIER); |
| 473 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 474 | SKIP_WRITE_BARRIER); |
| 475 | } |
| 476 | |
| 477 | |
| 478 | void FeedbackNexus::ConfigureMegamorphic() { |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 479 | // Keyed ICs must use ConfigureMegamorphicKeyed. |
| 480 | DCHECK_NE(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector()->GetKind(slot())); |
| 481 | DCHECK_NE(FeedbackVectorSlotKind::KEYED_STORE_IC, vector()->GetKind(slot())); |
| 482 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 483 | Isolate* isolate = GetIsolate(); |
| 484 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), |
| 485 | SKIP_WRITE_BARRIER); |
| 486 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 487 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 488 | } |
| 489 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 490 | void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) { |
| 491 | Isolate* isolate = GetIsolate(); |
| 492 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), |
| 493 | SKIP_WRITE_BARRIER); |
| 494 | SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)), |
| 495 | SKIP_WRITE_BARRIER); |
| 496 | } |
| 497 | |
| 498 | void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) { |
| 499 | Isolate* isolate = GetIsolate(); |
| 500 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), |
| 501 | SKIP_WRITE_BARRIER); |
| 502 | SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)), |
| 503 | SKIP_WRITE_BARRIER); |
| 504 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 505 | |
| 506 | InlineCacheState LoadICNexus::StateFromFeedback() const { |
| 507 | Isolate* isolate = GetIsolate(); |
| 508 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 509 | |
| 510 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 511 | return UNINITIALIZED; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 512 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 513 | return MEGAMORPHIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 514 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 515 | return PREMONOMORPHIC; |
| 516 | } else if (feedback->IsFixedArray()) { |
| 517 | // Determine state purely by our structure, don't check if the maps are |
| 518 | // cleared. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 519 | return POLYMORPHIC; |
| 520 | } else if (feedback->IsWeakCell()) { |
| 521 | // Don't check if the map is cleared. |
| 522 | return MONOMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 523 | } |
| 524 | |
| 525 | return UNINITIALIZED; |
| 526 | } |
| 527 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 528 | InlineCacheState LoadGlobalICNexus::StateFromFeedback() const { |
| 529 | Isolate* isolate = GetIsolate(); |
| 530 | Object* feedback = GetFeedback(); |
| 531 | |
| 532 | Object* extra = GetFeedbackExtra(); |
| 533 | if (!WeakCell::cast(feedback)->cleared() || |
| 534 | extra != *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 535 | return MONOMORPHIC; |
| 536 | } |
| 537 | return UNINITIALIZED; |
| 538 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 539 | |
| 540 | InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { |
| 541 | Isolate* isolate = GetIsolate(); |
| 542 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 543 | |
| 544 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 545 | return UNINITIALIZED; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 546 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 547 | return PREMONOMORPHIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 548 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 549 | return MEGAMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 550 | } else if (feedback->IsFixedArray()) { |
| 551 | // Determine state purely by our structure, don't check if the maps are |
| 552 | // cleared. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 553 | return POLYMORPHIC; |
| 554 | } else if (feedback->IsWeakCell()) { |
| 555 | // Don't check if the map is cleared. |
| 556 | return MONOMORPHIC; |
| 557 | } else if (feedback->IsName()) { |
| 558 | Object* extra = GetFeedbackExtra(); |
| 559 | FixedArray* extra_array = FixedArray::cast(extra); |
| 560 | return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
| 561 | } |
| 562 | |
| 563 | return UNINITIALIZED; |
| 564 | } |
| 565 | |
| 566 | |
| 567 | InlineCacheState StoreICNexus::StateFromFeedback() const { |
| 568 | Isolate* isolate = GetIsolate(); |
| 569 | Object* feedback = GetFeedback(); |
| 570 | |
| 571 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 572 | return UNINITIALIZED; |
| 573 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 574 | return MEGAMORPHIC; |
| 575 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 576 | return PREMONOMORPHIC; |
| 577 | } else if (feedback->IsFixedArray()) { |
| 578 | // Determine state purely by our structure, don't check if the maps are |
| 579 | // cleared. |
| 580 | return POLYMORPHIC; |
| 581 | } else if (feedback->IsWeakCell()) { |
| 582 | // Don't check if the map is cleared. |
| 583 | return MONOMORPHIC; |
| 584 | } |
| 585 | |
| 586 | return UNINITIALIZED; |
| 587 | } |
| 588 | |
| 589 | |
| 590 | InlineCacheState KeyedStoreICNexus::StateFromFeedback() const { |
| 591 | Isolate* isolate = GetIsolate(); |
| 592 | Object* feedback = GetFeedback(); |
| 593 | |
| 594 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 595 | return UNINITIALIZED; |
| 596 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 597 | return PREMONOMORPHIC; |
| 598 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 599 | return MEGAMORPHIC; |
| 600 | } else if (feedback->IsFixedArray()) { |
| 601 | // Determine state purely by our structure, don't check if the maps are |
| 602 | // cleared. |
| 603 | return POLYMORPHIC; |
| 604 | } else if (feedback->IsWeakCell()) { |
| 605 | // Don't check if the map is cleared. |
| 606 | return MONOMORPHIC; |
| 607 | } else if (feedback->IsName()) { |
| 608 | Object* extra = GetFeedbackExtra(); |
| 609 | FixedArray* extra_array = FixedArray::cast(extra); |
| 610 | return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 611 | } |
| 612 | |
| 613 | return UNINITIALIZED; |
| 614 | } |
| 615 | |
| 616 | |
| 617 | InlineCacheState CallICNexus::StateFromFeedback() const { |
| 618 | Isolate* isolate = GetIsolate(); |
| 619 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 620 | DCHECK(GetFeedbackExtra() == |
| 621 | *TypeFeedbackVector::UninitializedSentinel(isolate) || |
| 622 | GetFeedbackExtra()->IsSmi()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 623 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 624 | if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 625 | return GENERIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 626 | } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 627 | return MONOMORPHIC; |
| 628 | } |
| 629 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 630 | CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 631 | return UNINITIALIZED; |
| 632 | } |
| 633 | |
| 634 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 635 | int CallICNexus::ExtractCallCount() { |
| 636 | Object* call_count = GetFeedbackExtra(); |
| 637 | if (call_count->IsSmi()) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 638 | int value = Smi::cast(call_count)->value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 639 | return value; |
| 640 | } |
| 641 | return -1; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 642 | } |
| 643 | |
| 644 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 645 | void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } |
| 646 | |
| 647 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 648 | void CallICNexus::ConfigureMonomorphicArray() { |
| 649 | Object* feedback = GetFeedback(); |
| 650 | if (!feedback->IsAllocationSite()) { |
| 651 | Handle<AllocationSite> new_site = |
| 652 | GetIsolate()->factory()->NewAllocationSite(); |
| 653 | SetFeedback(*new_site); |
| 654 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 655 | SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 656 | } |
| 657 | |
| 658 | |
| 659 | void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 660 | Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function); |
| 661 | SetFeedback(*new_cell); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 662 | SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 663 | } |
| 664 | |
| 665 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 666 | void CallICNexus::ConfigureMegamorphic() { |
| 667 | FeedbackNexus::ConfigureMegamorphic(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 668 | } |
| 669 | |
| 670 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 671 | void CallICNexus::ConfigureMegamorphic(int call_count) { |
| 672 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 673 | SKIP_WRITE_BARRIER); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 674 | SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 675 | } |
| 676 | |
| 677 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 678 | void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 679 | Handle<Code> handler) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 680 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 681 | SetFeedback(*cell); |
| 682 | SetFeedbackExtra(*handler); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 683 | } |
| 684 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 685 | void LoadGlobalICNexus::ConfigureUninitialized() { |
| 686 | Isolate* isolate = GetIsolate(); |
| 687 | SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER); |
| 688 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 689 | SKIP_WRITE_BARRIER); |
| 690 | } |
| 691 | |
| 692 | void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) { |
| 693 | Isolate* isolate = GetIsolate(); |
| 694 | SetFeedback(*isolate->factory()->NewWeakCell(cell)); |
| 695 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 696 | SKIP_WRITE_BARRIER); |
| 697 | } |
| 698 | |
| 699 | void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) { |
| 700 | SetFeedback(GetIsolate()->heap()->empty_weak_cell()); |
| 701 | SetFeedbackExtra(*handler); |
| 702 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 703 | |
| 704 | void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 705 | Handle<Map> receiver_map, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 706 | Handle<Code> handler) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 707 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 708 | if (name.is_null()) { |
| 709 | SetFeedback(*cell); |
| 710 | SetFeedbackExtra(*handler); |
| 711 | } else { |
| 712 | Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
| 713 | SetFeedback(*name); |
| 714 | array->set(0, *cell); |
| 715 | array->set(1, *handler); |
| 716 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 717 | } |
| 718 | |
| 719 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 720 | void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
| 721 | Handle<Code> handler) { |
| 722 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 723 | SetFeedback(*cell); |
| 724 | SetFeedbackExtra(*handler); |
| 725 | } |
| 726 | |
| 727 | |
| 728 | void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name, |
| 729 | Handle<Map> receiver_map, |
| 730 | Handle<Code> handler) { |
| 731 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 732 | if (name.is_null()) { |
| 733 | SetFeedback(*cell); |
| 734 | SetFeedbackExtra(*handler); |
| 735 | } else { |
| 736 | Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
| 737 | SetFeedback(*name); |
| 738 | array->set(0, *cell); |
| 739 | array->set(1, *handler); |
| 740 | } |
| 741 | } |
| 742 | |
| 743 | |
| 744 | void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 745 | CodeHandleList* handlers) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 746 | Isolate* isolate = GetIsolate(); |
| 747 | int receiver_count = maps->length(); |
| 748 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2); |
| 749 | InstallHandlers(array, maps, handlers); |
| 750 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 751 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 752 | } |
| 753 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 754 | void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 755 | MapHandleList* maps, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 756 | CodeHandleList* handlers) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 757 | int receiver_count = maps->length(); |
| 758 | DCHECK(receiver_count > 1); |
| 759 | Handle<FixedArray> array; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 760 | if (name.is_null()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 761 | array = EnsureArrayOfSize(receiver_count * 2); |
| 762 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 763 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 764 | } else { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 765 | array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 766 | SetFeedback(*name); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 767 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 768 | |
| 769 | InstallHandlers(array, maps, handlers); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 770 | } |
| 771 | |
| 772 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 773 | void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 774 | CodeHandleList* handlers) { |
| 775 | Isolate* isolate = GetIsolate(); |
| 776 | int receiver_count = maps->length(); |
| 777 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2); |
| 778 | InstallHandlers(array, maps, handlers); |
| 779 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 780 | SKIP_WRITE_BARRIER); |
| 781 | } |
| 782 | |
| 783 | |
| 784 | void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name, |
| 785 | MapHandleList* maps, |
| 786 | CodeHandleList* handlers) { |
| 787 | int receiver_count = maps->length(); |
| 788 | DCHECK(receiver_count > 1); |
| 789 | Handle<FixedArray> array; |
| 790 | if (name.is_null()) { |
| 791 | array = EnsureArrayOfSize(receiver_count * 2); |
| 792 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 793 | SKIP_WRITE_BARRIER); |
| 794 | } else { |
| 795 | array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 796 | SetFeedback(*name); |
| 797 | } |
| 798 | |
| 799 | InstallHandlers(array, maps, handlers); |
| 800 | } |
| 801 | |
| 802 | |
| 803 | void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 804 | MapHandleList* transitioned_maps, |
| 805 | CodeHandleList* handlers) { |
| 806 | int receiver_count = maps->length(); |
| 807 | DCHECK(receiver_count > 1); |
| 808 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3); |
| 809 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 810 | SKIP_WRITE_BARRIER); |
| 811 | |
| 812 | Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value(); |
| 813 | for (int i = 0; i < receiver_count; ++i) { |
| 814 | Handle<Map> map = maps->at(i); |
| 815 | Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 816 | array->set(i * 3, *cell); |
| 817 | if (!transitioned_maps->at(i).is_null()) { |
| 818 | Handle<Map> transitioned_map = transitioned_maps->at(i); |
| 819 | cell = Map::WeakCellForMap(transitioned_map); |
| 820 | array->set((i * 3) + 1, *cell); |
| 821 | } else { |
| 822 | array->set((i * 3) + 1, *undefined_value); |
| 823 | } |
| 824 | array->set((i * 3) + 2, *handlers->at(i)); |
| 825 | } |
| 826 | } |
| 827 | |
| 828 | |
| 829 | int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 830 | Isolate* isolate = GetIsolate(); |
| 831 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 832 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 833 | if (feedback->IsFixedArray() || is_named_feedback) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 834 | int found = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 835 | if (is_named_feedback) { |
| 836 | feedback = GetFeedbackExtra(); |
| 837 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 838 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 839 | // The array should be of the form |
| 840 | // [map, handler, map, handler, ...] |
| 841 | // or |
| 842 | // [map, map, handler, map, map, handler, ...] |
| 843 | DCHECK(array->length() >= 2); |
| 844 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 845 | for (int i = 0; i < array->length(); i += increment) { |
| 846 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 847 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 848 | if (!cell->cleared()) { |
| 849 | Map* map = Map::cast(cell->value()); |
| 850 | maps->Add(handle(map, isolate)); |
| 851 | found++; |
| 852 | } |
| 853 | } |
| 854 | return found; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 855 | } else if (feedback->IsWeakCell()) { |
| 856 | WeakCell* cell = WeakCell::cast(feedback); |
| 857 | if (!cell->cleared()) { |
| 858 | Map* map = Map::cast(cell->value()); |
| 859 | maps->Add(handle(map, isolate)); |
| 860 | return 1; |
| 861 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 862 | } |
| 863 | |
| 864 | return 0; |
| 865 | } |
| 866 | |
| 867 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 868 | MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 869 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 870 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 871 | if (feedback->IsFixedArray() || is_named_feedback) { |
| 872 | if (is_named_feedback) { |
| 873 | feedback = GetFeedbackExtra(); |
| 874 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 875 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 876 | DCHECK(array->length() >= 2); |
| 877 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 878 | for (int i = 0; i < array->length(); i += increment) { |
| 879 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 880 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 881 | if (!cell->cleared()) { |
| 882 | Map* array_map = Map::cast(cell->value()); |
| 883 | if (array_map == *map) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 884 | Code* code = Code::cast(array->get(i + increment - 1)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 885 | DCHECK(code->kind() == Code::HANDLER); |
| 886 | return handle(code); |
| 887 | } |
| 888 | } |
| 889 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 890 | } else if (feedback->IsWeakCell()) { |
| 891 | WeakCell* cell = WeakCell::cast(feedback); |
| 892 | if (!cell->cleared()) { |
| 893 | Map* cell_map = Map::cast(cell->value()); |
| 894 | if (cell_map == *map) { |
| 895 | Code* code = Code::cast(GetFeedbackExtra()); |
| 896 | DCHECK(code->kind() == Code::HANDLER); |
| 897 | return handle(code); |
| 898 | } |
| 899 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 900 | } |
| 901 | |
| 902 | return MaybeHandle<Code>(); |
| 903 | } |
| 904 | |
| 905 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 906 | bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 907 | Object* feedback = GetFeedback(); |
| 908 | int count = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 909 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 910 | if (feedback->IsFixedArray() || is_named_feedback) { |
| 911 | if (is_named_feedback) { |
| 912 | feedback = GetFeedbackExtra(); |
| 913 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 914 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 915 | // The array should be of the form |
| 916 | // [map, handler, map, handler, ...] |
| 917 | // or |
| 918 | // [map, map, handler, map, map, handler, ...] |
| 919 | // Be sure to skip handlers whose maps have been cleared. |
| 920 | DCHECK(array->length() >= 2); |
| 921 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 922 | for (int i = 0; i < array->length(); i += increment) { |
| 923 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 924 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 925 | if (!cell->cleared()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 926 | Code* code = Code::cast(array->get(i + increment - 1)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 927 | DCHECK(code->kind() == Code::HANDLER); |
| 928 | code_list->Add(handle(code)); |
| 929 | count++; |
| 930 | } |
| 931 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 932 | } else if (feedback->IsWeakCell()) { |
| 933 | WeakCell* cell = WeakCell::cast(feedback); |
| 934 | if (!cell->cleared()) { |
| 935 | Code* code = Code::cast(GetFeedbackExtra()); |
| 936 | DCHECK(code->kind() == Code::HANDLER); |
| 937 | code_list->Add(handle(code)); |
| 938 | count++; |
| 939 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 940 | } |
| 941 | return count == length; |
| 942 | } |
| 943 | |
| 944 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 945 | void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } |
| 946 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 947 | void LoadGlobalICNexus::Clear(Code* host) { |
| 948 | LoadGlobalIC::Clear(GetIsolate(), host, this); |
| 949 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 950 | |
| 951 | void KeyedLoadICNexus::Clear(Code* host) { |
| 952 | KeyedLoadIC::Clear(GetIsolate(), host, this); |
| 953 | } |
| 954 | |
| 955 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 956 | Name* KeyedLoadICNexus::FindFirstName() const { |
| 957 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 958 | if (IsPropertyNameFeedback(feedback)) { |
| 959 | return Name::cast(feedback); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 960 | } |
| 961 | return NULL; |
| 962 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 963 | |
| 964 | |
| 965 | Name* KeyedStoreICNexus::FindFirstName() const { |
| 966 | Object* feedback = GetFeedback(); |
| 967 | if (IsPropertyNameFeedback(feedback)) { |
| 968 | return Name::cast(feedback); |
| 969 | } |
| 970 | return NULL; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 971 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 972 | |
| 973 | |
| 974 | void StoreICNexus::Clear(Code* host) { |
| 975 | StoreIC::Clear(GetIsolate(), host, this); |
| 976 | } |
| 977 | |
| 978 | |
| 979 | void KeyedStoreICNexus::Clear(Code* host) { |
| 980 | KeyedStoreIC::Clear(GetIsolate(), host, this); |
| 981 | } |
| 982 | |
| 983 | |
| 984 | KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { |
| 985 | KeyedAccessStoreMode mode = STANDARD_STORE; |
| 986 | MapHandleList maps; |
| 987 | CodeHandleList handlers; |
| 988 | |
| 989 | if (GetKeyType() == PROPERTY) return mode; |
| 990 | |
| 991 | ExtractMaps(&maps); |
| 992 | FindHandlers(&handlers, maps.length()); |
| 993 | for (int i = 0; i < handlers.length(); i++) { |
| 994 | // The first handler that isn't the slow handler will have the bits we need. |
| 995 | Handle<Code> handler = handlers.at(i); |
| 996 | CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key()); |
| 997 | uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key()); |
| 998 | CHECK(major_key == CodeStub::KeyedStoreSloppyArguments || |
| 999 | major_key == CodeStub::StoreFastElement || |
| 1000 | major_key == CodeStub::StoreElement || |
| 1001 | major_key == CodeStub::ElementsTransitionAndStore || |
| 1002 | major_key == CodeStub::NoCache); |
| 1003 | if (major_key != CodeStub::NoCache) { |
| 1004 | mode = CommonStoreModeBits::decode(minor_key); |
| 1005 | break; |
| 1006 | } |
| 1007 | } |
| 1008 | |
| 1009 | return mode; |
| 1010 | } |
| 1011 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1012 | IcCheckType KeyedLoadICNexus::GetKeyType() const { |
| 1013 | Object* feedback = GetFeedback(); |
| 1014 | if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) { |
| 1015 | return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value()); |
| 1016 | } |
| 1017 | return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT; |
| 1018 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1019 | |
| 1020 | IcCheckType KeyedStoreICNexus::GetKeyType() const { |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1021 | Object* feedback = GetFeedback(); |
| 1022 | if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) { |
| 1023 | return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value()); |
| 1024 | } |
| 1025 | return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1026 | } |
| 1027 | } // namespace internal |
| 1028 | } // namespace v8 |