Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/ic/ic.h" | 7 #include "src/ic/ic.h" |
| 8 #include "src/ic/ic-state.h" | 8 #include "src/ic/ic-state.h" |
| 9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/type-feedback-vector-inl.h" | 10 #include "src/type-feedback-vector-inl.h" |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 // static | 114 // static |
| 115 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( | 115 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
| 116 Isolate* isolate, Handle<TypeFeedbackVector> vector) { | 116 Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
| 117 Handle<TypeFeedbackVector> result; | 117 Handle<TypeFeedbackVector> result; |
| 118 result = Handle<TypeFeedbackVector>::cast( | 118 result = Handle<TypeFeedbackVector>::cast( |
| 119 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); | 119 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); |
| 120 return result; | 120 return result; |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 // This logic is copied from | |
| 125 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. | |
| 126 // TODO(mvstanton): with weak handling of all vector ics, this logic should | |
| 127 // actually be completely eliminated and we no longer need to clear the | |
| 128 // vector ICs. | |
| 129 static bool ClearLogic(Heap* heap, int ic_age, Code::Kind kind, | |
| 130 InlineCacheState state) { | |
| 131 if (FLAG_cleanup_code_caches_at_gc && | |
| 132 (kind == Code::CALL_IC || state == MEGAMORPHIC || state == GENERIC || | |
| 133 state == POLYMORPHIC || heap->flush_monomorphic_ics() || | |
| 134 // TODO(mvstanton): is this ic_age granular enough? it comes from | |
| 135 // the SharedFunctionInfo which may change on a different schedule | |
| 136 // than ic targets. | |
| 137 // ic_age != heap->global_ic_age() || | |
| 138 // is_invalidated_weak_stub || | |
| 139 heap->isolate()->serializer_enabled())) { | |
| 140 return true; | |
| 141 } | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 | |
| 124 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { | 146 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
| 125 int slots = Slots(); | 147 int slots = Slots(); |
| 126 Isolate* isolate = GetIsolate(); | 148 Isolate* isolate = GetIsolate(); |
| 127 Object* uninitialized_sentinel = | 149 Object* uninitialized_sentinel = |
| 128 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap()); | 150 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap()); |
| 129 | 151 |
| 130 for (int i = 0; i < slots; i++) { | 152 for (int i = 0; i < slots; i++) { |
| 131 FeedbackVectorSlot slot(i); | 153 FeedbackVectorSlot slot(i); |
| 132 Object* obj = Get(slot); | 154 Object* obj = Get(slot); |
| 133 if (obj->IsHeapObject()) { | 155 if (obj->IsHeapObject()) { |
| 134 InstanceType instance_type = | 156 InstanceType instance_type = |
| 135 HeapObject::cast(obj)->map()->instance_type(); | 157 HeapObject::cast(obj)->map()->instance_type(); |
| 136 // AllocationSites are exempt from clearing. They don't store Maps | 158 // AllocationSites are exempt from clearing. They don't store Maps |
| 137 // or Code pointers which can cause memory leaks if not cleared | 159 // or Code pointers which can cause memory leaks if not cleared |
| 138 // regularly. | 160 // regularly. |
| 139 if (instance_type != ALLOCATION_SITE_TYPE) { | 161 if (instance_type != ALLOCATION_SITE_TYPE) { |
| 140 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); | 162 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); |
| 141 } | 163 } |
| 142 } | 164 } |
| 143 } | 165 } |
| 144 | 166 |
| 145 slots = ICSlots(); | 167 slots = ICSlots(); |
| 146 if (slots == 0) return; | 168 if (slots == 0) return; |
| 147 | 169 |
| 148 // Now clear vector-based ICs. They are all CallICs. | 170 // Now clear vector-based ICs. They are all CallICs. |
|
Jakob Kummerow
2014/11/26 15:14:15
nit: s/They are all CallICs.//
mvstanton
2014/11/27 13:09:26
Done.
| |
| 149 // Try and pass the containing code (the "host"). | 171 // Try and pass the containing code (the "host"). |
| 172 Heap* heap = isolate->heap(); | |
| 150 Code* host = shared->code(); | 173 Code* host = shared->code(); |
| 174 // I'm not sure yet if this ic age is the correct one. | |
| 175 int ic_age = shared->ic_age(); | |
| 151 for (int i = 0; i < slots; i++) { | 176 for (int i = 0; i < slots; i++) { |
| 152 FeedbackVectorICSlot slot(i); | 177 FeedbackVectorICSlot slot(i); |
| 153 Object* obj = Get(slot); | 178 Object* obj = Get(slot); |
| 154 if (obj != uninitialized_sentinel) { | 179 if (obj != uninitialized_sentinel) { |
| 155 // TODO(mvstanton): To make this code work with --vector-ics, | 180 // Discover the correct Code::Kind. |
|
Jakob Kummerow
2014/11/26 15:14:15
nit: this comment doesn't add value
mvstanton
2014/11/27 13:09:26
Done.
| |
| 156 // additional Nexus types must be created. | 181 Code::Kind kind = GetKind(slot); |
| 157 DCHECK(!FLAG_vector_ics); | 182 if (kind == Code::CALL_IC) { |
| 158 DCHECK(GetKind(slot) == Code::CALL_IC); | 183 CallICNexus nexus(this, slot); |
| 159 CallICNexus nexus(this, slot); | 184 // bool is_invalidated = nexus.IsInvalidatedWeakIC(); |
|
Jakob Kummerow
2014/11/26 15:14:15
leftover?
mvstanton
2014/11/27 13:09:26
Yes, I think so, removed.
| |
| 160 ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); | 185 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { |
| 186 nexus.Clear(host); | |
| 187 } | |
| 188 } else if (kind == Code::LOAD_IC) { | |
| 189 LoadICNexus nexus(this, slot); | |
| 190 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { | |
| 191 nexus.Clear(host); | |
| 192 } | |
| 193 } else if (kind == Code::KEYED_LOAD_IC) { | |
| 194 KeyedLoadICNexus nexus(this, slot); | |
| 195 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { | |
| 196 nexus.Clear(host); | |
| 197 } | |
| 198 } | |
| 161 } | 199 } |
| 162 } | 200 } |
| 163 } | 201 } |
| 164 | 202 |
| 165 | 203 |
| 166 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { | 204 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
| 167 Isolate* isolate = GetIsolate(); | 205 Isolate* isolate = GetIsolate(); |
| 168 Handle<Object> feedback = handle(GetFeedback(), isolate); | 206 Handle<Object> feedback = handle(GetFeedback(), isolate); |
| 169 if (!feedback->IsFixedArray() || | 207 if (!feedback->IsFixedArray() || |
| 170 FixedArray::cast(*feedback)->length() != length) { | 208 FixedArray::cast(*feedback)->length() != length) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 183 int receiver_count = types->length(); | 221 int receiver_count = types->length(); |
| 184 for (int current = 0; current < receiver_count; ++current) { | 222 for (int current = 0; current < receiver_count; ++current) { |
| 185 Handle<HeapType> type = types->at(current); | 223 Handle<HeapType> type = types->at(current); |
| 186 Handle<Map> map = IC::TypeToMap(*type, isolate); | 224 Handle<Map> map = IC::TypeToMap(*type, isolate); |
| 187 array->set(start_index + (current * 2), *map); | 225 array->set(start_index + (current * 2), *map); |
| 188 array->set(start_index + (current * 2 + 1), *handlers->at(current)); | 226 array->set(start_index + (current * 2 + 1), *handlers->at(current)); |
| 189 } | 227 } |
| 190 } | 228 } |
| 191 | 229 |
| 192 | 230 |
| 231 InlineCacheState LoadICNexus::StateFromFeedback() const { | |
| 232 Isolate* isolate = GetIsolate(); | |
| 233 InlineCacheState state = UNINITIALIZED; | |
| 234 Object* feedback = GetFeedback(); | |
| 235 if (feedback == *vector()->UninitializedSentinel(isolate)) { | |
| 236 state = UNINITIALIZED; | |
|
Jakob Kummerow
2014/11/26 15:14:15
consider to directly "return UNINITIALIZED;" (and
mvstanton
2014/11/27 13:09:26
Done.
| |
| 237 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { | |
| 238 state = MEGAMORPHIC; | |
| 239 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { | |
| 240 state = PREMONOMORPHIC; | |
| 241 } else if (feedback->IsFixedArray()) { | |
| 242 FixedArray* array = FixedArray::cast(feedback); | |
| 243 int length = array->length(); | |
| 244 DCHECK(length >= 2); | |
| 245 if (length == 2) { | |
| 246 state = MONOMORPHIC; | |
| 247 } else if (length > 2) { | |
|
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 2)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
| |
| 248 state = POLYMORPHIC; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 return state; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { | |
| 257 Isolate* isolate = GetIsolate(); | |
| 258 InlineCacheState state = UNINITIALIZED; | |
| 259 Object* feedback = GetFeedback(); | |
| 260 if (feedback == *vector()->UninitializedSentinel(isolate)) { | |
| 261 state = UNINITIALIZED; | |
| 262 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { | |
| 263 state = PREMONOMORPHIC; | |
| 264 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { | |
| 265 state = MEGAMORPHIC; | |
| 266 } else if (feedback == *vector()->GenericSentinel(isolate)) { | |
| 267 state = GENERIC; | |
| 268 } else if (feedback->IsFixedArray()) { | |
| 269 FixedArray* array = FixedArray::cast(feedback); | |
| 270 int length = array->length(); | |
| 271 DCHECK(length >= 3); | |
| 272 | |
| 273 if (length == 3) { | |
| 274 state = MONOMORPHIC; | |
| 275 } else if (length > 3) { | |
|
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 3)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
| |
| 276 state = POLYMORPHIC; | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 return state; | |
| 281 } | |
| 282 | |
| 283 | |
| 193 InlineCacheState CallICNexus::StateFromFeedback() const { | 284 InlineCacheState CallICNexus::StateFromFeedback() const { |
| 194 Isolate* isolate = GetIsolate(); | 285 Isolate* isolate = GetIsolate(); |
| 195 InlineCacheState state = UNINITIALIZED; | 286 InlineCacheState state = UNINITIALIZED; |
| 196 Object* feedback = GetFeedback(); | 287 Object* feedback = GetFeedback(); |
| 197 | 288 |
| 198 if (feedback == *vector()->MegamorphicSentinel(isolate)) { | 289 if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
| 199 state = GENERIC; | 290 state = GENERIC; |
| 200 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { | 291 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { |
| 201 state = MONOMORPHIC; | 292 state = MONOMORPHIC; |
| 202 } else { | 293 } else { |
| 203 CHECK(feedback == *vector()->UninitializedSentinel(isolate)); | 294 CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
| 204 } | 295 } |
| 205 | 296 |
| 206 return state; | 297 return state; |
| 207 } | 298 } |
| 208 | 299 |
| 209 | 300 |
| 301 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } | |
| 302 | |
| 303 | |
| 210 void CallICNexus::ConfigureGeneric() { | 304 void CallICNexus::ConfigureGeneric() { |
| 211 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | 305 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
| 212 } | 306 } |
| 213 | 307 |
| 214 | 308 |
| 215 void CallICNexus::ConfigureMonomorphicArray() { | 309 void CallICNexus::ConfigureMonomorphicArray() { |
| 216 Object* feedback = GetFeedback(); | 310 Object* feedback = GetFeedback(); |
| 217 if (!feedback->IsAllocationSite()) { | 311 if (!feedback->IsAllocationSite()) { |
| 218 Handle<AllocationSite> new_site = | 312 Handle<AllocationSite> new_site = |
| 219 GetIsolate()->factory()->NewAllocationSite(); | 313 GetIsolate()->factory()->NewAllocationSite(); |
| 220 SetFeedback(*new_site); | 314 SetFeedback(*new_site); |
| 221 } | 315 } |
| 222 } | 316 } |
| 223 | 317 |
| 224 | 318 |
| 225 void CallICNexus::ConfigureUninitialized() { | 319 void CallICNexus::ConfigureUninitialized() { |
| 226 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), | 320 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), |
| 227 SKIP_WRITE_BARRIER); | 321 SKIP_WRITE_BARRIER); |
| 228 } | 322 } |
| 229 | 323 |
| 230 | 324 |
| 231 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { | 325 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
| 232 SetFeedback(*function); | 326 SetFeedback(*function); |
| 233 } | 327 } |
| 234 | 328 |
| 235 | 329 |
| 330 void KeyedLoadICNexus::ConfigureGeneric() { | |
| 331 SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
|
Jakob Kummerow
2014/11/26 15:14:15
Looks like return raw pointers in the various vect
mvstanton
2014/11/27 13:09:26
Yes, I'll come back for that later. I think I want
| |
| 332 } | |
| 333 | |
| 334 | |
| 335 void KeyedLoadICNexus::ConfigureMegamorphic() { | |
| 336 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
| 337 } | |
| 338 | |
| 339 | |
| 340 void LoadICNexus::ConfigureMegamorphic() { | |
| 341 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
| 342 } | |
| 343 | |
| 344 | |
| 345 void LoadICNexus::ConfigurePremonomorphic() { | |
| 346 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), | |
| 347 SKIP_WRITE_BARRIER); | |
| 348 } | |
| 349 | |
| 350 | |
| 351 void KeyedLoadICNexus::ConfigurePremonomorphic() { | |
| 352 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), | |
| 353 SKIP_WRITE_BARRIER); | |
| 354 } | |
| 355 | |
| 356 | |
| 357 void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type, | |
| 358 Handle<Code> handler) { | |
| 359 Handle<FixedArray> array = EnsureArrayOfSize(2); | |
| 360 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); | |
| 361 array->set(0, *receiver_map); | |
| 362 array->set(1, *handler); | |
| 363 } | |
| 364 | |
| 365 | |
| 366 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, | |
| 367 Handle<HeapType> type, | |
| 368 Handle<Code> handler) { | |
| 369 Handle<FixedArray> array = EnsureArrayOfSize(3); | |
| 370 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); | |
| 371 if (name.is_null()) { | |
| 372 array->set(0, Smi::FromInt(0)); | |
| 373 } else { | |
| 374 array->set(0, *name); | |
| 375 } | |
| 376 array->set(1, *receiver_map); | |
| 377 array->set(2, *handler); | |
| 378 } | |
| 379 | |
| 380 | |
| 381 void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types, | |
| 382 CodeHandleList* handlers) { | |
| 383 int receiver_count = types->length(); | |
| 384 EnsureArrayOfSize(receiver_count * 2); | |
| 385 InstallHandlers(0, types, handlers); | |
| 386 } | |
| 387 | |
| 388 | |
| 389 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, | |
| 390 TypeHandleList* types, | |
| 391 CodeHandleList* handlers) { | |
| 392 int receiver_count = types->length(); | |
| 393 Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2); | |
| 394 if (name.is_null()) { | |
| 395 array->set(0, Smi::FromInt(0)); | |
| 396 } else { | |
| 397 array->set(0, *name); | |
| 398 } | |
| 399 InstallHandlers(1, types, handlers); | |
| 400 } | |
| 401 | |
| 402 | |
| 236 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { | 403 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { |
| 237 Isolate* isolate = GetIsolate(); | 404 Isolate* isolate = GetIsolate(); |
| 238 Object* feedback = GetFeedback(); | 405 Object* feedback = GetFeedback(); |
| 239 if (feedback->IsFixedArray()) { | 406 if (feedback->IsFixedArray()) { |
| 240 FixedArray* array = FixedArray::cast(feedback); | 407 FixedArray* array = FixedArray::cast(feedback); |
| 241 // The array should be of the form [<optional name>], then | 408 // The array should be of the form [<optional name>], then |
| 242 // [map, handler, map, handler, ... ] | 409 // [map, handler, map, handler, ... ] |
| 243 DCHECK(array->length() >= (2 + start_index)); | 410 DCHECK(array->length() >= (2 + start_index)); |
| 244 for (int i = start_index; i < array->length(); i += 2) { | 411 for (int i = start_index; i < array->length(); i += 2) { |
| 245 Map* map = Map::cast(array->get(i)); | 412 Map* map = Map::cast(array->get(i)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 DCHECK(array->length() >= (2 + start_index)); | 449 DCHECK(array->length() >= (2 + start_index)); |
| 283 for (int i = start_index; i < array->length(); i += 2) { | 450 for (int i = start_index; i < array->length(); i += 2) { |
| 284 Code* code = Code::cast(array->get(i + 1)); | 451 Code* code = Code::cast(array->get(i + 1)); |
| 285 DCHECK(code->kind() == Code::HANDLER); | 452 DCHECK(code->kind() == Code::HANDLER); |
| 286 code_list->Add(handle(code)); | 453 code_list->Add(handle(code)); |
| 287 count++; | 454 count++; |
| 288 } | 455 } |
| 289 } | 456 } |
| 290 return count == length; | 457 return count == length; |
| 291 } | 458 } |
| 459 | |
| 460 | |
| 461 int LoadICNexus::ExtractMaps(MapHandleList* maps) const { | |
| 462 return FeedbackNexus::ExtractMaps(0, maps); | |
| 463 } | |
| 464 | |
| 465 | |
| 466 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } | |
| 467 | |
| 468 | |
| 469 void KeyedLoadICNexus::Clear(Code* host) { | |
| 470 KeyedLoadIC::Clear(GetIsolate(), host, this); | |
| 471 } | |
| 472 | |
| 473 | |
| 474 int KeyedLoadICNexus::ExtractMaps(MapHandleList* maps) const { | |
| 475 return FeedbackNexus::ExtractMaps(1, maps); | |
| 476 } | |
| 477 | |
| 478 | |
| 479 MaybeHandle<Code> LoadICNexus::FindHandlerForMap(Handle<Map> map) const { | |
| 480 return FeedbackNexus::FindHandlerForMap(0, map); | |
| 481 } | |
| 482 | |
| 483 | |
| 484 MaybeHandle<Code> KeyedLoadICNexus::FindHandlerForMap(Handle<Map> map) const { | |
| 485 return FeedbackNexus::FindHandlerForMap(1, map); | |
| 486 } | |
| 487 | |
| 488 | |
| 489 bool LoadICNexus::FindHandlers(CodeHandleList* code_list, int length) const { | |
| 490 return FeedbackNexus::FindHandlers(0, code_list, length); | |
| 491 } | |
| 492 | |
| 493 | |
| 494 bool KeyedLoadICNexus::FindHandlers(CodeHandleList* code_list, | |
| 495 int length) const { | |
| 496 return FeedbackNexus::FindHandlers(1, code_list, length); | |
| 497 } | |
| 498 | |
| 499 | |
| 500 Name* KeyedLoadICNexus::FindFirstName() const { | |
| 501 Object* feedback = GetFeedback(); | |
| 502 if (feedback->IsFixedArray()) { | |
| 503 FixedArray* array = FixedArray::cast(feedback); | |
| 504 DCHECK(array->length() >= 3); | |
| 505 Object* name = array->get(0); | |
| 506 if (name->IsName()) return Name::cast(name); | |
| 507 } | |
| 508 return NULL; | |
| 509 } | |
| 292 } | 510 } |
| 293 } // namespace v8::internal | 511 } // namespace v8::internal |
| OLD | NEW |