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

Side by Side Diff: src/objects.cc

Issue 14888005: Make Object.freeze fast (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Handle review comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698