| 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 |