| 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 Handle<Code> code = Handle<Code>::cast(map_or_code); | 224 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 228 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | 225 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); |
| 229 return map == NULL || CanRetainOtherContext(map, *native_context_) | 226 return map == NULL || CanRetainOtherContext(map, *native_context_) |
| 230 ? Handle<Map>::null() | 227 ? Handle<Map>::null() |
| 231 : Handle<Map>(map); | 228 : Handle<Map>(map); |
| 232 } | 229 } |
| 233 return Handle<Map>::cast(map_or_code); | 230 return Handle<Map>::cast(map_or_code); |
| 234 } | 231 } |
| 235 | 232 |
| 236 | 233 |
| 237 Handle<Map> TypeFeedbackOracle::CompareNilMonomorphicReceiverType( | |
| 238 CompareOperation* expr) { | |
| 239 Handle<Object> maybe_code = GetInfo(expr->CompareOperationFeedbackId()); | |
| 240 if (maybe_code->IsCode()) { | |
| 241 Map* map = Handle<Code>::cast(maybe_code)->FindFirstMap(); | |
| 242 if (map == NULL) return Handle<Map>(); | |
| 243 map = map->CurrentMapForDeprecated(); | |
| 244 return map == NULL || CanRetainOtherContext(map, *native_context_) | |
| 245 ? Handle<Map>() | |
| 246 : Handle<Map>(map); | |
| 247 } else if (maybe_code->IsMap()) { | |
| 248 ASSERT(!Handle<Map>::cast(maybe_code)->is_deprecated()); | |
| 249 return Handle<Map>::cast(maybe_code); | |
| 250 } | |
| 251 return Handle<Map>(); | |
| 252 } | |
| 253 | |
| 254 | |
| 255 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 234 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 256 TypeFeedbackId ast_id) { | 235 TypeFeedbackId ast_id) { |
| 257 Handle<Object> map_or_code = GetInfo(ast_id); | 236 Handle<Object> map_or_code = GetInfo(ast_id); |
| 258 if (map_or_code->IsCode()) { | 237 if (map_or_code->IsCode()) { |
| 259 Handle<Code> code = Handle<Code>::cast(map_or_code); | 238 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 260 if (code->kind() == Code::KEYED_STORE_IC) { | 239 if (code->kind() == Code::KEYED_STORE_IC) { |
| 261 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); | 240 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 262 } | 241 } |
| 263 } | 242 } |
| 264 return STANDARD_STORE; | 243 return STANDARD_STORE; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { | 334 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { |
| 356 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); | 335 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); |
| 357 if (!object->IsCode()) return false; | 336 if (!object->IsCode()) return false; |
| 358 Handle<Code> code = Handle<Code>::cast(object); | 337 Handle<Code> code = Handle<Code>::cast(object); |
| 359 if (!code->is_load_stub()) return false; | 338 if (!code->is_load_stub()) return false; |
| 360 if (code->ic_state() != MONOMORPHIC) return false; | 339 if (code->ic_state() != MONOMORPHIC) return false; |
| 361 return stub->Describes(*code); | 340 return stub->Describes(*code); |
| 362 } | 341 } |
| 363 | 342 |
| 364 | 343 |
| 365 static TypeInfo TypeFromCompareType(CompareIC::State state) { | 344 void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id, |
| 366 switch (state) { | 345 Handle<Type>* left_type, |
| 367 case CompareIC::UNINITIALIZED: | 346 Handle<Type>* right_type, |
| 368 // Uninitialized means never executed. | 347 Handle<Type>* overall_type, |
| 369 return TypeInfo::Uninitialized(); | 348 Handle<Type>* compare_nil_type) { |
| 370 case CompareIC::SMI: | 349 *left_type = *right_type = *overall_type = *compare_nil_type = |
| 371 return TypeInfo::Smi(); | 350 handle(Type::Any(), isolate_); |
| 372 case CompareIC::NUMBER: | 351 Handle<Object> info = GetInfo(id); |
| 373 return TypeInfo::Number(); | 352 if (!info->IsCode()) return; |
| 374 case CompareIC::INTERNALIZED_STRING: | 353 Handle<Code> code = Handle<Code>::cast(info); |
| 375 return TypeInfo::InternalizedString(); | 354 |
| 376 case CompareIC::STRING: | 355 Handle<Map> map; |
| 377 return TypeInfo::String(); | 356 Map* raw_map = code->FindFirstMap(); |
| 378 case CompareIC::OBJECT: | 357 if (raw_map != NULL) { |
| 379 case CompareIC::KNOWN_OBJECT: | 358 raw_map = raw_map->CurrentMapForDeprecated(); |
| 380 // TODO(kasperl): We really need a type for JS objects here. | 359 if (!CanRetainOtherContext(raw_map, *native_context_)) { |
| 381 return TypeInfo::NonPrimitive(); | 360 map = handle(raw_map, isolate_); |
| 382 case CompareIC::GENERIC: | 361 } |
| 383 default: | 362 } |
| 384 return TypeInfo::Unknown(); | 363 |
| 364 if (code->is_compare_ic_stub()) { |
| 365 int stub_minor_key = code->stub_info(); |
| 366 CompareIC::State left_state, right_state, handler_state; |
| 367 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, |
| 368 &handler_state, NULL); |
| 369 *left_type = CompareIC::StateToType(isolate_, left_state); |
| 370 *right_type = CompareIC::StateToType(isolate_, right_state); |
| 371 *overall_type = CompareIC::StateToType(isolate_, handler_state, map); |
| 372 } else if (code->is_compare_nil_ic_stub()) { |
| 373 CompareNilICStub::State state(code->compare_nil_state()); |
| 374 *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map); |
| 385 } | 375 } |
| 386 } | 376 } |
| 387 | 377 |
| 388 | 378 |
| 389 void TypeFeedbackOracle::CompareType(CompareOperation* expr, | |
| 390 TypeInfo* left_type, | |
| 391 TypeInfo* right_type, | |
| 392 TypeInfo* overall_type) { | |
| 393 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 394 TypeInfo unknown = TypeInfo::Unknown(); | |
| 395 if (!object->IsCode()) { | |
| 396 *left_type = *right_type = *overall_type = unknown; | |
| 397 return; | |
| 398 } | |
| 399 Handle<Code> code = Handle<Code>::cast(object); | |
| 400 if (!code->is_compare_ic_stub()) { | |
| 401 *left_type = *right_type = *overall_type = unknown; | |
| 402 return; | |
| 403 } | |
| 404 | |
| 405 int stub_minor_key = code->stub_info(); | |
| 406 CompareIC::State left_state, right_state, handler_state; | |
| 407 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, | |
| 408 &handler_state, NULL); | |
| 409 *left_type = TypeFromCompareType(left_state); | |
| 410 *right_type = TypeFromCompareType(right_state); | |
| 411 *overall_type = TypeFromCompareType(handler_state); | |
| 412 } | |
| 413 | |
| 414 | |
| 415 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | |
| 416 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 417 if (!object->IsCode()) return Handle<Map>::null(); | |
| 418 Handle<Code> code = Handle<Code>::cast(object); | |
| 419 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | |
| 420 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | |
| 421 if (state != CompareIC::KNOWN_OBJECT) { | |
| 422 return Handle<Map>::null(); | |
| 423 } | |
| 424 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | |
| 425 return map == NULL || CanRetainOtherContext(map, *native_context_) | |
| 426 ? Handle<Map>::null() | |
| 427 : Handle<Map>(map); | |
| 428 } | |
| 429 | |
| 430 | |
| 431 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 379 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { |
| 432 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); | 380 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); |
| 433 TypeInfo unknown = TypeInfo::Unknown(); | 381 TypeInfo unknown = TypeInfo::Unknown(); |
| 434 if (!object->IsCode()) return unknown; | 382 if (!object->IsCode()) return unknown; |
| 435 Handle<Code> code = Handle<Code>::cast(object); | 383 Handle<Code> code = Handle<Code>::cast(object); |
| 436 ASSERT(code->is_unary_op_stub()); | 384 ASSERT(code->is_unary_op_stub()); |
| 437 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 385 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( |
| 438 code->unary_op_type()); | 386 code->unary_op_type()); |
| 439 switch (type) { | 387 switch (type) { |
| 440 case UnaryOpIC::SMI: | 388 case UnaryOpIC::SMI: |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); | 436 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); |
| 489 *fixed_right_arg_value = | 437 *fixed_right_arg_value = |
| 490 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); | 438 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); |
| 491 return; | 439 return; |
| 492 } | 440 } |
| 493 // Not a binary op stub. | 441 // Not a binary op stub. |
| 494 *left = *right = *result = unknown; | 442 *left = *right = *result = unknown; |
| 495 } | 443 } |
| 496 | 444 |
| 497 | 445 |
| 498 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 446 Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) { |
| 499 Handle<Object> object = GetInfo(clause->CompareId()); | 447 Handle<Object> info = GetInfo(id); |
| 500 TypeInfo unknown = TypeInfo::Unknown(); | 448 Handle<Type> result(Type::None(), isolate_); |
| 501 if (!object->IsCode()) return unknown; | 449 if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) { |
| 502 Handle<Code> code = Handle<Code>::cast(object); | 450 Handle<Code> code = Handle<Code>::cast(info); |
| 503 if (!code->is_compare_ic_stub()) return unknown; | 451 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); |
| 504 | 452 result = CompareIC::StateToType(isolate_, state); |
| 505 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | 453 } |
| 506 return TypeFromCompareType(state); | 454 return result; |
| 507 } | 455 } |
| 508 | 456 |
| 509 | 457 |
| 510 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 458 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { |
| 511 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); | 459 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); |
| 512 TypeInfo unknown = TypeInfo::Unknown(); | 460 TypeInfo unknown = TypeInfo::Unknown(); |
| 513 if (!object->IsCode()) return unknown; | 461 if (!object->IsCode()) return unknown; |
| 514 Handle<Code> code = Handle<Code>::cast(object); | 462 Handle<Code> code = Handle<Code>::cast(object); |
| 515 if (!code->is_binary_op_stub()) return unknown; | 463 if (!code->is_binary_op_stub()) return unknown; |
| 516 | 464 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 } | 575 } |
| 628 } | 576 } |
| 629 | 577 |
| 630 | 578 |
| 631 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { | 579 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { |
| 632 Handle<Object> object = GetInfo(id); | 580 Handle<Object> object = GetInfo(id); |
| 633 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 581 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
| 634 } | 582 } |
| 635 | 583 |
| 636 | 584 |
| 637 byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) { | |
| 638 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 639 if (object->IsCode() && | |
| 640 Handle<Code>::cast(object)->is_compare_nil_ic_stub()) { | |
| 641 return Handle<Code>::cast(object)->compare_nil_types(); | |
| 642 } else { | |
| 643 return CompareNilICStub::Types::FullCompare().ToIntegral(); | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 | |
| 648 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 585 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 649 // themselves are not GC-safe, so we first get all infos, then we create the | 586 // themselves are not GC-safe, so we first get all infos, then we create the |
| 650 // dictionary (possibly triggering GC), and finally we relocate the collected | 587 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 651 // infos before we process them. | 588 // infos before we process them. |
| 652 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 589 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 653 DisallowHeapAllocation no_allocation; | 590 DisallowHeapAllocation no_allocation; |
| 654 ZoneList<RelocInfo> infos(16, zone()); | 591 ZoneList<RelocInfo> infos(16, zone()); |
| 655 HandleScope scope(isolate_); | 592 HandleScope scope(isolate_); |
| 656 GetRelocInfos(code, &infos); | 593 GetRelocInfos(code, &infos); |
| 657 CreateDictionary(code, &infos); | 594 CreateDictionary(code, &infos); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 USE(maybe_result); | 713 USE(maybe_result); |
| 777 #ifdef DEBUG | 714 #ifdef DEBUG |
| 778 Object* result = NULL; | 715 Object* result = NULL; |
| 779 // Dictionary has been allocated with sufficient size for all elements. | 716 // Dictionary has been allocated with sufficient size for all elements. |
| 780 ASSERT(maybe_result->ToObject(&result)); | 717 ASSERT(maybe_result->ToObject(&result)); |
| 781 ASSERT(*dictionary_ == result); | 718 ASSERT(*dictionary_ == result); |
| 782 #endif | 719 #endif |
| 783 } | 720 } |
| 784 | 721 |
| 785 } } // namespace v8::internal | 722 } } // namespace v8::internal |
| OLD | NEW |