| 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 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 Object* raw_transitions = map->raw_transitions(); | 226 Object* raw_transitions = map->raw_transitions(); |
| 227 if (IsFullTransitionArray(raw_transitions)) { | 227 if (IsFullTransitionArray(raw_transitions)) { |
| 228 TransitionArray* transitions = TransitionArray::cast(raw_transitions); | 228 TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
| 229 return transitions->number_of_transitions() < kMaxNumberOfTransitions; | 229 return transitions->number_of_transitions() < kMaxNumberOfTransitions; |
| 230 } | 230 } |
| 231 return true; | 231 return true; |
| 232 } | 232 } |
| 233 | 233 |
| 234 | 234 |
| 235 // static | 235 // static |
| 236 void TransitionArray::PutPrototypeTransition(Handle<Map> map, | 236 Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map, |
| 237 Handle<Object> prototype, | 237 Handle<Object> prototype, |
| 238 Handle<Map> target_map) { | 238 Handle<Map> target_map) { |
| 239 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); | 239 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
| 240 // Don't cache prototype transition if this map is either shared, or a map of | 240 // Don't cache prototype transition if this map is either shared, or a map of |
| 241 // a prototype. | 241 // a prototype. |
| 242 if (map->is_prototype_map()) return; | 242 if (map->is_prototype_map()) return map; |
| 243 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return; | 243 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map; |
| 244 | 244 |
| 245 const int header = kProtoTransitionHeaderSize; | 245 const int header = kProtoTransitionHeaderSize; |
| 246 | 246 |
| 247 Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map); | |
| 248 | |
| 249 Handle<FixedArray> cache(GetPrototypeTransitions(*map)); | 247 Handle<FixedArray> cache(GetPrototypeTransitions(*map)); |
| 250 int capacity = cache->length() - header; | 248 int capacity = cache->length() - header; |
| 251 int transitions = NumberOfPrototypeTransitions(*cache) + 1; | 249 int transitions = NumberOfPrototypeTransitions(*cache) + 1; |
| 252 | 250 |
| 253 if (transitions > capacity) { | 251 if (transitions > capacity) { |
| 254 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. | 252 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. |
| 255 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); | 253 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); |
| 256 if (new_capacity == capacity) return; | 254 if (new_capacity == capacity) return map; |
| 257 | 255 |
| 258 cache = FixedArray::CopySize(cache, header + new_capacity); | 256 cache = FixedArray::CopySize(cache, header + new_capacity); |
| 259 if (capacity < 0) { | 257 if (capacity < 0) { |
| 260 // There was no prototype transitions array before, so the size | 258 // There was no prototype transitions array before, so the size |
| 261 // couldn't be copied. Initialize it explicitly. | 259 // couldn't be copied. Initialize it explicitly. |
| 262 SetNumberOfPrototypeTransitions(*cache, 0); | 260 SetNumberOfPrototypeTransitions(*cache, 0); |
| 263 } | 261 } |
| 264 | 262 |
| 265 SetPrototypeTransitions(map, cache); | 263 SetPrototypeTransitions(map, cache); |
| 266 } | 264 } |
| 267 | 265 |
| 268 // Reload number of transitions as GC might shrink them. | 266 // Reload number of transitions as GC might shrink them. |
| 269 int last = NumberOfPrototypeTransitions(*cache); | 267 int last = NumberOfPrototypeTransitions(*cache); |
| 270 int entry = header + last; | 268 int entry = header + last; |
| 271 | 269 |
| 272 cache->set(entry, *target_cell); | 270 cache->set(entry, *target_map); |
| 273 SetNumberOfPrototypeTransitions(*cache, last + 1); | 271 SetNumberOfPrototypeTransitions(*cache, last + 1); |
| 272 |
| 273 return map; |
| 274 } | 274 } |
| 275 | 275 |
| 276 | 276 |
| 277 // static | 277 // static |
| 278 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map, | 278 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map, |
| 279 Handle<Object> prototype) { | 279 Handle<Object> prototype) { |
| 280 DisallowHeapAllocation no_gc; | 280 DisallowHeapAllocation no_gc; |
| 281 FixedArray* cache = GetPrototypeTransitions(*map); | 281 FixedArray* cache = GetPrototypeTransitions(*map); |
| 282 int number_of_transitions = NumberOfPrototypeTransitions(cache); | 282 int number_of_transitions = NumberOfPrototypeTransitions(cache); |
| 283 for (int i = 0; i < number_of_transitions; i++) { | 283 for (int i = 0; i < number_of_transitions; i++) { |
| 284 WeakCell* target_cell = | 284 Map* target = Map::cast(cache->get(kProtoTransitionHeaderSize + i)); |
| 285 WeakCell::cast(cache->get(kProtoTransitionHeaderSize + i)); | 285 if (target->prototype() == *prototype) return handle(target); |
| 286 if (!target_cell->cleared() && | |
| 287 Map::cast(target_cell->value())->prototype() == *prototype) { | |
| 288 return handle(Map::cast(target_cell->value())); | |
| 289 } | |
| 290 } | 286 } |
| 291 return Handle<Map>(); | 287 return Handle<Map>(); |
| 292 } | 288 } |
| 293 | 289 |
| 294 | 290 |
| 295 // static | 291 // static |
| 296 FixedArray* TransitionArray::GetPrototypeTransitions(Map* map) { | 292 FixedArray* TransitionArray::GetPrototypeTransitions(Map* map) { |
| 297 Object* raw_transitions = map->raw_transitions(); | 293 Object* raw_transitions = map->raw_transitions(); |
| 298 Heap* heap = map->GetHeap(); | 294 Heap* heap = map->GetHeap(); |
| 299 if (!IsFullTransitionArray(raw_transitions)) { | 295 if (!IsFullTransitionArray(raw_transitions)) { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 void TransitionArray::TraverseTransitionTreeInternal(Map* map, | 429 void TransitionArray::TraverseTransitionTreeInternal(Map* map, |
| 434 TraverseCallback callback, | 430 TraverseCallback callback, |
| 435 void* data) { | 431 void* data) { |
| 436 Object* raw_transitions = map->raw_transitions(); | 432 Object* raw_transitions = map->raw_transitions(); |
| 437 if (IsFullTransitionArray(raw_transitions)) { | 433 if (IsFullTransitionArray(raw_transitions)) { |
| 438 TransitionArray* transitions = TransitionArray::cast(raw_transitions); | 434 TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
| 439 if (transitions->HasPrototypeTransitions()) { | 435 if (transitions->HasPrototypeTransitions()) { |
| 440 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); | 436 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); |
| 441 for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { | 437 for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { |
| 442 int index = TransitionArray::kProtoTransitionHeaderSize + i; | 438 int index = TransitionArray::kProtoTransitionHeaderSize + i; |
| 443 WeakCell* cell = WeakCell::cast(proto_trans->get(index)); | 439 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), |
| 444 TraverseTransitionTreeInternal(Map::cast(cell->value()), callback, | 440 callback, data); |
| 445 data); | |
| 446 } | 441 } |
| 447 } | 442 } |
| 448 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | 443 for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
| 449 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); | 444 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); |
| 450 } | 445 } |
| 451 } else if (IsSimpleTransition(raw_transitions)) { | 446 } else if (IsSimpleTransition(raw_transitions)) { |
| 452 TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions), | 447 TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions), |
| 453 callback, data); | 448 callback, data); |
| 454 } | 449 } |
| 455 callback(map, data); | 450 callback(map, data); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 PropertyAttributes attributes, | 508 PropertyAttributes attributes, |
| 514 int* out_insertion_index) { | 509 int* out_insertion_index) { |
| 515 int transition = SearchName(name, out_insertion_index); | 510 int transition = SearchName(name, out_insertion_index); |
| 516 if (transition == kNotFound) { | 511 if (transition == kNotFound) { |
| 517 return kNotFound; | 512 return kNotFound; |
| 518 } | 513 } |
| 519 return SearchDetails(transition, kind, attributes, out_insertion_index); | 514 return SearchDetails(transition, kind, attributes, out_insertion_index); |
| 520 } | 515 } |
| 521 } // namespace internal | 516 } // namespace internal |
| 522 } // namespace v8 | 517 } // namespace v8 |
| OLD | NEW |