Keep function.prototype fast.
BUG= R=ishell@chromium.org Review URL: https://codereview.chromium.org/437083004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22826 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b3ee436730
commit
f947eff31d
@ -1318,7 +1318,7 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
||||
// maps between prototypes of different constructors.
|
||||
Handle<JSFunction> object_function(native_context->object_function());
|
||||
DCHECK(object_function->has_initial_map());
|
||||
new_map = Map::Copy(handle(object_function->initial_map()));
|
||||
new_map = Map::CopyAsPrototypeMap(handle(object_function->initial_map()));
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
||||
|
@ -2115,6 +2115,7 @@ bool JSObject::HasFastProperties() {
|
||||
|
||||
bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
|
||||
if (unused_property_fields() != 0) return false;
|
||||
if (is_prototype_map()) return false;
|
||||
int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
|
||||
int limit = Max(minimum, inobject_properties());
|
||||
int external = NumberOfFields() - inobject_properties();
|
||||
@ -4445,6 +4446,15 @@ bool Map::is_extensible() {
|
||||
}
|
||||
|
||||
|
||||
void Map::mark_prototype_map() {
|
||||
set_bit_field2(IsPrototypeMapBits::update(bit_field2(), true));
|
||||
}
|
||||
|
||||
bool Map::is_prototype_map() {
|
||||
return IsPrototypeMapBits::decode(bit_field2());
|
||||
}
|
||||
|
||||
|
||||
void Map::set_is_shared(bool value) {
|
||||
set_bit_field3(IsShared::update(bit_field3(), value));
|
||||
}
|
||||
|
@ -7266,6 +7266,13 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Map> Map::CopyAsPrototypeMap(Handle<Map> map) {
|
||||
Handle<Map> result = Copy(map);
|
||||
result->mark_prototype_map();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<Map> Map::Copy(Handle<Map> map) {
|
||||
Handle<DescriptorArray> descriptors(map->instance_descriptors());
|
||||
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
|
||||
@ -10003,7 +10010,12 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
|
||||
// First some logic for the map of the prototype to make sure it is in fast
|
||||
// mode.
|
||||
if (value->IsJSObject()) {
|
||||
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
|
||||
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
|
||||
@ -10120,15 +10132,9 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
|
||||
Handle<Object> prototype;
|
||||
if (function->has_instance_prototype()) {
|
||||
prototype = handle(function->instance_prototype(), isolate);
|
||||
for (PrototypeIterator iter(isolate, prototype,
|
||||
PrototypeIterator::START_AT_RECEIVER);
|
||||
!iter.IsAtEnd(); iter.Advance()) {
|
||||
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
|
||||
break;
|
||||
}
|
||||
JSObject::OptimizeAsPrototype(
|
||||
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
|
||||
}
|
||||
// TODO(verwaest): Remove once "delete" keeps objects marked as prototypes
|
||||
// fast as well.
|
||||
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(prototype));
|
||||
} else {
|
||||
prototype = isolate->factory()->NewFunctionPrototype(function);
|
||||
}
|
||||
|
@ -6204,6 +6204,8 @@ class Map: public HeapObject {
|
||||
|
||||
inline void set_is_extensible(bool value);
|
||||
inline bool is_extensible();
|
||||
inline void mark_prototype_map();
|
||||
inline bool is_prototype_map();
|
||||
|
||||
inline void set_elements_kind(ElementsKind elements_kind) {
|
||||
DCHECK(elements_kind < kElementsKindCount);
|
||||
@ -6537,6 +6539,7 @@ class Map: public HeapObject {
|
||||
// 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);
|
||||
|
||||
@ -6736,7 +6739,7 @@ class Map: public HeapObject {
|
||||
// Bit positions for bit field 2
|
||||
static const int kIsExtensible = 0;
|
||||
static const int kStringWrapperSafeForDefaultValueOf = 1;
|
||||
// Currently bit 2 is not used.
|
||||
class IsPrototypeMapBits : public BitField<bool, 2, 1> {};
|
||||
class ElementsKindBits: public BitField<ElementsKind, 3, 5> {};
|
||||
|
||||
// Derived values from bit field 2
|
||||
|
@ -72,10 +72,15 @@ function test(use_new, add_first, set__proto__, same_map_as) {
|
||||
// Still fast
|
||||
assertTrue(%HasFastProperties(proto));
|
||||
AddProps(proto);
|
||||
if (set__proto__) {
|
||||
// After we add all those properties it went slow mode again :-(
|
||||
assertFalse(%HasFastProperties(proto));
|
||||
} else {
|
||||
// .prototype keeps it fast.
|
||||
assertTrue(%HasFastProperties(proto));
|
||||
}
|
||||
if (same_map_as && !add_first) {
|
||||
}
|
||||
if (same_map_as && !add_first && set__proto__) {
|
||||
assertTrue(%HaveSameMap(same_map_as, proto));
|
||||
}
|
||||
return proto;
|
||||
|
Loading…
Reference in New Issue
Block a user