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 4448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4459 | 4459 |
4460 | 4460 |
4461 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { | 4461 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { |
4462 if (HasFastProperties()) return this; | 4462 if (HasFastProperties()) return this; |
4463 ASSERT(!IsGlobalObject()); | 4463 ASSERT(!IsGlobalObject()); |
4464 return property_dictionary()-> | 4464 return property_dictionary()-> |
4465 TransformPropertiesToFastFor(this, unused_property_fields); | 4465 TransformPropertiesToFastFor(this, unused_property_fields); |
4466 } | 4466 } |
4467 | 4467 |
4468 | 4468 |
| 4469 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary( |
| 4470 Isolate* isolate, |
| 4471 FixedArrayBase* array, |
| 4472 int length, |
| 4473 SeededNumberDictionary* dictionary) { |
| 4474 Heap* heap = isolate->heap(); |
| 4475 bool has_double_elements = array->IsFixedDoubleArray(); |
| 4476 for (int i = 0; i < length; i++) { |
| 4477 Object* value = NULL; |
| 4478 if (has_double_elements) { |
| 4479 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
| 4480 if (double_array->is_the_hole(i)) { |
| 4481 value = isolate->heap()->the_hole_value(); |
| 4482 } else { |
| 4483 // Objects must be allocated in the old object space, since the |
| 4484 // overall number of HeapNumbers needed for the conversion might |
| 4485 // exceed the capacity of new space, and we would fail repeatedly |
| 4486 // trying to convert the FixedDoubleArray. |
| 4487 MaybeObject* maybe_value_object = |
| 4488 heap->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 4489 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 4490 } |
| 4491 } else { |
| 4492 value = FixedArray::cast(array)->get(i); |
| 4493 } |
| 4494 if (!value->IsTheHole()) { |
| 4495 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); |
| 4496 MaybeObject* maybe_result = |
| 4497 dictionary->AddNumberEntry(i, value, details); |
| 4498 if (!maybe_result->To(&dictionary)) return maybe_result; |
| 4499 } |
| 4500 } |
| 4501 return dictionary; |
| 4502 } |
| 4503 |
| 4504 |
4469 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4505 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4470 Handle<JSObject> object) { | 4506 Handle<JSObject> object) { |
4471 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4507 CALL_HEAP_FUNCTION(object->GetIsolate(), |
4472 object->NormalizeElements(), | 4508 object->NormalizeElements(), |
4473 SeededNumberDictionary); | 4509 SeededNumberDictionary); |
4474 } | 4510 } |
4475 | 4511 |
4476 | 4512 |
4477 MaybeObject* JSObject::NormalizeElements() { | 4513 MaybeObject* JSObject::NormalizeElements() { |
4478 ASSERT(!HasExternalArrayElements()); | 4514 ASSERT(!HasExternalArrayElements()); |
(...skipping 11 matching lines...) Expand all Loading... |
4490 ASSERT(HasFastSmiOrObjectElements() || | 4526 ASSERT(HasFastSmiOrObjectElements() || |
4491 HasFastDoubleElements() || | 4527 HasFastDoubleElements() || |
4492 HasFastArgumentsElements()); | 4528 HasFastArgumentsElements()); |
4493 // Compute the effective length and allocate a new backing store. | 4529 // Compute the effective length and allocate a new backing store. |
4494 int length = IsJSArray() | 4530 int length = IsJSArray() |
4495 ? Smi::cast(JSArray::cast(this)->length())->value() | 4531 ? Smi::cast(JSArray::cast(this)->length())->value() |
4496 : array->length(); | 4532 : array->length(); |
4497 int old_capacity = 0; | 4533 int old_capacity = 0; |
4498 int used_elements = 0; | 4534 int used_elements = 0; |
4499 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 4535 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
4500 SeededNumberDictionary* dictionary = NULL; | 4536 SeededNumberDictionary* dictionary; |
4501 { Object* object; | 4537 MaybeObject* maybe_dictionary = |
4502 MaybeObject* maybe = | 4538 SeededNumberDictionary::Allocate(GetHeap(), used_elements); |
4503 SeededNumberDictionary::Allocate(GetHeap(), used_elements); | 4539 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
4504 if (!maybe->ToObject(&object)) return maybe; | |
4505 dictionary = SeededNumberDictionary::cast(object); | |
4506 } | |
4507 | 4540 |
4508 // Copy the elements to the new backing store. | 4541 maybe_dictionary = CopyFastElementsToDictionary( |
4509 bool has_double_elements = array->IsFixedDoubleArray(); | 4542 GetIsolate(), array, length, dictionary); |
4510 for (int i = 0; i < length; i++) { | 4543 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
4511 Object* value = NULL; | |
4512 if (has_double_elements) { | |
4513 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); | |
4514 if (double_array->is_the_hole(i)) { | |
4515 value = GetIsolate()->heap()->the_hole_value(); | |
4516 } else { | |
4517 // Objects must be allocated in the old object space, since the | |
4518 // overall number of HeapNumbers needed for the conversion might | |
4519 // exceed the capacity of new space, and we would fail repeatedly | |
4520 // trying to convert the FixedDoubleArray. | |
4521 MaybeObject* maybe_value_object = | |
4522 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | |
4523 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | |
4524 } | |
4525 } else { | |
4526 ASSERT(old_map->has_fast_smi_or_object_elements()); | |
4527 value = FixedArray::cast(array)->get(i); | |
4528 } | |
4529 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); | |
4530 if (!value->IsTheHole()) { | |
4531 Object* result; | |
4532 MaybeObject* maybe_result = | |
4533 dictionary->AddNumberEntry(i, value, details); | |
4534 if (!maybe_result->ToObject(&result)) return maybe_result; | |
4535 dictionary = SeededNumberDictionary::cast(result); | |
4536 } | |
4537 } | |
4538 | 4544 |
4539 // Switch to using the dictionary as the backing storage for elements. | 4545 // Switch to using the dictionary as the backing storage for elements. |
4540 if (is_arguments) { | 4546 if (is_arguments) { |
4541 FixedArray::cast(elements())->set(1, dictionary); | 4547 FixedArray::cast(elements())->set(1, dictionary); |
4542 } else { | 4548 } else { |
4543 // Set the new map first to satify the elements type assert in | 4549 // Set the new map first to satify the elements type assert in |
4544 // set_elements(). | 4550 // set_elements(). |
4545 Object* new_map; | 4551 Map* new_map; |
4546 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), | 4552 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), |
4547 DICTIONARY_ELEMENTS); | 4553 DICTIONARY_ELEMENTS); |
4548 if (!maybe->ToObject(&new_map)) return maybe; | 4554 if (!maybe->To(&new_map)) return maybe; |
4549 set_map(Map::cast(new_map)); | 4555 set_map(new_map); |
4550 set_elements(dictionary); | 4556 set_elements(dictionary); |
4551 } | 4557 } |
4552 | 4558 |
4553 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> | 4559 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
4554 Increment(); | 4560 Increment(); |
4555 | 4561 |
4556 #ifdef DEBUG | 4562 #ifdef DEBUG |
4557 if (FLAG_trace_normalization) { | 4563 if (FLAG_trace_normalization) { |
4558 PrintF("Object elements have been normalized:\n"); | 4564 PrintF("Object elements have been normalized:\n"); |
4559 Print(); | 4565 Print(); |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5285 SeededNumberDictionary* dictionary = NULL; | 5291 SeededNumberDictionary* dictionary = NULL; |
5286 { MaybeObject* maybe = NormalizeElements(); | 5292 { MaybeObject* maybe = NormalizeElements(); |
5287 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; | 5293 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; |
5288 } | 5294 } |
5289 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 5295 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
5290 // Make sure that we never go back to fast case. | 5296 // Make sure that we never go back to fast case. |
5291 dictionary->set_requires_slow_elements(); | 5297 dictionary->set_requires_slow_elements(); |
5292 | 5298 |
5293 // Do a map transition, other objects with this map may still | 5299 // Do a map transition, other objects with this map may still |
5294 // be extensible. | 5300 // be extensible. |
| 5301 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
5295 Map* new_map; | 5302 Map* new_map; |
5296 MaybeObject* maybe = map()->Copy(); | 5303 MaybeObject* maybe = map()->Copy(); |
5297 if (!maybe->To(&new_map)) return maybe; | 5304 if (!maybe->To(&new_map)) return maybe; |
5298 | 5305 |
5299 new_map->set_is_extensible(false); | 5306 new_map->set_is_extensible(false); |
5300 set_map(new_map); | 5307 set_map(new_map); |
5301 ASSERT(!map()->is_extensible()); | 5308 ASSERT(!map()->is_extensible()); |
5302 return new_map; | 5309 return new_map; |
5303 } | 5310 } |
5304 | 5311 |
5305 | 5312 |
| 5313 template<typename Dictionary> |
| 5314 static void FreezeDictionary(Dictionary* dictionary) { |
| 5315 int capacity = dictionary->Capacity(); |
| 5316 for (int i = 0; i < capacity; i++) { |
| 5317 Object* k = dictionary->KeyAt(i); |
| 5318 if (dictionary->IsKey(k)) { |
| 5319 PropertyDetails details = dictionary->DetailsAt(i); |
| 5320 details = details.CopyAddAttributes(FROZEN); |
| 5321 dictionary->DetailsAtPut(i, details); |
| 5322 } |
| 5323 } |
| 5324 } |
| 5325 |
| 5326 |
| 5327 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { |
| 5328 // Freezing non-strict arguments should be handled elsewhere. |
| 5329 ASSERT(!HasNonStrictArgumentsElements()); |
| 5330 |
| 5331 Heap* heap = isolate->heap(); |
| 5332 |
| 5333 if (map()->is_frozen()) return this; |
| 5334 |
| 5335 if (IsAccessCheckNeeded() && |
| 5336 !isolate->MayNamedAccess(this, |
| 5337 heap->undefined_value(), |
| 5338 v8::ACCESS_KEYS)) { |
| 5339 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); |
| 5340 return heap->false_value(); |
| 5341 } |
| 5342 |
| 5343 if (IsJSGlobalProxy()) { |
| 5344 Object* proto = GetPrototype(); |
| 5345 if (proto->IsNull()) return this; |
| 5346 ASSERT(proto->IsJSGlobalObject()); |
| 5347 return JSObject::cast(proto)->Freeze(isolate); |
| 5348 } |
| 5349 |
| 5350 // It's not possible to freeze objects with external array elements |
| 5351 if (HasExternalArrayElements()) { |
| 5352 HandleScope scope(isolate); |
| 5353 Handle<Object> object(this, isolate); |
| 5354 Handle<Object> error = |
| 5355 isolate->factory()->NewTypeError( |
| 5356 "cant_prevent_ext_external_array_elements", |
| 5357 HandleVector(&object, 1)); |
| 5358 return isolate->Throw(*error); |
| 5359 } |
| 5360 |
| 5361 SeededNumberDictionary* new_element_dictionary = NULL; |
| 5362 if (!elements()->IsDictionary()) { |
| 5363 int length = IsJSArray() |
| 5364 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 5365 : elements()->length(); |
| 5366 if (length > 0) { |
| 5367 int capacity = 0; |
| 5368 int used = 0; |
| 5369 GetElementsCapacityAndUsage(&capacity, &used); |
| 5370 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); |
| 5371 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; |
| 5372 // Make sure that we never go back to fast case. |
| 5373 new_element_dictionary->set_requires_slow_elements(); |
| 5374 |
| 5375 // Move elements to a dictionary; avoid calling NormalizeElements to avoid |
| 5376 // unnecessary transitions. |
| 5377 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, |
| 5378 new_element_dictionary); |
| 5379 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; |
| 5380 |
| 5381 // Freeze all the elements in the dictionary. |
| 5382 FreezeDictionary(new_element_dictionary); |
| 5383 } else { |
| 5384 // No existing elements, use a pre-allocated empty backing store |
| 5385 new_element_dictionary = heap->empty_slow_element_dictionary(); |
| 5386 } |
| 5387 } |
| 5388 |
| 5389 LookupResult result(isolate); |
| 5390 map()->LookupTransition(this, heap->frozen_symbol(), &result); |
| 5391 if (result.IsTransition()) { |
| 5392 Map* transition_map = result.GetTransitionTarget(); |
| 5393 ASSERT(transition_map->has_dictionary_elements()); |
| 5394 ASSERT(transition_map->is_frozen()); |
| 5395 ASSERT(!transition_map->is_extensible()); |
| 5396 set_map(transition_map); |
| 5397 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { |
| 5398 // Create a new descriptor array with fully-frozen properties |
| 5399 int num_descriptors = map()->NumberOfOwnDescriptors(); |
| 5400 DescriptorArray* new_descriptors; |
| 5401 MaybeObject* maybe_descriptors = |
| 5402 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, |
| 5403 FROZEN); |
| 5404 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5405 |
| 5406 Map* new_map; |
| 5407 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors( |
| 5408 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol()); |
| 5409 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 5410 new_map->freeze(); |
| 5411 new_map->set_is_extensible(false); |
| 5412 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5413 set_map(new_map); |
| 5414 } else { |
| 5415 // Slow path: need to normalize properties for safety |
| 5416 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 5417 if (maybe->IsFailure()) return maybe; |
| 5418 |
| 5419 // Create a new map, since other objects with this map may be extensible. |
| 5420 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5421 Map* new_map; |
| 5422 MaybeObject* maybe_copy = map()->Copy(); |
| 5423 if (!maybe_copy->To(&new_map)) return maybe_copy; |
| 5424 new_map->freeze(); |
| 5425 new_map->set_is_extensible(false); |
| 5426 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5427 set_map(new_map); |
| 5428 |
| 5429 // Freeze dictionary-mode properties |
| 5430 FreezeDictionary(property_dictionary()); |
| 5431 } |
| 5432 |
| 5433 ASSERT(map()->has_dictionary_elements()); |
| 5434 if (new_element_dictionary != NULL) |
| 5435 set_elements(new_element_dictionary); |
| 5436 |
| 5437 return this; |
| 5438 } |
| 5439 |
| 5440 |
5306 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { | 5441 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { |
5307 StackLimitCheck check(isolate); | 5442 StackLimitCheck check(isolate); |
5308 if (check.HasOverflowed()) return isolate->StackOverflow(); | 5443 if (check.HasOverflowed()) return isolate->StackOverflow(); |
5309 | 5444 |
5310 if (map()->is_deprecated()) { | 5445 if (map()->is_deprecated()) { |
5311 MaybeObject* maybe_failure = MigrateInstance(); | 5446 MaybeObject* maybe_failure = MigrateInstance(); |
5312 if (maybe_failure->IsFailure()) return maybe_failure; | 5447 if (maybe_failure->IsFailure()) return maybe_failure; |
5313 } | 5448 } |
5314 | 5449 |
5315 Heap* heap = isolate->heap(); | 5450 Heap* heap = isolate->heap(); |
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6320 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6455 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
6321 | 6456 |
6322 set_transitions(transitions); | 6457 set_transitions(transitions); |
6323 set_owns_descriptors(false); | 6458 set_owns_descriptors(false); |
6324 | 6459 |
6325 return result; | 6460 return result; |
6326 } | 6461 } |
6327 | 6462 |
6328 | 6463 |
6329 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6464 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 6465 TransitionFlag flag, |
6330 Name* name, | 6466 Name* name, |
6331 TransitionFlag flag, | 6467 SimpleTransitionFlag simple_flag) { |
6332 int descriptor_index) { | |
6333 ASSERT(descriptors->IsSortedNoDuplicates()); | 6468 ASSERT(descriptors->IsSortedNoDuplicates()); |
6334 | 6469 |
6335 Map* result; | 6470 Map* result; |
6336 MaybeObject* maybe_result = CopyDropDescriptors(); | 6471 MaybeObject* maybe_result = CopyDropDescriptors(); |
6337 if (!maybe_result->To(&result)) return maybe_result; | 6472 if (!maybe_result->To(&result)) return maybe_result; |
6338 | 6473 |
6339 result->InitializeDescriptors(descriptors); | 6474 result->InitializeDescriptors(descriptors); |
6340 | 6475 |
6341 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6476 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
6342 TransitionArray* transitions; | 6477 TransitionArray* transitions; |
6343 SimpleTransitionFlag simple_flag = | |
6344 (descriptor_index == descriptors->number_of_descriptors() - 1) | |
6345 ? SIMPLE_TRANSITION | |
6346 : FULL_TRANSITION; | |
6347 ASSERT(name == descriptors->GetKey(descriptor_index)); | |
6348 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6478 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
6349 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6479 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
6350 | |
6351 set_transitions(transitions); | 6480 set_transitions(transitions); |
6352 result->SetBackPointer(this); | 6481 result->SetBackPointer(this); |
6353 } else { | 6482 } else { |
6354 descriptors->InitializeRepresentations(Representation::Tagged()); | 6483 descriptors->InitializeRepresentations(Representation::Tagged()); |
6355 } | 6484 } |
6356 | 6485 |
6357 return result; | 6486 return result; |
6358 } | 6487 } |
6359 | 6488 |
6360 | 6489 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6458 JSFunction* ctor = JSFunction::cast(constructor()); | 6587 JSFunction* ctor = JSFunction::cast(constructor()); |
6459 Map* map = ctor->initial_map(); | 6588 Map* map = ctor->initial_map(); |
6460 DescriptorArray* descriptors = map->instance_descriptors(); | 6589 DescriptorArray* descriptors = map->instance_descriptors(); |
6461 | 6590 |
6462 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6591 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
6463 DescriptorArray* new_descriptors; | 6592 DescriptorArray* new_descriptors; |
6464 MaybeObject* maybe_descriptors = | 6593 MaybeObject* maybe_descriptors = |
6465 descriptors->CopyUpTo(number_of_own_descriptors); | 6594 descriptors->CopyUpTo(number_of_own_descriptors); |
6466 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6595 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6467 | 6596 |
6468 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); | 6597 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
6469 } | 6598 } |
6470 | 6599 |
6471 | 6600 |
6472 MaybeObject* Map::Copy() { | 6601 MaybeObject* Map::Copy() { |
6473 DescriptorArray* descriptors = instance_descriptors(); | 6602 DescriptorArray* descriptors = instance_descriptors(); |
6474 DescriptorArray* new_descriptors; | 6603 DescriptorArray* new_descriptors; |
6475 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6604 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
6476 MaybeObject* maybe_descriptors = | 6605 MaybeObject* maybe_descriptors = |
6477 descriptors->CopyUpTo(number_of_own_descriptors); | 6606 descriptors->CopyUpTo(number_of_own_descriptors); |
6478 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6607 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6479 | 6608 |
6480 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); | 6609 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
6481 } | 6610 } |
6482 | 6611 |
6483 | 6612 |
6484 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 6613 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
6485 TransitionFlag flag) { | 6614 TransitionFlag flag) { |
6486 DescriptorArray* descriptors = instance_descriptors(); | 6615 DescriptorArray* descriptors = instance_descriptors(); |
6487 | 6616 |
6488 // Ensure the key is unique. | 6617 // Ensure the key is unique. |
6489 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); | 6618 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); |
6490 if (maybe_failure->IsFailure()) return maybe_failure; | 6619 if (maybe_failure->IsFailure()) return maybe_failure; |
(...skipping 20 matching lines...) Expand all Loading... |
6511 | 6640 |
6512 if (old_size != descriptors->number_of_descriptors()) { | 6641 if (old_size != descriptors->number_of_descriptors()) { |
6513 new_descriptors->SetNumberOfDescriptors(new_size); | 6642 new_descriptors->SetNumberOfDescriptors(new_size); |
6514 new_descriptors->Set(old_size, descriptor, witness); | 6643 new_descriptors->Set(old_size, descriptor, witness); |
6515 new_descriptors->Sort(); | 6644 new_descriptors->Sort(); |
6516 } else { | 6645 } else { |
6517 new_descriptors->Append(descriptor, witness); | 6646 new_descriptors->Append(descriptor, witness); |
6518 } | 6647 } |
6519 | 6648 |
6520 Name* key = descriptor->GetKey(); | 6649 Name* key = descriptor->GetKey(); |
6521 int insertion_index = new_descriptors->number_of_descriptors() - 1; | 6650 return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION); |
6522 | |
6523 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); | |
6524 } | 6651 } |
6525 | 6652 |
6526 | 6653 |
6527 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 6654 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
6528 TransitionFlag flag) { | 6655 TransitionFlag flag) { |
6529 DescriptorArray* old_descriptors = instance_descriptors(); | 6656 DescriptorArray* old_descriptors = instance_descriptors(); |
6530 | 6657 |
6531 // Ensure the key is unique. | 6658 // Ensure the key is unique. |
6532 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); | 6659 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); |
6533 if (maybe_result->IsFailure()) return maybe_result; | 6660 if (maybe_result->IsFailure()) return maybe_result; |
6534 | 6661 |
6535 // We replace the key if it is already present. | 6662 // We replace the key if it is already present. |
6536 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 6663 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
6537 if (index != DescriptorArray::kNotFound) { | 6664 if (index != DescriptorArray::kNotFound) { |
6538 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 6665 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
6539 } | 6666 } |
6540 return CopyAddDescriptor(descriptor, flag); | 6667 return CopyAddDescriptor(descriptor, flag); |
6541 } | 6668 } |
6542 | 6669 |
6543 | 6670 |
6544 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { | 6671 MaybeObject* DescriptorArray::CopyUpToAddAttributes( |
| 6672 int enumeration_index, PropertyAttributes attributes) { |
6545 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 6673 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
6546 | 6674 |
6547 int size = enumeration_index; | 6675 int size = enumeration_index; |
6548 | 6676 |
6549 DescriptorArray* descriptors; | 6677 DescriptorArray* descriptors; |
6550 MaybeObject* maybe_descriptors = Allocate(size); | 6678 MaybeObject* maybe_descriptors = Allocate(size); |
6551 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 6679 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
6552 DescriptorArray::WhitenessWitness witness(descriptors); | 6680 DescriptorArray::WhitenessWitness witness(descriptors); |
6553 | 6681 |
6554 for (int i = 0; i < size; ++i) { | 6682 if (attributes != NONE) { |
6555 descriptors->CopyFrom(i, this, i, witness); | 6683 for (int i = 0; i < size; ++i) { |
| 6684 PropertyDetails details = GetDetails(i).CopyAddAttributes(attributes); |
| 6685 Descriptor desc(GetKey(i), GetValue(i), details); |
| 6686 descriptors->Set(i, &desc, witness); |
| 6687 } |
| 6688 } else { |
| 6689 for (int i = 0; i < size; ++i) { |
| 6690 descriptors->CopyFrom(i, this, i, witness); |
| 6691 } |
6556 } | 6692 } |
6557 | 6693 |
6558 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); | 6694 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); |
6559 | 6695 |
6560 return descriptors; | 6696 return descriptors; |
6561 } | 6697 } |
6562 | 6698 |
6563 | 6699 |
6564 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, | 6700 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, |
6565 Descriptor* descriptor, | 6701 Descriptor* descriptor, |
(...skipping 20 matching lines...) Expand all Loading... |
6586 if (i == insertion_index) { | 6722 if (i == insertion_index) { |
6587 new_descriptors->Set(i, descriptor, witness); | 6723 new_descriptors->Set(i, descriptor, witness); |
6588 } else { | 6724 } else { |
6589 new_descriptors->CopyFrom(i, descriptors, i, witness); | 6725 new_descriptors->CopyFrom(i, descriptors, i, witness); |
6590 } | 6726 } |
6591 } | 6727 } |
6592 | 6728 |
6593 // Re-sort if descriptors were removed. | 6729 // Re-sort if descriptors were removed. |
6594 if (new_size != descriptors->length()) new_descriptors->Sort(); | 6730 if (new_size != descriptors->length()) new_descriptors->Sort(); |
6595 | 6731 |
6596 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); | 6732 SimpleTransitionFlag simple_flag = |
| 6733 (insertion_index == descriptors->number_of_descriptors() - 1) |
| 6734 ? SIMPLE_TRANSITION |
| 6735 : FULL_TRANSITION; |
| 6736 return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag); |
6597 } | 6737 } |
6598 | 6738 |
6599 | 6739 |
6600 void Map::UpdateCodeCache(Handle<Map> map, | 6740 void Map::UpdateCodeCache(Handle<Map> map, |
6601 Handle<Name> name, | 6741 Handle<Name> name, |
6602 Handle<Code> code) { | 6742 Handle<Code> code) { |
6603 Isolate* isolate = map->GetIsolate(); | 6743 Isolate* isolate = map->GetIsolate(); |
6604 CALL_HEAP_FUNCTION_VOID(isolate, | 6744 CALL_HEAP_FUNCTION_VOID(isolate, |
6605 map->UpdateCodeCache(*name, *code)); | 6745 map->UpdateCodeCache(*name, *code)); |
6606 } | 6746 } |
(...skipping 6743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13350 | 13490 |
13351 template class HashTable<ObjectHashTableShape<2>, Object*>; | 13491 template class HashTable<ObjectHashTableShape<2>, Object*>; |
13352 | 13492 |
13353 template class Dictionary<NameDictionaryShape, Name*>; | 13493 template class Dictionary<NameDictionaryShape, Name*>; |
13354 | 13494 |
13355 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; | 13495 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; |
13356 | 13496 |
13357 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; | 13497 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; |
13358 | 13498 |
13359 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13499 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
13360 Allocate(Heap* heap, int at_least_space_for); | 13500 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); |
13361 | 13501 |
13362 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13502 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
13363 Allocate(Heap* heap, int at_least_space_for); | 13503 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); |
13364 | 13504 |
13365 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: | 13505 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: |
13366 Allocate(Heap* heap, int n); | 13506 Allocate(Heap* heap, int n, PretenureFlag pretenure); |
13367 | 13507 |
13368 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( | 13508 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( |
13369 uint32_t, Object*); | 13509 uint32_t, Object*); |
13370 | 13510 |
13371 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13511 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
13372 AtPut(uint32_t, Object*); | 13512 AtPut(uint32_t, Object*); |
13373 | 13513 |
13374 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13514 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
13375 SlowReverseLookup(Object* value); | 13515 SlowReverseLookup(Object* value); |
13376 | 13516 |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14300 int entry = cache->FindInsertionEntry(key.Hash()); | 14440 int entry = cache->FindInsertionEntry(key.Hash()); |
14301 cache->set(EntryToIndex(entry), array); | 14441 cache->set(EntryToIndex(entry), array); |
14302 cache->set(EntryToIndex(entry) + 1, value); | 14442 cache->set(EntryToIndex(entry) + 1, value); |
14303 cache->ElementAdded(); | 14443 cache->ElementAdded(); |
14304 return cache; | 14444 return cache; |
14305 } | 14445 } |
14306 | 14446 |
14307 | 14447 |
14308 template<typename Shape, typename Key> | 14448 template<typename Shape, typename Key> |
14309 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, | 14449 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, |
14310 int at_least_space_for) { | 14450 int at_least_space_for, |
| 14451 PretenureFlag pretenure) { |
14311 Object* obj; | 14452 Object* obj; |
14312 { MaybeObject* maybe_obj = | 14453 { MaybeObject* maybe_obj = |
14313 HashTable<Shape, Key>::Allocate(heap, at_least_space_for); | 14454 HashTable<Shape, Key>::Allocate( |
| 14455 heap, |
| 14456 at_least_space_for, |
| 14457 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, |
| 14458 pretenure); |
14314 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 14459 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
14315 } | 14460 } |
14316 // Initialize the next enumeration index. | 14461 // Initialize the next enumeration index. |
14317 Dictionary<Shape, Key>::cast(obj)-> | 14462 Dictionary<Shape, Key>::cast(obj)-> |
14318 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 14463 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
14319 return obj; | 14464 return obj; |
14320 } | 14465 } |
14321 | 14466 |
14322 | 14467 |
14323 void NameDictionary::DoGenerateNewEnumerationIndices( | 14468 void NameDictionary::DoGenerateNewEnumerationIndices( |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15428 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15573 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
15429 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15574 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
15430 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15575 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
15431 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15576 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
15432 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15577 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
15433 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15578 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
15434 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15579 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
15435 } | 15580 } |
15436 | 15581 |
15437 } } // namespace v8::internal | 15582 } } // namespace v8::internal |
OLD | NEW |