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

Side by Side Diff: src/objects.cc

Issue 24256004: Handlify JSObject::Freeze method. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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/runtime.cc » ('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 4607 matching lines...) Expand 10 before | Expand all | Expand 10 after
4618 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); 4618 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4619 MaybeObject* maybe_result = 4619 MaybeObject* maybe_result =
4620 dictionary->AddNumberEntry(i, value, details); 4620 dictionary->AddNumberEntry(i, value, details);
4621 if (!maybe_result->To(&dictionary)) return maybe_result; 4621 if (!maybe_result->To(&dictionary)) return maybe_result;
4622 } 4622 }
4623 } 4623 }
4624 return dictionary; 4624 return dictionary;
4625 } 4625 }
4626 4626
4627 4627
4628 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4629 Handle<FixedArrayBase> array,
4630 int length,
4631 Handle<SeededNumberDictionary> dict) {
4632 Isolate* isolate = array->GetIsolate();
4633 CALL_HEAP_FUNCTION(isolate,
4634 CopyFastElementsToDictionary(
4635 isolate, *array, length, *dict),
4636 SeededNumberDictionary);
4637 }
4638
4639
4628 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 4640 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4629 Handle<JSObject> object) { 4641 Handle<JSObject> object) {
4630 CALL_HEAP_FUNCTION(object->GetIsolate(), 4642 CALL_HEAP_FUNCTION(object->GetIsolate(),
4631 object->NormalizeElements(), 4643 object->NormalizeElements(),
4632 SeededNumberDictionary); 4644 SeededNumberDictionary);
4633 } 4645 }
4634 4646
4635 4647
4636 MaybeObject* JSObject::NormalizeElements() { 4648 MaybeObject* JSObject::NormalizeElements() {
4637 ASSERT(!HasExternalArrayElements()); 4649 ASSERT(!HasExternalArrayElements());
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
5433 attrs |= READ_ONLY; 5445 attrs |= READ_ONLY;
5434 } 5446 }
5435 details = details.CopyAddAttributes( 5447 details = details.CopyAddAttributes(
5436 static_cast<PropertyAttributes>(attrs)); 5448 static_cast<PropertyAttributes>(attrs));
5437 dictionary->DetailsAtPut(i, details); 5449 dictionary->DetailsAtPut(i, details);
5438 } 5450 }
5439 } 5451 }
5440 } 5452 }
5441 5453
5442 5454
5443 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { 5455 Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
5444 // Freezing non-strict arguments should be handled elsewhere. 5456 // Freezing non-strict arguments should be handled elsewhere.
5445 ASSERT(!HasNonStrictArgumentsElements()); 5457 ASSERT(!object->HasNonStrictArgumentsElements());
5446 5458
5447 Heap* heap = isolate->heap(); 5459 if (object->map()->is_frozen()) return object;
5448 5460
5449 if (map()->is_frozen()) return this; 5461 Isolate* isolate = object->GetIsolate();
5450 5462 if (object->IsAccessCheckNeeded() &&
5451 if (IsAccessCheckNeeded() && 5463 !isolate->MayNamedAccess(*object,
5452 !isolate->MayNamedAccess(this, 5464 isolate->heap()->undefined_value(),
5453 heap->undefined_value(),
5454 v8::ACCESS_KEYS)) { 5465 v8::ACCESS_KEYS)) {
5455 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); 5466 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5456 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 5467 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5457 return heap->false_value(); 5468 return isolate->factory()->false_value();
5458 } 5469 }
5459 5470
5460 if (IsJSGlobalProxy()) { 5471 if (object->IsJSGlobalProxy()) {
5461 Object* proto = GetPrototype(); 5472 Handle<Object> proto(object->GetPrototype(), isolate);
5462 if (proto->IsNull()) return this; 5473 if (proto->IsNull()) return object;
5463 ASSERT(proto->IsJSGlobalObject()); 5474 ASSERT(proto->IsJSGlobalObject());
5464 return JSObject::cast(proto)->Freeze(isolate); 5475 return Freeze(Handle<JSObject>::cast(proto));
5465 } 5476 }
5466 5477
5467 // It's not possible to freeze objects with external array elements 5478 // It's not possible to freeze objects with external array elements
5468 if (HasExternalArrayElements()) { 5479 if (object->HasExternalArrayElements()) {
5469 HandleScope scope(isolate);
5470 Handle<Object> object(this, isolate);
5471 Handle<Object> error = 5480 Handle<Object> error =
5472 isolate->factory()->NewTypeError( 5481 isolate->factory()->NewTypeError(
5473 "cant_prevent_ext_external_array_elements", 5482 "cant_prevent_ext_external_array_elements",
5474 HandleVector(&object, 1)); 5483 HandleVector(&object, 1));
5475 return isolate->Throw(*error); 5484 isolate->Throw(*error);
5485 return Handle<Object>();
5476 } 5486 }
5477 5487
5478 SeededNumberDictionary* new_element_dictionary = NULL; 5488 Handle<SeededNumberDictionary> new_element_dictionary;
5479 if (!elements()->IsDictionary()) { 5489 if (!object->elements()->IsDictionary()) {
5480 int length = IsJSArray() 5490 int length = object->IsJSArray()
5481 ? Smi::cast(JSArray::cast(this)->length())->value() 5491 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5482 : elements()->length(); 5492 : object->elements()->length();
5483 if (length > 0) { 5493 if (length > 0) {
5484 int capacity = 0; 5494 int capacity = 0;
5485 int used = 0; 5495 int used = 0;
5486 GetElementsCapacityAndUsage(&capacity, &used); 5496 object->GetElementsCapacityAndUsage(&capacity, &used);
5487 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); 5497 new_element_dictionary =
5488 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; 5498 isolate->factory()->NewSeededNumberDictionary(used);
5489 5499
5490 // Move elements to a dictionary; avoid calling NormalizeElements to avoid 5500 // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5491 // unnecessary transitions. 5501 // unnecessary transitions.
5492 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, 5502 new_element_dictionary = CopyFastElementsToDictionary(
5493 new_element_dictionary); 5503 handle(object->elements()), length, new_element_dictionary);
5494 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
5495 } else { 5504 } else {
5496 // No existing elements, use a pre-allocated empty backing store 5505 // No existing elements, use a pre-allocated empty backing store
5497 new_element_dictionary = heap->empty_slow_element_dictionary(); 5506 new_element_dictionary =
5507 isolate->factory()->empty_slow_element_dictionary();
5498 } 5508 }
5499 } 5509 }
5500 5510
5501 LookupResult result(isolate); 5511 LookupResult result(isolate);
5502 map()->LookupTransition(this, heap->frozen_symbol(), &result); 5512 Handle<Map> old_map(object->map());
5513 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
5503 if (result.IsTransition()) { 5514 if (result.IsTransition()) {
5504 Map* transition_map = result.GetTransitionTarget(); 5515 Map* transition_map = result.GetTransitionTarget();
5505 ASSERT(transition_map->has_dictionary_elements()); 5516 ASSERT(transition_map->has_dictionary_elements());
5506 ASSERT(transition_map->is_frozen()); 5517 ASSERT(transition_map->is_frozen());
5507 ASSERT(!transition_map->is_extensible()); 5518 ASSERT(!transition_map->is_extensible());
5508 set_map(transition_map); 5519 object->set_map(transition_map);
5509 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { 5520 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5510 // Create a new descriptor array with fully-frozen properties 5521 // Create a new descriptor array with fully-frozen properties
5511 int num_descriptors = map()->NumberOfOwnDescriptors(); 5522 int num_descriptors = old_map->NumberOfOwnDescriptors();
5512 DescriptorArray* new_descriptors; 5523 Handle<DescriptorArray> new_descriptors =
5513 MaybeObject* maybe_descriptors = 5524 DescriptorArray::CopyUpToAddAttributes(
5514 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, 5525 handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
5515 FROZEN); 5526 Handle<Map> new_map = Map::CopyReplaceDescriptors(
5516 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5527 old_map, new_descriptors, INSERT_TRANSITION,
5517 5528 isolate->factory()->frozen_symbol());
5518 Map* new_map;
5519 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(
5520 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol());
5521 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5522 new_map->freeze(); 5529 new_map->freeze();
5523 new_map->set_is_extensible(false); 5530 new_map->set_is_extensible(false);
5524 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 5531 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5525 set_map(new_map); 5532 object->set_map(*new_map);
5526 } else { 5533 } else {
5527 // Slow path: need to normalize properties for safety 5534 // Slow path: need to normalize properties for safety
5528 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 5535 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5529 if (maybe->IsFailure()) return maybe;
5530 5536
5531 // Create a new map, since other objects with this map may be extensible. 5537 // Create a new map, since other objects with this map may be extensible.
5532 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5538 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5533 Map* new_map; 5539 Handle<Map> new_map = Map::Copy(handle(object->map()));
5534 MaybeObject* maybe_copy = map()->Copy();
5535 if (!maybe_copy->To(&new_map)) return maybe_copy;
5536 new_map->freeze(); 5540 new_map->freeze();
5537 new_map->set_is_extensible(false); 5541 new_map->set_is_extensible(false);
5538 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 5542 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5539 set_map(new_map); 5543 object->set_map(*new_map);
5540 5544
5541 // Freeze dictionary-mode properties 5545 // Freeze dictionary-mode properties
5542 FreezeDictionary(property_dictionary()); 5546 FreezeDictionary(object->property_dictionary());
5543 } 5547 }
5544 5548
5545 ASSERT(map()->has_dictionary_elements()); 5549 ASSERT(object->map()->has_dictionary_elements());
5546 if (new_element_dictionary != NULL) { 5550 if (!new_element_dictionary.is_null()) {
5547 set_elements(new_element_dictionary); 5551 object->set_elements(*new_element_dictionary);
5548 } 5552 }
5549 5553
5550 if (elements() != heap->empty_slow_element_dictionary()) { 5554 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5551 SeededNumberDictionary* dictionary = element_dictionary(); 5555 SeededNumberDictionary* dictionary = object->element_dictionary();
5552 // Make sure we never go back to the fast case 5556 // Make sure we never go back to the fast case
5553 dictionary->set_requires_slow_elements(); 5557 dictionary->set_requires_slow_elements();
5554 // Freeze all elements in the dictionary 5558 // Freeze all elements in the dictionary
5555 FreezeDictionary(dictionary); 5559 FreezeDictionary(dictionary);
5556 } 5560 }
5557 5561
5558 return this; 5562 return object;
5559 } 5563 }
5560 5564
5561 5565
5562 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { 5566 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) {
5563 if (map()->is_observed()) 5567 if (map()->is_observed())
5564 return isolate->heap()->undefined_value(); 5568 return isolate->heap()->undefined_value();
5565 5569
5566 Heap* heap = isolate->heap(); 5570 Heap* heap = isolate->heap();
5567 5571
5568 if (!HasExternalArrayElements()) { 5572 if (!HasExternalArrayElements()) {
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after
6606 result->InitializeDescriptors(new_descriptors); 6610 result->InitializeDescriptors(new_descriptors);
6607 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); 6611 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
6608 6612
6609 set_transitions(transitions); 6613 set_transitions(transitions);
6610 set_owns_descriptors(false); 6614 set_owns_descriptors(false);
6611 6615
6612 return result; 6616 return result;
6613 } 6617 }
6614 6618
6615 6619
6620 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
6621 Handle<DescriptorArray> descriptors,
6622 TransitionFlag flag,
6623 Handle<Name> name) {
6624 CALL_HEAP_FUNCTION(map->GetIsolate(),
6625 map->CopyReplaceDescriptors(*descriptors, flag, *name),
6626 Map);
6627 }
6628
6629
6616 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, 6630 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
6617 TransitionFlag flag, 6631 TransitionFlag flag,
6618 Name* name, 6632 Name* name,
6619 SimpleTransitionFlag simple_flag) { 6633 SimpleTransitionFlag simple_flag) {
6620 ASSERT(descriptors->IsSortedNoDuplicates()); 6634 ASSERT(descriptors->IsSortedNoDuplicates());
6621 6635
6622 Map* result; 6636 Map* result;
6623 MaybeObject* maybe_result = CopyDropDescriptors(); 6637 MaybeObject* maybe_result = CopyDropDescriptors();
6624 if (!maybe_result->To(&result)) return maybe_result; 6638 if (!maybe_result->To(&result)) return maybe_result;
6625 6639
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
6859 6873
6860 // We replace the key if it is already present. 6874 // We replace the key if it is already present.
6861 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); 6875 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
6862 if (index != DescriptorArray::kNotFound) { 6876 if (index != DescriptorArray::kNotFound) {
6863 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); 6877 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
6864 } 6878 }
6865 return CopyAddDescriptor(descriptor, flag); 6879 return CopyAddDescriptor(descriptor, flag);
6866 } 6880 }
6867 6881
6868 6882
6883 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
6884 Handle<DescriptorArray> desc,
6885 int enumeration_index,
6886 PropertyAttributes attributes) {
6887 CALL_HEAP_FUNCTION(desc->GetIsolate(),
6888 desc->CopyUpToAddAttributes(enumeration_index, attributes),
6889 DescriptorArray);
6890 }
6891
6892
6869 MaybeObject* DescriptorArray::CopyUpToAddAttributes( 6893 MaybeObject* DescriptorArray::CopyUpToAddAttributes(
6870 int enumeration_index, PropertyAttributes attributes) { 6894 int enumeration_index, PropertyAttributes attributes) {
6871 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); 6895 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
6872 6896
6873 int size = enumeration_index; 6897 int size = enumeration_index;
6874 6898
6875 DescriptorArray* descriptors; 6899 DescriptorArray* descriptors;
6876 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); 6900 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size);
6877 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; 6901 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
6878 DescriptorArray::WhitenessWitness witness(descriptors); 6902 DescriptorArray::WhitenessWitness witness(descriptors);
(...skipping 9246 matching lines...) Expand 10 before | Expand all | Expand 10 after
16125 #define ERROR_MESSAGES_TEXTS(C, T) T, 16149 #define ERROR_MESSAGES_TEXTS(C, T) T,
16126 static const char* error_messages_[] = { 16150 static const char* error_messages_[] = {
16127 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16151 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16128 }; 16152 };
16129 #undef ERROR_MESSAGES_TEXTS 16153 #undef ERROR_MESSAGES_TEXTS
16130 return error_messages_[reason]; 16154 return error_messages_[reason];
16131 } 16155 }
16132 16156
16133 16157
16134 } } // namespace v8::internal 16158 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698