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

Side by Side Diff: src/objects.cc

Issue 450303003: Tag all prototypes as proto, except those set using __proto__ (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove is_shared from Map Created 6 years, 4 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-debug.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 // 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 "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/allocation-site-scopes.h" 8 #include "src/allocation-site-scopes.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 3452 matching lines...) Expand 10 before | Expand all | Expand 10 after
3463 ElementsKind to_kind) { 3463 ElementsKind to_kind) {
3464 ElementsKind from_kind = map->elements_kind(); 3464 ElementsKind from_kind = map->elements_kind();
3465 3465
3466 if (from_kind == to_kind) { 3466 if (from_kind == to_kind) {
3467 return map; 3467 return map;
3468 } 3468 }
3469 3469
3470 bool allow_store_transition = 3470 bool allow_store_transition =
3471 // Only remember the map transition if there is not an already existing 3471 // Only remember the map transition if there is not an already existing
3472 // non-matching element transition. 3472 // non-matching element transition.
3473 !map->IsUndefined() && !map->is_shared() && 3473 !map->IsUndefined() && !map->is_dictionary_map() &&
3474 IsTransitionElementsKind(from_kind); 3474 IsTransitionElementsKind(from_kind);
3475 3475
3476 // Only store fast element maps in ascending generality. 3476 // Only store fast element maps in ascending generality.
3477 if (IsFastElementsKind(to_kind)) { 3477 if (IsFastElementsKind(to_kind)) {
3478 allow_store_transition &= 3478 allow_store_transition &=
3479 IsTransitionableFastElementsKind(from_kind) && 3479 IsTransitionableFastElementsKind(from_kind) &&
3480 IsMoreGeneralElementsKindTransition(from_kind, to_kind); 3480 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3481 } 3481 }
3482 3482
3483 if (!allow_store_transition) { 3483 if (!allow_store_transition) {
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after
4433 4433
4434 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { 4434 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4435 Handle<FixedArray> array( 4435 Handle<FixedArray> array(
4436 isolate->factory()->NewFixedArray(kEntries, TENURED)); 4436 isolate->factory()->NewFixedArray(kEntries, TENURED));
4437 return Handle<NormalizedMapCache>::cast(array); 4437 return Handle<NormalizedMapCache>::cast(array);
4438 } 4438 }
4439 4439
4440 4440
4441 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map, 4441 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4442 PropertyNormalizationMode mode) { 4442 PropertyNormalizationMode mode) {
4443 // Only use the cache once it is initialized.
4444 if (!IsNormalizedMapCache(this)) return MaybeHandle<Map>();
4443 DisallowHeapAllocation no_gc; 4445 DisallowHeapAllocation no_gc;
4444 Object* value = FixedArray::get(GetIndex(fast_map)); 4446 Object* value = FixedArray::get(GetIndex(fast_map));
4445 if (!value->IsMap() || 4447 if (!value->IsMap() ||
4446 !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) { 4448 !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4447 return MaybeHandle<Map>(); 4449 return MaybeHandle<Map>();
4448 } 4450 }
4449 return handle(Map::cast(value)); 4451 return handle(Map::cast(value));
4450 } 4452 }
4451 4453
4452 4454
4453 void NormalizedMapCache::Set(Handle<Map> fast_map, 4455 void NormalizedMapCache::Set(Handle<Map> fast_map,
4454 Handle<Map> normalized_map) { 4456 Handle<Map> normalized_map) {
4457 // Only use the cache once it is initialized.
4458 if (!IsNormalizedMapCache(this)) return;
4455 DisallowHeapAllocation no_gc; 4459 DisallowHeapAllocation no_gc;
4456 DCHECK(normalized_map->is_dictionary_map()); 4460 DCHECK(normalized_map->is_dictionary_map());
4457 FixedArray::set(GetIndex(fast_map), *normalized_map); 4461 FixedArray::set(GetIndex(fast_map), *normalized_map);
4458 } 4462 }
4459 4463
4460 4464
4461 void NormalizedMapCache::Clear() { 4465 void NormalizedMapCache::Clear() {
4462 int entries = length(); 4466 int entries = length();
4463 for (int i = 0; i != entries; i++) { 4467 for (int i = 0; i != entries; i++) {
4464 set_undefined(i); 4468 set_undefined(i);
(...skipping 2509 matching lines...) Expand 10 before | Expand all | Expand 10 after
6974 PropertyNormalizationMode mode) { 6978 PropertyNormalizationMode mode) {
6975 DCHECK(!fast_map->is_dictionary_map()); 6979 DCHECK(!fast_map->is_dictionary_map());
6976 6980
6977 Isolate* isolate = fast_map->GetIsolate(); 6981 Isolate* isolate = fast_map->GetIsolate();
6978 Handle<NormalizedMapCache> cache( 6982 Handle<NormalizedMapCache> cache(
6979 isolate->context()->native_context()->normalized_map_cache()); 6983 isolate->context()->native_context()->normalized_map_cache());
6980 6984
6981 Handle<Map> new_map; 6985 Handle<Map> new_map;
6982 if (cache->Get(fast_map, mode).ToHandle(&new_map)) { 6986 if (cache->Get(fast_map, mode).ToHandle(&new_map)) {
6983 #ifdef VERIFY_HEAP 6987 #ifdef VERIFY_HEAP
6984 if (FLAG_verify_heap) { 6988 if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6985 new_map->SharedMapVerify();
6986 }
6987 #endif 6989 #endif
6988 #ifdef ENABLE_SLOW_DCHECKS 6990 #ifdef ENABLE_SLOW_DCHECKS
6989 if (FLAG_enable_slow_asserts) { 6991 if (FLAG_enable_slow_asserts) {
6990 // The cached map should match newly created normalized map bit-by-bit, 6992 // The cached map should match newly created normalized map bit-by-bit,
6991 // except for the code cache, which can contain some ics which can be 6993 // except for the code cache, which can contain some ics which can be
6992 // applied to the shared map. 6994 // applied to the shared map.
6993 Handle<Map> fresh = Map::CopyNormalized( 6995 Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6994 fast_map, mode, SHARED_NORMALIZED_MAP);
6995 6996
6996 DCHECK(memcmp(fresh->address(), 6997 DCHECK(memcmp(fresh->address(),
6997 new_map->address(), 6998 new_map->address(),
6998 Map::kCodeCacheOffset) == 0); 6999 Map::kCodeCacheOffset) == 0);
6999 STATIC_ASSERT(Map::kDependentCodeOffset == 7000 STATIC_ASSERT(Map::kDependentCodeOffset ==
7000 Map::kCodeCacheOffset + kPointerSize); 7001 Map::kCodeCacheOffset + kPointerSize);
7001 int offset = Map::kDependentCodeOffset + kPointerSize; 7002 int offset = Map::kDependentCodeOffset + kPointerSize;
7002 DCHECK(memcmp(fresh->address() + offset, 7003 DCHECK(memcmp(fresh->address() + offset,
7003 new_map->address() + offset, 7004 new_map->address() + offset,
7004 Map::kSize - offset) == 0); 7005 Map::kSize - offset) == 0);
7005 } 7006 }
7006 #endif 7007 #endif
7007 } else { 7008 } else {
7008 new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP); 7009 new_map = Map::CopyNormalized(fast_map, mode);
7009 cache->Set(fast_map, new_map); 7010 cache->Set(fast_map, new_map);
7010 isolate->counters()->normalized_maps()->Increment(); 7011 isolate->counters()->normalized_maps()->Increment();
7011 } 7012 }
7012 fast_map->NotifyLeafMapLayoutChange(); 7013 fast_map->NotifyLeafMapLayoutChange();
7013 return new_map; 7014 return new_map;
7014 } 7015 }
7015 7016
7016 7017
7017 Handle<Map> Map::CopyNormalized(Handle<Map> map, 7018 Handle<Map> Map::CopyNormalized(Handle<Map> map,
7018 PropertyNormalizationMode mode, 7019 PropertyNormalizationMode mode) {
7019 NormalizedMapSharingMode sharing) {
7020 int new_instance_size = map->instance_size(); 7020 int new_instance_size = map->instance_size();
7021 if (mode == CLEAR_INOBJECT_PROPERTIES) { 7021 if (mode == CLEAR_INOBJECT_PROPERTIES) {
7022 new_instance_size -= map->inobject_properties() * kPointerSize; 7022 new_instance_size -= map->inobject_properties() * kPointerSize;
7023 } 7023 }
7024 7024
7025 Handle<Map> result = RawCopy(map, new_instance_size); 7025 Handle<Map> result = RawCopy(map, new_instance_size);
7026 7026
7027 if (mode != CLEAR_INOBJECT_PROPERTIES) { 7027 if (mode != CLEAR_INOBJECT_PROPERTIES) {
7028 result->set_inobject_properties(map->inobject_properties()); 7028 result->set_inobject_properties(map->inobject_properties());
7029 } 7029 }
7030 7030
7031 result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
7032 result->set_dictionary_map(true); 7031 result->set_dictionary_map(true);
7033 result->set_migration_target(false); 7032 result->set_migration_target(false);
7034 7033
7035 #ifdef VERIFY_HEAP 7034 #ifdef VERIFY_HEAP
7036 if (FLAG_verify_heap && result->is_shared()) { 7035 if (FLAG_verify_heap) result->DictionaryMapVerify();
7037 result->SharedMapVerify();
7038 }
7039 #endif 7036 #endif
7040 7037
7041 return result; 7038 return result;
7042 } 7039 }
7043 7040
7044 7041
7045 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { 7042 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
7046 Handle<Map> result = RawCopy(map, map->instance_size()); 7043 Handle<Map> result = RawCopy(map, map->instance_size());
7047 7044
7048 // Please note instance_type and instance_size are set when allocated. 7045 // Please note instance_type and instance_size are set when allocated.
7049 result->set_inobject_properties(map->inobject_properties()); 7046 result->set_inobject_properties(map->inobject_properties());
7050 result->set_unused_property_fields(map->unused_property_fields()); 7047 result->set_unused_property_fields(map->unused_property_fields());
7051 7048
7052 result->set_pre_allocated_property_fields( 7049 result->set_pre_allocated_property_fields(
7053 map->pre_allocated_property_fields()); 7050 map->pre_allocated_property_fields());
7054 result->set_is_shared(false);
7055 result->ClearCodeCache(map->GetHeap()); 7051 result->ClearCodeCache(map->GetHeap());
7056 map->NotifyLeafMapLayoutChange(); 7052 map->NotifyLeafMapLayoutChange();
7057 return result; 7053 return result;
7058 } 7054 }
7059 7055
7060 7056
7061 Handle<Map> Map::ShareDescriptor(Handle<Map> map, 7057 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
7062 Handle<DescriptorArray> descriptors, 7058 Handle<DescriptorArray> descriptors,
7063 Descriptor* descriptor) { 7059 Descriptor* descriptor) {
7064 // Sanity check. This path is only to be taken if the map owns its descriptor 7060 // Sanity check. This path is only to be taken if the map owns its descriptor
(...skipping 2740 matching lines...) Expand 10 before | Expand all | Expand 10 after
9805 DCHECK(shrink_by % kEntryLength == 0); 9801 DCHECK(shrink_by % kEntryLength == 0);
9806 DCHECK(shrink_by <= code_map->length() - kEntriesStart); 9802 DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9807 // Always trim even when array is cleared because of heap verifier. 9803 // Always trim even when array is cleared because of heap verifier.
9808 GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by); 9804 GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
9809 if (code_map->length() == kEntriesStart) { 9805 if (code_map->length() == kEntriesStart) {
9810 ClearOptimizedCodeMap(); 9806 ClearOptimizedCodeMap();
9811 } 9807 }
9812 } 9808 }
9813 9809
9814 9810
9815 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { 9811 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9812 PrototypeOptimizationMode mode) {
9816 if (object->IsGlobalObject()) return; 9813 if (object->IsGlobalObject()) return;
9817 9814 if (object->IsJSGlobalProxy()) return;
9818 // Make sure prototypes are fast objects and their maps have the bit set 9815 if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
9819 // so they remain fast. 9816 // First normalize to ensure all JSFunctions are CONSTANT.
9817 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
9818 }
9820 if (!object->HasFastProperties()) { 9819 if (!object->HasFastProperties()) {
9821 MigrateSlowToFast(object, 0); 9820 JSObject::MigrateSlowToFast(object, 0);
9821 }
9822 if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
9823 !object->map()->is_prototype_map()) {
9824 Handle<Map> new_map = Map::Copy(handle(object->map()));
9825 JSObject::MigrateToMap(object, new_map);
9826 object->map()->set_is_prototype_map(true);
9822 } 9827 }
9823 } 9828 }
9824 9829
9825 9830
9826 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 9831 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9827 if (!object->map()->is_prototype_map()) return; 9832 if (!object->map()->is_prototype_map()) return;
9828 OptimizeAsPrototype(object); 9833 OptimizeAsPrototype(object, FAST_PROTOTYPE);
9829 } 9834 }
9830 9835
9831 9836
9832 Handle<Object> CacheInitialJSArrayMaps( 9837 Handle<Object> CacheInitialJSArrayMaps(
9833 Handle<Context> native_context, Handle<Map> initial_map) { 9838 Handle<Context> native_context, Handle<Map> initial_map) {
9834 // Replace all of the cached initial array maps in the native context with 9839 // Replace all of the cached initial array maps in the native context with
9835 // the appropriate transitioned elements kind maps. 9840 // the appropriate transitioned elements kind maps.
9836 Factory* factory = native_context->GetIsolate()->factory(); 9841 Factory* factory = native_context->GetIsolate()->factory();
9837 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 9842 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9838 kElementsKindCount, TENURED); 9843 kElementsKindCount, TENURED);
(...skipping 30 matching lines...) Expand all
9869 // Now some logic for the maps of the objects that are created by using this 9874 // Now some logic for the maps of the objects that are created by using this
9870 // function as a constructor. 9875 // function as a constructor.
9871 if (function->has_initial_map()) { 9876 if (function->has_initial_map()) {
9872 // If the function has allocated the initial map replace it with a 9877 // If the function has allocated the initial map replace it with a
9873 // copy containing the new prototype. Also complete any in-object 9878 // copy containing the new prototype. Also complete any in-object
9874 // slack tracking that is in progress at this point because it is 9879 // slack tracking that is in progress at this point because it is
9875 // still tracking the old copy. 9880 // still tracking the old copy.
9876 if (function->IsInobjectSlackTrackingInProgress()) { 9881 if (function->IsInobjectSlackTrackingInProgress()) {
9877 function->CompleteInobjectSlackTracking(); 9882 function->CompleteInobjectSlackTracking();
9878 } 9883 }
9884
9879 Handle<Map> initial_map(function->initial_map(), isolate); 9885 Handle<Map> initial_map(function->initial_map(), isolate);
9880 Handle<Map> new_map = Map::Copy(initial_map);
9881 new_map->set_prototype(*value);
9882 9886
9883 // If the function is used as the global Array function, cache the 9887 if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9884 // initial map (and transitioned versions) in the native context. 9888 initial_map->instance_type() == JS_OBJECT_TYPE) {
9885 Context* native_context = function->context()->native_context(); 9889 // Put the value in the initial map field until an initial map is needed.
9886 Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); 9890 // At that point, a new initial map is created and the prototype is put
9887 if (array_function->IsJSFunction() && 9891 // into the initial map where it belongs.
9888 *function == JSFunction::cast(array_function)) { 9892 function->set_prototype_or_initial_map(*value);
9889 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map); 9893 } else {
9894 Handle<Map> new_map = Map::Copy(initial_map);
9895 JSFunction::SetInitialMap(function, new_map, value);
9896
9897 // If the function is used as the global Array function, cache the
9898 // initial map (and transitioned versions) in the native context.
9899 Context* native_context = function->context()->native_context();
9900 Object* array_function =
9901 native_context->get(Context::ARRAY_FUNCTION_INDEX);
9902 if (array_function->IsJSFunction() &&
9903 *function == JSFunction::cast(array_function)) {
9904 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
9905 }
9890 } 9906 }
9891 9907
9892 JSFunction::SetInitialMap(function, new_map);
9893
9894 // Deoptimize all code that embeds the previous initial map. 9908 // Deoptimize all code that embeds the previous initial map.
9895 initial_map->dependent_code()->DeoptimizeDependentCodeGroup( 9909 initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9896 isolate, DependentCode::kInitialMapChangedGroup); 9910 isolate, DependentCode::kInitialMapChangedGroup);
9897 } else { 9911 } else {
9898 // Put the value in the initial map field until an initial map is 9912 // Put the value in the initial map field until an initial map is
9899 // needed. At that point, a new initial map is created and the 9913 // needed. At that point, a new initial map is created and the
9900 // prototype is put into the initial map where it belongs. 9914 // prototype is put into the initial map where it belongs.
9901 function->set_prototype_or_initial_map(*value); 9915 function->set_prototype_or_initial_map(*value);
9902 } 9916 }
9903 isolate->heap()->ClearInstanceofCache(); 9917 isolate->heap()->ClearInstanceofCache();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
9949 return false; 9963 return false;
9950 } 9964 }
9951 #endif 9965 #endif
9952 9966
9953 set_map(no_prototype_map); 9967 set_map(no_prototype_map);
9954 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); 9968 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9955 return true; 9969 return true;
9956 } 9970 }
9957 9971
9958 9972
9959 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map) { 9973 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9960 if (map->prototype()->IsJSObject()) { 9974 Handle<Object> prototype) {
9961 Handle<JSObject> js_proto = handle(JSObject::cast(map->prototype())); 9975 if (prototype->IsJSObject()) {
9962 if (!js_proto->map()->is_prototype_map() && 9976 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
9963 !js_proto->map()->IsGlobalObjectMap() && 9977 JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
9964 !js_proto->map()->IsJSGlobalProxyMap()) {
9965 // Normalize and turn fast again to make all functions CONSTANT
9966 // properties.
9967 if (!js_proto->GetIsolate()->bootstrapper()->IsActive()) {
9968 JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0);
9969 }
9970 if (!js_proto->HasFastProperties()) {
9971 JSObject::MigrateSlowToFast(js_proto, 0);
9972 }
9973 if (js_proto->HasFastProperties()) {
9974 Handle<Map> new_map = Map::Copy(handle(js_proto->map()));
9975 JSObject::MigrateToMap(js_proto, new_map);
9976 js_proto->map()->set_is_prototype_map(true);
9977 }
9978 }
9979 } 9978 }
9979 map->set_prototype(*prototype);
9980 function->set_prototype_or_initial_map(*map); 9980 function->set_prototype_or_initial_map(*map);
9981 map->set_constructor(*function); 9981 map->set_constructor(*function);
9982 } 9982 }
9983 9983
9984 9984
9985 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { 9985 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9986 if (function->has_initial_map()) return; 9986 if (function->has_initial_map()) return;
9987 Isolate* isolate = function->GetIsolate(); 9987 Isolate* isolate = function->GetIsolate();
9988 9988
9989 // First create a new map with the size and number of in-object properties 9989 // First create a new map with the size and number of in-object properties
(...skipping 14 matching lines...) Expand all
10004 10004
10005 // Fetch or allocate prototype. 10005 // Fetch or allocate prototype.
10006 Handle<Object> prototype; 10006 Handle<Object> prototype;
10007 if (function->has_instance_prototype()) { 10007 if (function->has_instance_prototype()) {
10008 prototype = handle(function->instance_prototype(), isolate); 10008 prototype = handle(function->instance_prototype(), isolate);
10009 } else { 10009 } else {
10010 prototype = isolate->factory()->NewFunctionPrototype(function); 10010 prototype = isolate->factory()->NewFunctionPrototype(function);
10011 } 10011 }
10012 map->set_inobject_properties(in_object_properties); 10012 map->set_inobject_properties(in_object_properties);
10013 map->set_unused_property_fields(in_object_properties); 10013 map->set_unused_property_fields(in_object_properties);
10014 map->set_prototype(*prototype);
10015 DCHECK(map->has_fast_object_elements()); 10014 DCHECK(map->has_fast_object_elements());
10016 10015
10017 // Finally link initial map and constructor function. 10016 // Finally link initial map and constructor function.
10018 JSFunction::SetInitialMap(function, map); 10017 JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10019 10018
10020 if (!function->shared()->is_generator()) { 10019 if (!function->shared()->is_generator()) {
10021 function->StartInobjectSlackTracking(); 10020 function->StartInobjectSlackTracking();
10022 } 10021 }
10023 } 10022 }
10024 10023
10025 10024
10026 void JSFunction::SetInstanceClassName(String* name) { 10025 void JSFunction::SetInstanceClassName(String* name) {
10027 shared()->set_instance_class_name(name); 10026 shared()->set_instance_class_name(name);
10028 } 10027 }
(...skipping 1741 matching lines...) Expand 10 before | Expand all | Expand 10 after
11770 11769
11771 11770
11772 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, 11771 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11773 Handle<Object> prototype, 11772 Handle<Object> prototype,
11774 Handle<Map> target_map) { 11773 Handle<Map> target_map) {
11775 DCHECK(target_map->IsMap()); 11774 DCHECK(target_map->IsMap());
11776 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); 11775 DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
11777 // Don't cache prototype transition if this map is either shared, or a map of 11776 // Don't cache prototype transition if this map is either shared, or a map of
11778 // a prototype. 11777 // a prototype.
11779 if (map->is_prototype_map()) return map; 11778 if (map->is_prototype_map()) return map;
11780 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; 11779 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
11781 11780
11782 const int step = kProtoTransitionElementsPerEntry; 11781 const int step = kProtoTransitionElementsPerEntry;
11783 const int header = kProtoTransitionHeaderSize; 11782 const int header = kProtoTransitionHeaderSize;
11784 11783
11785 Handle<FixedArray> cache(map->GetPrototypeTransitions()); 11784 Handle<FixedArray> cache(map->GetPrototypeTransitions());
11786 int capacity = (cache->length() - header) / step; 11785 int capacity = (cache->length() - header) / step;
11787 int transitions = map->NumberOfProtoTransitions() + 1; 11786 int transitions = map->NumberOfProtoTransitions() + 1;
11788 11787
11789 if (transitions > capacity) { 11788 if (transitions > capacity) {
11790 if (capacity > kMaxCachedPrototypeTransitions) return map; 11789 if (capacity > kMaxCachedPrototypeTransitions) return map;
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
12093 new_map = Copy(map); 12092 new_map = Copy(map);
12094 PutPrototypeTransition(map, prototype, new_map); 12093 PutPrototypeTransition(map, prototype, new_map);
12095 new_map->set_prototype(*prototype); 12094 new_map->set_prototype(*prototype);
12096 } 12095 }
12097 return new_map; 12096 return new_map;
12098 } 12097 }
12099 12098
12100 12099
12101 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 12100 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12102 Handle<Object> value, 12101 Handle<Object> value,
12103 bool skip_hidden_prototypes) { 12102 bool from_javascript) {
12104 #ifdef DEBUG 12103 #ifdef DEBUG
12105 int size = object->Size(); 12104 int size = object->Size();
12106 #endif 12105 #endif
12107 12106
12108 Isolate* isolate = object->GetIsolate(); 12107 Isolate* isolate = object->GetIsolate();
12109 Heap* heap = isolate->heap(); 12108 Heap* heap = isolate->heap();
12110 // Silently ignore the change if value is not a JSObject or null. 12109 // Silently ignore the change if value is not a JSObject or null.
12111 // SpiderMonkey behaves this way. 12110 // SpiderMonkey behaves this way.
12112 if (!value->IsJSReceiver() && !value->IsNull()) return value; 12111 if (!value->IsJSReceiver() && !value->IsNull()) return value;
12113 12112
(...skipping 24 matching lines...) Expand all
12138 Handle<Object> error = isolate->factory()->NewError( 12137 Handle<Object> error = isolate->factory()->NewError(
12139 "cyclic_proto", HandleVector<Object>(NULL, 0)); 12138 "cyclic_proto", HandleVector<Object>(NULL, 0));
12140 return isolate->Throw<Object>(error); 12139 return isolate->Throw<Object>(error);
12141 } 12140 }
12142 } 12141 }
12143 12142
12144 bool dictionary_elements_in_chain = 12143 bool dictionary_elements_in_chain =
12145 object->map()->DictionaryElementsInPrototypeChainOnly(); 12144 object->map()->DictionaryElementsInPrototypeChainOnly();
12146 Handle<JSObject> real_receiver = object; 12145 Handle<JSObject> real_receiver = object;
12147 12146
12148 if (skip_hidden_prototypes) { 12147 if (from_javascript) {
12149 // Find the first object in the chain whose prototype object is not 12148 // Find the first object in the chain whose prototype object is not
12150 // hidden and set the new prototype on that object. 12149 // hidden and set the new prototype on that object.
12151 PrototypeIterator iter(isolate, real_receiver); 12150 PrototypeIterator iter(isolate, real_receiver);
12152 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 12151 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12153 real_receiver = 12152 real_receiver =
12154 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 12153 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12155 iter.Advance(); 12154 iter.Advance();
12156 } 12155 }
12157 } 12156 }
12158 12157
12159 // Set the new prototype of the object. 12158 // Set the new prototype of the object.
12160 Handle<Map> map(real_receiver->map()); 12159 Handle<Map> map(real_receiver->map());
12161 12160
12162 // Nothing to do if prototype is already set. 12161 // Nothing to do if prototype is already set.
12163 if (map->prototype() == *value) return value; 12162 if (map->prototype() == *value) return value;
12164 12163
12165 if (value->IsJSObject()) { 12164 if (value->IsJSObject()) {
12166 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); 12165 PrototypeOptimizationMode mode =
12166 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12167 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
12167 } 12168 }
12168 12169
12169 Handle<Map> new_map = Map::TransitionToPrototype(map, value); 12170 Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12170 DCHECK(new_map->prototype() == *value); 12171 DCHECK(new_map->prototype() == *value);
12171 JSObject::MigrateToMap(real_receiver, new_map); 12172 JSObject::MigrateToMap(real_receiver, new_map);
12172 12173
12173 if (!dictionary_elements_in_chain && 12174 if (!dictionary_elements_in_chain &&
12174 new_map->DictionaryElementsInPrototypeChainOnly()) { 12175 new_map->DictionaryElementsInPrototypeChainOnly()) {
12175 // If the prototype chain didn't previously have element callbacks, then 12176 // If the prototype chain didn't previously have element callbacks, then
12176 // KeyedStoreICs need to be cleared to ensure any that involve this 12177 // KeyedStoreICs need to be cleared to ensure any that involve this
(...skipping 4721 matching lines...) Expand 10 before | Expand all | Expand 10 after
16898 #define ERROR_MESSAGES_TEXTS(C, T) T, 16899 #define ERROR_MESSAGES_TEXTS(C, T) T,
16899 static const char* error_messages_[] = { 16900 static const char* error_messages_[] = {
16900 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16901 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16901 }; 16902 };
16902 #undef ERROR_MESSAGES_TEXTS 16903 #undef ERROR_MESSAGES_TEXTS
16903 return error_messages_[reason]; 16904 return error_messages_[reason];
16904 } 16905 }
16905 16906
16906 16907
16907 } } // namespace v8::internal 16908 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698