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) { |
| 18 | return feedback->IsString() || |
| 19 | (feedback->IsSymbol() && !Symbol::cast(feedback)->is_private()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 20 | } |
| 21 | |
| 22 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 23 | std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) { |
| 24 | return os << TypeFeedbackMetadata::Kind2String(kind); |
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 | FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( |
| 29 | FeedbackVectorSlot slot) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 30 | int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 31 | int data = Smi::cast(get(index))->value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 32 | return VectorICComputer::decode(data, slot.ToInt()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 36 | void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, |
| 37 | FeedbackVectorSlotKind kind) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 38 | int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
| 39 | int data = Smi::cast(get(index))->value(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 40 | int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 41 | set(index, Smi::FromInt(new_data)); |
| 42 | } |
| 43 | |
| 44 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 45 | template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
| 46 | Isolate* isolate, const StaticFeedbackVectorSpec* spec); |
| 47 | template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
| 48 | Isolate* isolate, const FeedbackVectorSpec* spec); |
| 49 | |
| 50 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 51 | // static |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 52 | template <typename Spec> |
| 53 | Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate, |
| 54 | const Spec* spec) { |
| 55 | const int slot_count = spec->slots(); |
| 56 | const int slot_kinds_length = VectorICComputer::word_count(slot_count); |
| 57 | const int length = slot_kinds_length + kReservedIndexCount; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 58 | if (length == kReservedIndexCount) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 59 | return Handle<TypeFeedbackMetadata>::cast( |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 60 | isolate->factory()->empty_fixed_array()); |
| 61 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 62 | #ifdef DEBUG |
| 63 | for (int i = 0; i < slot_count;) { |
| 64 | FeedbackVectorSlotKind kind = spec->GetKind(i); |
| 65 | int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
| 66 | for (int j = 1; j < entry_size; j++) { |
| 67 | FeedbackVectorSlotKind kind = spec->GetKind(i + j); |
| 68 | DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind); |
| 69 | } |
| 70 | i += entry_size; |
| 71 | } |
| 72 | #endif |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 73 | |
| 74 | Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 75 | array->set(kSlotsCountIndex, Smi::FromInt(slot_count)); |
| 76 | // Fill the bit-vector part with zeros. |
| 77 | for (int i = 0; i < slot_kinds_length; i++) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 78 | array->set(kReservedIndexCount + i, Smi::FromInt(0)); |
| 79 | } |
| 80 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 81 | Handle<TypeFeedbackMetadata> metadata = |
| 82 | Handle<TypeFeedbackMetadata>::cast(array); |
| 83 | for (int i = 0; i < slot_count; i++) { |
| 84 | metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i)); |
| 85 | } |
| 86 | return metadata; |
| 87 | } |
| 88 | |
| 89 | |
| 90 | bool TypeFeedbackMetadata::SpecDiffersFrom( |
| 91 | const FeedbackVectorSpec* other_spec) const { |
| 92 | if (other_spec->slots() != slot_count()) { |
| 93 | return true; |
| 94 | } |
| 95 | |
| 96 | int slots = slot_count(); |
| 97 | for (int i = 0; i < slots; i++) { |
| 98 | if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) { |
| 99 | return true; |
| 100 | } |
| 101 | } |
| 102 | return false; |
| 103 | } |
| 104 | |
| 105 | |
| 106 | const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { |
| 107 | switch (kind) { |
| 108 | case FeedbackVectorSlotKind::INVALID: |
| 109 | return "INVALID"; |
| 110 | case FeedbackVectorSlotKind::CALL_IC: |
| 111 | return "CALL_IC"; |
| 112 | case FeedbackVectorSlotKind::LOAD_IC: |
| 113 | return "LOAD_IC"; |
| 114 | case FeedbackVectorSlotKind::KEYED_LOAD_IC: |
| 115 | return "KEYED_LOAD_IC"; |
| 116 | case FeedbackVectorSlotKind::STORE_IC: |
| 117 | return "STORE_IC"; |
| 118 | case FeedbackVectorSlotKind::KEYED_STORE_IC: |
| 119 | return "KEYED_STORE_IC"; |
| 120 | case FeedbackVectorSlotKind::GENERAL: |
| 121 | return "STUB"; |
| 122 | case FeedbackVectorSlotKind::KINDS_NUMBER: |
| 123 | break; |
| 124 | } |
| 125 | UNREACHABLE(); |
| 126 | return "?"; |
| 127 | } |
| 128 | |
| 129 | |
| 130 | // static |
| 131 | Handle<TypeFeedbackVector> TypeFeedbackVector::New( |
| 132 | Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) { |
| 133 | Factory* factory = isolate->factory(); |
| 134 | |
| 135 | const int slot_count = metadata->slot_count(); |
| 136 | const int length = slot_count + kReservedIndexCount; |
| 137 | if (length == kReservedIndexCount) { |
| 138 | return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array()); |
| 139 | } |
| 140 | |
| 141 | Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); |
| 142 | array->set(kMetadataIndex, *metadata); |
| 143 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 144 | // Ensure we can skip the write barrier |
| 145 | Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 146 | DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel); |
| 147 | for (int i = kReservedIndexCount; i < length; i++) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 148 | array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
| 149 | } |
| 150 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 151 | return Handle<TypeFeedbackVector>::cast(array); |
| 152 | } |
| 153 | |
| 154 | |
| 155 | // static |
| 156 | int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, |
| 157 | FeedbackVectorSlot slot) { |
| 158 | return kReservedIndexCount + slot.ToInt(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | |
| 162 | // static |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 163 | Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
| 164 | Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
| 165 | Handle<TypeFeedbackVector> result; |
| 166 | result = Handle<TypeFeedbackVector>::cast( |
| 167 | isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); |
| 168 | return result; |
| 169 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 170 | |
| 171 | |
| 172 | // This logic is copied from |
| 173 | // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 174 | static bool ClearLogic(Isolate* isolate) { |
| 175 | return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 179 | void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, |
| 180 | bool force_clear) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 181 | Isolate* isolate = GetIsolate(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 182 | |
| 183 | if (!force_clear && !ClearLogic(isolate)) return; |
| 184 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 185 | Object* uninitialized_sentinel = |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 186 | TypeFeedbackVector::RawUninitializedSentinel(isolate); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 187 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 188 | TypeFeedbackMetadataIterator iter(metadata()); |
| 189 | while (iter.HasNext()) { |
| 190 | FeedbackVectorSlot slot = iter.Next(); |
| 191 | FeedbackVectorSlotKind kind = iter.kind(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 192 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 193 | Object* obj = Get(slot); |
| 194 | if (obj != uninitialized_sentinel) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 195 | switch (kind) { |
| 196 | case FeedbackVectorSlotKind::CALL_IC: { |
| 197 | CallICNexus nexus(this, slot); |
| 198 | nexus.Clear(shared->code()); |
| 199 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 200 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 201 | case FeedbackVectorSlotKind::LOAD_IC: { |
| 202 | LoadICNexus nexus(this, slot); |
| 203 | nexus.Clear(shared->code()); |
| 204 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 205 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 206 | case FeedbackVectorSlotKind::KEYED_LOAD_IC: { |
| 207 | KeyedLoadICNexus nexus(this, slot); |
| 208 | nexus.Clear(shared->code()); |
| 209 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 210 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 211 | case FeedbackVectorSlotKind::STORE_IC: { |
| 212 | StoreICNexus nexus(this, slot); |
| 213 | nexus.Clear(shared->code()); |
| 214 | break; |
| 215 | } |
| 216 | case FeedbackVectorSlotKind::KEYED_STORE_IC: { |
| 217 | KeyedStoreICNexus nexus(this, slot); |
| 218 | nexus.Clear(shared->code()); |
| 219 | break; |
| 220 | } |
| 221 | case FeedbackVectorSlotKind::GENERAL: { |
| 222 | if (obj->IsHeapObject()) { |
| 223 | InstanceType instance_type = |
| 224 | HeapObject::cast(obj)->map()->instance_type(); |
| 225 | // AllocationSites are exempt from clearing. They don't store Maps |
| 226 | // or Code pointers which can cause memory leaks if not cleared |
| 227 | // regularly. |
| 228 | if (instance_type != ALLOCATION_SITE_TYPE) { |
| 229 | Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); |
| 230 | } |
| 231 | } |
| 232 | break; |
| 233 | } |
| 234 | case FeedbackVectorSlotKind::INVALID: |
| 235 | case FeedbackVectorSlotKind::KINDS_NUMBER: |
| 236 | UNREACHABLE(); |
| 237 | break; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 238 | } |
| 239 | } |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 244 | // static |
| 245 | void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) { |
| 246 | SharedFunctionInfo::Iterator iterator(isolate); |
| 247 | SharedFunctionInfo* shared; |
| 248 | while ((shared = iterator.Next())) { |
| 249 | TypeFeedbackVector* vector = shared->feedback_vector(); |
| 250 | vector->ClearKeyedStoreICs(shared); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | |
| 255 | void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) { |
| 256 | Isolate* isolate = GetIsolate(); |
| 257 | |
| 258 | Code* host = shared->code(); |
| 259 | Object* uninitialized_sentinel = |
| 260 | TypeFeedbackVector::RawUninitializedSentinel(isolate); |
| 261 | |
| 262 | TypeFeedbackMetadataIterator iter(metadata()); |
| 263 | while (iter.HasNext()) { |
| 264 | FeedbackVectorSlot slot = iter.Next(); |
| 265 | FeedbackVectorSlotKind kind = iter.kind(); |
| 266 | if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue; |
| 267 | Object* obj = Get(slot); |
| 268 | if (obj != uninitialized_sentinel) { |
| 269 | KeyedStoreICNexus nexus(this, slot); |
| 270 | nexus.Clear(host); |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | |
| 276 | // static |
| 277 | Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) { |
| 278 | return isolate->factory()->dummy_vector(); |
| 279 | } |
| 280 | |
| 281 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 282 | Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
| 283 | Isolate* isolate = GetIsolate(); |
| 284 | Handle<Object> feedback = handle(GetFeedback(), isolate); |
| 285 | if (!feedback->IsFixedArray() || |
| 286 | FixedArray::cast(*feedback)->length() != length) { |
| 287 | Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
| 288 | SetFeedback(*array); |
| 289 | return array; |
| 290 | } |
| 291 | return Handle<FixedArray>::cast(feedback); |
| 292 | } |
| 293 | |
| 294 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 295 | Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 296 | Isolate* isolate = GetIsolate(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 297 | Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate); |
| 298 | if (!feedback_extra->IsFixedArray() || |
| 299 | FixedArray::cast(*feedback_extra)->length() != length) { |
| 300 | Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
| 301 | SetFeedbackExtra(*array); |
| 302 | return array; |
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 | return Handle<FixedArray>::cast(feedback_extra); |
| 305 | } |
| 306 | |
| 307 | |
| 308 | void FeedbackNexus::InstallHandlers(Handle<FixedArray> array, |
| 309 | MapHandleList* maps, |
| 310 | CodeHandleList* handlers) { |
| 311 | int receiver_count = maps->length(); |
| 312 | for (int current = 0; current < receiver_count; ++current) { |
| 313 | Handle<Map> map = maps->at(current); |
| 314 | Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 315 | array->set(current * 2, *cell); |
| 316 | array->set(current * 2 + 1, *handlers->at(current)); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | |
| 321 | void FeedbackNexus::ConfigureUninitialized() { |
| 322 | SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 323 | SKIP_WRITE_BARRIER); |
| 324 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 325 | SKIP_WRITE_BARRIER); |
| 326 | } |
| 327 | |
| 328 | |
| 329 | void FeedbackNexus::ConfigurePremonomorphic() { |
| 330 | SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()), |
| 331 | SKIP_WRITE_BARRIER); |
| 332 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 333 | SKIP_WRITE_BARRIER); |
| 334 | } |
| 335 | |
| 336 | |
| 337 | void FeedbackNexus::ConfigureMegamorphic() { |
| 338 | Isolate* isolate = GetIsolate(); |
| 339 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate), |
| 340 | SKIP_WRITE_BARRIER); |
| 341 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 342 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 343 | } |
| 344 | |
| 345 | |
| 346 | InlineCacheState LoadICNexus::StateFromFeedback() const { |
| 347 | Isolate* isolate = GetIsolate(); |
| 348 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 349 | |
| 350 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 351 | return UNINITIALIZED; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 352 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 353 | return MEGAMORPHIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 354 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 355 | return PREMONOMORPHIC; |
| 356 | } else if (feedback->IsFixedArray()) { |
| 357 | // Determine state purely by our structure, don't check if the maps are |
| 358 | // cleared. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 359 | return POLYMORPHIC; |
| 360 | } else if (feedback->IsWeakCell()) { |
| 361 | // Don't check if the map is cleared. |
| 362 | return MONOMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | return UNINITIALIZED; |
| 366 | } |
| 367 | |
| 368 | |
| 369 | InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { |
| 370 | Isolate* isolate = GetIsolate(); |
| 371 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 372 | |
| 373 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 374 | return UNINITIALIZED; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 375 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 376 | return PREMONOMORPHIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 377 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 378 | return MEGAMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 379 | } else if (feedback->IsFixedArray()) { |
| 380 | // Determine state purely by our structure, don't check if the maps are |
| 381 | // cleared. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 382 | return POLYMORPHIC; |
| 383 | } else if (feedback->IsWeakCell()) { |
| 384 | // Don't check if the map is cleared. |
| 385 | return MONOMORPHIC; |
| 386 | } else if (feedback->IsName()) { |
| 387 | Object* extra = GetFeedbackExtra(); |
| 388 | FixedArray* extra_array = FixedArray::cast(extra); |
| 389 | return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
| 390 | } |
| 391 | |
| 392 | return UNINITIALIZED; |
| 393 | } |
| 394 | |
| 395 | |
| 396 | InlineCacheState StoreICNexus::StateFromFeedback() const { |
| 397 | Isolate* isolate = GetIsolate(); |
| 398 | Object* feedback = GetFeedback(); |
| 399 | |
| 400 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 401 | return UNINITIALIZED; |
| 402 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 403 | return MEGAMORPHIC; |
| 404 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 405 | return PREMONOMORPHIC; |
| 406 | } else if (feedback->IsFixedArray()) { |
| 407 | // Determine state purely by our structure, don't check if the maps are |
| 408 | // cleared. |
| 409 | return POLYMORPHIC; |
| 410 | } else if (feedback->IsWeakCell()) { |
| 411 | // Don't check if the map is cleared. |
| 412 | return MONOMORPHIC; |
| 413 | } |
| 414 | |
| 415 | return UNINITIALIZED; |
| 416 | } |
| 417 | |
| 418 | |
| 419 | InlineCacheState KeyedStoreICNexus::StateFromFeedback() const { |
| 420 | Isolate* isolate = GetIsolate(); |
| 421 | Object* feedback = GetFeedback(); |
| 422 | |
| 423 | if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) { |
| 424 | return UNINITIALIZED; |
| 425 | } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) { |
| 426 | return PREMONOMORPHIC; |
| 427 | } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
| 428 | return MEGAMORPHIC; |
| 429 | } else if (feedback->IsFixedArray()) { |
| 430 | // Determine state purely by our structure, don't check if the maps are |
| 431 | // cleared. |
| 432 | return POLYMORPHIC; |
| 433 | } else if (feedback->IsWeakCell()) { |
| 434 | // Don't check if the map is cleared. |
| 435 | return MONOMORPHIC; |
| 436 | } else if (feedback->IsName()) { |
| 437 | Object* extra = GetFeedbackExtra(); |
| 438 | FixedArray* extra_array = FixedArray::cast(extra); |
| 439 | return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | return UNINITIALIZED; |
| 443 | } |
| 444 | |
| 445 | |
| 446 | InlineCacheState CallICNexus::StateFromFeedback() const { |
| 447 | Isolate* isolate = GetIsolate(); |
| 448 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 449 | DCHECK(GetFeedbackExtra() == |
| 450 | *TypeFeedbackVector::UninitializedSentinel(isolate) || |
| 451 | GetFeedbackExtra()->IsSmi()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 452 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 453 | if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 454 | return GENERIC; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 455 | } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 456 | return MONOMORPHIC; |
| 457 | } |
| 458 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 459 | CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 460 | return UNINITIALIZED; |
| 461 | } |
| 462 | |
| 463 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 464 | int CallICNexus::ExtractCallCount() { |
| 465 | Object* call_count = GetFeedbackExtra(); |
| 466 | if (call_count->IsSmi()) { |
| 467 | int value = Smi::cast(call_count)->value() / 2; |
| 468 | return value; |
| 469 | } |
| 470 | return -1; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 471 | } |
| 472 | |
| 473 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 474 | void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } |
| 475 | |
| 476 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 477 | void CallICNexus::ConfigureMonomorphicArray() { |
| 478 | Object* feedback = GetFeedback(); |
| 479 | if (!feedback->IsAllocationSite()) { |
| 480 | Handle<AllocationSite> new_site = |
| 481 | GetIsolate()->factory()->NewAllocationSite(); |
| 482 | SetFeedback(*new_site); |
| 483 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 484 | SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 485 | } |
| 486 | |
| 487 | |
| 488 | void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 489 | Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function); |
| 490 | SetFeedback(*new_cell); |
| 491 | SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 495 | void CallICNexus::ConfigureMegamorphic() { |
| 496 | FeedbackNexus::ConfigureMegamorphic(); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 497 | } |
| 498 | |
| 499 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 500 | void CallICNexus::ConfigureMegamorphic(int call_count) { |
| 501 | SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 502 | SKIP_WRITE_BARRIER); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 503 | SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement), |
| 504 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 505 | } |
| 506 | |
| 507 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 508 | void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 509 | Handle<Code> handler) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 510 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 511 | SetFeedback(*cell); |
| 512 | SetFeedbackExtra(*handler); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 513 | } |
| 514 | |
| 515 | |
| 516 | void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 517 | Handle<Map> receiver_map, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 518 | Handle<Code> handler) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 519 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 520 | if (name.is_null()) { |
| 521 | SetFeedback(*cell); |
| 522 | SetFeedbackExtra(*handler); |
| 523 | } else { |
| 524 | Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
| 525 | SetFeedback(*name); |
| 526 | array->set(0, *cell); |
| 527 | array->set(1, *handler); |
| 528 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 529 | } |
| 530 | |
| 531 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 532 | void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map, |
| 533 | Handle<Code> handler) { |
| 534 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 535 | SetFeedback(*cell); |
| 536 | SetFeedbackExtra(*handler); |
| 537 | } |
| 538 | |
| 539 | |
| 540 | void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name, |
| 541 | Handle<Map> receiver_map, |
| 542 | Handle<Code> handler) { |
| 543 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 544 | if (name.is_null()) { |
| 545 | SetFeedback(*cell); |
| 546 | SetFeedbackExtra(*handler); |
| 547 | } else { |
| 548 | Handle<FixedArray> array = EnsureExtraArrayOfSize(2); |
| 549 | SetFeedback(*name); |
| 550 | array->set(0, *cell); |
| 551 | array->set(1, *handler); |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | |
| 556 | void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 557 | CodeHandleList* handlers) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 558 | Isolate* isolate = GetIsolate(); |
| 559 | int receiver_count = maps->length(); |
| 560 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2); |
| 561 | InstallHandlers(array, maps, handlers); |
| 562 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 563 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 564 | } |
| 565 | |
| 566 | |
| 567 | void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 568 | MapHandleList* maps, |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 569 | CodeHandleList* handlers) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 570 | int receiver_count = maps->length(); |
| 571 | DCHECK(receiver_count > 1); |
| 572 | Handle<FixedArray> array; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 573 | if (name.is_null()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 574 | array = EnsureArrayOfSize(receiver_count * 2); |
| 575 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 576 | SKIP_WRITE_BARRIER); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 577 | } else { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 578 | array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 579 | SetFeedback(*name); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 580 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 581 | |
| 582 | InstallHandlers(array, maps, handlers); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 583 | } |
| 584 | |
| 585 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 586 | void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 587 | CodeHandleList* handlers) { |
| 588 | Isolate* isolate = GetIsolate(); |
| 589 | int receiver_count = maps->length(); |
| 590 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2); |
| 591 | InstallHandlers(array, maps, handlers); |
| 592 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate), |
| 593 | SKIP_WRITE_BARRIER); |
| 594 | } |
| 595 | |
| 596 | |
| 597 | void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name, |
| 598 | MapHandleList* maps, |
| 599 | CodeHandleList* handlers) { |
| 600 | int receiver_count = maps->length(); |
| 601 | DCHECK(receiver_count > 1); |
| 602 | Handle<FixedArray> array; |
| 603 | if (name.is_null()) { |
| 604 | array = EnsureArrayOfSize(receiver_count * 2); |
| 605 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 606 | SKIP_WRITE_BARRIER); |
| 607 | } else { |
| 608 | array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 609 | SetFeedback(*name); |
| 610 | } |
| 611 | |
| 612 | InstallHandlers(array, maps, handlers); |
| 613 | } |
| 614 | |
| 615 | |
| 616 | void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 617 | MapHandleList* transitioned_maps, |
| 618 | CodeHandleList* handlers) { |
| 619 | int receiver_count = maps->length(); |
| 620 | DCHECK(receiver_count > 1); |
| 621 | Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3); |
| 622 | SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 623 | SKIP_WRITE_BARRIER); |
| 624 | |
| 625 | Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value(); |
| 626 | for (int i = 0; i < receiver_count; ++i) { |
| 627 | Handle<Map> map = maps->at(i); |
| 628 | Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 629 | array->set(i * 3, *cell); |
| 630 | if (!transitioned_maps->at(i).is_null()) { |
| 631 | Handle<Map> transitioned_map = transitioned_maps->at(i); |
| 632 | cell = Map::WeakCellForMap(transitioned_map); |
| 633 | array->set((i * 3) + 1, *cell); |
| 634 | } else { |
| 635 | array->set((i * 3) + 1, *undefined_value); |
| 636 | } |
| 637 | array->set((i * 3) + 2, *handlers->at(i)); |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | |
| 642 | int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 643 | Isolate* isolate = GetIsolate(); |
| 644 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 645 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 646 | if (feedback->IsFixedArray() || is_named_feedback) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 647 | int found = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 648 | if (is_named_feedback) { |
| 649 | feedback = GetFeedbackExtra(); |
| 650 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 651 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 652 | // The array should be of the form |
| 653 | // [map, handler, map, handler, ...] |
| 654 | // or |
| 655 | // [map, map, handler, map, map, handler, ...] |
| 656 | DCHECK(array->length() >= 2); |
| 657 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 658 | for (int i = 0; i < array->length(); i += increment) { |
| 659 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 660 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 661 | if (!cell->cleared()) { |
| 662 | Map* map = Map::cast(cell->value()); |
| 663 | maps->Add(handle(map, isolate)); |
| 664 | found++; |
| 665 | } |
| 666 | } |
| 667 | return found; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 668 | } else if (feedback->IsWeakCell()) { |
| 669 | WeakCell* cell = WeakCell::cast(feedback); |
| 670 | if (!cell->cleared()) { |
| 671 | Map* map = Map::cast(cell->value()); |
| 672 | maps->Add(handle(map, isolate)); |
| 673 | return 1; |
| 674 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 675 | } |
| 676 | |
| 677 | return 0; |
| 678 | } |
| 679 | |
| 680 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 681 | MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 682 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 683 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 684 | if (feedback->IsFixedArray() || is_named_feedback) { |
| 685 | if (is_named_feedback) { |
| 686 | feedback = GetFeedbackExtra(); |
| 687 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 688 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 689 | DCHECK(array->length() >= 2); |
| 690 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 691 | for (int i = 0; i < array->length(); i += increment) { |
| 692 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 693 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 694 | if (!cell->cleared()) { |
| 695 | Map* array_map = Map::cast(cell->value()); |
| 696 | if (array_map == *map) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 697 | Code* code = Code::cast(array->get(i + increment - 1)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 698 | DCHECK(code->kind() == Code::HANDLER); |
| 699 | return handle(code); |
| 700 | } |
| 701 | } |
| 702 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 703 | } else if (feedback->IsWeakCell()) { |
| 704 | WeakCell* cell = WeakCell::cast(feedback); |
| 705 | if (!cell->cleared()) { |
| 706 | Map* cell_map = Map::cast(cell->value()); |
| 707 | if (cell_map == *map) { |
| 708 | Code* code = Code::cast(GetFeedbackExtra()); |
| 709 | DCHECK(code->kind() == Code::HANDLER); |
| 710 | return handle(code); |
| 711 | } |
| 712 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 713 | } |
| 714 | |
| 715 | return MaybeHandle<Code>(); |
| 716 | } |
| 717 | |
| 718 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 719 | bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 720 | Object* feedback = GetFeedback(); |
| 721 | int count = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 722 | bool is_named_feedback = IsPropertyNameFeedback(feedback); |
| 723 | if (feedback->IsFixedArray() || is_named_feedback) { |
| 724 | if (is_named_feedback) { |
| 725 | feedback = GetFeedbackExtra(); |
| 726 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 727 | FixedArray* array = FixedArray::cast(feedback); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 728 | // The array should be of the form |
| 729 | // [map, handler, map, handler, ...] |
| 730 | // or |
| 731 | // [map, map, handler, map, map, handler, ...] |
| 732 | // Be sure to skip handlers whose maps have been cleared. |
| 733 | DCHECK(array->length() >= 2); |
| 734 | int increment = array->get(1)->IsCode() ? 2 : 3; |
| 735 | for (int i = 0; i < array->length(); i += increment) { |
| 736 | DCHECK(array->get(i)->IsWeakCell()); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 737 | WeakCell* cell = WeakCell::cast(array->get(i)); |
| 738 | if (!cell->cleared()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 739 | Code* code = Code::cast(array->get(i + increment - 1)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 740 | DCHECK(code->kind() == Code::HANDLER); |
| 741 | code_list->Add(handle(code)); |
| 742 | count++; |
| 743 | } |
| 744 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 745 | } else if (feedback->IsWeakCell()) { |
| 746 | WeakCell* cell = WeakCell::cast(feedback); |
| 747 | if (!cell->cleared()) { |
| 748 | Code* code = Code::cast(GetFeedbackExtra()); |
| 749 | DCHECK(code->kind() == Code::HANDLER); |
| 750 | code_list->Add(handle(code)); |
| 751 | count++; |
| 752 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 753 | } |
| 754 | return count == length; |
| 755 | } |
| 756 | |
| 757 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 758 | void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } |
| 759 | |
| 760 | |
| 761 | void KeyedLoadICNexus::Clear(Code* host) { |
| 762 | KeyedLoadIC::Clear(GetIsolate(), host, this); |
| 763 | } |
| 764 | |
| 765 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 766 | Name* KeyedLoadICNexus::FindFirstName() const { |
| 767 | Object* feedback = GetFeedback(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 768 | if (IsPropertyNameFeedback(feedback)) { |
| 769 | return Name::cast(feedback); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 770 | } |
| 771 | return NULL; |
| 772 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 773 | |
| 774 | |
| 775 | Name* KeyedStoreICNexus::FindFirstName() const { |
| 776 | Object* feedback = GetFeedback(); |
| 777 | if (IsPropertyNameFeedback(feedback)) { |
| 778 | return Name::cast(feedback); |
| 779 | } |
| 780 | return NULL; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 781 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame^] | 782 | |
| 783 | |
| 784 | void StoreICNexus::Clear(Code* host) { |
| 785 | StoreIC::Clear(GetIsolate(), host, this); |
| 786 | } |
| 787 | |
| 788 | |
| 789 | void KeyedStoreICNexus::Clear(Code* host) { |
| 790 | KeyedStoreIC::Clear(GetIsolate(), host, this); |
| 791 | } |
| 792 | |
| 793 | |
| 794 | KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { |
| 795 | KeyedAccessStoreMode mode = STANDARD_STORE; |
| 796 | MapHandleList maps; |
| 797 | CodeHandleList handlers; |
| 798 | |
| 799 | if (GetKeyType() == PROPERTY) return mode; |
| 800 | |
| 801 | ExtractMaps(&maps); |
| 802 | FindHandlers(&handlers, maps.length()); |
| 803 | for (int i = 0; i < handlers.length(); i++) { |
| 804 | // The first handler that isn't the slow handler will have the bits we need. |
| 805 | Handle<Code> handler = handlers.at(i); |
| 806 | CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key()); |
| 807 | uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key()); |
| 808 | CHECK(major_key == CodeStub::KeyedStoreSloppyArguments || |
| 809 | major_key == CodeStub::StoreFastElement || |
| 810 | major_key == CodeStub::StoreElement || |
| 811 | major_key == CodeStub::ElementsTransitionAndStore || |
| 812 | major_key == CodeStub::NoCache); |
| 813 | if (major_key != CodeStub::NoCache) { |
| 814 | mode = CommonStoreModeBits::decode(minor_key); |
| 815 | break; |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | return mode; |
| 820 | } |
| 821 | |
| 822 | |
| 823 | IcCheckType KeyedStoreICNexus::GetKeyType() const { |
| 824 | // The structure of the vector slots tells us the type. |
| 825 | return GetFeedback()->IsName() ? PROPERTY : ELEMENT; |
| 826 | } |
| 827 | } // namespace internal |
| 828 | } // namespace v8 |