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 |