Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: src/objects.cc

Issue 10575032: In-place shrinking of descriptor arrays with non-live transitions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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(&copy)) return maybe_copy; 6097 if (!maybe_copy->To(&copy)) return maybe_copy;
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 // This function should only be called from within the GC, since it uses
7347 // IncrementLiveBytesFromGC. If called from anywhere else, this results in an
7348 // inconsistent live-bytes count.
7349 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
7350 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
7351 // For now this trick is only applied to fixed arrays in new and paged space.
7352 // In large object space the object's start must coincide with chunk
7353 // and thus the trick is just not applicable.
7354 ASSERT(!HEAP->lo_space()->Contains(elms));
7355
7356 const int len = elms->length();
7357
7358 ASSERT(to_trim < len);
7359
7360 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
7361
7362 #ifdef DEBUG
7363 if (to_trim > FixedArray::kHeaderSize / kPointerSize &&
7364 !heap->InNewSpace(elms)) {
Michael Starzinger 2012/06/25 12:48:38 Since it's debug code now, I think we should just
7365 // If we are doing a big trim in old space then we zap the space.
7366 Object** zap = reinterpret_cast<Object**>(new_end);
7367 zap++; // Header of filler must be at least one word so skip that.
Michael Starzinger 2012/06/25 12:48:38 Using the same reasoning, I think we should also j
7368 for (int i = 1; i < to_trim; i++) {
7369 *zap++ = Smi::FromInt(0);
7370 }
7371 }
7372 #endif
7373
7374 int size_delta = to_trim * kPointerSize;
7375
7376 // Technically in new space this write might be omitted (except for
7377 // debug mode which iterates through the heap), but to play safer
7378 // we still do it.
7379 heap->CreateFillerObjectAt(new_end, size_delta);
7380
7381 elms->set_length(len - to_trim);
7382
7383 // Maintain marking consistency for IncrementalMarking.
7384 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
7385 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
7386 }
7387 }
7388
7389
7390 static bool ClearNonLiveTransitionsFromDescriptor(Heap* heap,
Michael Starzinger 2012/06/25 12:48:38 Add a comment describing the semantics of the retu
7391 DescriptorArray* d,
7392 int descriptor_index) {
7393 // If the pair (value, details) is a map transition, check if the target is
7394 // live. If not, null the descriptor. Also drop the back pointer for that
7395 // map transition, so that this map is not reached again by following a back
7396 // pointer from that non-live map.
7397 PropertyDetails details(d->GetDetails(descriptor_index));
7398 switch (details.type()) {
7399 case MAP_TRANSITION:
7400 case CONSTANT_TRANSITION:
7401 return ClearBackPointer(heap, d->GetValue(descriptor_index));
7402 case CALLBACKS: {
7403 Object* object = d->GetValue(descriptor_index);
7404 if (object->IsAccessorPair()) {
7405 bool cleared = true;
7406 AccessorPair* accessors = AccessorPair::cast(object);
7407 Object* getter = accessors->getter();
7408 if (getter->IsMap()) {
7409 if (ClearBackPointer(heap, getter)) {
7410 accessors->set_getter(heap->the_hole_value());
7411 } else {
7412 cleared = false;
7413 }
7414 } else if (!getter->IsTheHole()) {
7415 cleared = false;
7416 }
7417 Object* setter = accessors->setter();
7418 if (setter->IsMap()) {
7419 if (ClearBackPointer(heap, setter)) {
7420 accessors->set_setter(heap->the_hole_value());
7421 } else {
7422 cleared = false;
7423 }
7424 } else if (!setter->IsTheHole()) {
7425 cleared = false;
7426 }
7427 return cleared;
7428 }
7429 return false;
7430 }
7431 case NORMAL:
7432 case FIELD:
7433 case CONSTANT_FUNCTION:
7434 case HANDLER:
7435 case INTERCEPTOR:
7436 return false;
7437 case NONEXISTENT:
7438 break;
7439 }
7440 UNREACHABLE();
7441 return true;
7442 }
7443
7444
7351 void Map::ClearNonLiveTransitions(Heap* heap) { 7445 void Map::ClearNonLiveTransitions(Heap* heap) {
7352 DescriptorArray* d = DescriptorArray::cast( 7446 Object* array = *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset);
7353 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset)); 7447 // If there are no descriptors to be cleared, return.
7354 if (d->IsEmpty()) return; 7448 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7449 // properly cleared.
7450 if (array->IsSmi()) return;
7451 DescriptorArray* d = DescriptorArray::cast(array);
7452
7453 int descriptor_index = 0;
7454 // Compact all live descriptors to the left.
7455 for (int i = 0; i < d->number_of_descriptors(); ++i) {
7456 if (!ClearNonLiveTransitionsFromDescriptor(heap, d, i)) {
7457 if (i != descriptor_index) {
7458 d->SetKeyUnchecked(heap, descriptor_index, d->GetKey(i));
7459 d->SetDetailsUnchecked(descriptor_index, d->GetDetails(i).AsSmi());
7460 d->SetValueUnchecked(heap, descriptor_index, d->GetValue(i));
7461 }
7462 descriptor_index++;
7463 }
7464 }
7465
7355 Map* elements_transition = d->elements_transition_map(); 7466 Map* elements_transition = d->elements_transition_map();
7356 if (elements_transition != NULL && 7467 if (elements_transition != NULL &&
7357 ClearBackPointer(heap, elements_transition)) { 7468 ClearBackPointer(heap, elements_transition)) {
7469 elements_transition = NULL;
7358 d->ClearElementsTransition(); 7470 d->ClearElementsTransition();
7471 } else {
7472 // If there are no descriptors to be cleared, return.
7473 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7474 // properly cleared.
7475 if (descriptor_index == d->number_of_descriptors()) return;
7359 } 7476 }
7360 Smi* NullDescriptorDetails = 7477
7361 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); 7478 // If the final descriptor array does not contain any live descriptors, remove
7362 for (int i = 0; i < d->number_of_descriptors(); ++i) { 7479 // the descriptor array from the map.
7363 // If the pair (value, details) is a map transition, check if the target is 7480 if (descriptor_index == 0 && elements_transition == NULL) {
7364 // live. If not, null the descriptor. Also drop the back pointer for that 7481 ClearDescriptorArray();
7365 // map transition, so that this map is not reached again by following a back 7482 return;
7366 // pointer from that non-live map. 7483 }
7367 bool keep_entry = false; 7484
7368 PropertyDetails details(d->GetDetails(i)); 7485 int trim = d->number_of_descriptors() - descriptor_index;
7369 switch (details.type()) { 7486 if (trim > 0) {
7370 case MAP_TRANSITION: 7487 RightTrimFixedArray(heap, d, trim * DescriptorArray::kDescriptorSize);
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 }
7412 // Make sure that an entry containing only dead transitions gets collected.
7413 // What we *really* want to do here is removing this entry completely, but
7414 // for technical reasons we can't do this, so we zero it out instead.
7415 if (!keep_entry) {
7416 d->SetDetailsUnchecked(i, NullDescriptorDetails);
7417 d->SetNullValueUnchecked(i, heap);
7418 }
7419 } 7488 }
7420 } 7489 }
7421 7490
7422 7491
7423 int Map::Hash() { 7492 int Map::Hash() {
7424 // For performance reasons we only hash the 3 most variable fields of a map: 7493 // For performance reasons we only hash the 3 most variable fields of a map:
7425 // constructor, prototype and bit_field2. 7494 // constructor, prototype and bit_field2.
7426 7495
7427 // Shift away the tag. 7496 // Shift away the tag.
7428 int hash = (static_cast<uint32_t>( 7497 int hash = (static_cast<uint32_t>(
(...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after
8537 const char* Code::PropertyType2String(PropertyType type) { 8606 const char* Code::PropertyType2String(PropertyType type) {
8538 switch (type) { 8607 switch (type) {
8539 case NORMAL: return "NORMAL"; 8608 case NORMAL: return "NORMAL";
8540 case FIELD: return "FIELD"; 8609 case FIELD: return "FIELD";
8541 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; 8610 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8542 case CALLBACKS: return "CALLBACKS"; 8611 case CALLBACKS: return "CALLBACKS";
8543 case HANDLER: return "HANDLER"; 8612 case HANDLER: return "HANDLER";
8544 case INTERCEPTOR: return "INTERCEPTOR"; 8613 case INTERCEPTOR: return "INTERCEPTOR";
8545 case MAP_TRANSITION: return "MAP_TRANSITION"; 8614 case MAP_TRANSITION: return "MAP_TRANSITION";
8546 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; 8615 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8547 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; 8616 case NONEXISTENT:
8617 UNREACHABLE();
8618 break;
8548 } 8619 }
8549 UNREACHABLE(); // keep the compiler happy 8620 UNREACHABLE(); // keep the compiler happy
8550 return NULL; 8621 return NULL;
8551 } 8622 }
8552 8623
8553 8624
8554 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { 8625 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8555 const char* name = NULL; 8626 const char* name = NULL;
8556 switch (kind) { 8627 switch (kind) {
8557 case CALL_IC: 8628 case CALL_IC:
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after
11236 Object* value = ValueAt(entry); 11307 Object* value = ValueAt(entry);
11237 if (!value->IsAccessorPair()) return false; 11308 if (!value->IsAccessorPair()) return false;
11238 AccessorPair* accessors = AccessorPair::cast(value); 11309 AccessorPair* accessors = AccessorPair::cast(value);
11239 return accessors->getter()->IsMap() || accessors->setter()->IsMap(); 11310 return accessors->getter()->IsMap() || accessors->setter()->IsMap();
11240 } 11311 }
11241 case NORMAL: 11312 case NORMAL:
11242 case FIELD: 11313 case FIELD:
11243 case CONSTANT_FUNCTION: 11314 case CONSTANT_FUNCTION:
11244 case HANDLER: 11315 case HANDLER:
11245 case INTERCEPTOR: 11316 case INTERCEPTOR:
11246 case NULL_DESCRIPTOR:
11247 return false; 11317 return false;
11318 case NONEXISTENT:
11319 UNREACHABLE();
11320 break;
11248 } 11321 }
11249 UNREACHABLE(); // Keep the compiler happy. 11322 UNREACHABLE(); // Keep the compiler happy.
11250 return false; 11323 return false;
11251 } 11324 }
11252 11325
11253 11326
11254 template<typename Shape, typename Key> 11327 template<typename Shape, typename Key>
11255 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) { 11328 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11256 ASSERT(NumberOfElements() < new_table->Capacity()); 11329 ASSERT(NumberOfElements() < new_table->Capacity());
11257 11330
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after
13278 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13351 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13279 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13352 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13280 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13353 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13281 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13354 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13282 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13355 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13283 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13356 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13284 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13357 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13285 } 13358 }
13286 13359
13287 } } // namespace v8::internal 13360 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698