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

Side by Side Diff: src/objects.cc

Issue 1239803004: Bubble up the transitions associated with PreventExtensionsWithTransition (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix nits Created 5 years, 5 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
« no previous file with comments | « src/objects.h ('k') | no next file » | 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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <iomanip> 5 #include <iomanip>
6 #include <sstream> 6 #include <sstream>
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 2343 matching lines...) Expand 10 before | Expand all | Expand 10 after
2354 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, 2354 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2355 PropertyKind new_kind, 2355 PropertyKind new_kind,
2356 PropertyAttributes new_attributes, 2356 PropertyAttributes new_attributes,
2357 Representation new_representation, 2357 Representation new_representation,
2358 Handle<HeapType> new_field_type, 2358 Handle<HeapType> new_field_type,
2359 StoreMode store_mode) { 2359 StoreMode store_mode) {
2360 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. 2360 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet.
2361 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); 2361 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2362 Isolate* isolate = old_map->GetIsolate(); 2362 Isolate* isolate = old_map->GetIsolate();
2363 2363
2364 Handle<Map> real_old_map = old_map;
2365 Handle<Object> prev_object = handle(old_map->GetBackPointer(), isolate);
2366 PropertyAttributes extra_attributes = NONE;
2367 if (!prev_object->IsUndefined()) {
Igor Sheludko 2015/09/16 13:09:15 How about adding "!old_map->is_extensible() &&" to
2368 Handle<Map> prev_map = Handle<Map>::cast(prev_object);
2369 Map* transition = TransitionArray::SearchSpecial(
2370 *prev_map, *isolate->factory()->nonextensible_symbol());
2371 if (transition == *old_map) {
2372 old_map = prev_map;
2373 } else {
2374 transition = TransitionArray::SearchSpecial(
2375 *prev_map, *isolate->factory()->sealed_symbol());
2376 if (transition == *old_map) {
2377 extra_attributes = SEALED;
2378 old_map = prev_map;
2379 } else {
2380 Map* transition = TransitionArray::SearchSpecial(
2381 *prev_map, *isolate->factory()->frozen_symbol());
2382 if (transition == *old_map) {
2383 extra_attributes = FROZEN;
2384 old_map = prev_map;
2385 }
2386 }
2387 }
2388 }
2389
2364 Handle<DescriptorArray> old_descriptors( 2390 Handle<DescriptorArray> old_descriptors(
2365 old_map->instance_descriptors(), isolate); 2391 old_map->instance_descriptors(), isolate);
2366 int old_nof = old_map->NumberOfOwnDescriptors(); 2392 int old_nof = old_map->NumberOfOwnDescriptors();
2367 2393
2368 // If it's just a representation generalization case (i.e. property kind and 2394 // If it's just a representation generalization case (i.e. property kind and
2369 // attributes stays unchanged) it's fine to transition from None to anything 2395 // attributes stays unchanged) it's fine to transition from None to anything
2370 // but double without any modification to the object, because the default 2396 // but double without any modification to the object, because the default
2371 // uninitialized value for representation None can be overwritten by both 2397 // uninitialized value for representation None can be overwritten by both
2372 // smi and tagged values. Doubles, however, would require a box allocation. 2398 // smi and tagged values. Doubles, however, would require a box allocation.
2373 if (modify_index >= 0 && !new_representation.IsNone() && 2399 if (modify_index >= 0 && !new_representation.IsNone() &&
(...skipping 15 matching lines...) Expand all
2389 } 2415 }
2390 Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate); 2416 Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2391 2417
2392 GeneralizeFieldType(field_owner, modify_index, new_representation, 2418 GeneralizeFieldType(field_owner, modify_index, new_representation,
2393 new_field_type); 2419 new_field_type);
2394 DCHECK(old_descriptors->GetDetails(modify_index) 2420 DCHECK(old_descriptors->GetDetails(modify_index)
2395 .representation() 2421 .representation()
2396 .Equals(new_representation)); 2422 .Equals(new_representation));
2397 DCHECK( 2423 DCHECK(
2398 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); 2424 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2399 return old_map; 2425 return real_old_map;
2400 } 2426 }
2401 } 2427 }
2402 2428
2403 // Check the state of the root map. 2429 // Check the state of the root map.
2404 Handle<Map> root_map(old_map->FindRootMap(), isolate); 2430 Handle<Map> root_map(old_map->FindRootMap(), isolate);
2405 if (!old_map->EquivalentToForTransition(*root_map)) { 2431 if (!old_map->EquivalentToForTransition(*root_map)) {
2406 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2432 return CopyGeneralizeAllRepresentations(
2407 new_kind, new_attributes, 2433 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2408 "GenAll_NotEquivalent"); 2434 "GenAll_NotEquivalent");
2409 } 2435 }
2410 2436
2411 ElementsKind from_kind = root_map->elements_kind(); 2437 ElementsKind from_kind = root_map->elements_kind();
2412 ElementsKind to_kind = old_map->elements_kind(); 2438 ElementsKind to_kind = old_map->elements_kind();
2413 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. 2439 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
2414 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && 2440 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
2415 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && 2441 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
2416 !(IsTransitionableFastElementsKind(from_kind) && 2442 !(IsTransitionableFastElementsKind(from_kind) &&
2417 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { 2443 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2418 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2444 return CopyGeneralizeAllRepresentations(
2419 new_kind, new_attributes, 2445 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2420 "GenAll_InvalidElementsTransition"); 2446 "GenAll_InvalidElementsTransition");
2421 } 2447 }
2422 int root_nof = root_map->NumberOfOwnDescriptors(); 2448 int root_nof = root_map->NumberOfOwnDescriptors();
2423 if (modify_index >= 0 && modify_index < root_nof) { 2449 if (modify_index >= 0 && modify_index < root_nof) {
2424 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 2450 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2425 if (old_details.kind() != new_kind || 2451 if (old_details.kind() != new_kind ||
2426 old_details.attributes() != new_attributes) { 2452 old_details.attributes() != new_attributes) {
2427 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2453 return CopyGeneralizeAllRepresentations(
2428 new_kind, new_attributes, 2454 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2429 "GenAll_RootModification1"); 2455 "GenAll_RootModification1");
2430 } 2456 }
2431 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || 2457 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2432 (old_details.type() == DATA && 2458 (old_details.type() == DATA &&
2433 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || 2459 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2434 !new_representation.fits_into(old_details.representation())))) { 2460 !new_representation.fits_into(old_details.representation())))) {
2435 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2461 return CopyGeneralizeAllRepresentations(
2436 new_kind, new_attributes, 2462 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2437 "GenAll_RootModification2"); 2463 "GenAll_RootModification2");
2438 } 2464 }
2439 } 2465 }
2440 2466
2441 // From here on, use the map with correct elements kind as root map. 2467 // From here on, use the map with correct elements kind as root map.
2442 if (from_kind != to_kind) { 2468 if (from_kind != to_kind) {
2443 root_map = Map::AsElementsKind(root_map, to_kind); 2469 root_map = Map::AsElementsKind(root_map, to_kind);
2444 } 2470 }
2445 2471
2446 Handle<Map> target_map = root_map; 2472 Handle<Map> target_map = root_map;
2447 for (int i = root_nof; i < old_nof; ++i) { 2473 for (int i = root_nof; i < old_nof; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 Handle<DescriptorArray> tmp_descriptors = handle( 2507 Handle<DescriptorArray> tmp_descriptors = handle(
2482 tmp_map->instance_descriptors(), isolate); 2508 tmp_map->instance_descriptors(), isolate);
2483 2509
2484 // Check if target map is incompatible. 2510 // Check if target map is incompatible.
2485 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 2511 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2486 DCHECK_EQ(next_kind, tmp_details.kind()); 2512 DCHECK_EQ(next_kind, tmp_details.kind());
2487 DCHECK_EQ(next_attributes, tmp_details.attributes()); 2513 DCHECK_EQ(next_attributes, tmp_details.attributes());
2488 if (next_kind == kAccessor && 2514 if (next_kind == kAccessor &&
2489 !EqualImmutableValues(old_descriptors->GetValue(i), 2515 !EqualImmutableValues(old_descriptors->GetValue(i),
2490 tmp_descriptors->GetValue(i))) { 2516 tmp_descriptors->GetValue(i))) {
2491 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2517 return CopyGeneralizeAllRepresentations(
2492 new_kind, new_attributes, 2518 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2493 "GenAll_Incompatible"); 2519 "GenAll_Incompatible");
2494 } 2520 }
2495 if (next_location == kField && tmp_details.location() == kDescriptor) break; 2521 if (next_location == kField && tmp_details.location() == kDescriptor) break;
2496 2522
2497 Representation tmp_representation = tmp_details.representation(); 2523 Representation tmp_representation = tmp_details.representation();
2498 if (!next_representation.fits_into(tmp_representation)) break; 2524 if (!next_representation.fits_into(tmp_representation)) break;
2499 2525
2500 PropertyLocation old_location = old_details.location(); 2526 PropertyLocation old_location = old_details.location();
2501 PropertyLocation tmp_location = tmp_details.location(); 2527 PropertyLocation tmp_location = tmp_details.location();
2502 if (tmp_location == kField) { 2528 if (tmp_location == kField) {
2503 if (next_kind == kData) { 2529 if (next_kind == kData) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2540 if (modify_index >= 0) { 2566 if (modify_index >= 0) {
2541 PropertyDetails details = target_descriptors->GetDetails(modify_index); 2567 PropertyDetails details = target_descriptors->GetDetails(modify_index);
2542 DCHECK_EQ(new_kind, details.kind()); 2568 DCHECK_EQ(new_kind, details.kind());
2543 DCHECK_EQ(new_attributes, details.attributes()); 2569 DCHECK_EQ(new_attributes, details.attributes());
2544 DCHECK(new_representation.fits_into(details.representation())); 2570 DCHECK(new_representation.fits_into(details.representation()));
2545 DCHECK(details.location() != kField || 2571 DCHECK(details.location() != kField ||
2546 new_field_type->NowIs( 2572 new_field_type->NowIs(
2547 target_descriptors->GetFieldType(modify_index))); 2573 target_descriptors->GetFieldType(modify_index)));
2548 } 2574 }
2549 #endif 2575 #endif
2576
2550 if (*target_map != *old_map) { 2577 if (*target_map != *old_map) {
2578 // Add any preventExtensions/seal/freeze transition back onto the end.
2579 if (!old_map.is_identical_to(real_old_map)) {
2580 MaybeHandle<Map> transition_map = TransitionForPreventExtensions(
2581 target_map, extra_attributes,
2582 AsTransitionMarker(isolate, extra_attributes));
2583 if (!transition_map.ToHandle(&target_map)) {
2584 return CopyGeneralizeAllRepresentations(
2585 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2586 "GenAll_CantHaveMoreTransitions");
2587 }
Igor Sheludko 2015/09/16 13:09:15 You should add if (*target_map != *real_old_map)
2588 }
2551 old_map->NotifyLeafMapLayoutChange(); 2589 old_map->NotifyLeafMapLayoutChange();
2590 return target_map;
2552 } 2591 }
2553 return target_map; 2592 return real_old_map;
2554 } 2593 }
2555 2594
2556 // Find the last compatible target map in the transition tree. 2595 // Find the last compatible target map in the transition tree.
2557 for (int i = target_nof; i < old_nof; ++i) { 2596 for (int i = target_nof; i < old_nof; ++i) {
2558 PropertyDetails old_details = old_descriptors->GetDetails(i); 2597 PropertyDetails old_details = old_descriptors->GetDetails(i);
2559 PropertyKind next_kind; 2598 PropertyKind next_kind;
2560 PropertyAttributes next_attributes; 2599 PropertyAttributes next_attributes;
2561 if (modify_index == i) { 2600 if (modify_index == i) {
2562 next_kind = new_kind; 2601 next_kind = new_kind;
2563 next_attributes = new_attributes; 2602 next_attributes = new_attributes;
(...skipping 10 matching lines...) Expand all
2574 2613
2575 // Check if target map is compatible. 2614 // Check if target map is compatible.
2576 #ifdef DEBUG 2615 #ifdef DEBUG
2577 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); 2616 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2578 DCHECK_EQ(next_kind, tmp_details.kind()); 2617 DCHECK_EQ(next_kind, tmp_details.kind());
2579 DCHECK_EQ(next_attributes, tmp_details.attributes()); 2618 DCHECK_EQ(next_attributes, tmp_details.attributes());
2580 #endif 2619 #endif
2581 if (next_kind == kAccessor && 2620 if (next_kind == kAccessor &&
2582 !EqualImmutableValues(old_descriptors->GetValue(i), 2621 !EqualImmutableValues(old_descriptors->GetValue(i),
2583 tmp_descriptors->GetValue(i))) { 2622 tmp_descriptors->GetValue(i))) {
2584 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2623 return CopyGeneralizeAllRepresentations(
2585 new_kind, new_attributes, 2624 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2586 "GenAll_Incompatible"); 2625 "GenAll_Incompatible");
2587 } 2626 }
2588 DCHECK(!tmp_map->is_deprecated()); 2627 DCHECK(!tmp_map->is_deprecated());
2589 target_map = tmp_map; 2628 target_map = tmp_map;
2590 } 2629 }
2591 target_nof = target_map->NumberOfOwnDescriptors(); 2630 target_nof = target_map->NumberOfOwnDescriptors();
2592 target_descriptors = handle(target_map->instance_descriptors(), isolate); 2631 target_descriptors = handle(target_map->instance_descriptors(), isolate);
2593 2632
2594 // Allocate a new descriptor array large enough to hold the required 2633 // Allocate a new descriptor array large enough to hold the required
2595 // descriptors, with minimally the exact same size as the old descriptor 2634 // descriptors, with minimally the exact same size as the old descriptor
2596 // array. 2635 // array.
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 } 2840 }
2802 bool transition_target_deprecated = split_map->DeprecateTarget( 2841 bool transition_target_deprecated = split_map->DeprecateTarget(
2803 split_kind, old_descriptors->GetKey(split_nof), split_attributes, 2842 split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2804 *new_descriptors, *new_layout_descriptor); 2843 *new_descriptors, *new_layout_descriptor);
2805 2844
2806 // If |transition_target_deprecated| is true then the transition array 2845 // If |transition_target_deprecated| is true then the transition array
2807 // already contains entry for given descriptor. This means that the transition 2846 // already contains entry for given descriptor. This means that the transition
2808 // could be inserted regardless of whether transitions array is full or not. 2847 // could be inserted regardless of whether transitions array is full or not.
2809 if (!transition_target_deprecated && 2848 if (!transition_target_deprecated &&
2810 !TransitionArray::CanHaveMoreTransitions(split_map)) { 2849 !TransitionArray::CanHaveMoreTransitions(split_map)) {
2811 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 2850 return CopyGeneralizeAllRepresentations(
2812 new_kind, new_attributes, 2851 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2813 "GenAll_CantHaveMoreTransitions"); 2852 "GenAll_CantHaveMoreTransitions");
2853 }
2854
2855 // Add missing transitions.
2856 Handle<Map> new_map = split_map;
2857 for (int i = split_nof; i < old_nof; ++i) {
2858 new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2859 new_layout_descriptor);
2860 }
2861 new_map->set_owns_descriptors(true);
2862
2863 // Add any preventExtensions/seal/freeze transition back onto the end.
2864 if (!old_map.is_identical_to(real_old_map)) {
2865 MaybeHandle<Map> transition_map = TransitionForPreventExtensions(
Igor Sheludko 2015/09/16 13:09:15 It does not make sense to search for transition he
2866 new_map, extra_attributes,
2867 AsTransitionMarker(isolate, extra_attributes));
2868 if (!transition_map.ToHandle(&new_map)) {
2869 return CopyGeneralizeAllRepresentations(
2870 real_old_map, modify_index, store_mode, new_kind, new_attributes,
2871 "GenAll_CantHaveMoreTransitions");
2872 }
2814 } 2873 }
2815 2874
2816 old_map->NotifyLeafMapLayoutChange(); 2875 old_map->NotifyLeafMapLayoutChange();
2817 2876
2818 if (FLAG_trace_generalization && modify_index >= 0) { 2877 if (FLAG_trace_generalization && modify_index >= 0) {
2819 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 2878 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2820 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); 2879 PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2821 Handle<HeapType> old_field_type = 2880 Handle<HeapType> old_field_type =
2822 (old_details.type() == DATA) 2881 (old_details.type() == DATA)
2823 ? handle(old_descriptors->GetFieldType(modify_index), isolate) 2882 ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2824 : HeapType::Constant( 2883 : HeapType::Constant(
2825 handle(old_descriptors->GetValue(modify_index), isolate), 2884 handle(old_descriptors->GetValue(modify_index), isolate),
2826 isolate); 2885 isolate);
2827 Handle<HeapType> new_field_type = 2886 Handle<HeapType> new_field_type =
2828 (new_details.type() == DATA) 2887 (new_details.type() == DATA)
2829 ? handle(new_descriptors->GetFieldType(modify_index), isolate) 2888 ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2830 : HeapType::Constant( 2889 : HeapType::Constant(
2831 handle(new_descriptors->GetValue(modify_index), isolate), 2890 handle(new_descriptors->GetValue(modify_index), isolate),
2832 isolate); 2891 isolate);
2833 old_map->PrintGeneralization( 2892 old_map->PrintGeneralization(
2834 stdout, "", modify_index, split_nof, old_nof, 2893 stdout, "", modify_index, split_nof, old_nof,
2835 old_details.location() == kDescriptor && store_mode == FORCE_FIELD, 2894 old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2836 old_details.representation(), new_details.representation(), 2895 old_details.representation(), new_details.representation(),
2837 *old_field_type, *new_field_type); 2896 *old_field_type, *new_field_type);
2838 } 2897 }
2839 2898
2840 // Add missing transitions.
2841 Handle<Map> new_map = split_map;
2842 for (int i = split_nof; i < old_nof; ++i) {
2843 new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2844 new_layout_descriptor);
2845 }
2846 new_map->set_owns_descriptors(true);
2847 return new_map; 2899 return new_map;
2848 } 2900 }
2849 2901
2850 2902
2851 // Generalize the representation of all DATA descriptors. 2903 // Generalize the representation of all DATA descriptors.
2852 Handle<Map> Map::GeneralizeAllFieldRepresentations( 2904 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2853 Handle<Map> map) { 2905 Handle<Map> map) {
2854 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 2906 Handle<DescriptorArray> descriptors(map->instance_descriptors());
2855 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { 2907 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2856 PropertyDetails details = descriptors->GetDetails(i); 2908 PropertyDetails details = descriptors->GetDetails(i);
(...skipping 2695 matching lines...) Expand 10 before | Expand all | Expand 10 after
5552 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), 5604 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5553 Object); 5605 Object);
5554 } 5606 }
5555 5607
5556 Handle<SeededNumberDictionary> new_element_dictionary; 5608 Handle<SeededNumberDictionary> new_element_dictionary;
5557 if (!object->elements()->IsDictionary()) { 5609 if (!object->elements()->IsDictionary()) {
5558 new_element_dictionary = GetNormalizedElementDictionary(object); 5610 new_element_dictionary = GetNormalizedElementDictionary(object);
5559 isolate->UpdateArrayProtectorOnNormalizeElements(object); 5611 isolate->UpdateArrayProtectorOnNormalizeElements(object);
5560 } 5612 }
5561 5613
5562 Handle<Symbol> transition_marker; 5614 Handle<Symbol> transition_marker = Map::AsTransitionMarker(isolate, attrs);
5563 if (attrs == NONE) {
5564 transition_marker = isolate->factory()->nonextensible_symbol();
5565 } else if (attrs == SEALED) {
5566 transition_marker = isolate->factory()->sealed_symbol();
5567 } else {
5568 DCHECK(attrs == FROZEN);
5569 transition_marker = isolate->factory()->frozen_symbol();
5570 }
5571 5615
5572 Handle<Map> old_map(object->map(), isolate); 5616 Handle<Map> old_map(object->map(), isolate);
5573 Map* transition = 5617 MaybeHandle<Map> transition_map =
5574 TransitionArray::SearchSpecial(*old_map, *transition_marker); 5618 Map::TransitionForPreventExtensions(old_map, attrs, transition_marker);
5575 if (transition != NULL) { 5619 Handle<Map> new_map;
5576 Handle<Map> transition_map(transition, isolate); 5620 if (!transition_map.ToHandle(&new_map)) {
5577 DCHECK(transition_map->has_dictionary_elements());
5578 DCHECK(!transition_map->is_extensible());
5579 JSObject::MigrateToMap(object, transition_map);
5580 } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5581 // Create a new descriptor array with the appropriate property attributes
5582 Handle<Map> new_map = Map::CopyForPreventExtensions(
5583 old_map, attrs, transition_marker, "CopyForPreventExtensions");
5584 JSObject::MigrateToMap(object, new_map);
5585 } else {
5586 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); 5621 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5587 // Slow path: need to normalize properties for safety 5622 // Slow path: need to normalize properties for safety
5588 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, 5623 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5589 "SlowPreventExtensions"); 5624 "SlowPreventExtensions");
5590 5625
5591 // Create a new map, since other objects with this map may be extensible. 5626 // Create a new map, since other objects with this map may be extensible.
5592 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5627 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5593 Handle<Map> new_map = 5628 new_map = Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5594 Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5595 new_map->set_is_extensible(false); 5629 new_map->set_is_extensible(false);
5596 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 5630 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5597 JSObject::MigrateToMap(object, new_map); 5631 JSObject::MigrateToMap(object, new_map);
5598 5632
5599 if (attrs != NONE) { 5633 if (attrs != NONE) {
5600 if (object->IsGlobalObject()) { 5634 if (object->IsGlobalObject()) {
5601 ApplyAttributesToDictionary(object->global_dictionary(), attrs); 5635 ApplyAttributesToDictionary(object->global_dictionary(), attrs);
5602 } else { 5636 } else {
5603 ApplyAttributesToDictionary(object->property_dictionary(), attrs); 5637 ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5604 } 5638 }
5605 } 5639 }
5640 } else {
5641 JSObject::MigrateToMap(object, new_map);
5606 } 5642 }
5607 5643
5608 DCHECK(object->map()->has_dictionary_elements()); 5644 DCHECK(object->map()->has_dictionary_elements());
5609 if (!new_element_dictionary.is_null()) { 5645 if (!new_element_dictionary.is_null()) {
5610 object->set_elements(*new_element_dictionary); 5646 object->set_elements(*new_element_dictionary);
5611 } 5647 }
5612 5648
5613 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { 5649 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5614 SeededNumberDictionary* dictionary = object->element_dictionary(); 5650 SeededNumberDictionary* dictionary = object->element_dictionary();
5615 // Make sure we never go back to the fast case 5651 // Make sure we never go back to the fast case
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after
6899 isolate); 6935 isolate);
6900 Handle<Map> new_map = CopyReplaceDescriptors( 6936 Handle<Map> new_map = CopyReplaceDescriptors(
6901 map, new_desc, new_layout_descriptor, INSERT_TRANSITION, 6937 map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
6902 transition_marker, reason, SPECIAL_TRANSITION); 6938 transition_marker, reason, SPECIAL_TRANSITION);
6903 new_map->set_is_extensible(false); 6939 new_map->set_is_extensible(false);
6904 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 6940 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6905 return new_map; 6941 return new_map;
6906 } 6942 }
6907 6943
6908 6944
6945 MaybeHandle<Map> Map::TransitionForPreventExtensions(
6946 Handle<Map> old_map, PropertyAttributes attrs,
6947 Handle<Symbol> transition_marker) {
6948 Isolate* isolate = old_map->GetIsolate();
6949 Map* transition =
6950 TransitionArray::SearchSpecial(*old_map, *transition_marker);
6951 if (transition != NULL) {
6952 Handle<Map> transition_map(transition, isolate);
6953 DCHECK(transition_map->has_dictionary_elements());
6954 DCHECK(!transition_map->is_extensible());
6955 return transition_map;
6956 } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
6957 // Create a new descriptor array with the appropriate property attributes
6958 Handle<Map> new_map = Map::CopyForPreventExtensions(
6959 old_map, attrs, transition_marker, "CopyForPreventExtensions");
6960 return new_map;
6961 }
6962 return MaybeHandle<Map>();
6963 }
6964
6965
6966 Handle<Symbol> Map::AsTransitionMarker(Isolate* isolate,
6967 PropertyAttributes attrs) {
6968 if (attrs == NONE) {
6969 return isolate->factory()->nonextensible_symbol();
6970 } else if (attrs == SEALED) {
6971 return isolate->factory()->sealed_symbol();
6972 } else {
6973 DCHECK(attrs == FROZEN);
6974 return isolate->factory()->frozen_symbol();
6975 }
6976 }
6977
6978
6909 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) { 6979 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) {
6910 DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE); 6980 DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
6911 DCHECK(map->IsJSProxyMap()); 6981 DCHECK(map->IsJSProxyMap());
6912 6982
6913 Isolate* isolate = map->GetIsolate(); 6983 Isolate* isolate = map->GetIsolate();
6914 6984
6915 // Allocate fresh map. 6985 // Allocate fresh map.
6916 // TODO(rossberg): Once we optimize proxies, cache these maps. 6986 // TODO(rossberg): Once we optimize proxies, cache these maps.
6917 Handle<Map> new_map = isolate->factory()->NewMap(type, size); 6987 Handle<Map> new_map = isolate->factory()->NewMap(type, size);
6918 6988
(...skipping 8988 matching lines...) Expand 10 before | Expand all | Expand 10 after
15907 Handle<Object> new_value) { 15977 Handle<Object> new_value) {
15908 if (cell->value() != *new_value) { 15978 if (cell->value() != *new_value) {
15909 cell->set_value(*new_value); 15979 cell->set_value(*new_value);
15910 Isolate* isolate = cell->GetIsolate(); 15980 Isolate* isolate = cell->GetIsolate();
15911 cell->dependent_code()->DeoptimizeDependentCodeGroup( 15981 cell->dependent_code()->DeoptimizeDependentCodeGroup(
15912 isolate, DependentCode::kPropertyCellChangedGroup); 15982 isolate, DependentCode::kPropertyCellChangedGroup);
15913 } 15983 }
15914 } 15984 }
15915 } // namespace internal 15985 } // namespace internal
15916 } // namespace v8 15986 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698