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 #ifndef V8_HYDROGEN_H_ | 5 #ifndef V8_HYDROGEN_H_ |
6 #define V8_HYDROGEN_H_ | 6 #define V8_HYDROGEN_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 2412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 HValue* object, HIfContinuation* continuation); | 2423 HValue* object, HIfContinuation* continuation); |
2424 | 2424 |
2425 Handle<JSFunction> array_function() { | 2425 Handle<JSFunction> array_function() { |
2426 return handle(isolate()->native_context()->array_function()); | 2426 return handle(isolate()->native_context()->array_function()); |
2427 } | 2427 } |
2428 | 2428 |
2429 bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site); | 2429 bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site); |
2430 void BuildInlinedCallArray(Expression* expression, int argument_count, | 2430 void BuildInlinedCallArray(Expression* expression, int argument_count, |
2431 Handle<AllocationSite> site); | 2431 Handle<AllocationSite> site); |
2432 | 2432 |
2433 class LookupResult FINAL BASE_EMBEDDED { | |
2434 public: | |
2435 LookupResult() | |
2436 : lookup_type_(NOT_FOUND), | |
2437 details_(NONE, DATA, Representation::None()) {} | |
2438 | |
2439 void LookupDescriptor(Map* map, Name* name) { | |
2440 DescriptorArray* descriptors = map->instance_descriptors(); | |
2441 int number = descriptors->SearchWithCache(name, map); | |
2442 if (number == DescriptorArray::kNotFound) return NotFound(); | |
2443 lookup_type_ = DESCRIPTOR_TYPE; | |
2444 details_ = descriptors->GetDetails(number); | |
2445 number_ = number; | |
2446 } | |
2447 | |
2448 void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) { | |
2449 int transition_index = map->SearchTransition(kData, name, attributes); | |
2450 if (transition_index == TransitionArray::kNotFound) return NotFound(); | |
2451 lookup_type_ = TRANSITION_TYPE; | |
2452 transition_ = handle(map->GetTransition(transition_index)); | |
2453 number_ = transition_->LastAdded(); | |
2454 details_ = transition_->instance_descriptors()->GetDetails(number_); | |
2455 } | |
2456 | |
2457 void NotFound() { | |
2458 lookup_type_ = NOT_FOUND; | |
2459 details_ = PropertyDetails(NONE, DATA, 0); | |
2460 } | |
2461 | |
2462 Representation representation() const { | |
2463 DCHECK(IsFound()); | |
2464 return details_.representation(); | |
2465 } | |
2466 | |
2467 // Property callbacks does not include transitions to callbacks. | |
2468 bool IsAccessorConstant() const { | |
2469 return !IsTransition() && details_.type() == ACCESSOR_CONSTANT; | |
2470 } | |
2471 | |
2472 bool IsReadOnly() const { | |
2473 DCHECK(IsFound()); | |
2474 return details_.IsReadOnly(); | |
2475 } | |
2476 | |
2477 bool IsData() const { | |
2478 return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA; | |
2479 } | |
2480 | |
2481 bool IsDataConstant() const { | |
2482 return lookup_type_ == DESCRIPTOR_TYPE && | |
2483 details_.type() == DATA_CONSTANT; | |
2484 } | |
2485 | |
2486 bool IsConfigurable() const { return details_.IsConfigurable(); } | |
2487 bool IsFound() const { return lookup_type_ != NOT_FOUND; } | |
2488 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; } | |
2489 | |
2490 // Is the result is a property excluding transitions and the null | |
2491 // descriptor? | |
2492 bool IsProperty() const { return IsFound() && !IsTransition(); } | |
2493 | |
2494 Handle<Map> GetTransitionTarget() const { | |
2495 DCHECK(IsTransition()); | |
2496 return transition_; | |
2497 } | |
2498 | |
2499 bool IsTransitionToData() const { | |
2500 return IsTransition() && details_.type() == DATA; | |
2501 } | |
2502 | |
2503 int GetLocalFieldIndexFromMap(Map* map) const { | |
2504 return GetFieldIndexFromMap(map) - map->inobject_properties(); | |
2505 } | |
2506 | |
2507 Object* GetConstantFromMap(Map* map) const { | |
2508 DCHECK(details_.type() == DATA_CONSTANT); | |
2509 return GetValueFromMap(map); | |
2510 } | |
2511 | |
2512 Object* GetValueFromMap(Map* map) const { | |
2513 DCHECK(lookup_type_ == DESCRIPTOR_TYPE || | |
2514 lookup_type_ == TRANSITION_TYPE); | |
2515 DCHECK(number_ < map->NumberOfOwnDescriptors()); | |
2516 return map->instance_descriptors()->GetValue(number_); | |
2517 } | |
2518 | |
2519 int GetFieldIndexFromMap(Map* map) const { | |
2520 DCHECK(lookup_type_ == DESCRIPTOR_TYPE || | |
2521 lookup_type_ == TRANSITION_TYPE); | |
2522 DCHECK(number_ < map->NumberOfOwnDescriptors()); | |
2523 return map->instance_descriptors()->GetFieldIndex(number_); | |
2524 } | |
2525 | |
2526 HeapType* GetFieldTypeFromMap(Map* map) const { | |
2527 DCHECK_NE(NOT_FOUND, lookup_type_); | |
2528 DCHECK(number_ < map->NumberOfOwnDescriptors()); | |
2529 return map->instance_descriptors()->GetFieldType(number_); | |
2530 } | |
2531 | |
2532 Map* GetFieldOwnerFromMap(Map* map) const { | |
2533 DCHECK(lookup_type_ == DESCRIPTOR_TYPE || | |
2534 lookup_type_ == TRANSITION_TYPE); | |
2535 DCHECK(number_ < map->NumberOfOwnDescriptors()); | |
2536 return map->FindFieldOwner(number_); | |
2537 } | |
2538 | |
2539 private: | |
2540 // Where did we find the result; | |
2541 enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_; | |
2542 | |
2543 Handle<Map> transition_; | |
2544 int number_; | |
2545 PropertyDetails details_; | |
2546 }; | |
2547 | |
2548 class PropertyAccessInfo { | 2433 class PropertyAccessInfo { |
2549 public: | 2434 public: |
2550 PropertyAccessInfo(HOptimizedGraphBuilder* builder, | 2435 PropertyAccessInfo(HOptimizedGraphBuilder* builder, |
2551 PropertyAccessType access_type, Handle<Map> map, | 2436 PropertyAccessType access_type, Handle<Map> map, |
2552 Handle<String> name) | 2437 Handle<String> name) |
2553 : builder_(builder), | 2438 : builder_(builder), |
2554 access_type_(access_type), | 2439 access_type_(access_type), |
2555 map_(map), | 2440 map_(map), |
2556 name_(name), | 2441 name_(name), |
2557 field_type_(HType::Tagged()), | 2442 field_type_(HType::Tagged()), |
2558 access_(HObjectAccess::ForMap()) {} | 2443 access_(HObjectAccess::ForMap()), |
| 2444 lookup_type_(NOT_FOUND), |
| 2445 details_(NONE, DATA, Representation::None()) {} |
2559 | 2446 |
2560 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic | 2447 // Checkes whether this PropertyAccessInfo can be handled as a monomorphic |
2561 // load named. It additionally fills in the fields necessary to generate the | 2448 // load named. It additionally fills in the fields necessary to generate the |
2562 // lookup code. | 2449 // lookup code. |
2563 bool CanAccessMonomorphic(); | 2450 bool CanAccessMonomorphic(); |
2564 | 2451 |
2565 // Checks whether all types behave uniform when loading name. If all maps | 2452 // Checks whether all types behave uniform when loading name. If all maps |
2566 // behave the same, a single monomorphic load instruction can be emitted, | 2453 // behave the same, a single monomorphic load instruction can be emitted, |
2567 // guarded by a single map-checks instruction that whether the receiver is | 2454 // guarded by a single map-checks instruction that whether the receiver is |
2568 // an instance of any of the types. | 2455 // an instance of any of the types. |
(...skipping 28 matching lines...) Expand all Loading... |
2597 return false; | 2484 return false; |
2598 } | 2485 } |
2599 | 2486 |
2600 bool has_holder() { return !holder_.is_null(); } | 2487 bool has_holder() { return !holder_.is_null(); } |
2601 bool IsLoad() const { return access_type_ == LOAD; } | 2488 bool IsLoad() const { return access_type_ == LOAD; } |
2602 | 2489 |
2603 Isolate* isolate() const { return builder_->isolate(); } | 2490 Isolate* isolate() const { return builder_->isolate(); } |
2604 Handle<JSObject> holder() { return holder_; } | 2491 Handle<JSObject> holder() { return holder_; } |
2605 Handle<JSFunction> accessor() { return accessor_; } | 2492 Handle<JSFunction> accessor() { return accessor_; } |
2606 Handle<Object> constant() { return constant_; } | 2493 Handle<Object> constant() { return constant_; } |
2607 Handle<Map> transition() { return lookup_.GetTransitionTarget(); } | 2494 Handle<Map> transition() { return transition_; } |
2608 SmallMapList* field_maps() { return &field_maps_; } | 2495 SmallMapList* field_maps() { return &field_maps_; } |
2609 HType field_type() const { return field_type_; } | 2496 HType field_type() const { return field_type_; } |
2610 HObjectAccess access() { return access_; } | 2497 HObjectAccess access() { return access_; } |
2611 | 2498 |
2612 bool IsFound() const { return lookup_.IsFound(); } | 2499 bool IsFound() const { return lookup_type_ != NOT_FOUND; } |
2613 bool IsProperty() const { return lookup_.IsProperty(); } | 2500 bool IsProperty() const { return IsFound() && !IsTransition(); } |
2614 bool IsData() const { return lookup_.IsData(); } | 2501 bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; } |
2615 bool IsDataConstant() const { return lookup_.IsDataConstant(); } | 2502 bool IsData() const { |
2616 bool IsAccessorConstant() const { return lookup_.IsAccessorConstant(); } | 2503 return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA; |
2617 bool IsTransition() const { return lookup_.IsTransition(); } | 2504 } |
2618 | 2505 bool IsDataConstant() const { |
2619 bool IsConfigurable() const { return lookup_.IsConfigurable(); } | 2506 return lookup_type_ == DESCRIPTOR_TYPE && |
2620 bool IsReadOnly() const { return lookup_.IsReadOnly(); } | 2507 details_.type() == DATA_CONSTANT; |
| 2508 } |
| 2509 bool IsAccessorConstant() const { |
| 2510 return !IsTransition() && details_.type() == ACCESSOR_CONSTANT; |
| 2511 } |
| 2512 bool IsConfigurable() const { return details_.IsConfigurable(); } |
| 2513 bool IsReadOnly() const { return details_.IsReadOnly(); } |
2621 | 2514 |
2622 bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; } | 2515 bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; } |
2623 bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; } | 2516 bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; } |
2624 bool IsValueWrapped() { return IsStringType() || IsNumberType(); } | 2517 bool IsValueWrapped() { return IsStringType() || IsNumberType(); } |
2625 bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; } | 2518 bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; } |
2626 | 2519 |
2627 private: | 2520 private: |
| 2521 Handle<Object> GetConstantFromMap(Handle<Map> map) const { |
| 2522 DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_); |
| 2523 DCHECK(number_ < map->NumberOfOwnDescriptors()); |
| 2524 return handle(map->instance_descriptors()->GetValue(number_), isolate()); |
| 2525 } |
2628 Handle<Object> GetAccessorsFromMap(Handle<Map> map) const { | 2526 Handle<Object> GetAccessorsFromMap(Handle<Map> map) const { |
2629 return handle(lookup_.GetValueFromMap(*map), isolate()); | 2527 return GetConstantFromMap(map); |
2630 } | |
2631 Handle<Object> GetConstantFromMap(Handle<Map> map) const { | |
2632 return handle(lookup_.GetConstantFromMap(*map), isolate()); | |
2633 } | 2528 } |
2634 Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const { | 2529 Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const { |
2635 return handle(lookup_.GetFieldTypeFromMap(*map), isolate()); | 2530 DCHECK(IsFound()); |
| 2531 DCHECK(number_ < map->NumberOfOwnDescriptors()); |
| 2532 return handle(map->instance_descriptors()->GetFieldType(number_), |
| 2533 isolate()); |
2636 } | 2534 } |
2637 Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const { | 2535 Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const { |
2638 return handle(lookup_.GetFieldOwnerFromMap(*map)); | 2536 DCHECK(IsFound()); |
| 2537 DCHECK(number_ < map->NumberOfOwnDescriptors()); |
| 2538 return handle(map->FindFieldOwner(number_)); |
2639 } | 2539 } |
2640 int GetLocalFieldIndexFromMap(Handle<Map> map) const { | 2540 int GetLocalFieldIndexFromMap(Handle<Map> map) const { |
2641 return lookup_.GetLocalFieldIndexFromMap(*map); | 2541 DCHECK(lookup_type_ == DESCRIPTOR_TYPE || |
| 2542 lookup_type_ == TRANSITION_TYPE); |
| 2543 DCHECK(number_ < map->NumberOfOwnDescriptors()); |
| 2544 int field_index = map->instance_descriptors()->GetFieldIndex(number_); |
| 2545 return field_index - map->inobject_properties(); |
2642 } | 2546 } |
2643 Representation representation() const { return lookup_.representation(); } | 2547 |
| 2548 void LookupDescriptor(Map* map, Name* name) { |
| 2549 DescriptorArray* descriptors = map->instance_descriptors(); |
| 2550 int number = descriptors->SearchWithCache(name, map); |
| 2551 if (number == DescriptorArray::kNotFound) return NotFound(); |
| 2552 lookup_type_ = DESCRIPTOR_TYPE; |
| 2553 details_ = descriptors->GetDetails(number); |
| 2554 number_ = number; |
| 2555 } |
| 2556 void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) { |
| 2557 int transition_index = map->SearchTransition(kData, name, attributes); |
| 2558 if (transition_index == TransitionArray::kNotFound) return NotFound(); |
| 2559 lookup_type_ = TRANSITION_TYPE; |
| 2560 transition_ = handle(map->GetTransition(transition_index)); |
| 2561 number_ = transition_->LastAdded(); |
| 2562 details_ = transition_->instance_descriptors()->GetDetails(number_); |
| 2563 } |
| 2564 void NotFound() { |
| 2565 lookup_type_ = NOT_FOUND; |
| 2566 details_ = PropertyDetails(NONE, DATA, 0); |
| 2567 } |
| 2568 Representation representation() const { |
| 2569 DCHECK(IsFound()); |
| 2570 return details_.representation(); |
| 2571 } |
| 2572 bool IsTransitionToData() const { |
| 2573 return IsTransition() && details_.type() == DATA; |
| 2574 } |
2644 | 2575 |
2645 Zone* zone() { return builder_->zone(); } | 2576 Zone* zone() { return builder_->zone(); } |
2646 CompilationInfo* top_info() { return builder_->top_info(); } | 2577 CompilationInfo* top_info() { return builder_->top_info(); } |
2647 CompilationInfo* current_info() { return builder_->current_info(); } | 2578 CompilationInfo* current_info() { return builder_->current_info(); } |
2648 | 2579 |
2649 bool LoadResult(Handle<Map> map); | 2580 bool LoadResult(Handle<Map> map); |
2650 void LoadFieldMaps(Handle<Map> map); | 2581 void LoadFieldMaps(Handle<Map> map); |
2651 bool LookupDescriptor(); | 2582 bool LookupDescriptor(); |
2652 bool LookupInPrototypes(); | 2583 bool LookupInPrototypes(); |
2653 bool IsCompatible(PropertyAccessInfo* other); | 2584 bool IsCompatible(PropertyAccessInfo* other); |
2654 | 2585 |
2655 void GeneralizeRepresentation(Representation r) { | 2586 void GeneralizeRepresentation(Representation r) { |
2656 access_ = access_.WithRepresentation( | 2587 access_ = access_.WithRepresentation( |
2657 access_.representation().generalize(r)); | 2588 access_.representation().generalize(r)); |
2658 } | 2589 } |
2659 | 2590 |
2660 LookupResult lookup_; | |
2661 HOptimizedGraphBuilder* builder_; | 2591 HOptimizedGraphBuilder* builder_; |
2662 PropertyAccessType access_type_; | 2592 PropertyAccessType access_type_; |
2663 Handle<Map> map_; | 2593 Handle<Map> map_; |
2664 Handle<String> name_; | 2594 Handle<String> name_; |
2665 Handle<JSObject> holder_; | 2595 Handle<JSObject> holder_; |
2666 Handle<JSFunction> accessor_; | 2596 Handle<JSFunction> accessor_; |
2667 Handle<JSObject> api_holder_; | 2597 Handle<JSObject> api_holder_; |
2668 Handle<Object> constant_; | 2598 Handle<Object> constant_; |
2669 SmallMapList field_maps_; | 2599 SmallMapList field_maps_; |
2670 HType field_type_; | 2600 HType field_type_; |
2671 HObjectAccess access_; | 2601 HObjectAccess access_; |
| 2602 |
| 2603 enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_; |
| 2604 Handle<Map> transition_; |
| 2605 int number_; |
| 2606 PropertyDetails details_; |
2672 }; | 2607 }; |
2673 | 2608 |
2674 HInstruction* BuildMonomorphicAccess(PropertyAccessInfo* info, | 2609 HInstruction* BuildMonomorphicAccess(PropertyAccessInfo* info, |
2675 HValue* object, | 2610 HValue* object, |
2676 HValue* checked_object, | 2611 HValue* checked_object, |
2677 HValue* value, | 2612 HValue* value, |
2678 BailoutId ast_id, | 2613 BailoutId ast_id, |
2679 BailoutId return_id, | 2614 BailoutId return_id, |
2680 bool can_inline_accessor = true); | 2615 bool can_inline_accessor = true); |
2681 | 2616 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3032 } | 2967 } |
3033 | 2968 |
3034 private: | 2969 private: |
3035 HGraphBuilder* builder_; | 2970 HGraphBuilder* builder_; |
3036 }; | 2971 }; |
3037 | 2972 |
3038 | 2973 |
3039 } } // namespace v8::internal | 2974 } } // namespace v8::internal |
3040 | 2975 |
3041 #endif // V8_HYDROGEN_H_ | 2976 #endif // V8_HYDROGEN_H_ |
OLD | NEW |