| 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 #include "src/v8.h" |    5 #include "src/v8.h" | 
|    6  |    6  | 
|    7 #include "src/objects.h" |    7 #include "src/objects.h" | 
|    8 #include "src/transitions-inl.h" |    8 #include "src/transitions-inl.h" | 
|    9 #include "src/utils.h" |    9 #include "src/utils.h" | 
|   10  |   10  | 
|   11 namespace v8 { |   11 namespace v8 { | 
|   12 namespace internal { |   12 namespace internal { | 
|   13  |   13  | 
|   14  |   14  | 
|   15 // static |   15 // static | 
|   16 void TransitionArray::Insert(Handle<Map> map, Handle<Name> name, |   16 void TransitionArray::Insert(Handle<Map> map, Handle<Name> name, | 
|   17                              Handle<Map> target, SimpleTransitionFlag flag) { |   17                              Handle<Map> target, SimpleTransitionFlag flag) { | 
|   18   Isolate* isolate = map->GetIsolate(); |   18   Isolate* isolate = map->GetIsolate(); | 
|   19   target->SetBackPointer(*map); |   19   target->SetBackPointer(*map); | 
|   20   Handle<WeakCell> cell = Map::WeakCellForMap(target); |  | 
|   21  |   20  | 
|   22   // If the map doesn't have any transitions at all yet, install the new one. |   21   // If the map doesn't have any transitions at all yet, install the new one. | 
|   23   if (CanStoreSimpleTransition(map->raw_transitions())) { |   22   if (CanStoreSimpleTransition(map->raw_transitions())) { | 
|   24     if (flag == SIMPLE_PROPERTY_TRANSITION) { |   23     if (flag == SIMPLE_PROPERTY_TRANSITION) { | 
 |   24       Handle<WeakCell> cell = Map::WeakCellForMap(target); | 
|   25       ReplaceTransitions(map, *cell); |   25       ReplaceTransitions(map, *cell); | 
|   26       return; |   26       return; | 
|   27     } |   27     } | 
|   28     // If the flag requires a full TransitionArray, allocate one. |   28     // If the flag requires a full TransitionArray, allocate one. | 
|   29     Handle<TransitionArray> result = Allocate(isolate, 0, 1); |   29     Handle<TransitionArray> result = Allocate(isolate, 0, 1); | 
|   30     ReplaceTransitions(map, *result); |   30     ReplaceTransitions(map, *result); | 
|   31   } |   31   } | 
|   32  |   32  | 
|   33   bool is_special_transition = flag == SPECIAL_TRANSITION; |   33   bool is_special_transition = flag == SPECIAL_TRANSITION; | 
|   34   // If the map has a simple transition, check if it should be overwritten. |   34   // If the map has a simple transition, check if it should be overwritten. | 
|   35   if (IsSimpleTransition(map->raw_transitions())) { |   35   if (IsSimpleTransition(map->raw_transitions())) { | 
|   36     Map* old_target = GetSimpleTransition(map->raw_transitions()); |   36     Map* old_target = GetSimpleTransition(map->raw_transitions()); | 
|   37     Name* key = GetSimpleTransitionKey(old_target); |   37     Name* key = GetSimpleTransitionKey(old_target); | 
|   38     PropertyDetails old_details = GetSimpleTargetDetails(old_target); |   38     PropertyDetails old_details = GetSimpleTargetDetails(old_target); | 
|   39     PropertyDetails new_details = is_special_transition |   39     PropertyDetails new_details = is_special_transition | 
|   40                                       ? PropertyDetails::Empty() |   40                                       ? PropertyDetails::Empty() | 
|   41                                       : GetTargetDetails(*name, *target); |   41                                       : GetTargetDetails(*name, *target); | 
|   42     if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && |   42     if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && | 
|   43         old_details.kind() == new_details.kind() && |   43         old_details.kind() == new_details.kind() && | 
|   44         old_details.attributes() == new_details.attributes()) { |   44         old_details.attributes() == new_details.attributes()) { | 
 |   45       Handle<WeakCell> cell = Map::WeakCellForMap(target); | 
|   45       ReplaceTransitions(map, *cell); |   46       ReplaceTransitions(map, *cell); | 
|   46       return; |   47       return; | 
|   47     } |   48     } | 
|   48     // Otherwise allocate a full TransitionArray with slack for a new entry. |   49     // Otherwise allocate a full TransitionArray with slack for a new entry. | 
|   49     Handle<TransitionArray> result = Allocate(isolate, 1, 1); |   50     Handle<TransitionArray> result = Allocate(isolate, 1, 1); | 
|   50     // Re-read existing data; the allocation might have caused it to be cleared. |   51     // Re-read existing data; the allocation might have caused it to be cleared. | 
|   51     if (IsSimpleTransition(map->raw_transitions())) { |   52     if (IsSimpleTransition(map->raw_transitions())) { | 
|   52       old_target = GetSimpleTransition(map->raw_transitions()); |   53       old_target = GetSimpleTransition(map->raw_transitions()); | 
|   53       result->Set(0, GetSimpleTransitionKey(old_target), |   54       result->NoIncrementalWriteBarrierSet( | 
|   54                   GetSimpleTransitionCell(map->raw_transitions())); |   55           0, GetSimpleTransitionKey(old_target), old_target); | 
|   55     } else { |   56     } else { | 
|   56       result->SetNumberOfTransitions(0); |   57       result->SetNumberOfTransitions(0); | 
|   57     } |   58     } | 
|   58     ReplaceTransitions(map, *result); |   59     ReplaceTransitions(map, *result); | 
|   59   } |   60   } | 
|   60  |   61  | 
|   61   // At this point, we know that the map has a full TransitionArray. |   62   // At this point, we know that the map has a full TransitionArray. | 
|   62   DCHECK(IsFullTransitionArray(map->raw_transitions())); |   63   DCHECK(IsFullTransitionArray(map->raw_transitions())); | 
|   63  |   64  | 
|   64   int number_of_transitions = 0; |   65   int number_of_transitions = 0; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|   75     number_of_transitions = array->number_of_transitions(); |   76     number_of_transitions = array->number_of_transitions(); | 
|   76     new_nof = number_of_transitions; |   77     new_nof = number_of_transitions; | 
|   77  |   78  | 
|   78     int index = |   79     int index = | 
|   79         is_special_transition |   80         is_special_transition | 
|   80             ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) |   81             ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) | 
|   81             : array->Search(details.kind(), *name, details.attributes(), |   82             : array->Search(details.kind(), *name, details.attributes(), | 
|   82                             &insertion_index); |   83                             &insertion_index); | 
|   83     // If an existing entry was found, overwrite it and return. |   84     // If an existing entry was found, overwrite it and return. | 
|   84     if (index != kNotFound) { |   85     if (index != kNotFound) { | 
|   85       array->SetTargetCell(index, *cell); |   86       array->SetTarget(index, *target); | 
|   86       return; |   87       return; | 
|   87     } |   88     } | 
|   88  |   89  | 
|   89     ++new_nof; |   90     ++new_nof; | 
|   90     CHECK(new_nof <= kMaxNumberOfTransitions); |   91     CHECK(new_nof <= kMaxNumberOfTransitions); | 
|   91     DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |   92     DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); | 
|   92  |   93  | 
|   93     // If there is enough capacity, insert new entry into the existing array. |   94     // If there is enough capacity, insert new entry into the existing array. | 
|   94     if (new_nof <= Capacity(array)) { |   95     if (new_nof <= Capacity(array)) { | 
|   95       array->SetNumberOfTransitions(new_nof); |   96       array->SetNumberOfTransitions(new_nof); | 
|   96       for (index = number_of_transitions; index > insertion_index; --index) { |   97       for (index = number_of_transitions; index > insertion_index; --index) { | 
|   97         array->SetKey(index, array->GetKey(index - 1)); |   98         array->SetKey(index, array->GetKey(index - 1)); | 
|   98         array->SetTargetCell(index, array->GetTargetCell(index - 1)); |   99         array->SetTarget(index, array->GetTarget(index - 1)); | 
|   99       } |  100       } | 
|  100       array->SetKey(index, *name); |  101       array->SetKey(index, *name); | 
|  101       array->SetTargetCell(index, *cell); |  102       array->SetTarget(index, *target); | 
|  102       SLOW_DCHECK(array->IsSortedNoDuplicates()); |  103       SLOW_DCHECK(array->IsSortedNoDuplicates()); | 
|  103       return; |  104       return; | 
|  104     } |  105     } | 
|  105   } |  106   } | 
|  106  |  107  | 
|  107   // We're gonna need a bigger TransitionArray. |  108   // We're gonna need a bigger TransitionArray. | 
|  108   Handle<TransitionArray> result = Allocate( |  109   Handle<TransitionArray> result = Allocate( | 
|  109       map->GetIsolate(), new_nof, |  110       map->GetIsolate(), new_nof, | 
|  110       Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); |  111       Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); | 
|  111  |  112  | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|  137     result->Shrink(ToKeyIndex(new_nof)); |  138     result->Shrink(ToKeyIndex(new_nof)); | 
|  138     result->SetNumberOfTransitions(new_nof); |  139     result->SetNumberOfTransitions(new_nof); | 
|  139   } |  140   } | 
|  140  |  141  | 
|  141   if (array->HasPrototypeTransitions()) { |  142   if (array->HasPrototypeTransitions()) { | 
|  142     result->SetPrototypeTransitions(array->GetPrototypeTransitions()); |  143     result->SetPrototypeTransitions(array->GetPrototypeTransitions()); | 
|  143   } |  144   } | 
|  144  |  145  | 
|  145   DCHECK_NE(kNotFound, insertion_index); |  146   DCHECK_NE(kNotFound, insertion_index); | 
|  146   for (int i = 0; i < insertion_index; ++i) { |  147   for (int i = 0; i < insertion_index; ++i) { | 
|  147     result->CopyFrom(array, i, i); |  148     result->NoIncrementalWriteBarrierCopyFrom(array, i, i); | 
|  148   } |  149   } | 
|  149   result->Set(insertion_index, *name, *cell); |  150   result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target); | 
|  150   for (int i = insertion_index; i < number_of_transitions; ++i) { |  151   for (int i = insertion_index; i < number_of_transitions; ++i) { | 
|  151     result->CopyFrom(array, i, i + 1); |  152     result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1); | 
|  152   } |  153   } | 
|  153  |  154  | 
|  154   SLOW_DCHECK(result->IsSortedNoDuplicates()); |  155   SLOW_DCHECK(result->IsSortedNoDuplicates()); | 
|  155   ReplaceTransitions(map, *result); |  156   ReplaceTransitions(map, *result); | 
|  156 } |  157 } | 
|  157  |  158  | 
|  158  |  159  | 
|  159 // static |  160 // static | 
|  160 Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name, |  161 Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name, | 
|  161                                        PropertyAttributes attributes) { |  162                                        PropertyAttributes attributes) { | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  341                                                   int number_of_transitions, |  342                                                   int number_of_transitions, | 
|  342                                                   int slack) { |  343                                                   int slack) { | 
|  343   Handle<FixedArray> array = isolate->factory()->NewFixedArray( |  344   Handle<FixedArray> array = isolate->factory()->NewFixedArray( | 
|  344       LengthFor(number_of_transitions + slack)); |  345       LengthFor(number_of_transitions + slack)); | 
|  345   array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); |  346   array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); | 
|  346   array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); |  347   array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); | 
|  347   return Handle<TransitionArray>::cast(array); |  348   return Handle<TransitionArray>::cast(array); | 
|  348 } |  349 } | 
|  349  |  350  | 
|  350  |  351  | 
|  351 void TransitionArray::CopyFrom(TransitionArray* origin, int origin_transition, |  352 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, | 
|  352                                int target_transition) { |  353                                                         int origin_transition, | 
|  353   Set(target_transition, origin->GetKey(origin_transition), |  354                                                         int target_transition) { | 
|  354       origin->GetTargetCell(origin_transition)); |  355   NoIncrementalWriteBarrierSet(target_transition, | 
 |  356                                origin->GetKey(origin_transition), | 
 |  357                                origin->GetTarget(origin_transition)); | 
|  355 } |  358 } | 
|  356  |  359  | 
|  357  |  360  | 
|  358 static void ZapTransitionArray(TransitionArray* transitions) { |  361 static void ZapTransitionArray(TransitionArray* transitions) { | 
|  359   MemsetPointer(transitions->data_start(), |  362   MemsetPointer(transitions->data_start(), | 
|  360                 transitions->GetHeap()->the_hole_value(), |  363                 transitions->GetHeap()->the_hole_value(), | 
|  361                 transitions->length()); |  364                 transitions->length()); | 
|  362 } |  365 } | 
|  363  |  366  | 
|  364  |  367  | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  412   Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); |  415   Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); | 
|  413   DisallowHeapAllocation no_gc; |  416   DisallowHeapAllocation no_gc; | 
|  414   // Reload pointer after the allocation that just happened. |  417   // Reload pointer after the allocation that just happened. | 
|  415   raw_transitions = map->raw_transitions(); |  418   raw_transitions = map->raw_transitions(); | 
|  416   int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0; |  419   int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0; | 
|  417   if (new_nof != nof) { |  420   if (new_nof != nof) { | 
|  418     DCHECK(new_nof == 0); |  421     DCHECK(new_nof == 0); | 
|  419     result->Shrink(ToKeyIndex(0)); |  422     result->Shrink(ToKeyIndex(0)); | 
|  420     result->SetNumberOfTransitions(0); |  423     result->SetNumberOfTransitions(0); | 
|  421   } else if (nof == 1) { |  424   } else if (nof == 1) { | 
|  422     WeakCell* target_cell = GetSimpleTransitionCell(raw_transitions); |  425     Map* target = GetSimpleTransition(raw_transitions); | 
|  423     Name* key = GetSimpleTransitionKey(Map::cast(target_cell->value())); |  426     Name* key = GetSimpleTransitionKey(target); | 
|  424     result->Set(0, key, target_cell); |  427     result->NoIncrementalWriteBarrierSet(0, key, target); | 
|  425   } |  428   } | 
|  426   ReplaceTransitions(map, *result); |  429   ReplaceTransitions(map, *result); | 
|  427 } |  430 } | 
|  428  |  431  | 
|  429  |  432  | 
|  430 void TransitionArray::TraverseTransitionTreeInternal(Map* map, |  433 void TransitionArray::TraverseTransitionTreeInternal(Map* map, | 
|  431                                                      TraverseCallback callback, |  434                                                      TraverseCallback callback, | 
|  432                                                      void* data) { |  435                                                      void* data) { | 
|  433   Object* raw_transitions = map->raw_transitions(); |  436   Object* raw_transitions = map->raw_transitions(); | 
|  434   if (IsFullTransitionArray(raw_transitions)) { |  437   if (IsFullTransitionArray(raw_transitions)) { | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  510                             PropertyAttributes attributes, |  513                             PropertyAttributes attributes, | 
|  511                             int* out_insertion_index) { |  514                             int* out_insertion_index) { | 
|  512   int transition = SearchName(name, out_insertion_index); |  515   int transition = SearchName(name, out_insertion_index); | 
|  513   if (transition == kNotFound) { |  516   if (transition == kNotFound) { | 
|  514     return kNotFound; |  517     return kNotFound; | 
|  515   } |  518   } | 
|  516   return SearchDetails(transition, kind, attributes, out_insertion_index); |  519   return SearchDetails(transition, kind, attributes, out_insertion_index); | 
|  517 } |  520 } | 
|  518 }  // namespace internal |  521 }  // namespace internal | 
|  519 }  // namespace v8 |  522 }  // namespace v8 | 
| OLD | NEW |