| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
| 36 #include "type-info.h" | 36 #include "type-info.h" |
| 37 | 37 |
| 38 #include "ic-inl.h" | 38 #include "ic-inl.h" |
| 39 #include "objects-inl.h" | 39 #include "objects-inl.h" |
| 40 | 40 |
| 41 namespace v8 { | 41 namespace v8 { |
| 42 namespace internal { | 42 namespace internal { |
| 43 | 43 |
| 44 | 44 |
| 45 TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) { | 45 TypeInfo TypeInfo::FromValue(Handle<Object> value) { |
| 46 TypeInfo info; | |
| 47 if (value->IsSmi()) { | 46 if (value->IsSmi()) { |
| 48 info = TypeInfo::Smi(); | 47 return TypeInfo::Smi(); |
| 49 } else if (value->IsHeapNumber()) { | 48 } else if (value->IsHeapNumber()) { |
| 50 info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) | 49 return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) |
| 51 ? TypeInfo::Integer32() | 50 ? TypeInfo::Integer32() |
| 52 : TypeInfo::Double(); | 51 : TypeInfo::Double(); |
| 53 } else if (value->IsString()) { | 52 } else if (value->IsString()) { |
| 54 info = TypeInfo::String(); | 53 return TypeInfo::String(); |
| 55 } else { | |
| 56 info = TypeInfo::Unknown(); | |
| 57 } | 54 } |
| 58 return info; | 55 return TypeInfo::Unknown(); |
| 59 } | 56 } |
| 60 | 57 |
| 61 | 58 |
| 62 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 59 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 63 Handle<Context> native_context, | 60 Handle<Context> native_context, |
| 64 Isolate* isolate, | 61 Isolate* isolate, |
| 65 Zone* zone) | 62 Zone* zone) |
| 66 : native_context_(native_context), | 63 : native_context_(native_context), |
| 67 isolate_(isolate), | 64 isolate_(isolate), |
| 68 zone_(zone) { | 65 zone_(zone) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 Handle<Code> code = Handle<Code>::cast(map_or_code); | 225 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 229 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | 226 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); |
| 230 return map == NULL || CanRetainOtherContext(map, *native_context_) | 227 return map == NULL || CanRetainOtherContext(map, *native_context_) |
| 231 ? Handle<Map>::null() | 228 ? Handle<Map>::null() |
| 232 : Handle<Map>(map); | 229 : Handle<Map>(map); |
| 233 } | 230 } |
| 234 return Handle<Map>::cast(map_or_code); | 231 return Handle<Map>::cast(map_or_code); |
| 235 } | 232 } |
| 236 | 233 |
| 237 | 234 |
| 238 Handle<Map> TypeFeedbackOracle::CompareNilMonomorphicReceiverType( | |
| 239 CompareOperation* expr) { | |
| 240 Handle<Object> maybe_code = GetInfo(expr->CompareOperationFeedbackId()); | |
| 241 if (maybe_code->IsCode()) { | |
| 242 Map* map = Handle<Code>::cast(maybe_code)->FindFirstMap(); | |
| 243 if (map == NULL) return Handle<Map>(); | |
| 244 map = map->CurrentMapForDeprecated(); | |
| 245 return map == NULL || CanRetainOtherContext(map, *native_context_) | |
| 246 ? Handle<Map>() | |
| 247 : Handle<Map>(map); | |
| 248 } else if (maybe_code->IsMap()) { | |
| 249 ASSERT(!Handle<Map>::cast(maybe_code)->is_deprecated()); | |
| 250 return Handle<Map>::cast(maybe_code); | |
| 251 } | |
| 252 return Handle<Map>(); | |
| 253 } | |
| 254 | |
| 255 | |
| 256 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 235 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 257 TypeFeedbackId ast_id) { | 236 TypeFeedbackId ast_id) { |
| 258 Handle<Object> map_or_code = GetInfo(ast_id); | 237 Handle<Object> map_or_code = GetInfo(ast_id); |
| 259 if (map_or_code->IsCode()) { | 238 if (map_or_code->IsCode()) { |
| 260 Handle<Code> code = Handle<Code>::cast(map_or_code); | 239 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 261 if (code->kind() == Code::KEYED_STORE_IC) { | 240 if (code->kind() == Code::KEYED_STORE_IC) { |
| 262 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); | 241 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 263 } | 242 } |
| 264 } | 243 } |
| 265 return STANDARD_STORE; | 244 return STANDARD_STORE; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { | 336 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { |
| 358 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); | 337 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); |
| 359 if (!object->IsCode()) return false; | 338 if (!object->IsCode()) return false; |
| 360 Handle<Code> code = Handle<Code>::cast(object); | 339 Handle<Code> code = Handle<Code>::cast(object); |
| 361 if (!code->is_load_stub()) return false; | 340 if (!code->is_load_stub()) return false; |
| 362 if (code->ic_state() != MONOMORPHIC) return false; | 341 if (code->ic_state() != MONOMORPHIC) return false; |
| 363 return stub->Describes(*code); | 342 return stub->Describes(*code); |
| 364 } | 343 } |
| 365 | 344 |
| 366 | 345 |
| 367 static TypeInfo TypeFromCompareType(CompareIC::State state) { | 346 void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id, |
| 368 switch (state) { | 347 Handle<Type>* left_type, |
| 369 case CompareIC::UNINITIALIZED: | 348 Handle<Type>* right_type, |
| 370 // Uninitialized means never executed. | 349 Handle<Type>* overall_type, |
| 371 return TypeInfo::Uninitialized(); | 350 Handle<Type>* compare_nil_type) { |
| 372 case CompareIC::SMI: | 351 *left_type = *right_type = *overall_type = *compare_nil_type = |
| 373 return TypeInfo::Smi(); | 352 handle(Type::Any(), isolate_); |
| 374 case CompareIC::NUMBER: | 353 Handle<Object> info = GetInfo(id); |
| 375 return TypeInfo::Number(); | 354 if (!info->IsCode()) return; |
| 376 case CompareIC::INTERNALIZED_STRING: | 355 Handle<Code> code = Handle<Code>::cast(info); |
| 377 return TypeInfo::InternalizedString(); | 356 |
| 378 case CompareIC::STRING: | 357 Handle<Map> map; |
| 379 return TypeInfo::String(); | 358 Map* raw_map = code->FindFirstMap(); |
| 380 case CompareIC::OBJECT: | 359 if (raw_map != NULL) { |
| 381 case CompareIC::KNOWN_OBJECT: | 360 raw_map = raw_map->CurrentMapForDeprecated(); |
| 382 // TODO(kasperl): We really need a type for JS objects here. | 361 if (!CanRetainOtherContext(raw_map, *native_context_)) { |
| 383 return TypeInfo::NonPrimitive(); | 362 map = handle(raw_map, isolate_); |
| 384 case CompareIC::GENERIC: | 363 } |
| 385 default: | 364 } |
| 386 return TypeInfo::Unknown(); | 365 |
| 366 if (code->is_compare_ic_stub()) { |
| 367 int stub_minor_key = code->stub_info(); |
| 368 CompareIC::State left_state, right_state, handler_state; |
| 369 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, |
| 370 &handler_state, NULL); |
| 371 *left_type = CompareIC::StateToType(isolate_, left_state); |
| 372 *right_type = CompareIC::StateToType(isolate_, right_state); |
| 373 *overall_type = CompareIC::StateToType(isolate_, handler_state, map); |
| 374 } else if (code->is_compare_nil_ic_stub()) { |
| 375 CompareNilICStub::State state(code->compare_nil_state()); |
| 376 *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map); |
| 387 } | 377 } |
| 388 } | 378 } |
| 389 | 379 |
| 390 | 380 |
| 391 void TypeFeedbackOracle::CompareType(CompareOperation* expr, | |
| 392 TypeInfo* left_type, | |
| 393 TypeInfo* right_type, | |
| 394 TypeInfo* overall_type) { | |
| 395 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 396 TypeInfo unknown = TypeInfo::Unknown(); | |
| 397 if (!object->IsCode()) { | |
| 398 *left_type = *right_type = *overall_type = unknown; | |
| 399 return; | |
| 400 } | |
| 401 Handle<Code> code = Handle<Code>::cast(object); | |
| 402 if (!code->is_compare_ic_stub()) { | |
| 403 *left_type = *right_type = *overall_type = unknown; | |
| 404 return; | |
| 405 } | |
| 406 | |
| 407 int stub_minor_key = code->stub_info(); | |
| 408 CompareIC::State left_state, right_state, handler_state; | |
| 409 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, | |
| 410 &handler_state, NULL); | |
| 411 *left_type = TypeFromCompareType(left_state); | |
| 412 *right_type = TypeFromCompareType(right_state); | |
| 413 *overall_type = TypeFromCompareType(handler_state); | |
| 414 } | |
| 415 | |
| 416 | |
| 417 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | |
| 418 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 419 if (!object->IsCode()) return Handle<Map>::null(); | |
| 420 Handle<Code> code = Handle<Code>::cast(object); | |
| 421 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | |
| 422 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | |
| 423 if (state != CompareIC::KNOWN_OBJECT) { | |
| 424 return Handle<Map>::null(); | |
| 425 } | |
| 426 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | |
| 427 return map == NULL || CanRetainOtherContext(map, *native_context_) | |
| 428 ? Handle<Map>::null() | |
| 429 : Handle<Map>(map); | |
| 430 } | |
| 431 | |
| 432 | |
| 433 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 381 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { |
| 434 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); | 382 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); |
| 435 TypeInfo unknown = TypeInfo::Unknown(); | 383 TypeInfo unknown = TypeInfo::Unknown(); |
| 436 if (!object->IsCode()) return unknown; | 384 if (!object->IsCode()) return unknown; |
| 437 Handle<Code> code = Handle<Code>::cast(object); | 385 Handle<Code> code = Handle<Code>::cast(object); |
| 438 ASSERT(code->is_unary_op_stub()); | 386 ASSERT(code->is_unary_op_stub()); |
| 439 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 387 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( |
| 440 code->unary_op_type()); | 388 code->unary_op_type()); |
| 441 switch (type) { | 389 switch (type) { |
| 442 case UnaryOpIC::SMI: | 390 case UnaryOpIC::SMI: |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); | 438 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); |
| 491 *fixed_right_arg_value = | 439 *fixed_right_arg_value = |
| 492 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); | 440 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); |
| 493 return; | 441 return; |
| 494 } | 442 } |
| 495 // Not a binary op stub. | 443 // Not a binary op stub. |
| 496 *left = *right = *result = unknown; | 444 *left = *right = *result = unknown; |
| 497 } | 445 } |
| 498 | 446 |
| 499 | 447 |
| 500 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 448 Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) { |
| 501 Handle<Object> object = GetInfo(clause->CompareId()); | 449 Handle<Object> info = GetInfo(id); |
| 502 TypeInfo unknown = TypeInfo::Unknown(); | 450 Handle<Type> result(Type::None(), isolate_); |
| 503 if (!object->IsCode()) return unknown; | 451 if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) { |
| 504 Handle<Code> code = Handle<Code>::cast(object); | 452 Handle<Code> code = Handle<Code>::cast(info); |
| 505 if (!code->is_compare_ic_stub()) return unknown; | 453 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); |
| 506 | 454 result = CompareIC::StateToType(isolate_, state); |
| 507 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | 455 } |
| 508 return TypeFromCompareType(state); | 456 return result; |
| 509 } | 457 } |
| 510 | 458 |
| 511 | 459 |
| 512 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 460 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { |
| 513 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); | 461 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); |
| 514 TypeInfo unknown = TypeInfo::Unknown(); | 462 TypeInfo unknown = TypeInfo::Unknown(); |
| 515 if (!object->IsCode()) return unknown; | 463 if (!object->IsCode()) return unknown; |
| 516 Handle<Code> code = Handle<Code>::cast(object); | 464 Handle<Code> code = Handle<Code>::cast(object); |
| 517 if (!code->is_binary_op_stub()) return unknown; | 465 if (!code->is_binary_op_stub()) return unknown; |
| 518 | 466 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 } | 577 } |
| 630 } | 578 } |
| 631 | 579 |
| 632 | 580 |
| 633 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { | 581 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { |
| 634 Handle<Object> object = GetInfo(id); | 582 Handle<Object> object = GetInfo(id); |
| 635 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 583 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
| 636 } | 584 } |
| 637 | 585 |
| 638 | 586 |
| 639 byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) { | |
| 640 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 641 if (object->IsCode() && | |
| 642 Handle<Code>::cast(object)->is_compare_nil_ic_stub()) { | |
| 643 return Handle<Code>::cast(object)->compare_nil_types(); | |
| 644 } else { | |
| 645 return CompareNilICStub::Types::FullCompare().ToIntegral(); | |
| 646 } | |
| 647 } | |
| 648 | |
| 649 | |
| 650 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 587 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 651 // themselves are not GC-safe, so we first get all infos, then we create the | 588 // themselves are not GC-safe, so we first get all infos, then we create the |
| 652 // dictionary (possibly triggering GC), and finally we relocate the collected | 589 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 653 // infos before we process them. | 590 // infos before we process them. |
| 654 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 591 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 655 DisallowHeapAllocation no_allocation; | 592 DisallowHeapAllocation no_allocation; |
| 656 ZoneList<RelocInfo> infos(16, zone()); | 593 ZoneList<RelocInfo> infos(16, zone()); |
| 657 HandleScope scope(isolate_); | 594 HandleScope scope(isolate_); |
| 658 GetRelocInfos(code, &infos); | 595 GetRelocInfos(code, &infos); |
| 659 CreateDictionary(code, &infos); | 596 CreateDictionary(code, &infos); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 USE(maybe_result); | 715 USE(maybe_result); |
| 779 #ifdef DEBUG | 716 #ifdef DEBUG |
| 780 Object* result = NULL; | 717 Object* result = NULL; |
| 781 // Dictionary has been allocated with sufficient size for all elements. | 718 // Dictionary has been allocated with sufficient size for all elements. |
| 782 ASSERT(maybe_result->ToObject(&result)); | 719 ASSERT(maybe_result->ToObject(&result)); |
| 783 ASSERT(*dictionary_ == result); | 720 ASSERT(*dictionary_ == result); |
| 784 #endif | 721 #endif |
| 785 } | 722 } |
| 786 | 723 |
| 787 } } // namespace v8::internal | 724 } } // namespace v8::internal |
| OLD | NEW |