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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 645bb4a74e39f81272c0c9e3c4c4d913976224fc..90220f0f31137fc67c106db8bb0d1a898ffb86d6 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3470,7 +3470,7 @@ Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
bool allow_store_transition =
// Only remember the map transition if there is not an already existing
// non-matching element transition.
- !map->IsUndefined() && !map->is_shared() &&
+ !map->IsUndefined() && !map->is_dictionary_map() &&
IsTransitionElementsKind(from_kind);
// Only store fast element maps in ascending generality.
@@ -4440,6 +4440,8 @@ Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
PropertyNormalizationMode mode) {
+ // Only use the cache once it is initialized.
+ if (!IsNormalizedMapCache(this)) return MaybeHandle<Map>();
DisallowHeapAllocation no_gc;
Object* value = FixedArray::get(GetIndex(fast_map));
if (!value->IsMap() ||
@@ -4452,6 +4454,8 @@ MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
void NormalizedMapCache::Set(Handle<Map> fast_map,
Handle<Map> normalized_map) {
+ // Only use the cache once it is initialized.
+ if (!IsNormalizedMapCache(this)) return;
DisallowHeapAllocation no_gc;
DCHECK(normalized_map->is_dictionary_map());
FixedArray::set(GetIndex(fast_map), *normalized_map);
@@ -6981,17 +6985,14 @@ Handle<Map> Map::Normalize(Handle<Map> fast_map,
Handle<Map> new_map;
if (cache->Get(fast_map, mode).ToHandle(&new_map)) {
#ifdef VERIFY_HEAP
- if (FLAG_verify_heap) {
- new_map->SharedMapVerify();
- }
+ if (FLAG_verify_heap) new_map->DictionaryMapVerify();
#endif
#ifdef ENABLE_SLOW_DCHECKS
if (FLAG_enable_slow_asserts) {
// The cached map should match newly created normalized map bit-by-bit,
// except for the code cache, which can contain some ics which can be
// applied to the shared map.
- Handle<Map> fresh = Map::CopyNormalized(
- fast_map, mode, SHARED_NORMALIZED_MAP);
+ Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
DCHECK(memcmp(fresh->address(),
new_map->address(),
@@ -7005,7 +7006,7 @@ Handle<Map> Map::Normalize(Handle<Map> fast_map,
}
#endif
} else {
- new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP);
+ new_map = Map::CopyNormalized(fast_map, mode);
cache->Set(fast_map, new_map);
isolate->counters()->normalized_maps()->Increment();
}
@@ -7015,8 +7016,7 @@ Handle<Map> Map::Normalize(Handle<Map> fast_map,
Handle<Map> Map::CopyNormalized(Handle<Map> map,
- PropertyNormalizationMode mode,
- NormalizedMapSharingMode sharing) {
+ PropertyNormalizationMode mode) {
int new_instance_size = map->instance_size();
if (mode == CLEAR_INOBJECT_PROPERTIES) {
new_instance_size -= map->inobject_properties() * kPointerSize;
@@ -7028,14 +7028,11 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map,
result->set_inobject_properties(map->inobject_properties());
}
- result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
result->set_dictionary_map(true);
result->set_migration_target(false);
#ifdef VERIFY_HEAP
- if (FLAG_verify_heap && result->is_shared()) {
- result->SharedMapVerify();
- }
+ if (FLAG_verify_heap) result->DictionaryMapVerify();
#endif
return result;
@@ -7051,7 +7048,6 @@ Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
result->set_pre_allocated_property_fields(
map->pre_allocated_property_fields());
- result->set_is_shared(false);
result->ClearCodeCache(map->GetHeap());
map->NotifyLeafMapLayoutChange();
return result;
@@ -9812,20 +9808,29 @@ void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
}
-void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
+void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
+ PrototypeOptimizationMode mode) {
if (object->IsGlobalObject()) return;
-
- // Make sure prototypes are fast objects and their maps have the bit set
- // so they remain fast.
+ if (object->IsJSGlobalProxy()) return;
+ if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
+ // First normalize to ensure all JSFunctions are CONSTANT.
+ JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
+ }
if (!object->HasFastProperties()) {
- MigrateSlowToFast(object, 0);
+ JSObject::MigrateSlowToFast(object, 0);
+ }
+ if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
+ !object->map()->is_prototype_map()) {
+ Handle<Map> new_map = Map::Copy(handle(object->map()));
+ JSObject::MigrateToMap(object, new_map);
+ object->map()->set_is_prototype_map(true);
}
}
void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
if (!object->map()->is_prototype_map()) return;
- OptimizeAsPrototype(object);
+ OptimizeAsPrototype(object, FAST_PROTOTYPE);
}
@@ -9876,21 +9881,30 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
if (function->IsInobjectSlackTrackingInProgress()) {
function->CompleteInobjectSlackTracking();
}
+
Handle<Map> initial_map(function->initial_map(), isolate);
- Handle<Map> new_map = Map::Copy(initial_map);
- new_map->set_prototype(*value);
- // If the function is used as the global Array function, cache the
- // initial map (and transitioned versions) in the native context.
- Context* native_context = function->context()->native_context();
- Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
- if (array_function->IsJSFunction() &&
- *function == JSFunction::cast(array_function)) {
- CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
+ if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
+ initial_map->instance_type() == JS_OBJECT_TYPE) {
+ // Put the value in the initial map field until an initial map is needed.
+ // At that point, a new initial map is created and the prototype is put
+ // into the initial map where it belongs.
+ function->set_prototype_or_initial_map(*value);
+ } else {
+ Handle<Map> new_map = Map::Copy(initial_map);
+ JSFunction::SetInitialMap(function, new_map, value);
+
+ // If the function is used as the global Array function, cache the
+ // initial map (and transitioned versions) in the native context.
+ Context* native_context = function->context()->native_context();
+ Object* array_function =
+ native_context->get(Context::ARRAY_FUNCTION_INDEX);
+ if (array_function->IsJSFunction() &&
+ *function == JSFunction::cast(array_function)) {
+ CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
+ }
}
- JSFunction::SetInitialMap(function, new_map);
-
// Deoptimize all code that embeds the previous initial map.
initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
isolate, DependentCode::kInitialMapChangedGroup);
@@ -9956,27 +9970,13 @@ bool JSFunction::RemovePrototype() {
}
-void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map) {
- if (map->prototype()->IsJSObject()) {
- Handle<JSObject> js_proto = handle(JSObject::cast(map->prototype()));
- if (!js_proto->map()->is_prototype_map() &&
- !js_proto->map()->IsGlobalObjectMap() &&
- !js_proto->map()->IsJSGlobalProxyMap()) {
- // Normalize and turn fast again to make all functions CONSTANT
- // properties.
- if (!js_proto->GetIsolate()->bootstrapper()->IsActive()) {
- JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0);
- }
- if (!js_proto->HasFastProperties()) {
- JSObject::MigrateSlowToFast(js_proto, 0);
- }
- if (js_proto->HasFastProperties()) {
- Handle<Map> new_map = Map::Copy(handle(js_proto->map()));
- JSObject::MigrateToMap(js_proto, new_map);
- js_proto->map()->set_is_prototype_map(true);
- }
- }
+void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
+ Handle<Object> prototype) {
+ if (prototype->IsJSObject()) {
+ Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
+ JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
}
+ map->set_prototype(*prototype);
function->set_prototype_or_initial_map(*map);
map->set_constructor(*function);
}
@@ -10011,11 +10011,10 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
}
map->set_inobject_properties(in_object_properties);
map->set_unused_property_fields(in_object_properties);
- map->set_prototype(*prototype);
DCHECK(map->has_fast_object_elements());
// Finally link initial map and constructor function.
- JSFunction::SetInitialMap(function, map);
+ JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
if (!function->shared()->is_generator()) {
function->StartInobjectSlackTracking();
@@ -11777,7 +11776,7 @@ Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
// Don't cache prototype transition if this map is either shared, or a map of
// a prototype.
if (map->is_prototype_map()) return map;
- if (map->is_shared() || !FLAG_cache_prototype_transitions) return map;
+ if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
const int step = kProtoTransitionElementsPerEntry;
const int header = kProtoTransitionHeaderSize;
@@ -12100,7 +12099,7 @@ Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
Handle<Object> value,
- bool skip_hidden_prototypes) {
+ bool from_javascript) {
#ifdef DEBUG
int size = object->Size();
#endif
@@ -12145,7 +12144,7 @@ MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
object->map()->DictionaryElementsInPrototypeChainOnly();
Handle<JSObject> real_receiver = object;
- if (skip_hidden_prototypes) {
+ if (from_javascript) {
// Find the first object in the chain whose prototype object is not
// hidden and set the new prototype on that object.
PrototypeIterator iter(isolate, real_receiver);
@@ -12163,7 +12162,9 @@ MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
if (map->prototype() == *value) return value;
if (value->IsJSObject()) {
- JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
+ PrototypeOptimizationMode mode =
+ from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
+ JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
}
Handle<Map> new_map = Map::TransitionToPrototype(map, value);
« 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