Commit a1f3f024 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Mark as prototype only after instantiating the function

BUG=
R=ishell@chromium.org

Review URL: https://codereview.chromium.org/447293002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22979 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7b9e24e3
...@@ -480,8 +480,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { ...@@ -480,8 +480,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
Handle<JSFunction> object_fun = factory->NewFunction(object_name); Handle<JSFunction> object_fun = factory->NewFunction(object_name);
Handle<Map> object_function_map = Handle<Map> object_function_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
object_fun->set_initial_map(*object_function_map); JSFunction::SetInitialMap(object_fun, object_function_map);
object_function_map->set_constructor(*object_fun);
object_function_map->set_unused_property_fields( object_function_map->set_unused_property_fields(
JSObject::kInitialGlobalObjectUnusedPropertiesCount); JSObject::kInitialGlobalObjectUnusedPropertiesCount);
...@@ -1211,8 +1210,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object, ...@@ -1211,8 +1210,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
native_context()->set_sloppy_arguments_map(*map); native_context()->set_sloppy_arguments_map(*map);
DCHECK(!function->has_initial_map()); DCHECK(!function->has_initial_map());
function->set_initial_map(*map); JSFunction::SetInitialMap(function, map);
map->set_constructor(*function);
DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex); DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex);
DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex); DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
...@@ -1336,8 +1334,7 @@ void Genesis::InstallTypedArray( ...@@ -1336,8 +1334,7 @@ void Genesis::InstallTypedArray(
JS_TYPED_ARRAY_TYPE, JS_TYPED_ARRAY_TYPE,
JSTypedArray::kSizeWithInternalFields, JSTypedArray::kSizeWithInternalFields,
elements_kind); elements_kind);
result->set_initial_map(*initial_map); JSFunction::SetInitialMap(result, initial_map);
initial_map->set_constructor(*result);
*fun = result; *fun = result;
ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind); ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
...@@ -1658,7 +1655,7 @@ Handle<JSFunction> Genesis::InstallInternalArray( ...@@ -1658,7 +1655,7 @@ Handle<JSFunction> Genesis::InstallInternalArray(
Handle<Map> original_map(array_function->initial_map()); Handle<Map> original_map(array_function->initial_map());
Handle<Map> initial_map = Map::Copy(original_map); Handle<Map> initial_map = Map::Copy(original_map);
initial_map->set_elements_kind(elements_kind); initial_map->set_elements_kind(elements_kind);
array_function->set_initial_map(*initial_map); JSFunction::SetInitialMap(array_function, initial_map);
// Make "length" magic on instances. // Make "length" magic on instances.
Map::EnsureDescriptorSlack(initial_map, 1); Map::EnsureDescriptorSlack(initial_map, 1);
......
...@@ -1268,11 +1268,6 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, ...@@ -1268,11 +1268,6 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
? isolate()->sloppy_function_with_readonly_prototype_map() ? isolate()->sloppy_function_with_readonly_prototype_map()
: isolate()->sloppy_function_map(); : isolate()->sloppy_function_map();
Handle<JSFunction> result = NewFunction(map, name, code); Handle<JSFunction> result = NewFunction(map, name, code);
if (!prototype->IsTheHole()) {
Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
Handle<Map> new_map = Map::CopyAsPrototypeMap(handle(js_proto->map()));
JSObject::MigrateToMap(js_proto, new_map);
}
result->set_prototype_or_initial_map(*prototype); result->set_prototype_or_initial_map(*prototype);
return result; return result;
} }
...@@ -1293,9 +1288,9 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, ...@@ -1293,9 +1288,9 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
if (prototype->IsTheHole() && !function->shared()->is_generator()) { if (prototype->IsTheHole() && !function->shared()->is_generator()) {
prototype = NewFunctionPrototype(function); prototype = NewFunctionPrototype(function);
} }
initial_map->set_prototype(*prototype); initial_map->set_prototype(*prototype);
function->set_initial_map(*initial_map); JSFunction::SetInitialMap(function, initial_map);
initial_map->set_constructor(*function);
return function; return function;
} }
...@@ -1323,7 +1318,7 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) { ...@@ -1323,7 +1318,7 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
// maps between prototypes of different constructors. // maps between prototypes of different constructors.
Handle<JSFunction> object_function(native_context->object_function()); Handle<JSFunction> object_function(native_context->object_function());
DCHECK(object_function->has_initial_map()); DCHECK(object_function->has_initial_map());
new_map = Map::CopyAsPrototypeMap(handle(object_function->initial_map())); new_map = handle(object_function->initial_map());
} }
Handle<JSObject> prototype = NewJSObjectFromMap(new_map); Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
......
...@@ -4451,8 +4451,8 @@ bool Map::is_extensible() { ...@@ -4451,8 +4451,8 @@ bool Map::is_extensible() {
} }
void Map::mark_prototype_map() { void Map::set_is_prototype_map(bool value) {
set_bit_field2(IsPrototypeMapBits::update(bit_field2(), true)); set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value));
} }
bool Map::is_prototype_map() { bool Map::is_prototype_map() {
...@@ -5940,11 +5940,6 @@ Map* JSFunction::initial_map() { ...@@ -5940,11 +5940,6 @@ Map* JSFunction::initial_map() {
} }
void JSFunction::set_initial_map(Map* value) {
set_prototype_or_initial_map(value);
}
bool JSFunction::has_initial_map() { bool JSFunction::has_initial_map() {
return prototype_or_initial_map()->IsMap(); return prototype_or_initial_map()->IsMap();
} }
......
...@@ -7239,14 +7239,6 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) { ...@@ -7239,14 +7239,6 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
} }
Handle<Map> Map::CopyAsPrototypeMap(Handle<Map> map) {
if (map->is_prototype_map()) return map;
Handle<Map> result = Copy(map);
result->mark_prototype_map();
return result;
}
Handle<Map> Map::Copy(Handle<Map> map) { Handle<Map> Map::Copy(Handle<Map> map) {
Handle<DescriptorArray> descriptors(map->instance_descriptors()); Handle<DescriptorArray> descriptors(map->instance_descriptors());
int number_of_own_descriptors = map->NumberOfOwnDescriptors(); int number_of_own_descriptors = map->NumberOfOwnDescriptors();
...@@ -9874,17 +9866,6 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function, ...@@ -9874,17 +9866,6 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
DCHECK(value->IsJSReceiver()); DCHECK(value->IsJSReceiver());
// First some logic for the map of the prototype to make sure it is in fast
// mode.
if (value->IsJSObject()) {
Handle<JSObject> js_proto = Handle<JSObject>::cast(value);
JSObject::OptimizeAsPrototype(js_proto);
if (js_proto->HasFastProperties()) {
Handle<Map> new_map = Map::CopyAsPrototypeMap(handle(js_proto->map()));
JSObject::MigrateToMap(js_proto, new_map);
}
}
// Now some logic for the maps of the objects that are created by using this // Now some logic for the maps of the objects that are created by using this
// function as a constructor. // function as a constructor.
if (function->has_initial_map()) { if (function->has_initial_map()) {
...@@ -9908,7 +9889,7 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function, ...@@ -9908,7 +9889,7 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
CacheInitialJSArrayMaps(handle(native_context, isolate), new_map); CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
} }
function->set_initial_map(*new_map); JSFunction::SetInitialMap(function, new_map);
// Deoptimize all code that embeds the previous initial map. // Deoptimize all code that embeds the previous initial map.
initial_map->dependent_code()->DeoptimizeDependentCodeGroup( initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
...@@ -9975,6 +9956,32 @@ bool JSFunction::RemovePrototype() { ...@@ -9975,6 +9956,32 @@ 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);
}
}
}
function->set_prototype_or_initial_map(*map);
map->set_constructor(*function);
}
void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
if (function->has_initial_map()) return; if (function->has_initial_map()) return;
Isolate* isolate = function->GetIsolate(); Isolate* isolate = function->GetIsolate();
...@@ -10008,8 +10015,7 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { ...@@ -10008,8 +10015,7 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
DCHECK(map->has_fast_object_elements()); DCHECK(map->has_fast_object_elements());
// Finally link initial map and constructor function. // Finally link initial map and constructor function.
function->set_initial_map(*map); JSFunction::SetInitialMap(function, map);
map->set_constructor(*function);
if (!function->shared()->is_generator()) { if (!function->shared()->is_generator()) {
function->StartInobjectSlackTracking(); function->StartInobjectSlackTracking();
......
...@@ -6205,7 +6205,7 @@ class Map: public HeapObject { ...@@ -6205,7 +6205,7 @@ class Map: public HeapObject {
inline void set_is_extensible(bool value); inline void set_is_extensible(bool value);
inline bool is_extensible(); inline bool is_extensible();
inline void mark_prototype_map(); inline void set_is_prototype_map(bool value);
inline bool is_prototype_map(); inline bool is_prototype_map();
inline void set_elements_kind(ElementsKind elements_kind) { inline void set_elements_kind(ElementsKind elements_kind) {
...@@ -6540,7 +6540,6 @@ class Map: public HeapObject { ...@@ -6540,7 +6540,6 @@ class Map: public HeapObject {
// Returns a copy of the map, with all transitions dropped from the // Returns a copy of the map, with all transitions dropped from the
// instance descriptors. // instance descriptors.
static Handle<Map> Copy(Handle<Map> map); static Handle<Map> Copy(Handle<Map> map);
static Handle<Map> CopyAsPrototypeMap(Handle<Map> map);
static Handle<Map> Create(Handle<JSFunction> constructor, static Handle<Map> Create(Handle<JSFunction> constructor,
int extra_inobject_properties); int extra_inobject_properties);
...@@ -7781,7 +7780,7 @@ class JSFunction: public JSObject { ...@@ -7781,7 +7780,7 @@ class JSFunction: public JSObject {
// The initial map for an object created by this constructor. // The initial map for an object created by this constructor.
inline Map* initial_map(); inline Map* initial_map();
inline void set_initial_map(Map* value); static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map);
inline bool has_initial_map(); inline bool has_initial_map();
static void EnsureHasInitialMap(Handle<JSFunction> function); static void EnsureHasInitialMap(Handle<JSFunction> function);
......
...@@ -39,6 +39,7 @@ function SlowPrototype() { ...@@ -39,6 +39,7 @@ function SlowPrototype() {
SlowPrototype.prototype.bar = 2; SlowPrototype.prototype.bar = 2;
SlowPrototype.prototype.baz = 3; SlowPrototype.prototype.baz = 3;
delete SlowPrototype.prototype.baz; delete SlowPrototype.prototype.baz;
new SlowPrototype;
// Prototypes stay fast even after deleting properties. // Prototypes stay fast even after deleting properties.
assertTrue(%HasFastProperties(SlowPrototype.prototype)); assertTrue(%HasFastProperties(SlowPrototype.prototype));
......
...@@ -50,6 +50,8 @@ function DoProtoMagic(proto, set__proto__) { ...@@ -50,6 +50,8 @@ function DoProtoMagic(proto, set__proto__) {
(new Sub()).__proto__ = proto; (new Sub()).__proto__ = proto;
} else { } else {
Sub.prototype = proto; Sub.prototype = proto;
// Need to instantiate Sub to mark .prototype as prototype.
new Sub();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment