| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 4489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4500 | 4500 |
| 4501 | 4501 |
| 4502 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { | 4502 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { |
| 4503 if (HasFastProperties()) return this; | 4503 if (HasFastProperties()) return this; |
| 4504 ASSERT(!IsGlobalObject()); | 4504 ASSERT(!IsGlobalObject()); |
| 4505 return property_dictionary()-> | 4505 return property_dictionary()-> |
| 4506 TransformPropertiesToFastFor(this, unused_property_fields); | 4506 TransformPropertiesToFastFor(this, unused_property_fields); |
| 4507 } | 4507 } |
| 4508 | 4508 |
| 4509 | 4509 |
| 4510 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary( | |
| 4511 Isolate* isolate, | |
| 4512 FixedArrayBase* array, | |
| 4513 int length, | |
| 4514 SeededNumberDictionary* dictionary) { | |
| 4515 Heap* heap = isolate->heap(); | |
| 4516 bool has_double_elements = array->IsFixedDoubleArray(); | |
| 4517 for (int i = 0; i < length; i++) { | |
| 4518 Object* value = NULL; | |
| 4519 if (has_double_elements) { | |
| 4520 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); | |
| 4521 if (double_array->is_the_hole(i)) { | |
| 4522 value = isolate->heap()->the_hole_value(); | |
| 4523 } else { | |
| 4524 // Objects must be allocated in the old object space, since the | |
| 4525 // overall number of HeapNumbers needed for the conversion might | |
| 4526 // exceed the capacity of new space, and we would fail repeatedly | |
| 4527 // trying to convert the FixedDoubleArray. | |
| 4528 MaybeObject* maybe_value_object = | |
| 4529 heap->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | |
| 4530 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | |
| 4531 } | |
| 4532 } else { | |
| 4533 value = FixedArray::cast(array)->get(i); | |
| 4534 } | |
| 4535 if (!value->IsTheHole()) { | |
| 4536 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); | |
| 4537 MaybeObject* maybe_result = | |
| 4538 dictionary->AddNumberEntry(i, value, details); | |
| 4539 if (!maybe_result->To(&dictionary)) return maybe_result; | |
| 4540 } | |
| 4541 } | |
| 4542 return dictionary; | |
| 4543 } | |
| 4544 | |
| 4545 | |
| 4546 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4510 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
| 4547 Handle<JSObject> object) { | 4511 Handle<JSObject> object) { |
| 4548 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4512 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 4549 object->NormalizeElements(), | 4513 object->NormalizeElements(), |
| 4550 SeededNumberDictionary); | 4514 SeededNumberDictionary); |
| 4551 } | 4515 } |
| 4552 | 4516 |
| 4553 | 4517 |
| 4554 MaybeObject* JSObject::NormalizeElements() { | 4518 MaybeObject* JSObject::NormalizeElements() { |
| 4555 ASSERT(!HasExternalArrayElements()); | 4519 ASSERT(!HasExternalArrayElements()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4567 ASSERT(HasFastSmiOrObjectElements() || | 4531 ASSERT(HasFastSmiOrObjectElements() || |
| 4568 HasFastDoubleElements() || | 4532 HasFastDoubleElements() || |
| 4569 HasFastArgumentsElements()); | 4533 HasFastArgumentsElements()); |
| 4570 // Compute the effective length and allocate a new backing store. | 4534 // Compute the effective length and allocate a new backing store. |
| 4571 int length = IsJSArray() | 4535 int length = IsJSArray() |
| 4572 ? Smi::cast(JSArray::cast(this)->length())->value() | 4536 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 4573 : array->length(); | 4537 : array->length(); |
| 4574 int old_capacity = 0; | 4538 int old_capacity = 0; |
| 4575 int used_elements = 0; | 4539 int used_elements = 0; |
| 4576 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 4540 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 4577 SeededNumberDictionary* dictionary; | 4541 SeededNumberDictionary* dictionary = NULL; |
| 4578 MaybeObject* maybe_dictionary = | 4542 { Object* object; |
| 4579 SeededNumberDictionary::Allocate(GetHeap(), used_elements); | 4543 MaybeObject* maybe = |
| 4580 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4544 SeededNumberDictionary::Allocate(GetHeap(), used_elements); |
| 4545 if (!maybe->ToObject(&object)) return maybe; |
| 4546 dictionary = SeededNumberDictionary::cast(object); |
| 4547 } |
| 4581 | 4548 |
| 4582 maybe_dictionary = CopyFastElementsToDictionary( | 4549 // Copy the elements to the new backing store. |
| 4583 GetIsolate(), array, length, dictionary); | 4550 bool has_double_elements = array->IsFixedDoubleArray(); |
| 4584 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4551 for (int i = 0; i < length; i++) { |
| 4552 Object* value = NULL; |
| 4553 if (has_double_elements) { |
| 4554 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
| 4555 if (double_array->is_the_hole(i)) { |
| 4556 value = GetIsolate()->heap()->the_hole_value(); |
| 4557 } else { |
| 4558 // Objects must be allocated in the old object space, since the |
| 4559 // overall number of HeapNumbers needed for the conversion might |
| 4560 // exceed the capacity of new space, and we would fail repeatedly |
| 4561 // trying to convert the FixedDoubleArray. |
| 4562 MaybeObject* maybe_value_object = |
| 4563 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 4564 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 4565 } |
| 4566 } else { |
| 4567 ASSERT(old_map->has_fast_smi_or_object_elements()); |
| 4568 value = FixedArray::cast(array)->get(i); |
| 4569 } |
| 4570 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); |
| 4571 if (!value->IsTheHole()) { |
| 4572 Object* result; |
| 4573 MaybeObject* maybe_result = |
| 4574 dictionary->AddNumberEntry(i, value, details); |
| 4575 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4576 dictionary = SeededNumberDictionary::cast(result); |
| 4577 } |
| 4578 } |
| 4585 | 4579 |
| 4586 // Switch to using the dictionary as the backing storage for elements. | 4580 // Switch to using the dictionary as the backing storage for elements. |
| 4587 if (is_arguments) { | 4581 if (is_arguments) { |
| 4588 FixedArray::cast(elements())->set(1, dictionary); | 4582 FixedArray::cast(elements())->set(1, dictionary); |
| 4589 } else { | 4583 } else { |
| 4590 // Set the new map first to satify the elements type assert in | 4584 // Set the new map first to satify the elements type assert in |
| 4591 // set_elements(). | 4585 // set_elements(). |
| 4592 Map* new_map; | 4586 Object* new_map; |
| 4593 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), | 4587 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), |
| 4594 DICTIONARY_ELEMENTS); | 4588 DICTIONARY_ELEMENTS); |
| 4595 if (!maybe->To(&new_map)) return maybe; | 4589 if (!maybe->ToObject(&new_map)) return maybe; |
| 4596 set_map(new_map); | 4590 set_map(Map::cast(new_map)); |
| 4597 set_elements(dictionary); | 4591 set_elements(dictionary); |
| 4598 } | 4592 } |
| 4599 | 4593 |
| 4600 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> | 4594 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
| 4601 Increment(); | 4595 Increment(); |
| 4602 | 4596 |
| 4603 #ifdef DEBUG | 4597 #ifdef DEBUG |
| 4604 if (FLAG_trace_normalization) { | 4598 if (FLAG_trace_normalization) { |
| 4605 PrintF("Object elements have been normalized:\n"); | 4599 PrintF("Object elements have been normalized:\n"); |
| 4606 Print(); | 4600 Print(); |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5330 SeededNumberDictionary* dictionary = NULL; | 5324 SeededNumberDictionary* dictionary = NULL; |
| 5331 { MaybeObject* maybe = NormalizeElements(); | 5325 { MaybeObject* maybe = NormalizeElements(); |
| 5332 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; | 5326 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; |
| 5333 } | 5327 } |
| 5334 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 5328 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 5335 // Make sure that we never go back to fast case. | 5329 // Make sure that we never go back to fast case. |
| 5336 dictionary->set_requires_slow_elements(); | 5330 dictionary->set_requires_slow_elements(); |
| 5337 | 5331 |
| 5338 // Do a map transition, other objects with this map may still | 5332 // Do a map transition, other objects with this map may still |
| 5339 // be extensible. | 5333 // be extensible. |
| 5340 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | |
| 5341 Map* new_map; | 5334 Map* new_map; |
| 5342 MaybeObject* maybe = map()->Copy(); | 5335 MaybeObject* maybe = map()->Copy(); |
| 5343 if (!maybe->To(&new_map)) return maybe; | 5336 if (!maybe->To(&new_map)) return maybe; |
| 5344 | 5337 |
| 5345 new_map->set_is_extensible(false); | 5338 new_map->set_is_extensible(false); |
| 5346 set_map(new_map); | 5339 set_map(new_map); |
| 5347 ASSERT(!map()->is_extensible()); | 5340 ASSERT(!map()->is_extensible()); |
| 5348 return new_map; | 5341 return new_map; |
| 5349 } | 5342 } |
| 5350 | 5343 |
| 5351 | 5344 |
| 5352 template<typename Dictionary> | |
| 5353 static void FreezeDictionary(Dictionary* dictionary) { | |
| 5354 int capacity = dictionary->Capacity(); | |
| 5355 for (int i = 0; i < capacity; i++) { | |
| 5356 Object* k = dictionary->KeyAt(i); | |
| 5357 if (dictionary->IsKey(k)) { | |
| 5358 PropertyDetails details = dictionary->DetailsAt(i); | |
| 5359 details = details.CopyAddAttributes(FROZEN); | |
| 5360 dictionary->DetailsAtPut(i, details); | |
| 5361 } | |
| 5362 } | |
| 5363 } | |
| 5364 | |
| 5365 | |
| 5366 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { | |
| 5367 // Freezing non-strict arguments should be handled elsewhere. | |
| 5368 ASSERT(!HasNonStrictArgumentsElements()); | |
| 5369 | |
| 5370 Heap* heap = isolate->heap(); | |
| 5371 | |
| 5372 if (map()->is_frozen()) return this; | |
| 5373 | |
| 5374 if (IsAccessCheckNeeded() && | |
| 5375 !isolate->MayNamedAccess(this, | |
| 5376 heap->undefined_value(), | |
| 5377 v8::ACCESS_KEYS)) { | |
| 5378 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | |
| 5379 return heap->false_value(); | |
| 5380 } | |
| 5381 | |
| 5382 if (IsJSGlobalProxy()) { | |
| 5383 Object* proto = GetPrototype(); | |
| 5384 if (proto->IsNull()) return this; | |
| 5385 ASSERT(proto->IsJSGlobalObject()); | |
| 5386 return JSObject::cast(proto)->Freeze(isolate); | |
| 5387 } | |
| 5388 | |
| 5389 // It's not possible to freeze objects with external array elements | |
| 5390 if (HasExternalArrayElements()) { | |
| 5391 HandleScope scope(isolate); | |
| 5392 Handle<Object> object(this, isolate); | |
| 5393 Handle<Object> error = | |
| 5394 isolate->factory()->NewTypeError( | |
| 5395 "cant_prevent_ext_external_array_elements", | |
| 5396 HandleVector(&object, 1)); | |
| 5397 return isolate->Throw(*error); | |
| 5398 } | |
| 5399 | |
| 5400 SeededNumberDictionary* new_element_dictionary = NULL; | |
| 5401 if (!elements()->IsDictionary()) { | |
| 5402 int length = IsJSArray() | |
| 5403 ? Smi::cast(JSArray::cast(this)->length())->value() | |
| 5404 : elements()->length(); | |
| 5405 if (length > 0) { | |
| 5406 int capacity = 0; | |
| 5407 int used = 0; | |
| 5408 GetElementsCapacityAndUsage(&capacity, &used); | |
| 5409 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); | |
| 5410 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
| 5411 | |
| 5412 // Move elements to a dictionary; avoid calling NormalizeElements to avoid | |
| 5413 // unnecessary transitions. | |
| 5414 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, | |
| 5415 new_element_dictionary); | |
| 5416 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
| 5417 } else { | |
| 5418 // No existing elements, use a pre-allocated empty backing store | |
| 5419 new_element_dictionary = heap->empty_slow_element_dictionary(); | |
| 5420 } | |
| 5421 } | |
| 5422 | |
| 5423 LookupResult result(isolate); | |
| 5424 map()->LookupTransition(this, heap->frozen_symbol(), &result); | |
| 5425 if (result.IsTransition()) { | |
| 5426 Map* transition_map = result.GetTransitionTarget(); | |
| 5427 ASSERT(transition_map->has_dictionary_elements()); | |
| 5428 ASSERT(transition_map->is_frozen()); | |
| 5429 ASSERT(!transition_map->is_extensible()); | |
| 5430 set_map(transition_map); | |
| 5431 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { | |
| 5432 // Create a new descriptor array with fully-frozen properties | |
| 5433 int num_descriptors = map()->NumberOfOwnDescriptors(); | |
| 5434 DescriptorArray* new_descriptors; | |
| 5435 MaybeObject* maybe_descriptors = | |
| 5436 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, | |
| 5437 FROZEN); | |
| 5438 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 5439 | |
| 5440 Map* new_map; | |
| 5441 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors( | |
| 5442 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol()); | |
| 5443 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 5444 new_map->freeze(); | |
| 5445 new_map->set_is_extensible(false); | |
| 5446 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | |
| 5447 set_map(new_map); | |
| 5448 } else { | |
| 5449 // Slow path: need to normalize properties for safety | |
| 5450 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
| 5451 if (maybe->IsFailure()) return maybe; | |
| 5452 | |
| 5453 // Create a new map, since other objects with this map may be extensible. | |
| 5454 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | |
| 5455 Map* new_map; | |
| 5456 MaybeObject* maybe_copy = map()->Copy(); | |
| 5457 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
| 5458 new_map->freeze(); | |
| 5459 new_map->set_is_extensible(false); | |
| 5460 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | |
| 5461 set_map(new_map); | |
| 5462 | |
| 5463 // Freeze dictionary-mode properties | |
| 5464 FreezeDictionary(property_dictionary()); | |
| 5465 } | |
| 5466 | |
| 5467 ASSERT(map()->has_dictionary_elements()); | |
| 5468 if (new_element_dictionary != NULL) { | |
| 5469 set_elements(new_element_dictionary); | |
| 5470 } | |
| 5471 | |
| 5472 if (elements() != heap->empty_slow_element_dictionary()) { | |
| 5473 SeededNumberDictionary* dictionary = element_dictionary(); | |
| 5474 // Make sure we never go back to the fast case | |
| 5475 dictionary->set_requires_slow_elements(); | |
| 5476 // Freeze all elements in the dictionary | |
| 5477 FreezeDictionary(dictionary); | |
| 5478 } | |
| 5479 | |
| 5480 return this; | |
| 5481 } | |
| 5482 | |
| 5483 | |
| 5484 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { | 5345 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { |
| 5485 StackLimitCheck check(isolate); | 5346 StackLimitCheck check(isolate); |
| 5486 if (check.HasOverflowed()) return isolate->StackOverflow(); | 5347 if (check.HasOverflowed()) return isolate->StackOverflow(); |
| 5487 | 5348 |
| 5488 if (map()->is_deprecated()) { | 5349 if (map()->is_deprecated()) { |
| 5489 MaybeObject* maybe_failure = MigrateInstance(); | 5350 MaybeObject* maybe_failure = MigrateInstance(); |
| 5490 if (maybe_failure->IsFailure()) return maybe_failure; | 5351 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5491 } | 5352 } |
| 5492 | 5353 |
| 5493 Heap* heap = isolate->heap(); | 5354 Heap* heap = isolate->heap(); |
| (...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6498 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6359 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 6499 | 6360 |
| 6500 set_transitions(transitions); | 6361 set_transitions(transitions); |
| 6501 set_owns_descriptors(false); | 6362 set_owns_descriptors(false); |
| 6502 | 6363 |
| 6503 return result; | 6364 return result; |
| 6504 } | 6365 } |
| 6505 | 6366 |
| 6506 | 6367 |
| 6507 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6368 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 6369 Name* name, |
| 6508 TransitionFlag flag, | 6370 TransitionFlag flag, |
| 6509 Name* name, | 6371 int descriptor_index) { |
| 6510 SimpleTransitionFlag simple_flag) { | |
| 6511 ASSERT(descriptors->IsSortedNoDuplicates()); | 6372 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6512 | 6373 |
| 6513 Map* result; | 6374 Map* result; |
| 6514 MaybeObject* maybe_result = CopyDropDescriptors(); | 6375 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 6515 if (!maybe_result->To(&result)) return maybe_result; | 6376 if (!maybe_result->To(&result)) return maybe_result; |
| 6516 | 6377 |
| 6517 result->InitializeDescriptors(descriptors); | 6378 result->InitializeDescriptors(descriptors); |
| 6518 | 6379 |
| 6519 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6380 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
| 6520 TransitionArray* transitions; | 6381 TransitionArray* transitions; |
| 6382 SimpleTransitionFlag simple_flag = |
| 6383 (descriptor_index == descriptors->number_of_descriptors() - 1) |
| 6384 ? SIMPLE_TRANSITION |
| 6385 : FULL_TRANSITION; |
| 6386 ASSERT(name == descriptors->GetKey(descriptor_index)); |
| 6521 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6387 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
| 6522 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6388 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 6389 |
| 6523 set_transitions(transitions); | 6390 set_transitions(transitions); |
| 6524 result->SetBackPointer(this); | 6391 result->SetBackPointer(this); |
| 6525 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { | 6392 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { |
| 6526 descriptors->InitializeRepresentations(Representation::Tagged()); | 6393 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6527 } | 6394 } |
| 6528 | 6395 |
| 6529 return result; | 6396 return result; |
| 6530 } | 6397 } |
| 6531 | 6398 |
| 6532 | 6399 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6628 JSFunction* ctor = JSFunction::cast(constructor()); | 6495 JSFunction* ctor = JSFunction::cast(constructor()); |
| 6629 Map* map = ctor->initial_map(); | 6496 Map* map = ctor->initial_map(); |
| 6630 DescriptorArray* descriptors = map->instance_descriptors(); | 6497 DescriptorArray* descriptors = map->instance_descriptors(); |
| 6631 | 6498 |
| 6632 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6499 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 6633 DescriptorArray* new_descriptors; | 6500 DescriptorArray* new_descriptors; |
| 6634 MaybeObject* maybe_descriptors = | 6501 MaybeObject* maybe_descriptors = |
| 6635 descriptors->CopyUpTo(number_of_own_descriptors); | 6502 descriptors->CopyUpTo(number_of_own_descriptors); |
| 6636 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6503 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 6637 | 6504 |
| 6638 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6505 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); |
| 6639 } | 6506 } |
| 6640 | 6507 |
| 6641 | 6508 |
| 6642 MaybeObject* Map::Copy() { | 6509 MaybeObject* Map::Copy() { |
| 6643 DescriptorArray* descriptors = instance_descriptors(); | 6510 DescriptorArray* descriptors = instance_descriptors(); |
| 6644 DescriptorArray* new_descriptors; | 6511 DescriptorArray* new_descriptors; |
| 6645 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6512 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 6646 MaybeObject* maybe_descriptors = | 6513 MaybeObject* maybe_descriptors = |
| 6647 descriptors->CopyUpTo(number_of_own_descriptors); | 6514 descriptors->CopyUpTo(number_of_own_descriptors); |
| 6648 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6515 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 6649 | 6516 |
| 6650 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6517 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); |
| 6651 } | 6518 } |
| 6652 | 6519 |
| 6653 | 6520 |
| 6654 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 6521 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
| 6655 TransitionFlag flag) { | 6522 TransitionFlag flag) { |
| 6656 DescriptorArray* descriptors = instance_descriptors(); | 6523 DescriptorArray* descriptors = instance_descriptors(); |
| 6657 | 6524 |
| 6658 // Ensure the key is unique. | 6525 // Ensure the key is unique. |
| 6659 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); | 6526 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); |
| 6660 if (maybe_failure->IsFailure()) return maybe_failure; | 6527 if (maybe_failure->IsFailure()) return maybe_failure; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6681 | 6548 |
| 6682 if (old_size != descriptors->number_of_descriptors()) { | 6549 if (old_size != descriptors->number_of_descriptors()) { |
| 6683 new_descriptors->SetNumberOfDescriptors(new_size); | 6550 new_descriptors->SetNumberOfDescriptors(new_size); |
| 6684 new_descriptors->Set(old_size, descriptor, witness); | 6551 new_descriptors->Set(old_size, descriptor, witness); |
| 6685 new_descriptors->Sort(); | 6552 new_descriptors->Sort(); |
| 6686 } else { | 6553 } else { |
| 6687 new_descriptors->Append(descriptor, witness); | 6554 new_descriptors->Append(descriptor, witness); |
| 6688 } | 6555 } |
| 6689 | 6556 |
| 6690 Name* key = descriptor->GetKey(); | 6557 Name* key = descriptor->GetKey(); |
| 6691 return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION); | 6558 int insertion_index = new_descriptors->number_of_descriptors() - 1; |
| 6559 |
| 6560 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); |
| 6692 } | 6561 } |
| 6693 | 6562 |
| 6694 | 6563 |
| 6695 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 6564 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
| 6696 TransitionFlag flag) { | 6565 TransitionFlag flag) { |
| 6697 DescriptorArray* old_descriptors = instance_descriptors(); | 6566 DescriptorArray* old_descriptors = instance_descriptors(); |
| 6698 | 6567 |
| 6699 // Ensure the key is unique. | 6568 // Ensure the key is unique. |
| 6700 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); | 6569 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); |
| 6701 if (maybe_result->IsFailure()) return maybe_result; | 6570 if (maybe_result->IsFailure()) return maybe_result; |
| 6702 | 6571 |
| 6703 // We replace the key if it is already present. | 6572 // We replace the key if it is already present. |
| 6704 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 6573 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
| 6705 if (index != DescriptorArray::kNotFound) { | 6574 if (index != DescriptorArray::kNotFound) { |
| 6706 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 6575 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
| 6707 } | 6576 } |
| 6708 return CopyAddDescriptor(descriptor, flag); | 6577 return CopyAddDescriptor(descriptor, flag); |
| 6709 } | 6578 } |
| 6710 | 6579 |
| 6711 | 6580 |
| 6712 MaybeObject* DescriptorArray::CopyUpToAddAttributes( | 6581 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { |
| 6713 int enumeration_index, PropertyAttributes attributes) { | |
| 6714 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 6582 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
| 6715 | 6583 |
| 6716 int size = enumeration_index; | 6584 int size = enumeration_index; |
| 6717 | 6585 |
| 6718 DescriptorArray* descriptors; | 6586 DescriptorArray* descriptors; |
| 6719 MaybeObject* maybe_descriptors = Allocate(size); | 6587 MaybeObject* maybe_descriptors = Allocate(size); |
| 6720 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 6588 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 6721 DescriptorArray::WhitenessWitness witness(descriptors); | 6589 DescriptorArray::WhitenessWitness witness(descriptors); |
| 6722 | 6590 |
| 6723 if (attributes != NONE) { | 6591 for (int i = 0; i < size; ++i) { |
| 6724 for (int i = 0; i < size; ++i) { | 6592 descriptors->CopyFrom(i, this, i, witness); |
| 6725 PropertyDetails details = GetDetails(i).CopyAddAttributes(attributes); | |
| 6726 Descriptor desc(GetKey(i), GetValue(i), details); | |
| 6727 descriptors->Set(i, &desc, witness); | |
| 6728 } | |
| 6729 } else { | |
| 6730 for (int i = 0; i < size; ++i) { | |
| 6731 descriptors->CopyFrom(i, this, i, witness); | |
| 6732 } | |
| 6733 } | 6593 } |
| 6734 | 6594 |
| 6735 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); | 6595 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); |
| 6736 | 6596 |
| 6737 return descriptors; | 6597 return descriptors; |
| 6738 } | 6598 } |
| 6739 | 6599 |
| 6740 | 6600 |
| 6741 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, | 6601 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, |
| 6742 Descriptor* descriptor, | 6602 Descriptor* descriptor, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6763 if (i == insertion_index) { | 6623 if (i == insertion_index) { |
| 6764 new_descriptors->Set(i, descriptor, witness); | 6624 new_descriptors->Set(i, descriptor, witness); |
| 6765 } else { | 6625 } else { |
| 6766 new_descriptors->CopyFrom(i, descriptors, i, witness); | 6626 new_descriptors->CopyFrom(i, descriptors, i, witness); |
| 6767 } | 6627 } |
| 6768 } | 6628 } |
| 6769 | 6629 |
| 6770 // Re-sort if descriptors were removed. | 6630 // Re-sort if descriptors were removed. |
| 6771 if (new_size != descriptors->length()) new_descriptors->Sort(); | 6631 if (new_size != descriptors->length()) new_descriptors->Sort(); |
| 6772 | 6632 |
| 6773 SimpleTransitionFlag simple_flag = | 6633 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); |
| 6774 (insertion_index == descriptors->number_of_descriptors() - 1) | |
| 6775 ? SIMPLE_TRANSITION | |
| 6776 : FULL_TRANSITION; | |
| 6777 return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag); | |
| 6778 } | 6634 } |
| 6779 | 6635 |
| 6780 | 6636 |
| 6781 void Map::UpdateCodeCache(Handle<Map> map, | 6637 void Map::UpdateCodeCache(Handle<Map> map, |
| 6782 Handle<Name> name, | 6638 Handle<Name> name, |
| 6783 Handle<Code> code) { | 6639 Handle<Code> code) { |
| 6784 Isolate* isolate = map->GetIsolate(); | 6640 Isolate* isolate = map->GetIsolate(); |
| 6785 CALL_HEAP_FUNCTION_VOID(isolate, | 6641 CALL_HEAP_FUNCTION_VOID(isolate, |
| 6786 map->UpdateCodeCache(*name, *code)); | 6642 map->UpdateCodeCache(*name, *code)); |
| 6787 } | 6643 } |
| (...skipping 6732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13520 | 13376 |
| 13521 template class HashTable<ObjectHashTableShape<2>, Object*>; | 13377 template class HashTable<ObjectHashTableShape<2>, Object*>; |
| 13522 | 13378 |
| 13523 template class Dictionary<NameDictionaryShape, Name*>; | 13379 template class Dictionary<NameDictionaryShape, Name*>; |
| 13524 | 13380 |
| 13525 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; | 13381 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; |
| 13526 | 13382 |
| 13527 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; | 13383 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; |
| 13528 | 13384 |
| 13529 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13385 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
| 13530 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); | 13386 Allocate(Heap* heap, int at_least_space_for); |
| 13531 | 13387 |
| 13532 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13388 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
| 13533 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); | 13389 Allocate(Heap* heap, int at_least_space_for); |
| 13534 | 13390 |
| 13535 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: | 13391 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: |
| 13536 Allocate(Heap* heap, int n, PretenureFlag pretenure); | 13392 Allocate(Heap* heap, int n); |
| 13537 | 13393 |
| 13538 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( | 13394 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( |
| 13539 uint32_t, Object*); | 13395 uint32_t, Object*); |
| 13540 | 13396 |
| 13541 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13397 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
| 13542 AtPut(uint32_t, Object*); | 13398 AtPut(uint32_t, Object*); |
| 13543 | 13399 |
| 13544 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13400 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
| 13545 SlowReverseLookup(Object* value); | 13401 SlowReverseLookup(Object* value); |
| 13546 | 13402 |
| (...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14470 int entry = cache->FindInsertionEntry(key.Hash()); | 14326 int entry = cache->FindInsertionEntry(key.Hash()); |
| 14471 cache->set(EntryToIndex(entry), array); | 14327 cache->set(EntryToIndex(entry), array); |
| 14472 cache->set(EntryToIndex(entry) + 1, value); | 14328 cache->set(EntryToIndex(entry) + 1, value); |
| 14473 cache->ElementAdded(); | 14329 cache->ElementAdded(); |
| 14474 return cache; | 14330 return cache; |
| 14475 } | 14331 } |
| 14476 | 14332 |
| 14477 | 14333 |
| 14478 template<typename Shape, typename Key> | 14334 template<typename Shape, typename Key> |
| 14479 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, | 14335 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, |
| 14480 int at_least_space_for, | 14336 int at_least_space_for) { |
| 14481 PretenureFlag pretenure) { | |
| 14482 Object* obj; | 14337 Object* obj; |
| 14483 { MaybeObject* maybe_obj = | 14338 { MaybeObject* maybe_obj = |
| 14484 HashTable<Shape, Key>::Allocate( | 14339 HashTable<Shape, Key>::Allocate(heap, at_least_space_for); |
| 14485 heap, | |
| 14486 at_least_space_for, | |
| 14487 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, | |
| 14488 pretenure); | |
| 14489 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 14340 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 14490 } | 14341 } |
| 14491 // Initialize the next enumeration index. | 14342 // Initialize the next enumeration index. |
| 14492 Dictionary<Shape, Key>::cast(obj)-> | 14343 Dictionary<Shape, Key>::cast(obj)-> |
| 14493 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 14344 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 14494 return obj; | 14345 return obj; |
| 14495 } | 14346 } |
| 14496 | 14347 |
| 14497 | 14348 |
| 14498 void NameDictionary::DoGenerateNewEnumerationIndices( | 14349 void NameDictionary::DoGenerateNewEnumerationIndices( |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15603 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15454 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 15604 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15455 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 15605 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15456 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 15606 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15457 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 15607 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15458 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 15608 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15459 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 15609 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15460 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 15610 } | 15461 } |
| 15611 | 15462 |
| 15612 } } // namespace v8::internal | 15463 } } // namespace v8::internal |
| OLD | NEW |