Revision: 22979
Author: [email protected]
Date: Thu Aug 7 16:14:22 2014 UTC
Log: Mark as prototype only after instantiating the function
BUG=
[email protected]
Review URL: https://codereview.chromium.org/447293002
http://code.google.com/p/v8/source/detail?r=22979
Modified:
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/test/mjsunit/dictionary-properties.js
/branches/bleeding_edge/test/mjsunit/fast-prototype.js
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Wed Aug 6 15:50:40 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Thu Aug 7 16:14:22 2014 UTC
@@ -480,8 +480,7 @@
Handle<JSFunction> object_fun = factory->NewFunction(object_name);
Handle<Map> object_function_map =
factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
- object_fun->set_initial_map(*object_function_map);
- object_function_map->set_constructor(*object_fun);
+ JSFunction::SetInitialMap(object_fun, object_function_map);
object_function_map->set_unused_property_fields(
JSObject::kInitialGlobalObjectUnusedPropertiesCount);
@@ -1211,8 +1210,7 @@
native_context()->set_sloppy_arguments_map(*map);
DCHECK(!function->has_initial_map());
- function->set_initial_map(*map);
- map->set_constructor(*function);
+ JSFunction::SetInitialMap(function, map);
DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex);
DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
@@ -1336,8 +1334,7 @@
JS_TYPED_ARRAY_TYPE,
JSTypedArray::kSizeWithInternalFields,
elements_kind);
- result->set_initial_map(*initial_map);
- initial_map->set_constructor(*result);
+ JSFunction::SetInitialMap(result, initial_map);
*fun = result;
ElementsKind external_kind =
GetNextTransitionElementsKind(elements_kind);
@@ -1658,7 +1655,7 @@
Handle<Map> original_map(array_function->initial_map());
Handle<Map> initial_map = Map::Copy(original_map);
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.
Map::EnsureDescriptorSlack(initial_map, 1);
=======================================
--- /branches/bleeding_edge/src/factory.cc Tue Aug 5 09:24:27 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc Thu Aug 7 16:14:22 2014 UTC
@@ -1268,11 +1268,6 @@
? isolate()->sloppy_function_with_readonly_prototype_map()
: isolate()->sloppy_function_map();
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);
return result;
}
@@ -1293,9 +1288,9 @@
if (prototype->IsTheHole() && !function->shared()->is_generator()) {
prototype = NewFunctionPrototype(function);
}
+
initial_map->set_prototype(*prototype);
- function->set_initial_map(*initial_map);
- initial_map->set_constructor(*function);
+ JSFunction::SetInitialMap(function, initial_map);
return function;
}
@@ -1323,7 +1318,7 @@
// maps between prototypes of different constructors.
Handle<JSFunction> object_function(native_context->object_function());
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);
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Aug 7 12:21:01 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Thu Aug 7 16:14:22 2014 UTC
@@ -4451,8 +4451,8 @@
}
-void Map::mark_prototype_map() {
- set_bit_field2(IsPrototypeMapBits::update(bit_field2(), true));
+void Map::set_is_prototype_map(bool value) {
+ set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value));
}
bool Map::is_prototype_map() {
@@ -5938,11 +5938,6 @@
Map* JSFunction::initial_map() {
return Map::cast(prototype_or_initial_map());
}
-
-
-void JSFunction::set_initial_map(Map* value) {
- set_prototype_or_initial_map(value);
-}
bool JSFunction::has_initial_map() {
=======================================
--- /branches/bleeding_edge/src/objects.cc Thu Aug 7 15:33:14 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Thu Aug 7 16:14:22 2014 UTC
@@ -7237,14 +7237,6 @@
return new_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) {
@@ -9873,17 +9865,6 @@
Isolate* isolate = function->GetIsolate();
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
// function as a constructor.
@@ -9908,7 +9889,7 @@
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.
initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
@@ -9973,6 +9954,32 @@
set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
return true;
}
+
+
+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) {
@@ -10008,8 +10015,7 @@
DCHECK(map->has_fast_object_elements());
// Finally link initial map and constructor function.
- function->set_initial_map(*map);
- map->set_constructor(*function);
+ JSFunction::SetInitialMap(function, map);
if (!function->shared()->is_generator()) {
function->StartInobjectSlackTracking();
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Aug 7 15:33:14 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Thu Aug 7 16:14:22 2014 UTC
@@ -6205,7 +6205,7 @@
inline void set_is_extensible(bool value);
inline bool is_extensible();
- inline void mark_prototype_map();
+ inline void set_is_prototype_map(bool value);
inline bool is_prototype_map();
inline void set_elements_kind(ElementsKind elements_kind) {
@@ -6540,7 +6540,6 @@
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
static Handle<Map> Copy(Handle<Map> map);
- static Handle<Map> CopyAsPrototypeMap(Handle<Map> map);
static Handle<Map> Create(Handle<JSFunction> constructor,
int extra_inobject_properties);
@@ -7781,7 +7780,7 @@
// The initial map for an object created by this constructor.
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();
static void EnsureHasInitialMap(Handle<JSFunction> function);
=======================================
--- /branches/bleeding_edge/test/mjsunit/dictionary-properties.js Mon Aug
4 15:06:28 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/dictionary-properties.js Thu Aug
7 16:14:22 2014 UTC
@@ -39,6 +39,7 @@
SlowPrototype.prototype.bar = 2;
SlowPrototype.prototype.baz = 3;
delete SlowPrototype.prototype.baz;
+new SlowPrototype;
// Prototypes stay fast even after deleting properties.
assertTrue(%HasFastProperties(SlowPrototype.prototype));
=======================================
--- /branches/bleeding_edge/test/mjsunit/fast-prototype.js Mon Aug 4
15:02:07 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/fast-prototype.js Thu Aug 7
16:14:22 2014 UTC
@@ -50,6 +50,8 @@
(new Sub()).__proto__ = proto;
} else {
Sub.prototype = proto;
+ // Need to instantiate Sub to mark .prototype as prototype.
+ new Sub();
}
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.