| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/type-info.h" | 5 #include "src/type-info.h" |
| 6 | 6 |
| 7 #include "src/ast.h" | 7 #include "src/ast.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 65 |
| 66 if (obj->IsJSFunction() || obj->IsAllocationSite() || obj->IsSymbol() || | 66 if (obj->IsJSFunction() || obj->IsAllocationSite() || obj->IsSymbol() || |
| 67 obj->IsSimd128Value()) { | 67 obj->IsSimd128Value()) { |
| 68 return Handle<Object>(obj, isolate()); | 68 return Handle<Object>(obj, isolate()); |
| 69 } | 69 } |
| 70 | 70 |
| 71 return undefined; | 71 return undefined; |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 InlineCacheState TypeFeedbackOracle::LoadInlineCacheState(TypeFeedbackId id) { | |
| 76 Handle<Object> maybe_code = GetInfo(id); | |
| 77 if (maybe_code->IsCode()) { | |
| 78 Handle<Code> code = Handle<Code>::cast(maybe_code); | |
| 79 if (code->is_inline_cache_stub()) return code->ic_state(); | |
| 80 } | |
| 81 | |
| 82 // If we can't find an IC, assume we've seen *something*, but we don't know | |
| 83 // what. PREMONOMORPHIC roughly encodes this meaning. | |
| 84 return PREMONOMORPHIC; | |
| 85 } | |
| 86 | |
| 87 | |
| 88 InlineCacheState TypeFeedbackOracle::LoadInlineCacheState( | 75 InlineCacheState TypeFeedbackOracle::LoadInlineCacheState( |
| 89 FeedbackVectorSlot slot) { | 76 FeedbackVectorSlot slot) { |
| 90 if (!slot.IsInvalid()) { | 77 if (!slot.IsInvalid()) { |
| 91 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); | 78 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); |
| 92 if (kind == FeedbackVectorSlotKind::LOAD_IC) { | 79 if (kind == FeedbackVectorSlotKind::LOAD_IC) { |
| 93 LoadICNexus nexus(feedback_vector_, slot); | 80 LoadICNexus nexus(feedback_vector_, slot); |
| 94 return nexus.StateFromFeedback(); | 81 return nexus.StateFromFeedback(); |
| 95 } else if (kind == FeedbackVectorSlotKind::KEYED_LOAD_IC) { | 82 } else if (kind == FeedbackVectorSlotKind::KEYED_LOAD_IC) { |
| 96 KeyedLoadICNexus nexus(feedback_vector_, slot); | 83 KeyedLoadICNexus nexus(feedback_vector_, slot); |
| 97 return nexus.StateFromFeedback(); | 84 return nexus.StateFromFeedback(); |
| 98 } | 85 } |
| 99 } | 86 } |
| 100 | 87 |
| 101 // If we can't find an IC, assume we've seen *something*, but we don't know | 88 // If we can't find an IC, assume we've seen *something*, but we don't know |
| 102 // what. PREMONOMORPHIC roughly encodes this meaning. | 89 // what. PREMONOMORPHIC roughly encodes this meaning. |
| 103 return PREMONOMORPHIC; | 90 return PREMONOMORPHIC; |
| 104 } | 91 } |
| 105 | 92 |
| 106 | 93 |
| 107 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { | |
| 108 Handle<Object> maybe_code = GetInfo(ast_id); | |
| 109 if (!maybe_code->IsCode()) return false; | |
| 110 Handle<Code> code = Handle<Code>::cast(maybe_code); | |
| 111 return code->ic_state() == UNINITIALIZED; | |
| 112 } | |
| 113 | |
| 114 | |
| 115 bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackVectorSlot slot) { | 94 bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackVectorSlot slot) { |
| 116 if (!slot.IsInvalid()) { | 95 if (!slot.IsInvalid()) { |
| 117 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); | 96 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); |
| 118 if (kind == FeedbackVectorSlotKind::STORE_IC) { | 97 if (kind == FeedbackVectorSlotKind::STORE_IC) { |
| 119 StoreICNexus nexus(feedback_vector_, slot); | 98 StoreICNexus nexus(feedback_vector_, slot); |
| 120 return nexus.StateFromFeedback() == UNINITIALIZED; | 99 return nexus.StateFromFeedback() == UNINITIALIZED; |
| 121 } else if (kind == FeedbackVectorSlotKind::KEYED_STORE_IC) { | 100 } else if (kind == FeedbackVectorSlotKind::KEYED_STORE_IC) { |
| 122 KeyedStoreICNexus nexus(feedback_vector_, slot); | 101 KeyedStoreICNexus nexus(feedback_vector_, slot); |
| 123 return nexus.StateFromFeedback() == UNINITIALIZED; | 102 return nexus.StateFromFeedback() == UNINITIALIZED; |
| 124 } | 103 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 150 byte TypeFeedbackOracle::ForInType(FeedbackVectorSlot feedback_vector_slot) { | 129 byte TypeFeedbackOracle::ForInType(FeedbackVectorSlot feedback_vector_slot) { |
| 151 Handle<Object> value = GetInfo(feedback_vector_slot); | 130 Handle<Object> value = GetInfo(feedback_vector_slot); |
| 152 return value.is_identical_to( | 131 return value.is_identical_to( |
| 153 TypeFeedbackVector::UninitializedSentinel(isolate())) | 132 TypeFeedbackVector::UninitializedSentinel(isolate())) |
| 154 ? ForInStatement::FAST_FOR_IN | 133 ? ForInStatement::FAST_FOR_IN |
| 155 : ForInStatement::SLOW_FOR_IN; | 134 : ForInStatement::SLOW_FOR_IN; |
| 156 } | 135 } |
| 157 | 136 |
| 158 | 137 |
| 159 void TypeFeedbackOracle::GetStoreModeAndKeyType( | 138 void TypeFeedbackOracle::GetStoreModeAndKeyType( |
| 160 TypeFeedbackId ast_id, KeyedAccessStoreMode* store_mode, | |
| 161 IcCheckType* key_type) { | |
| 162 Handle<Object> maybe_code = GetInfo(ast_id); | |
| 163 if (maybe_code->IsCode()) { | |
| 164 Handle<Code> code = Handle<Code>::cast(maybe_code); | |
| 165 if (code->kind() == Code::KEYED_STORE_IC) { | |
| 166 ExtraICState extra_ic_state = code->extra_ic_state(); | |
| 167 *store_mode = KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state); | |
| 168 *key_type = KeyedStoreIC::GetKeyType(extra_ic_state); | |
| 169 return; | |
| 170 } | |
| 171 } | |
| 172 *store_mode = STANDARD_STORE; | |
| 173 *key_type = ELEMENT; | |
| 174 } | |
| 175 | |
| 176 | |
| 177 void TypeFeedbackOracle::GetStoreModeAndKeyType( | |
| 178 FeedbackVectorSlot slot, KeyedAccessStoreMode* store_mode, | 139 FeedbackVectorSlot slot, KeyedAccessStoreMode* store_mode, |
| 179 IcCheckType* key_type) { | 140 IcCheckType* key_type) { |
| 180 if (!slot.IsInvalid() && | 141 if (!slot.IsInvalid() && |
| 181 feedback_vector_->GetKind(slot) == | 142 feedback_vector_->GetKind(slot) == |
| 182 FeedbackVectorSlotKind::KEYED_STORE_IC) { | 143 FeedbackVectorSlotKind::KEYED_STORE_IC) { |
| 183 KeyedStoreICNexus nexus(feedback_vector_, slot); | 144 KeyedStoreICNexus nexus(feedback_vector_, slot); |
| 184 *store_mode = nexus.GetKeyedAccessStoreMode(); | 145 *store_mode = nexus.GetKeyedAccessStoreMode(); |
| 185 *key_type = nexus.GetKeyType(); | 146 *key_type = nexus.GetKeyType(); |
| 186 } else { | 147 } else { |
| 187 *store_mode = STANDARD_STORE; | 148 *store_mode = STANDARD_STORE; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( | 186 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( |
| 226 FeedbackVectorSlot slot) { | 187 FeedbackVectorSlot slot) { |
| 227 Handle<Object> info = GetInfo(slot); | 188 Handle<Object> info = GetInfo(slot); |
| 228 if (info->IsAllocationSite()) { | 189 if (info->IsAllocationSite()) { |
| 229 return Handle<AllocationSite>::cast(info); | 190 return Handle<AllocationSite>::cast(info); |
| 230 } | 191 } |
| 231 return Handle<AllocationSite>::null(); | 192 return Handle<AllocationSite>::null(); |
| 232 } | 193 } |
| 233 | 194 |
| 234 | 195 |
| 235 bool TypeFeedbackOracle::LoadIsBuiltin( | |
| 236 TypeFeedbackId id, Builtins::Name builtin) { | |
| 237 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); | |
| 238 } | |
| 239 | |
| 240 | |
| 241 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, | 196 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, |
| 242 Type** left_type, | 197 Type** left_type, |
| 243 Type** right_type, | 198 Type** right_type, |
| 244 Type** combined_type) { | 199 Type** combined_type) { |
| 245 Handle<Object> info = GetInfo(id); | 200 Handle<Object> info = GetInfo(id); |
| 246 if (!info->IsCode()) { | 201 if (!info->IsCode()) { |
| 247 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. | 202 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. |
| 248 *left_type = *right_type = *combined_type = Type::None(zone()); | 203 *left_type = *right_type = *combined_type = Type::None(zone()); |
| 249 return; | 204 return; |
| 250 } | 205 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 *key_type = ELEMENT; | 299 *key_type = ELEMENT; |
| 345 } else { | 300 } else { |
| 346 KeyedLoadICNexus nexus(feedback_vector_, slot); | 301 KeyedLoadICNexus nexus(feedback_vector_, slot); |
| 347 CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types); | 302 CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types); |
| 348 *is_string = HasOnlyStringMaps(receiver_types); | 303 *is_string = HasOnlyStringMaps(receiver_types); |
| 349 *key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT; | 304 *key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT; |
| 350 } | 305 } |
| 351 } | 306 } |
| 352 | 307 |
| 353 | 308 |
| 354 void TypeFeedbackOracle::AssignmentReceiverTypes(TypeFeedbackId id, | |
| 355 Handle<Name> name, | |
| 356 SmallMapList* receiver_types) { | |
| 357 receiver_types->Clear(); | |
| 358 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | |
| 359 CollectReceiverTypes(id, name, flags, receiver_types); | |
| 360 } | |
| 361 | |
| 362 | |
| 363 void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorSlot slot, | 309 void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorSlot slot, |
| 364 Handle<Name> name, | 310 Handle<Name> name, |
| 365 SmallMapList* receiver_types) { | 311 SmallMapList* receiver_types) { |
| 366 receiver_types->Clear(); | 312 receiver_types->Clear(); |
| 367 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | 313 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); |
| 368 CollectReceiverTypes(slot, name, flags, receiver_types); | 314 CollectReceiverTypes(slot, name, flags, receiver_types); |
| 369 } | 315 } |
| 370 | 316 |
| 371 | 317 |
| 372 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( | 318 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( |
| 373 TypeFeedbackId id, SmallMapList* receiver_types, | |
| 374 KeyedAccessStoreMode* store_mode, IcCheckType* key_type) { | |
| 375 receiver_types->Clear(); | |
| 376 CollectReceiverTypes(id, receiver_types); | |
| 377 GetStoreModeAndKeyType(id, store_mode, key_type); | |
| 378 } | |
| 379 | |
| 380 | |
| 381 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( | |
| 382 FeedbackVectorSlot slot, SmallMapList* receiver_types, | 319 FeedbackVectorSlot slot, SmallMapList* receiver_types, |
| 383 KeyedAccessStoreMode* store_mode, IcCheckType* key_type) { | 320 KeyedAccessStoreMode* store_mode, IcCheckType* key_type) { |
| 384 receiver_types->Clear(); | 321 receiver_types->Clear(); |
| 385 CollectReceiverTypes(slot, receiver_types); | 322 CollectReceiverTypes(slot, receiver_types); |
| 386 GetStoreModeAndKeyType(slot, store_mode, key_type); | 323 GetStoreModeAndKeyType(slot, store_mode, key_type); |
| 387 } | 324 } |
| 388 | 325 |
| 389 | 326 |
| 390 void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id, | |
| 391 SmallMapList* receiver_types) { | |
| 392 receiver_types->Clear(); | |
| 393 CollectReceiverTypes(id, receiver_types); | |
| 394 } | |
| 395 | |
| 396 | |
| 397 void TypeFeedbackOracle::CountReceiverTypes(FeedbackVectorSlot slot, | 327 void TypeFeedbackOracle::CountReceiverTypes(FeedbackVectorSlot slot, |
| 398 SmallMapList* receiver_types) { | 328 SmallMapList* receiver_types) { |
| 399 receiver_types->Clear(); | 329 receiver_types->Clear(); |
| 400 if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types); | 330 if (!slot.IsInvalid()) CollectReceiverTypes(slot, receiver_types); |
| 401 } | 331 } |
| 402 | 332 |
| 403 | 333 |
| 404 void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, | 334 void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, |
| 405 Handle<Name> name, | 335 Handle<Name> name, |
| 406 Code::Flags flags, | 336 Code::Flags flags, |
| 407 SmallMapList* types) { | 337 SmallMapList* types) { |
| 408 StoreICNexus nexus(feedback_vector_, slot); | 338 StoreICNexus nexus(feedback_vector_, slot); |
| 409 CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types); | 339 CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types); |
| 410 } | 340 } |
| 411 | 341 |
| 412 | 342 |
| 413 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | |
| 414 Handle<Name> name, | |
| 415 Code::Flags flags, | |
| 416 SmallMapList* types) { | |
| 417 Handle<Object> object = GetInfo(ast_id); | |
| 418 if (object->IsUndefined() || object->IsSmi()) return; | |
| 419 | |
| 420 DCHECK(object->IsCode()); | |
| 421 Handle<Code> code(Handle<Code>::cast(object)); | |
| 422 CollectReceiverTypes<Code>(*code, name, flags, types); | |
| 423 } | |
| 424 | |
| 425 | |
| 426 template <class T> | 343 template <class T> |
| 427 void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<Name> name, | 344 void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<Name> name, |
| 428 Code::Flags flags, | 345 Code::Flags flags, |
| 429 SmallMapList* types) { | 346 SmallMapList* types) { |
| 430 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 347 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
| 431 obj->ic_state() == MEGAMORPHIC) { | 348 obj->ic_state() == MEGAMORPHIC) { |
| 432 types->Reserve(4, zone()); | 349 types->Reserve(4, zone()); |
| 433 isolate()->stub_cache()->CollectMatchingMaps( | 350 isolate()->stub_cache()->CollectMatchingMaps( |
| 434 types, name, flags, native_context_, zone()); | 351 types, name, flags, native_context_, zone()); |
| 435 } else { | 352 } else { |
| 436 CollectReceiverTypes<T>(obj, types); | 353 CollectReceiverTypes<T>(obj, types); |
| 437 } | 354 } |
| 438 } | 355 } |
| 439 | 356 |
| 440 | 357 |
| 441 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | |
| 442 SmallMapList* types) { | |
| 443 Handle<Object> object = GetInfo(ast_id); | |
| 444 if (!object->IsCode()) return; | |
| 445 Handle<Code> code = Handle<Code>::cast(object); | |
| 446 CollectReceiverTypes<Code>(*code, types); | |
| 447 } | |
| 448 | |
| 449 | |
| 450 void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, | 358 void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, |
| 451 SmallMapList* types) { | 359 SmallMapList* types) { |
| 452 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); | 360 FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); |
| 453 if (kind == FeedbackVectorSlotKind::STORE_IC) { | 361 if (kind == FeedbackVectorSlotKind::STORE_IC) { |
| 454 StoreICNexus nexus(feedback_vector_, slot); | 362 StoreICNexus nexus(feedback_vector_, slot); |
| 455 CollectReceiverTypes<FeedbackNexus>(&nexus, types); | 363 CollectReceiverTypes<FeedbackNexus>(&nexus, types); |
| 456 } else { | 364 } else { |
| 457 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind); | 365 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind); |
| 458 KeyedStoreICNexus nexus(feedback_vector_, slot); | 366 KeyedStoreICNexus nexus(feedback_vector_, slot); |
| 459 CollectReceiverTypes<FeedbackNexus>(&nexus, types); | 367 CollectReceiverTypes<FeedbackNexus>(&nexus, types); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 // Dictionary has been allocated with sufficient size for all elements. | 474 // Dictionary has been allocated with sufficient size for all elements. |
| 567 DisallowHeapAllocation no_need_to_resize_dictionary; | 475 DisallowHeapAllocation no_need_to_resize_dictionary; |
| 568 HandleScope scope(isolate()); | 476 HandleScope scope(isolate()); |
| 569 USE(UnseededNumberDictionary::AtNumberPut( | 477 USE(UnseededNumberDictionary::AtNumberPut( |
| 570 dictionary_, IdToKey(ast_id), handle(target, isolate()))); | 478 dictionary_, IdToKey(ast_id), handle(target, isolate()))); |
| 571 } | 479 } |
| 572 | 480 |
| 573 | 481 |
| 574 } // namespace internal | 482 } // namespace internal |
| 575 } // namespace v8 | 483 } // namespace v8 |
| OLD | NEW |