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

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: 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/runtime.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 // 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 6961 matching lines...) Expand 10 before | Expand all | Expand 10 after
6972 6972
6973 Handle<Map> Map::Normalize(Handle<Map> fast_map, 6973 Handle<Map> Map::Normalize(Handle<Map> fast_map,
6974 PropertyNormalizationMode mode) { 6974 PropertyNormalizationMode mode) {
6975 DCHECK(!fast_map->is_dictionary_map()); 6975 DCHECK(!fast_map->is_dictionary_map());
6976 6976
6977 Isolate* isolate = fast_map->GetIsolate(); 6977 Isolate* isolate = fast_map->GetIsolate();
6978 Handle<NormalizedMapCache> cache( 6978 Handle<NormalizedMapCache> cache(
6979 isolate->context()->native_context()->normalized_map_cache()); 6979 isolate->context()->native_context()->normalized_map_cache());
6980 6980
6981 Handle<Map> new_map; 6981 Handle<Map> new_map;
6982 if (cache->Get(fast_map, mode).ToHandle(&new_map)) { 6982 if (!fast_map->is_prototype_map() &&
6983 cache->Get(fast_map, mode).ToHandle(&new_map)) {
6983 #ifdef VERIFY_HEAP 6984 #ifdef VERIFY_HEAP
6984 if (FLAG_verify_heap) { 6985 if (FLAG_verify_heap) {
6985 new_map->SharedMapVerify(); 6986 new_map->SharedMapVerify();
6986 } 6987 }
6987 #endif 6988 #endif
6988 #ifdef ENABLE_SLOW_DCHECKS 6989 #ifdef ENABLE_SLOW_DCHECKS
6989 if (FLAG_enable_slow_asserts) { 6990 if (FLAG_enable_slow_asserts) {
6990 // The cached map should match newly created normalized map bit-by-bit, 6991 // 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 6992 // except for the code cache, which can contain some ics which can be
6992 // applied to the shared map. 6993 // applied to the shared map.
6993 Handle<Map> fresh = Map::CopyNormalized( 6994 Handle<Map> fresh = Map::CopyNormalized(
6994 fast_map, mode, SHARED_NORMALIZED_MAP); 6995 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, SHARED_NORMALIZED_MAP);
7009 cache->Set(fast_map, new_map); 7010 if (!fast_map->is_prototype_map()) {
7010 isolate->counters()->normalized_maps()->Increment(); 7011 cache->Set(fast_map, new_map);
7012 isolate->counters()->normalized_maps()->Increment();
7013 }
7011 } 7014 }
7012 fast_map->NotifyLeafMapLayoutChange(); 7015 fast_map->NotifyLeafMapLayoutChange();
7013 return new_map; 7016 return new_map;
7014 } 7017 }
7015 7018
7016 7019
7017 Handle<Map> Map::CopyNormalized(Handle<Map> map, 7020 Handle<Map> Map::CopyNormalized(Handle<Map> map,
7018 PropertyNormalizationMode mode, 7021 PropertyNormalizationMode mode,
7019 NormalizedMapSharingMode sharing) { 7022 NormalizedMapSharingMode sharing) {
7020 int new_instance_size = map->instance_size(); 7023 int new_instance_size = map->instance_size();
(...skipping 2848 matching lines...) Expand 10 before | Expand all | Expand 10 after
9869 // Now some logic for the maps of the objects that are created by using this 9872 // Now some logic for the maps of the objects that are created by using this
9870 // function as a constructor. 9873 // function as a constructor.
9871 if (function->has_initial_map()) { 9874 if (function->has_initial_map()) {
9872 // If the function has allocated the initial map replace it with a 9875 // If the function has allocated the initial map replace it with a
9873 // copy containing the new prototype. Also complete any in-object 9876 // copy containing the new prototype. Also complete any in-object
9874 // slack tracking that is in progress at this point because it is 9877 // slack tracking that is in progress at this point because it is
9875 // still tracking the old copy. 9878 // still tracking the old copy.
9876 if (function->IsInobjectSlackTrackingInProgress()) { 9879 if (function->IsInobjectSlackTrackingInProgress()) {
9877 function->CompleteInobjectSlackTracking(); 9880 function->CompleteInobjectSlackTracking();
9878 } 9881 }
9882
9879 Handle<Map> initial_map(function->initial_map(), isolate); 9883 Handle<Map> initial_map(function->initial_map(), isolate);
9880 Handle<Map> new_map = Map::Copy(initial_map);
9881 new_map->set_prototype(*value);
9882 9884
9883 // If the function is used as the global Array function, cache the 9885 if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9884 // initial map (and transitioned versions) in the native context. 9886 initial_map->instance_type() == JS_OBJECT_TYPE) {
9885 Context* native_context = function->context()->native_context(); 9887 // 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); 9888 // At that point, a new initial map is created and the prototype is put
9887 if (array_function->IsJSFunction() && 9889 // into the initial map where it belongs.
9888 *function == JSFunction::cast(array_function)) { 9890 function->set_prototype_or_initial_map(*value);
9889 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map); 9891 } else {
9892 Handle<Map> new_map = Map::Copy(initial_map);
9893 JSFunction::SetInitialMap(function, new_map, value);
9894
9895 // If the function is used as the global Array function, cache the
9896 // initial map (and transitioned versions) in the native context.
9897 Context* native_context = function->context()->native_context();
9898 Object* array_function =
9899 native_context->get(Context::ARRAY_FUNCTION_INDEX);
9900 if (array_function->IsJSFunction() &&
9901 *function == JSFunction::cast(array_function)) {
9902 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
9903 }
9890 } 9904 }
9891 9905
9892 JSFunction::SetInitialMap(function, new_map);
9893
9894 // Deoptimize all code that embeds the previous initial map. 9906 // Deoptimize all code that embeds the previous initial map.
9895 initial_map->dependent_code()->DeoptimizeDependentCodeGroup( 9907 initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9896 isolate, DependentCode::kInitialMapChangedGroup); 9908 isolate, DependentCode::kInitialMapChangedGroup);
9897 } else { 9909 } else {
9898 // Put the value in the initial map field until an initial map is 9910 // 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 9911 // needed. At that point, a new initial map is created and the
9900 // prototype is put into the initial map where it belongs. 9912 // prototype is put into the initial map where it belongs.
9901 function->set_prototype_or_initial_map(*value); 9913 function->set_prototype_or_initial_map(*value);
9902 } 9914 }
9903 isolate->heap()->ClearInstanceofCache(); 9915 isolate->heap()->ClearInstanceofCache();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
9949 return false; 9961 return false;
9950 } 9962 }
9951 #endif 9963 #endif
9952 9964
9953 set_map(no_prototype_map); 9965 set_map(no_prototype_map);
9954 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); 9966 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9955 return true; 9967 return true;
9956 } 9968 }
9957 9969
9958 9970
9959 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map) { 9971 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9960 if (map->prototype()->IsJSObject()) { 9972 Handle<Object> prototype) {
9961 Handle<JSObject> js_proto = handle(JSObject::cast(map->prototype())); 9973 if (prototype->IsJSObject()) {
9974 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
9962 if (!js_proto->map()->is_prototype_map() && 9975 if (!js_proto->map()->is_prototype_map() &&
9963 !js_proto->map()->IsGlobalObjectMap() && 9976 !js_proto->map()->IsGlobalObjectMap() &&
9964 !js_proto->map()->IsJSGlobalProxyMap()) { 9977 !js_proto->map()->IsJSGlobalProxyMap()) {
9965 // Normalize and turn fast again to make all functions CONSTANT 9978 // Normalize and turn fast again to make all functions CONSTANT
9966 // properties. 9979 // properties.
9967 if (!js_proto->GetIsolate()->bootstrapper()->IsActive()) { 9980 if (!js_proto->GetIsolate()->bootstrapper()->IsActive()) {
9968 JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0); 9981 JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0);
9969 } 9982 }
9970 if (!js_proto->HasFastProperties()) { 9983 if (!js_proto->HasFastProperties()) {
9971 JSObject::MigrateSlowToFast(js_proto, 0); 9984 JSObject::MigrateSlowToFast(js_proto, 0);
9972 } 9985 }
9973 if (js_proto->HasFastProperties()) { 9986 if (js_proto->HasFastProperties()) {
9974 Handle<Map> new_map = Map::Copy(handle(js_proto->map())); 9987 Handle<Map> new_map = Map::Copy(handle(js_proto->map()));
9975 JSObject::MigrateToMap(js_proto, new_map); 9988 JSObject::MigrateToMap(js_proto, new_map);
9976 js_proto->map()->set_is_prototype_map(true); 9989 js_proto->map()->set_is_prototype_map(true);
9977 } 9990 }
9978 } 9991 }
9979 } 9992 }
9993 map->set_prototype(*prototype);
9980 function->set_prototype_or_initial_map(*map); 9994 function->set_prototype_or_initial_map(*map);
9981 map->set_constructor(*function); 9995 map->set_constructor(*function);
9982 } 9996 }
9983 9997
9984 9998
9985 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { 9999 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9986 if (function->has_initial_map()) return; 10000 if (function->has_initial_map()) return;
9987 Isolate* isolate = function->GetIsolate(); 10001 Isolate* isolate = function->GetIsolate();
9988 10002
9989 // First create a new map with the size and number of in-object properties 10003 // First create a new map with the size and number of in-object properties
(...skipping 14 matching lines...) Expand all
10004 10018
10005 // Fetch or allocate prototype. 10019 // Fetch or allocate prototype.
10006 Handle<Object> prototype; 10020 Handle<Object> prototype;
10007 if (function->has_instance_prototype()) { 10021 if (function->has_instance_prototype()) {
10008 prototype = handle(function->instance_prototype(), isolate); 10022 prototype = handle(function->instance_prototype(), isolate);
10009 } else { 10023 } else {
10010 prototype = isolate->factory()->NewFunctionPrototype(function); 10024 prototype = isolate->factory()->NewFunctionPrototype(function);
10011 } 10025 }
10012 map->set_inobject_properties(in_object_properties); 10026 map->set_inobject_properties(in_object_properties);
10013 map->set_unused_property_fields(in_object_properties); 10027 map->set_unused_property_fields(in_object_properties);
10014 map->set_prototype(*prototype);
10015 DCHECK(map->has_fast_object_elements()); 10028 DCHECK(map->has_fast_object_elements());
10016 10029
10017 // Finally link initial map and constructor function. 10030 // Finally link initial map and constructor function.
10018 JSFunction::SetInitialMap(function, map); 10031 JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10019 10032
10020 if (!function->shared()->is_generator()) { 10033 if (!function->shared()->is_generator()) {
10021 function->StartInobjectSlackTracking(); 10034 function->StartInobjectSlackTracking();
10022 } 10035 }
10023 } 10036 }
10024 10037
10025 10038
10026 void JSFunction::SetInstanceClassName(String* name) { 10039 void JSFunction::SetInstanceClassName(String* name) {
10027 shared()->set_instance_class_name(name); 10040 shared()->set_instance_class_name(name);
10028 } 10041 }
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after
12093 new_map = Copy(map); 12106 new_map = Copy(map);
12094 PutPrototypeTransition(map, prototype, new_map); 12107 PutPrototypeTransition(map, prototype, new_map);
12095 new_map->set_prototype(*prototype); 12108 new_map->set_prototype(*prototype);
12096 } 12109 }
12097 return new_map; 12110 return new_map;
12098 } 12111 }
12099 12112
12100 12113
12101 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 12114 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12102 Handle<Object> value, 12115 Handle<Object> value,
12103 bool skip_hidden_prototypes) { 12116 bool from_javascript) {
12104 #ifdef DEBUG 12117 #ifdef DEBUG
12105 int size = object->Size(); 12118 int size = object->Size();
12106 #endif 12119 #endif
12107 12120
12108 Isolate* isolate = object->GetIsolate(); 12121 Isolate* isolate = object->GetIsolate();
12109 Heap* heap = isolate->heap(); 12122 Heap* heap = isolate->heap();
12110 // Silently ignore the change if value is not a JSObject or null. 12123 // Silently ignore the change if value is not a JSObject or null.
12111 // SpiderMonkey behaves this way. 12124 // SpiderMonkey behaves this way.
12112 if (!value->IsJSReceiver() && !value->IsNull()) return value; 12125 if (!value->IsJSReceiver() && !value->IsNull()) return value;
12113 12126
(...skipping 24 matching lines...) Expand all
12138 Handle<Object> error = isolate->factory()->NewError( 12151 Handle<Object> error = isolate->factory()->NewError(
12139 "cyclic_proto", HandleVector<Object>(NULL, 0)); 12152 "cyclic_proto", HandleVector<Object>(NULL, 0));
12140 return isolate->Throw<Object>(error); 12153 return isolate->Throw<Object>(error);
12141 } 12154 }
12142 } 12155 }
12143 12156
12144 bool dictionary_elements_in_chain = 12157 bool dictionary_elements_in_chain =
12145 object->map()->DictionaryElementsInPrototypeChainOnly(); 12158 object->map()->DictionaryElementsInPrototypeChainOnly();
12146 Handle<JSObject> real_receiver = object; 12159 Handle<JSObject> real_receiver = object;
12147 12160
12148 if (skip_hidden_prototypes) { 12161 if (from_javascript) {
12149 // Find the first object in the chain whose prototype object is not 12162 // Find the first object in the chain whose prototype object is not
12150 // hidden and set the new prototype on that object. 12163 // hidden and set the new prototype on that object.
12151 PrototypeIterator iter(isolate, real_receiver); 12164 PrototypeIterator iter(isolate, real_receiver);
12152 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 12165 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12153 real_receiver = 12166 real_receiver =
12154 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 12167 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12155 iter.Advance(); 12168 iter.Advance();
12156 } 12169 }
12157 } 12170 }
12158 12171
12159 // Set the new prototype of the object. 12172 // Set the new prototype of the object.
12160 Handle<Map> map(real_receiver->map()); 12173 Handle<Map> map(real_receiver->map());
12161 12174
12162 // Nothing to do if prototype is already set. 12175 // Nothing to do if prototype is already set.
12163 if (map->prototype() == *value) return value; 12176 if (map->prototype() == *value) return value;
12164 12177
12165 if (value->IsJSObject()) { 12178 if (value->IsJSObject()) {
12166 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); 12179 Handle<JSObject> js_proto = Handle<JSObject>::cast(value);
12180 if (!from_javascript && !js_proto->IsJSGlobalProxy() &&
12181 !js_proto->IsGlobalObject() && !js_proto->map()->is_prototype_map()) {
12182 JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0);
12183 JSObject::MigrateSlowToFast(js_proto, 0);
12184 if (js_proto->HasFastProperties()) {
12185 Handle<Map> new_map = Map::Copy(handle(js_proto->map()));
12186 JSObject::MigrateToMap(js_proto, new_map);
12187 js_proto->map()->set_is_prototype_map(true);
12188 }
Igor Sheludko 2014/08/11 07:42:13 The "make-prototype-super-fast" piece of code look
12189 } else {
12190 JSObject::OptimizeAsPrototype(js_proto);
12191 }
12167 } 12192 }
12168 12193
12169 Handle<Map> new_map = Map::TransitionToPrototype(map, value); 12194 Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12170 DCHECK(new_map->prototype() == *value); 12195 DCHECK(new_map->prototype() == *value);
12171 JSObject::MigrateToMap(real_receiver, new_map); 12196 JSObject::MigrateToMap(real_receiver, new_map);
12172 12197
12173 if (!dictionary_elements_in_chain && 12198 if (!dictionary_elements_in_chain &&
12174 new_map->DictionaryElementsInPrototypeChainOnly()) { 12199 new_map->DictionaryElementsInPrototypeChainOnly()) {
12175 // If the prototype chain didn't previously have element callbacks, then 12200 // If the prototype chain didn't previously have element callbacks, then
12176 // KeyedStoreICs need to be cleared to ensure any that involve this 12201 // 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, 16923 #define ERROR_MESSAGES_TEXTS(C, T) T,
16899 static const char* error_messages_[] = { 16924 static const char* error_messages_[] = {
16900 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16925 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16901 }; 16926 };
16902 #undef ERROR_MESSAGES_TEXTS 16927 #undef ERROR_MESSAGES_TEXTS
16903 return error_messages_[reason]; 16928 return error_messages_[reason];
16904 } 16929 }
16905 16930
16906 16931
16907 } } // namespace v8::internal 16932 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698