Commit 1e65e201 authored by jkummerow's avatar jkummerow Committed by Commit bot

Fasterify JSObject::UnregisterPrototypeUser

When a (prototype) map registers as a user of its own prototype, it now remembers the index in that prototype's registry where it is listed.
This remembered index is used on un-registration to find the right slot to clear without walking the entire registry.
Compaction of the registry must update all entries' remembered indices.

BUG=chromium:517778,chromium:517406
LOG=n
R=yangguo@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#30079}
parent 6ea0d55d
...@@ -55,6 +55,7 @@ Handle<PrototypeInfo> Factory::NewPrototypeInfo() { ...@@ -55,6 +55,7 @@ Handle<PrototypeInfo> Factory::NewPrototypeInfo() {
Handle<PrototypeInfo> result = Handle<PrototypeInfo> result =
Handle<PrototypeInfo>::cast(NewStruct(PROTOTYPE_INFO_TYPE)); Handle<PrototypeInfo>::cast(NewStruct(PROTOTYPE_INFO_TYPE));
result->set_prototype_users(WeakFixedArray::Empty()); result->set_prototype_users(WeakFixedArray::Empty());
result->set_registry_slot(PrototypeInfo::UNREGISTERED);
result->set_validity_cell(Smi::FromInt(0)); result->set_validity_cell(Smi::FromInt(0));
result->set_constructor_name(Smi::FromInt(0)); result->set_constructor_name(Smi::FromInt(0));
return result; return result;
......
...@@ -4963,6 +4963,7 @@ ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset) ...@@ -4963,6 +4963,7 @@ ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
ACCESSORS(Box, value, Object, kValueOffset) ACCESSORS(Box, value, Object, kValueOffset)
ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset) ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset) ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
ACCESSORS(PrototypeInfo, constructor_name, Object, kConstructorNameOffset) ACCESSORS(PrototypeInfo, constructor_name, Object, kConstructorNameOffset)
......
...@@ -967,6 +967,7 @@ void Box::BoxPrint(std::ostream& os) { // NOLINT ...@@ -967,6 +967,7 @@ void Box::BoxPrint(std::ostream& os) { // NOLINT
void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { // NOLINT void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "PrototypeInfo"); HeapObject::PrintHeader(os, "PrototypeInfo");
os << "\n - prototype users: " << Brief(prototype_users()); os << "\n - prototype users: " << Brief(prototype_users());
os << "\n - registry slot: " << registry_slot();
os << "\n - validity cell: " << Brief(validity_cell()); os << "\n - validity cell: " << Brief(validity_cell());
os << "\n - constructor name: " << Brief(constructor_name()); os << "\n - constructor name: " << Brief(constructor_name());
os << "\n"; os << "\n";
......
This diff is collapsed.
...@@ -1906,13 +1906,15 @@ class JSObject: public JSReceiver { ...@@ -1906,13 +1906,15 @@ class JSObject: public JSReceiver {
PrototypeOptimizationMode mode); PrototypeOptimizationMode mode);
static void ReoptimizeIfPrototype(Handle<JSObject> object); static void ReoptimizeIfPrototype(Handle<JSObject> object);
static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate); static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate);
static bool RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype, static bool UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate);
Handle<HeapObject> user,
Isolate* isolate);
static bool UnregisterPrototypeUser(Handle<JSObject> prototype,
Handle<HeapObject> user);
static void InvalidatePrototypeChains(Map* map); static void InvalidatePrototypeChains(Map* map);
// Alternative implementation of WeakFixedArray::NullCallback.
class PrototypeRegistryCompactionCallback {
public:
static void Callback(Object* value, int old_index, int new_index);
};
// Retrieve interceptors. // Retrieve interceptors.
InterceptorInfo* GetNamedInterceptor(); InterceptorInfo* GetNamedInterceptor();
InterceptorInfo* GetIndexedInterceptor(); InterceptorInfo* GetIndexedInterceptor();
...@@ -2531,17 +2533,22 @@ class FixedDoubleArray: public FixedArrayBase { ...@@ -2531,17 +2533,22 @@ class FixedDoubleArray: public FixedArrayBase {
class WeakFixedArray : public FixedArray { class WeakFixedArray : public FixedArray {
public: public:
enum SearchForDuplicates { kAlwaysAdd, kAddIfNotFound };
// If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated. // If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated.
static Handle<WeakFixedArray> Add( // This function does not check if the value exists already, callers must
Handle<Object> maybe_array, Handle<HeapObject> value, // ensure this themselves if necessary.
SearchForDuplicates search_for_duplicates = kAlwaysAdd, static Handle<WeakFixedArray> Add(Handle<Object> maybe_array,
bool* was_present = NULL); Handle<HeapObject> value,
int* assigned_index = NULL);
// Returns true if an entry was found and removed. // Returns true if an entry was found and removed.
bool Remove(Handle<HeapObject> value); bool Remove(Handle<HeapObject> value);
class NullCallback {
public:
static void Callback(Object* value, int old_index, int new_index) {}
};
template <class CompactionCallback>
void Compact(); void Compact();
inline Object* Get(int index) const; inline Object* Get(int index) const;
...@@ -5467,6 +5474,8 @@ class Map: public HeapObject { ...@@ -5467,6 +5474,8 @@ class Map: public HeapObject {
// the given prototype's map). // the given prototype's map).
static Handle<PrototypeInfo> GetOrCreatePrototypeInfo( static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
Handle<JSObject> prototype, Isolate* isolate); Handle<JSObject> prototype, Isolate* isolate);
static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
Handle<Map> prototype_map, Isolate* isolate);
// [prototype chain validity cell]: Associated with a prototype object, // [prototype chain validity cell]: Associated with a prototype object,
// stored in that object's map's PrototypeInfo, indicates that prototype // stored in that object's map's PrototypeInfo, indicates that prototype
...@@ -6036,9 +6045,15 @@ class Box : public Struct { ...@@ -6036,9 +6045,15 @@ class Box : public Struct {
// Container for metadata stored on each prototype map. // Container for metadata stored on each prototype map.
class PrototypeInfo : public Struct { class PrototypeInfo : public Struct {
public: public:
static const int UNREGISTERED = -1;
// [prototype_users]: WeakFixedArray containing maps using this prototype, // [prototype_users]: WeakFixedArray containing maps using this prototype,
// or Smi(0) if uninitialized. // or Smi(0) if uninitialized.
DECL_ACCESSORS(prototype_users, Object) DECL_ACCESSORS(prototype_users, Object)
// [registry_slot]: Slot in prototype's user registry where this user
// is stored. Returns UNREGISTERED if this prototype has not been registered.
inline int registry_slot() const;
inline void set_registry_slot(int slot);
// [validity_cell]: Cell containing the validity bit for prototype chains // [validity_cell]: Cell containing the validity bit for prototype chains
// going through this object, or Smi(0) if uninitialized. // going through this object, or Smi(0) if uninitialized.
DECL_ACCESSORS(validity_cell, Object) DECL_ACCESSORS(validity_cell, Object)
...@@ -6052,7 +6067,8 @@ class PrototypeInfo : public Struct { ...@@ -6052,7 +6067,8 @@ class PrototypeInfo : public Struct {
DECLARE_VERIFIER(PrototypeInfo) DECLARE_VERIFIER(PrototypeInfo)
static const int kPrototypeUsersOffset = HeapObject::kHeaderSize; static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
static const int kValidityCellOffset = kPrototypeUsersOffset + kPointerSize; static const int kRegistrySlotOffset = kPrototypeUsersOffset + kPointerSize;
static const int kValidityCellOffset = kRegistrySlotOffset + kPointerSize;
static const int kConstructorNameOffset = kValidityCellOffset + kPointerSize; static const int kConstructorNameOffset = kValidityCellOffset + kPointerSize;
static const int kSize = kConstructorNameOffset + kPointerSize; static const int kSize = kConstructorNameOffset + kPointerSize;
......
...@@ -1926,7 +1926,23 @@ void Serializer::ObjectSerializer::Serialize() { ...@@ -1926,7 +1926,23 @@ void Serializer::ObjectSerializer::Serialize() {
if (object_->IsPrototypeInfo()) { if (object_->IsPrototypeInfo()) {
Object* prototype_users = PrototypeInfo::cast(object_)->prototype_users(); Object* prototype_users = PrototypeInfo::cast(object_)->prototype_users();
if (prototype_users->IsWeakFixedArray()) { if (prototype_users->IsWeakFixedArray()) {
WeakFixedArray::cast(prototype_users)->Compact(); WeakFixedArray* array = WeakFixedArray::cast(prototype_users);
array->Compact<JSObject::PrototypeRegistryCompactionCallback>();
}
}
// Compaction of a prototype users list can require the registered users
// to update their remembered slots. That doesn't work if those users
// have already been serialized themselves. So if this object is a
// registered user, compact its prototype's user list now.
if (object_->IsMap()) {
Map* map = Map::cast(object_);
if (map->is_prototype_map() && map->prototype_info()->IsPrototypeInfo() &&
PrototypeInfo::cast(map->prototype_info())->registry_slot() !=
PrototypeInfo::UNREGISTERED) {
JSObject* proto = JSObject::cast(map->prototype());
PrototypeInfo* info = PrototypeInfo::cast(proto->map()->prototype_info());
WeakFixedArray* array = WeakFixedArray::cast(info->prototype_users());
array->Compact<JSObject::PrototypeRegistryCompactionCallback>();
} }
} }
...@@ -1936,7 +1952,8 @@ void Serializer::ObjectSerializer::Serialize() { ...@@ -1936,7 +1952,8 @@ void Serializer::ObjectSerializer::Serialize() {
Script::cast(object_)->set_line_ends(undefined); Script::cast(object_)->set_line_ends(undefined);
Object* shared_list = Script::cast(object_)->shared_function_infos(); Object* shared_list = Script::cast(object_)->shared_function_infos();
if (shared_list->IsWeakFixedArray()) { if (shared_list->IsWeakFixedArray()) {
WeakFixedArray::cast(shared_list)->Compact(); WeakFixedArray::cast(shared_list)
->Compact<WeakFixedArray::NullCallback>();
} }
} }
......
...@@ -5954,7 +5954,7 @@ TEST(WeakFixedArray) { ...@@ -5954,7 +5954,7 @@ TEST(WeakFixedArray) {
Handle<HeapNumber> number = CcTest::i_isolate()->factory()->NewHeapNumber(1); Handle<HeapNumber> number = CcTest::i_isolate()->factory()->NewHeapNumber(1);
Handle<WeakFixedArray> array = WeakFixedArray::Add(Handle<Object>(), number); Handle<WeakFixedArray> array = WeakFixedArray::Add(Handle<Object>(), number);
array->Remove(number); array->Remove(number);
array->Compact(); array->Compact<WeakFixedArray::NullCallback>();
WeakFixedArray::Add(array, number); WeakFixedArray::Add(array, number);
} }
......
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