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 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
633 receiver, result->GetCallbackObject(), name); | 633 receiver, result->GetCallbackObject(), name); |
634 case HANDLER: | 634 case HANDLER: |
635 return result->proxy()->GetPropertyWithHandler(receiver, name); | 635 return result->proxy()->GetPropertyWithHandler(receiver, name); |
636 case INTERCEPTOR: { | 636 case INTERCEPTOR: { |
637 JSObject* recvr = JSObject::cast(receiver); | 637 JSObject* recvr = JSObject::cast(receiver); |
638 return result->holder()->GetPropertyWithInterceptor( | 638 return result->holder()->GetPropertyWithInterceptor( |
639 recvr, name, attributes); | 639 recvr, name, attributes); |
640 } | 640 } |
641 case MAP_TRANSITION: | 641 case MAP_TRANSITION: |
642 case CONSTANT_TRANSITION: | 642 case CONSTANT_TRANSITION: |
643 case NULL_DESCRIPTOR: | 643 break; |
644 case NONEXISTENT: | |
645 UNREACHABLE(); | |
644 break; | 646 break; |
645 } | 647 } |
646 UNREACHABLE(); | 648 UNREACHABLE(); |
647 return NULL; | 649 return NULL; |
648 } | 650 } |
649 | 651 |
650 | 652 |
651 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { | 653 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { |
652 Heap* heap = IsSmi() | 654 Heap* heap = IsSmi() |
653 ? Isolate::Current()->heap() | 655 ? Isolate::Current()->heap() |
(...skipping 1492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2146 *done = true; | 2148 *done = true; |
2147 return SetPropertyWithCallback(result.GetCallbackObject(), | 2149 return SetPropertyWithCallback(result.GetCallbackObject(), |
2148 name, value, result.holder(), strict_mode); | 2150 name, value, result.holder(), strict_mode); |
2149 } | 2151 } |
2150 case HANDLER: { | 2152 case HANDLER: { |
2151 return result.proxy()->SetPropertyViaPrototypesWithHandler( | 2153 return result.proxy()->SetPropertyViaPrototypesWithHandler( |
2152 this, name, value, attributes, strict_mode, done); | 2154 this, name, value, attributes, strict_mode, done); |
2153 } | 2155 } |
2154 case MAP_TRANSITION: | 2156 case MAP_TRANSITION: |
2155 case CONSTANT_TRANSITION: | 2157 case CONSTANT_TRANSITION: |
2156 case NULL_DESCRIPTOR: | 2158 break; |
2159 case NONEXISTENT: | |
2160 UNREACHABLE(); | |
2157 break; | 2161 break; |
2158 } | 2162 } |
2159 } | 2163 } |
2160 | 2164 |
2161 // If we get here with *done true, we have encountered a read-only property. | 2165 // If we get here with *done true, we have encountered a read-only property. |
2162 if (!FLAG_es5_readonly) *done = false; | 2166 if (!FLAG_es5_readonly) *done = false; |
2163 if (*done) { | 2167 if (*done) { |
2164 if (strict_mode == kNonStrictMode) return value; | 2168 if (strict_mode == kNonStrictMode) return value; |
2165 Handle<Object> args[] = { Handle<Object>(name), Handle<Object>(this)}; | 2169 Handle<Object> args[] = { Handle<Object>(name), Handle<Object>(this)}; |
2166 return isolate->Throw(*isolate->factory()->NewTypeError( | 2170 return isolate->Throw(*isolate->factory()->NewTypeError( |
(...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2928 JSFunction* function = | 2932 JSFunction* function = |
2929 JSFunction::cast(target_descriptors->GetValue(number)); | 2933 JSFunction::cast(target_descriptors->GetValue(number)); |
2930 if (value == function) { | 2934 if (value == function) { |
2931 set_map(target_map); | 2935 set_map(target_map); |
2932 return value; | 2936 return value; |
2933 } | 2937 } |
2934 // Otherwise, replace with a MAP_TRANSITION to a new map with a | 2938 // Otherwise, replace with a MAP_TRANSITION to a new map with a |
2935 // FIELD, even if the value is a constant function. | 2939 // FIELD, even if the value is a constant function. |
2936 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 2940 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
2937 } | 2941 } |
2938 case NULL_DESCRIPTOR: | |
2939 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | |
2940 case HANDLER: | 2942 case HANDLER: |
2943 case NONEXISTENT: | |
2941 UNREACHABLE(); | 2944 UNREACHABLE(); |
2942 return value; | 2945 return value; |
2943 } | 2946 } |
2944 UNREACHABLE(); // keep the compiler happy | 2947 UNREACHABLE(); // keep the compiler happy |
2945 return value; | 2948 return value; |
2946 } | 2949 } |
2947 | 2950 |
2948 | 2951 |
2949 // Set a real local property, even if it is READ_ONLY. If the property is not | 2952 // Set a real local property, even if it is READ_ONLY. If the property is not |
2950 // present, add it with attributes NONE. This code is an exact clone of | 2953 // present, add it with attributes NONE. This code is an exact clone of |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3026 // Preserve the attributes of this existing property. | 3029 // Preserve the attributes of this existing property. |
3027 attributes = result.GetAttributes(); | 3030 attributes = result.GetAttributes(); |
3028 return ConvertDescriptorToField(name, value, attributes); | 3031 return ConvertDescriptorToField(name, value, attributes); |
3029 case CALLBACKS: | 3032 case CALLBACKS: |
3030 case INTERCEPTOR: | 3033 case INTERCEPTOR: |
3031 // Override callback in clone | 3034 // Override callback in clone |
3032 return ConvertDescriptorToField(name, value, attributes); | 3035 return ConvertDescriptorToField(name, value, attributes); |
3033 case CONSTANT_TRANSITION: | 3036 case CONSTANT_TRANSITION: |
3034 // Replace with a MAP_TRANSITION to a new map with a FIELD, even | 3037 // Replace with a MAP_TRANSITION to a new map with a FIELD, even |
3035 // if the value is a function. | 3038 // if the value is a function. |
3036 case NULL_DESCRIPTOR: | |
3037 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 3039 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
3038 case HANDLER: | 3040 case HANDLER: |
3041 case NONEXISTENT: | |
3039 UNREACHABLE(); | 3042 UNREACHABLE(); |
3040 } | 3043 } |
3041 UNREACHABLE(); // keep the compiler happy | 3044 UNREACHABLE(); // keep the compiler happy |
3042 return value; | 3045 return value; |
3043 } | 3046 } |
3044 | 3047 |
3045 | 3048 |
3046 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 3049 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
3047 JSObject* receiver, | 3050 JSObject* receiver, |
3048 String* name, | 3051 String* name, |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3321 AccessorPair::cast(value)->CopyWithoutTransitions(); | 3324 AccessorPair::cast(value)->CopyWithoutTransitions(); |
3322 if (!maybe_copy->To(&value)) return maybe_copy; | 3325 if (!maybe_copy->To(&value)) return maybe_copy; |
3323 } | 3326 } |
3324 MaybeObject* maybe_dictionary = | 3327 MaybeObject* maybe_dictionary = |
3325 dictionary->Add(descs->GetKey(i), value, details); | 3328 dictionary->Add(descs->GetKey(i), value, details); |
3326 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 3329 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
3327 break; | 3330 break; |
3328 } | 3331 } |
3329 case MAP_TRANSITION: | 3332 case MAP_TRANSITION: |
3330 case CONSTANT_TRANSITION: | 3333 case CONSTANT_TRANSITION: |
3331 case NULL_DESCRIPTOR: | |
3332 case INTERCEPTOR: | 3334 case INTERCEPTOR: |
3333 break; | 3335 break; |
3334 case HANDLER: | 3336 case HANDLER: |
3335 case NORMAL: | 3337 case NORMAL: |
3338 case NONEXISTENT: | |
3336 UNREACHABLE(); | 3339 UNREACHABLE(); |
3337 break; | 3340 break; |
3338 } | 3341 } |
3339 } | 3342 } |
3340 | 3343 |
3341 Heap* current_heap = GetHeap(); | 3344 Heap* current_heap = GetHeap(); |
3342 | 3345 |
3343 // Copy the next enumeration index from instance descriptor. | 3346 // Copy the next enumeration index from instance descriptor. |
3344 int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); | 3347 int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); |
3345 dictionary->SetNextEnumerationIndex(index); | 3348 dictionary->SetNextEnumerationIndex(index); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3669 // hidden symbols hash code is zero (and no other string has hash | 3672 // hidden symbols hash code is zero (and no other string has hash |
3670 // code zero) it will always occupy the first entry if present. | 3673 // code zero) it will always occupy the first entry if present. |
3671 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3674 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
3672 if ((descriptors->number_of_descriptors() > 0) && | 3675 if ((descriptors->number_of_descriptors() > 0) && |
3673 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { | 3676 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { |
3674 if (descriptors->GetType(0) == FIELD) { | 3677 if (descriptors->GetType(0) == FIELD) { |
3675 Object* hidden_store = | 3678 Object* hidden_store = |
3676 this->FastPropertyAt(descriptors->GetFieldIndex(0)); | 3679 this->FastPropertyAt(descriptors->GetFieldIndex(0)); |
3677 return StringDictionary::cast(hidden_store); | 3680 return StringDictionary::cast(hidden_store); |
3678 } else { | 3681 } else { |
3679 ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR || | 3682 ASSERT(descriptors->GetType(0) == MAP_TRANSITION); |
3680 descriptors->GetType(0) == MAP_TRANSITION); | |
3681 } | 3683 } |
3682 } | 3684 } |
3683 } else { | 3685 } else { |
3684 PropertyAttributes attributes; | 3686 PropertyAttributes attributes; |
3685 // You can't install a getter on a property indexed by the hidden symbol, | 3687 // You can't install a getter on a property indexed by the hidden symbol, |
3686 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 3688 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
3687 // object. | 3689 // object. |
3688 Object* lookup = | 3690 Object* lookup = |
3689 GetLocalPropertyPostInterceptor(this, | 3691 GetLocalPropertyPostInterceptor(this, |
3690 GetHeap()->hidden_symbol(), | 3692 GetHeap()->hidden_symbol(), |
(...skipping 27 matching lines...) Expand all Loading... | |
3718 // in the descriptor array matches the hidden symbol. Since the | 3720 // in the descriptor array matches the hidden symbol. Since the |
3719 // hidden symbols hash code is zero (and no other string has hash | 3721 // hidden symbols hash code is zero (and no other string has hash |
3720 // code zero) it will always occupy the first entry if present. | 3722 // code zero) it will always occupy the first entry if present. |
3721 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3723 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
3722 if ((descriptors->number_of_descriptors() > 0) && | 3724 if ((descriptors->number_of_descriptors() > 0) && |
3723 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { | 3725 (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) { |
3724 if (descriptors->GetType(0) == FIELD) { | 3726 if (descriptors->GetType(0) == FIELD) { |
3725 this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary); | 3727 this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary); |
3726 return this; | 3728 return this; |
3727 } else { | 3729 } else { |
3728 ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR || | 3730 ASSERT(descriptors->GetType(0) == MAP_TRANSITION); |
3729 descriptors->GetType(0) == MAP_TRANSITION); | |
3730 } | 3731 } |
3731 } | 3732 } |
3732 } | 3733 } |
3733 MaybeObject* store_result = | 3734 MaybeObject* store_result = |
3734 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), | 3735 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), |
3735 dictionary, | 3736 dictionary, |
3736 DONT_ENUM, | 3737 DONT_ENUM, |
3737 kNonStrictMode, | 3738 kNonStrictMode, |
3738 OMIT_EXTENSIBILITY_CHECK); | 3739 OMIT_EXTENSIBILITY_CHECK); |
3739 if (store_result->IsFailure()) return store_result; | 3740 if (store_result->IsFailure()) return store_result; |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4166 result++; | 4167 result++; |
4167 } | 4168 } |
4168 } | 4169 } |
4169 return result; | 4170 return result; |
4170 } | 4171 } |
4171 | 4172 |
4172 | 4173 |
4173 int Map::PropertyIndexFor(String* name) { | 4174 int Map::PropertyIndexFor(String* name) { |
4174 DescriptorArray* descs = instance_descriptors(); | 4175 DescriptorArray* descs = instance_descriptors(); |
4175 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4176 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
4176 if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) { | 4177 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); |
4177 return descs->GetFieldIndex(i); | |
4178 } | |
4179 } | 4178 } |
4180 return -1; | 4179 return -1; |
4181 } | 4180 } |
4182 | 4181 |
4183 | 4182 |
4184 int Map::NextFreePropertyIndex() { | 4183 int Map::NextFreePropertyIndex() { |
4185 int max_index = -1; | 4184 int max_index = -1; |
4186 DescriptorArray* descs = instance_descriptors(); | 4185 DescriptorArray* descs = instance_descriptors(); |
4187 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4186 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
4188 if (descs->GetType(i) == FIELD) { | 4187 if (descs->GetType(i) == FIELD) { |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5075 *DescriptorArrayHeader() = Smi::FromInt(raw_index); | 5074 *DescriptorArrayHeader() = Smi::FromInt(raw_index); |
5076 return static_cast<Map*>(accessor); | 5075 return static_cast<Map*>(accessor); |
5077 } | 5076 } |
5078 break; | 5077 break; |
5079 } | 5078 } |
5080 case NORMAL: | 5079 case NORMAL: |
5081 case FIELD: | 5080 case FIELD: |
5082 case CONSTANT_FUNCTION: | 5081 case CONSTANT_FUNCTION: |
5083 case HANDLER: | 5082 case HANDLER: |
5084 case INTERCEPTOR: | 5083 case INTERCEPTOR: |
5085 case NULL_DESCRIPTOR: | |
5086 // We definitely have no map transition. | 5084 // We definitely have no map transition. |
5087 raw_index += 2; | 5085 raw_index += 2; |
5088 ++index; | 5086 ++index; |
5089 break; | 5087 break; |
5088 case NONEXISTENT: | |
5089 UNREACHABLE(); | |
5090 break; | |
5090 } | 5091 } |
5091 } | 5092 } |
5092 if (index == descriptor_array_->number_of_descriptors()) { | 5093 if (index == descriptor_array_->number_of_descriptors()) { |
5093 Map* elements_transition = descriptor_array_->elements_transition_map(); | 5094 Map* elements_transition = descriptor_array_->elements_transition_map(); |
5094 if (elements_transition != NULL) { | 5095 if (elements_transition != NULL) { |
5095 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); | 5096 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); |
5096 return elements_transition; | 5097 return elements_transition; |
5097 } | 5098 } |
5098 } | 5099 } |
5099 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 5100 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5869 | 5870 |
5870 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, | 5871 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, |
5871 TransitionFlag transition_flag) { | 5872 TransitionFlag transition_flag) { |
5872 // Transitions are only kept when inserting another transition. | 5873 // Transitions are only kept when inserting another transition. |
5873 // This precondition is not required by this function's implementation, but | 5874 // This precondition is not required by this function's implementation, but |
5874 // is currently required by the semantics of maps, so we check it. | 5875 // is currently required by the semantics of maps, so we check it. |
5875 // Conversely, we filter after replacing, so replacing a transition and | 5876 // Conversely, we filter after replacing, so replacing a transition and |
5876 // removing all other transitions is not supported. | 5877 // removing all other transitions is not supported. |
5877 bool remove_transitions = transition_flag == REMOVE_TRANSITIONS; | 5878 bool remove_transitions = transition_flag == REMOVE_TRANSITIONS; |
5878 ASSERT(remove_transitions == !descriptor->ContainsTransition()); | 5879 ASSERT(remove_transitions == !descriptor->ContainsTransition()); |
5879 ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR); | |
5880 | 5880 |
5881 // Ensure the key is a symbol. | 5881 // Ensure the key is a symbol. |
5882 { MaybeObject* maybe_result = descriptor->KeyToSymbol(); | 5882 { MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
5883 if (maybe_result->IsFailure()) return maybe_result; | 5883 if (maybe_result->IsFailure()) return maybe_result; |
5884 } | 5884 } |
5885 | 5885 |
5886 int new_size = 0; | 5886 int new_size = 0; |
5887 for (int i = 0; i < number_of_descriptors(); i++) { | 5887 for (int i = 0; i < number_of_descriptors(); i++) { |
5888 if (IsNullDescriptor(i)) continue; | |
5889 if (remove_transitions && IsTransitionOnly(i)) continue; | 5888 if (remove_transitions && IsTransitionOnly(i)) continue; |
5890 new_size++; | 5889 new_size++; |
5891 } | 5890 } |
5892 | 5891 |
5893 // If key is in descriptor, we replace it in-place when filtering. | 5892 // If key is in descriptor, we replace it in-place when filtering. |
5894 // Count a null descriptor for key as inserted, not replaced. | 5893 // Count a null descriptor for key as inserted, not replaced. |
5895 int index = Search(descriptor->GetKey()); | 5894 int index = Search(descriptor->GetKey()); |
5896 const bool replacing = (index != kNotFound); | 5895 const bool replacing = (index != kNotFound); |
5897 bool keep_enumeration_index = false; | 5896 bool keep_enumeration_index = false; |
5898 if (!replacing) { | 5897 if (!replacing) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5936 // and inserting or replacing a descriptor. | 5935 // and inserting or replacing a descriptor. |
5937 int to_index = 0; | 5936 int to_index = 0; |
5938 int insertion_index = -1; | 5937 int insertion_index = -1; |
5939 int from_index = 0; | 5938 int from_index = 0; |
5940 while (from_index < number_of_descriptors()) { | 5939 while (from_index < number_of_descriptors()) { |
5941 if (insertion_index < 0 && | 5940 if (insertion_index < 0 && |
5942 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) { | 5941 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) { |
5943 insertion_index = to_index++; | 5942 insertion_index = to_index++; |
5944 if (replacing) from_index++; | 5943 if (replacing) from_index++; |
5945 } else { | 5944 } else { |
5946 if (!(IsNullDescriptor(from_index) || | 5945 if (!(remove_transitions && IsTransitionOnly(from_index))) { |
5947 (remove_transitions && IsTransitionOnly(from_index)))) { | |
5948 MaybeObject* copy_result = | 5946 MaybeObject* copy_result = |
5949 new_descriptors->CopyFrom(to_index++, this, from_index, witness); | 5947 new_descriptors->CopyFrom(to_index++, this, from_index, witness); |
5950 if (copy_result->IsFailure()) return copy_result; | 5948 if (copy_result->IsFailure()) return copy_result; |
5951 } | 5949 } |
5952 from_index++; | 5950 from_index++; |
5953 } | 5951 } |
5954 } | 5952 } |
5955 if (insertion_index < 0) insertion_index = to_index++; | 5953 if (insertion_index < 0) insertion_index = to_index++; |
5956 | 5954 |
5957 ASSERT(insertion_index < new_descriptors->number_of_descriptors()); | 5955 ASSERT(insertion_index < new_descriptors->number_of_descriptors()); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6067 uint32_t mid_hash = mid_name->Hash(); | 6065 uint32_t mid_hash = mid_name->Hash(); |
6068 | 6066 |
6069 if (mid_hash >= hash) { | 6067 if (mid_hash >= hash) { |
6070 high = mid; | 6068 high = mid; |
6071 } else { | 6069 } else { |
6072 low = mid + 1; | 6070 low = mid + 1; |
6073 } | 6071 } |
6074 } | 6072 } |
6075 | 6073 |
6076 for (; low <= limit && GetKey(low)->Hash() == hash; ++low) { | 6074 for (; low <= limit && GetKey(low)->Hash() == hash; ++low) { |
6077 if (GetKey(low)->Equals(name) && !IsNullDescriptor(low)) | 6075 if (GetKey(low)->Equals(name)) return low; |
6078 return low; | |
6079 } | 6076 } |
6080 | 6077 |
6081 return kNotFound; | 6078 return kNotFound; |
6082 } | 6079 } |
6083 | 6080 |
6084 | 6081 |
6085 int DescriptorArray::LinearSearch(SearchMode mode, String* name, int len) { | 6082 int DescriptorArray::LinearSearch(SearchMode mode, String* name, int len) { |
6086 uint32_t hash = name->Hash(); | 6083 uint32_t hash = name->Hash(); |
6087 for (int number = 0; number < len; number++) { | 6084 for (int number = 0; number < len; number++) { |
6088 String* entry = GetKey(number); | 6085 String* entry = GetKey(number); |
6089 if (mode == EXPECT_SORTED && entry->Hash() > hash) break; | 6086 if (mode == EXPECT_SORTED && entry->Hash() > hash) break; |
6090 if (name->Equals(entry) && !IsNullDescriptor(number)) { | 6087 if (name->Equals(entry)) return number; |
6091 return number; | |
6092 } | |
6093 } | 6088 } |
6094 return kNotFound; | 6089 return kNotFound; |
6095 } | 6090 } |
6096 | 6091 |
6097 | 6092 |
6098 MaybeObject* AccessorPair::CopyWithoutTransitions() { | 6093 MaybeObject* AccessorPair::CopyWithoutTransitions() { |
6099 Heap* heap = GetHeap(); | 6094 Heap* heap = GetHeap(); |
6100 AccessorPair* copy; | 6095 AccessorPair* copy; |
6101 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 6096 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); |
6102 if (!maybe_copy->To(©)) return maybe_copy; | 6097 if (!maybe_copy->To(©)) return maybe_copy; |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7341 // Return true in case a back pointer has been cleared and false otherwise. | 7336 // Return true in case a back pointer has been cleared and false otherwise. |
7342 static bool ClearBackPointer(Heap* heap, Object* target) { | 7337 static bool ClearBackPointer(Heap* heap, Object* target) { |
7343 ASSERT(target->IsMap()); | 7338 ASSERT(target->IsMap()); |
7344 Map* map = Map::cast(target); | 7339 Map* map = Map::cast(target); |
7345 if (Marking::MarkBitFrom(map).Get()) return false; | 7340 if (Marking::MarkBitFrom(map).Get()) return false; |
7346 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | 7341 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); |
7347 return true; | 7342 return true; |
7348 } | 7343 } |
7349 | 7344 |
7350 | 7345 |
7346 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { | |
Michael Starzinger
2012/06/25 11:21:57
Add a comment that this function is only called fr
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7347 ASSERT(elms->map() != HEAP->fixed_cow_array_map()); | |
7348 // For now this trick is only applied to fixed arrays in new and paged space. | |
7349 // In large object space the object's start must coincide with chunk | |
7350 // and thus the trick is just not applicable. | |
7351 ASSERT(!HEAP->lo_space()->Contains(elms)); | |
7352 | |
7353 STATIC_ASSERT(FixedArray::kMapOffset == 0); | |
7354 STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize); | |
7355 STATIC_ASSERT(FixedArray::kHeaderSize == 2 * kPointerSize); | |
Michael Starzinger
2012/06/25 11:21:57
These asserts are not needed for left-trimming!
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7356 | |
7357 const int len = elms->length(); | |
Michael Starzinger
2012/06/25 11:21:57
Add an ASSERT(to_trim < len), other cases aren't h
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7358 | |
7359 Address new_end = elms->address() + FixedArray::kHeaderSize + | |
Michael Starzinger
2012/06/25 11:21:57
Better use "elms->address() + FixedArray::SizeFor(
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7360 (len - to_trim) * kPointerSize; | |
7361 if (to_trim > FixedArray::kHeaderSize / kPointerSize && | |
Michael Starzinger
2012/06/25 11:21:57
This condition doesn't make much sense to me. And
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7362 !heap->InNewSpace(elms)) { | |
7363 // If we are doing a big trim in old space then we zap the space that was | |
7364 // formerly part of the array so that the GC (aided by the card-based | |
Michael Starzinger
2012/06/25 11:21:57
Comment no longer applies.
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7365 // remembered set) won't find pointers to new-space there. | |
7366 Object** zap = reinterpret_cast<Object**>(new_end); | |
7367 zap++; // Header of filler must be at least one word so skip that. | |
7368 for (int i = 1; i < to_trim; i++) { | |
7369 *zap++ = Smi::FromInt(0); | |
7370 } | |
7371 } | |
7372 | |
7373 int size_delta = to_trim * kPointerSize; | |
7374 | |
7375 // Technically in new space this write might be omitted (except for | |
7376 // debug mode which iterates through the heap), but to play safer | |
7377 // we still do it. | |
7378 heap->CreateFillerObjectAt(new_end, size_delta); | |
7379 | |
7380 elms->set_length(len - to_trim); | |
7381 | |
7382 // Maintain marking consistency for IncrementalMarking. | |
7383 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { | |
7384 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); | |
7385 } | |
7386 } | |
7387 | |
7388 | |
7389 static bool ClearDescriptor(Heap* heap, | |
Michael Starzinger
2012/06/25 11:21:57
We should give this function the "ClearNonLive" pr
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7390 DescriptorArray* d, | |
7391 int descriptor_index) { | |
7392 // If the pair (value, details) is a map transition, check if the target is | |
7393 // live. If not, null the descriptor. Also drop the back pointer for that | |
7394 // map transition, so that this map is not reached again by following a back | |
7395 // pointer from that non-live map. | |
7396 PropertyDetails details(d->GetDetails(descriptor_index)); | |
7397 switch (details.type()) { | |
7398 case MAP_TRANSITION: | |
7399 case CONSTANT_TRANSITION: | |
7400 return ClearBackPointer(heap, d->GetValue(descriptor_index)); | |
7401 case CALLBACKS: { | |
7402 Object* object = d->GetValue(descriptor_index); | |
7403 if (object->IsAccessorPair()) { | |
7404 bool cleared = true; | |
7405 AccessorPair* accessors = AccessorPair::cast(object); | |
7406 Object* getter = accessors->getter(); | |
7407 if (getter->IsMap()) { | |
7408 if (ClearBackPointer(heap, getter)) { | |
7409 accessors->set_getter(heap->the_hole_value()); | |
7410 } else { | |
7411 cleared = false; | |
7412 } | |
7413 } else if (!getter->IsTheHole()) { | |
7414 cleared = false; | |
7415 } | |
7416 Object* setter = accessors->setter(); | |
7417 if (setter->IsMap()) { | |
7418 if (ClearBackPointer(heap, setter)) { | |
7419 accessors->set_setter(heap->the_hole_value()); | |
7420 } else { | |
7421 cleared = false; | |
7422 } | |
7423 } else if (!setter->IsTheHole()) { | |
7424 cleared = false; | |
7425 } | |
7426 return cleared; | |
7427 } | |
7428 return false; | |
7429 } | |
7430 case NORMAL: | |
7431 case FIELD: | |
7432 case CONSTANT_FUNCTION: | |
7433 case HANDLER: | |
7434 case INTERCEPTOR: | |
7435 return false; | |
7436 case NONEXISTENT: | |
7437 break; | |
7438 } | |
7439 UNREACHABLE(); | |
7440 return true; | |
7441 } | |
7442 | |
7443 | |
7351 void Map::ClearNonLiveTransitions(Heap* heap) { | 7444 void Map::ClearNonLiveTransitions(Heap* heap) { |
7352 DescriptorArray* d = DescriptorArray::cast( | 7445 Object* array = *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset); |
7353 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset)); | 7446 // If there are no descriptors to be cleared, return. |
7354 if (d->IsEmpty()) return; | 7447 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7448 // properly cleared. | |
7449 if (array->IsSmi()) return; | |
7450 DescriptorArray* d = DescriptorArray::cast(array); | |
7451 | |
7452 int descriptor_index = 0; | |
7453 // Find the first descriptor that can be cleared. | |
7454 while (descriptor_index < d->number_of_descriptors() && | |
Michael Starzinger
2012/06/25 11:21:57
Is there a strong reason why this loop is split in
Toon Verwaest
2012/06/25 12:20:48
Done.
| |
7455 !ClearDescriptor(heap, d, descriptor_index)) { | |
7456 ++descriptor_index; | |
7457 } | |
7458 | |
7355 Map* elements_transition = d->elements_transition_map(); | 7459 Map* elements_transition = d->elements_transition_map(); |
7356 if (elements_transition != NULL && | 7460 if (elements_transition != NULL && |
7357 ClearBackPointer(heap, elements_transition)) { | 7461 ClearBackPointer(heap, elements_transition)) { |
7462 elements_transition = NULL; | |
7358 d->ClearElementsTransition(); | 7463 d->ClearElementsTransition(); |
7464 } else { | |
7465 // If there are no descriptors to be cleared, return. | |
7466 // TODO(verwaest) Should be an assert, otherwise back pointers are not | |
7467 // properly cleared. | |
7468 if (descriptor_index == d->number_of_descriptors()) return; | |
7359 } | 7469 } |
7360 Smi* NullDescriptorDetails = | 7470 |
7361 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); | 7471 // Compact all live descriptors to the left. |
7362 for (int i = 0; i < d->number_of_descriptors(); ++i) { | 7472 for (int i = descriptor_index + 1; i < d->number_of_descriptors(); ++i) { |
7363 // If the pair (value, details) is a map transition, check if the target is | 7473 if (!ClearDescriptor(heap, d, i)) { |
7364 // live. If not, null the descriptor. Also drop the back pointer for that | 7474 d->SetKeyUnchecked(heap, descriptor_index, d->GetKey(i)); |
7365 // map transition, so that this map is not reached again by following a back | 7475 d->SetDetailsUnchecked(descriptor_index, d->GetDetails(i).AsSmi()); |
7366 // pointer from that non-live map. | 7476 d->SetValueUnchecked(heap, descriptor_index, d->GetValue(i)); |
7367 bool keep_entry = false; | 7477 descriptor_index++; |
7368 PropertyDetails details(d->GetDetails(i)); | |
7369 switch (details.type()) { | |
7370 case MAP_TRANSITION: | |
7371 case CONSTANT_TRANSITION: | |
7372 keep_entry = !ClearBackPointer(heap, d->GetValue(i)); | |
7373 break; | |
7374 case CALLBACKS: { | |
7375 Object* object = d->GetValue(i); | |
7376 if (object->IsAccessorPair()) { | |
7377 AccessorPair* accessors = AccessorPair::cast(object); | |
7378 Object* getter = accessors->getter(); | |
7379 if (getter->IsMap()) { | |
7380 if (ClearBackPointer(heap, getter)) { | |
7381 accessors->set_getter(heap->the_hole_value()); | |
7382 } else { | |
7383 keep_entry = true; | |
7384 } | |
7385 } else if (!getter->IsTheHole()) { | |
7386 keep_entry = true; | |
7387 } | |
7388 Object* setter = accessors->setter(); | |
7389 if (setter->IsMap()) { | |
7390 if (ClearBackPointer(heap, setter)) { | |
7391 accessors->set_setter(heap->the_hole_value()); | |
7392 } else { | |
7393 keep_entry = true; | |
7394 } | |
7395 } else if (!setter->IsTheHole()) { | |
7396 keep_entry = true; | |
7397 } | |
7398 } else { | |
7399 keep_entry = true; | |
7400 } | |
7401 break; | |
7402 } | |
7403 case NORMAL: | |
7404 case FIELD: | |
7405 case CONSTANT_FUNCTION: | |
7406 case HANDLER: | |
7407 case INTERCEPTOR: | |
7408 case NULL_DESCRIPTOR: | |
7409 keep_entry = true; | |
7410 break; | |
7411 } | 7478 } |
7412 // Make sure that an entry containing only dead transitions gets collected. | 7479 } |
7413 // What we *really* want to do here is removing this entry completely, but | 7480 |
7414 // for technical reasons we can't do this, so we zero it out instead. | 7481 // If the final descriptor array does not contain any live descriptors, remove |
7415 if (!keep_entry) { | 7482 // the descriptor array from the map. |
7416 d->SetDetailsUnchecked(i, NullDescriptorDetails); | 7483 if (descriptor_index == 0 && elements_transition == NULL) { |
7417 d->SetNullValueUnchecked(i, heap); | 7484 SetOwnBitField3(d->bit_field3_storage()); |
7418 } | 7485 return; |
7486 } | |
7487 | |
7488 int trim = d->number_of_descriptors() - descriptor_index; | |
7489 if (trim > 0) { | |
7490 RightTrimFixedArray(heap, d, trim * DescriptorArray::kDescriptorSize); | |
7419 } | 7491 } |
7420 } | 7492 } |
7421 | 7493 |
7422 | 7494 |
7423 int Map::Hash() { | 7495 int Map::Hash() { |
7424 // For performance reasons we only hash the 3 most variable fields of a map: | 7496 // For performance reasons we only hash the 3 most variable fields of a map: |
7425 // constructor, prototype and bit_field2. | 7497 // constructor, prototype and bit_field2. |
7426 | 7498 |
7427 // Shift away the tag. | 7499 // Shift away the tag. |
7428 int hash = (static_cast<uint32_t>( | 7500 int hash = (static_cast<uint32_t>( |
(...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8537 const char* Code::PropertyType2String(PropertyType type) { | 8609 const char* Code::PropertyType2String(PropertyType type) { |
8538 switch (type) { | 8610 switch (type) { |
8539 case NORMAL: return "NORMAL"; | 8611 case NORMAL: return "NORMAL"; |
8540 case FIELD: return "FIELD"; | 8612 case FIELD: return "FIELD"; |
8541 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; | 8613 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; |
8542 case CALLBACKS: return "CALLBACKS"; | 8614 case CALLBACKS: return "CALLBACKS"; |
8543 case HANDLER: return "HANDLER"; | 8615 case HANDLER: return "HANDLER"; |
8544 case INTERCEPTOR: return "INTERCEPTOR"; | 8616 case INTERCEPTOR: return "INTERCEPTOR"; |
8545 case MAP_TRANSITION: return "MAP_TRANSITION"; | 8617 case MAP_TRANSITION: return "MAP_TRANSITION"; |
8546 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; | 8618 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; |
8547 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; | 8619 case NONEXISTENT: |
8620 UNREACHABLE(); | |
8621 break; | |
8548 } | 8622 } |
8549 UNREACHABLE(); // keep the compiler happy | 8623 UNREACHABLE(); // keep the compiler happy |
8550 return NULL; | 8624 return NULL; |
8551 } | 8625 } |
8552 | 8626 |
8553 | 8627 |
8554 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { | 8628 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
8555 const char* name = NULL; | 8629 const char* name = NULL; |
8556 switch (kind) { | 8630 switch (kind) { |
8557 case CALL_IC: | 8631 case CALL_IC: |
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11236 Object* value = ValueAt(entry); | 11310 Object* value = ValueAt(entry); |
11237 if (!value->IsAccessorPair()) return false; | 11311 if (!value->IsAccessorPair()) return false; |
11238 AccessorPair* accessors = AccessorPair::cast(value); | 11312 AccessorPair* accessors = AccessorPair::cast(value); |
11239 return accessors->getter()->IsMap() || accessors->setter()->IsMap(); | 11313 return accessors->getter()->IsMap() || accessors->setter()->IsMap(); |
11240 } | 11314 } |
11241 case NORMAL: | 11315 case NORMAL: |
11242 case FIELD: | 11316 case FIELD: |
11243 case CONSTANT_FUNCTION: | 11317 case CONSTANT_FUNCTION: |
11244 case HANDLER: | 11318 case HANDLER: |
11245 case INTERCEPTOR: | 11319 case INTERCEPTOR: |
11246 case NULL_DESCRIPTOR: | |
11247 return false; | 11320 return false; |
11321 case NONEXISTENT: | |
11322 UNREACHABLE(); | |
11323 break; | |
11248 } | 11324 } |
11249 UNREACHABLE(); // Keep the compiler happy. | 11325 UNREACHABLE(); // Keep the compiler happy. |
11250 return false; | 11326 return false; |
11251 } | 11327 } |
11252 | 11328 |
11253 | 11329 |
11254 template<typename Shape, typename Key> | 11330 template<typename Shape, typename Key> |
11255 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) { | 11331 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) { |
11256 ASSERT(NumberOfElements() < new_table->Capacity()); | 11332 ASSERT(NumberOfElements() < new_table->Capacity()); |
11257 | 11333 |
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13278 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13354 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13279 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13355 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13280 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13356 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13281 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13357 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13282 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13358 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13283 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13359 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13284 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13360 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13285 } | 13361 } |
13286 | 13362 |
13287 } } // namespace v8::internal | 13363 } } // namespace v8::internal |
OLD | NEW |