[ic] Simplify handling of primitive maps.

This CL adds support for primitive maps to
1) PrototypeIterator,
2) PropertyHandlerCompiler::CheckPrototypes(),
3) Map::GetOrCreatePrototypeChainValidityCell(),
4) Prototype checks in data-driven ICs.

BUG=v8:5561

Review-Url: https://codereview.chromium.org/2466553002
Cr-Commit-Position: refs/heads/master@{#40673}
This commit is contained in:
ishell 2016-10-31 07:58:42 -07:00 committed by Commit bot
parent 16310b2e39
commit 7c22a153e2
17 changed files with 69 additions and 191 deletions

View File

@ -407,10 +407,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -429,17 +428,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ b(ne, miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ b(ne, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -449,15 +437,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -479,7 +466,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -437,10 +437,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -458,17 +457,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ B(ne, miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ B(ne, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -478,15 +466,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -507,7 +494,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -95,24 +95,9 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
Handle<Name> name,
Label* miss,
ReturnHolder return_what) {
PrototypeCheckType check_type = SKIP_RECEIVER;
int function_index = map()->IsPrimitiveMap()
? map()->GetConstructorFunctionIndex()
: Map::kNoConstructorFunctionIndex;
if (function_index != Map::kNoConstructorFunctionIndex) {
GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index,
scratch1(), miss);
Object* function = isolate()->native_context()->get(function_index);
Object* prototype = JSFunction::cast(function)->instance_prototype();
Handle<Map> map(JSObject::cast(prototype)->map());
set_map(map);
object_reg = scratch1();
check_type = CHECK_ALL_MAPS;
}
// Check that the maps starting from the prototype haven't changed.
return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
miss, check_type, return_what);
miss, return_what);
}
@ -123,7 +108,7 @@ Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
Label* miss,
ReturnHolder return_what) {
return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
miss, SKIP_RECEIVER, return_what);
miss, return_what);
}

View File

@ -13,7 +13,6 @@ namespace internal {
class CallOptimization;
enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
class PropertyHandlerCompiler : public PropertyAccessCompiler {
@ -99,7 +98,7 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
Register CheckPrototypes(Register object_reg, Register holder_reg,
Register scratch1, Register scratch2,
Handle<Name> name, Label* miss,
PrototypeCheckType check, ReturnHolder return_what);
ReturnHolder return_what);
Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
void set_holder(Handle<JSObject> holder) { holder_ = holder; }

View File

@ -411,10 +411,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -433,17 +432,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ j(not_equal, miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -453,15 +441,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -483,7 +470,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -862,7 +862,7 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
DCHECK(holder->HasFastProperties());
// The following kinds of receiver maps require custom handler compilation.
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalObjectMap()) {
if (receiver_map->IsJSGlobalObjectMap()) {
return -1;
}
// We don't encode the requirement to check access rights because we already

View File

@ -393,10 +393,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -415,17 +414,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Operand(Smi::FromInt(Map::kPrototypeChainValid)));
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ lw(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch1, Operand(scratch2));
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -435,15 +423,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -465,7 +452,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -393,10 +393,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -415,17 +414,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Operand(Smi::FromInt(Map::kPrototypeChainValid)));
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch1, Operand(scratch2));
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -435,15 +423,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -465,7 +452,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -402,10 +402,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -424,17 +423,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ bne(miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ b(ne, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -444,8 +432,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
@ -457,7 +445,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(current_map->IsJSGlobalProxyMap() ||
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -479,7 +466,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -385,7 +385,7 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -404,17 +404,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ bne(miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ b(ne, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -424,15 +413,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -454,7 +442,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -401,10 +401,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -424,17 +423,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ j(not_equal, miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ movp(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
// Keep track of the current object in register reg. On the first
// iteration, reg is an alias for object_reg, on later iterations,
// it is an alias for holder_reg.
@ -446,15 +434,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -476,7 +463,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -411,10 +411,9 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
}
}
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Handle<Map> receiver_map = map();
@ -433,17 +432,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
__ j(not_equal, miss);
}
// The prototype chain of primitives (and their JSValue wrappers) depends
// on the native context, which can't be guarded by validity cells.
// |object_reg| holds the native context specific prototype in this case;
// we need to check its map.
if (check == CHECK_ALL_MAPS) {
__ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
// Keep track of the current object in register reg.
Register reg = object_reg;
int depth = 0;
@ -453,15 +441,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()),
isolate());
Handle<Map> holder_map(holder()->map());
// Traverse the prototype chain and check the maps in the prototype chain for
// fast and global objects or do negative lookup for normal objects.
while (!current_map.is_identical_to(holder_map)) {
++depth;
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
@ -483,7 +470,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
// Go to the next object in the prototype chain.
current = prototype;
current = handle(JSObject::cast(current_map->prototype()));
current_map = handle(current->map());
}

View File

@ -129,7 +129,8 @@ Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver(
Handle<JSValue>::cast(result)->set_value(*receiver);
return result;
}
auto root = handle(receiver->GetRootMap(isolate)->prototype(), isolate);
auto root =
handle(receiver->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
if (root->IsNull(isolate)) {
unsigned int magic = 0xbbbbbbbb;
isolate->PushStackTraceAndDie(magic, *receiver, NULL, magic);

View File

@ -1931,7 +1931,7 @@ Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
}
}
Map* Object::GetRootMap(Isolate* isolate) {
Map* Object::GetPrototypeChainRootMap(Isolate* isolate) {
DisallowHeapAllocation no_alloc;
if (IsSmi()) {
Context* native_context = isolate->context()->native_context();
@ -1941,11 +1941,15 @@ Map* Object::GetRootMap(Isolate* isolate) {
// The object is either a number, a string, a symbol, a boolean, a SIMD value,
// a real JS object, or a Harmony proxy.
HeapObject* heap_object = HeapObject::cast(this);
if (heap_object->IsJSReceiver()) {
return heap_object->map();
return heap_object->map()->GetPrototypeChainRootMap(isolate);
}
Map* Map::GetPrototypeChainRootMap(Isolate* isolate) {
DisallowHeapAllocation no_alloc;
if (IsJSReceiverMap()) {
return this;
}
int constructor_function_index =
heap_object->map()->GetConstructorFunctionIndex();
int constructor_function_index = GetConstructorFunctionIndex();
if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
Context* native_context = isolate->context()->native_context();
JSFunction* constructor_function =
@ -12734,7 +12738,8 @@ void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
// static
Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
Isolate* isolate) {
Handle<Object> maybe_prototype(map->prototype(), isolate);
Handle<Object> maybe_prototype(
map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
// Ensure the prototype is registered with its own prototypes so its cell

View File

@ -1559,7 +1559,7 @@ class Object {
friend class StringStream;
// Return the map of the root of object's prototype chain.
Map* GetRootMap(Isolate* isolate);
Map* GetPrototypeChainRootMap(Isolate* isolate);
// Helper for SetProperty and SetSuperProperty.
// Return value is only meaningful if [found] is set to true on return.
@ -6332,6 +6332,9 @@ class Map: public HeapObject {
static const int kPrototypeChainValid = 0;
static const int kPrototypeChainInvalid = 1;
// Return the map of the root of object's prototype chain.
Map* GetPrototypeChainRootMap(Isolate* isolate);
// Returns a WeakCell object containing given prototype. The cell is cached
// in PrototypeInfo which is created lazily.
static Handle<WeakCell> GetOrCreatePrototypeWeakCell(

View File

@ -32,9 +32,9 @@ class PrototypeIterator {
PrototypeIterator(Isolate* isolate, Handle<JSReceiver> receiver,
WhereToStart where_to_start = kStartAtPrototype,
WhereToEnd where_to_end = END_AT_NULL)
: object_(NULL),
: isolate_(isolate),
object_(NULL),
handle_(receiver),
isolate_(isolate),
where_to_end_(where_to_end),
is_at_end_(false),
seen_proxies_(0) {
@ -45,8 +45,8 @@ class PrototypeIterator {
PrototypeIterator(Isolate* isolate, JSReceiver* receiver,
WhereToStart where_to_start = kStartAtPrototype,
WhereToEnd where_to_end = END_AT_NULL)
: object_(receiver),
isolate_(isolate),
: isolate_(isolate),
object_(receiver),
where_to_end_(where_to_end),
is_at_end_(false),
seen_proxies_(0) {
@ -54,16 +54,17 @@ class PrototypeIterator {
}
explicit PrototypeIterator(Map* receiver_map)
: object_(receiver_map->prototype()),
isolate_(receiver_map->GetIsolate()),
: isolate_(receiver_map->GetIsolate()),
object_(receiver_map->GetPrototypeChainRootMap(isolate_)->prototype()),
where_to_end_(END_AT_NULL),
is_at_end_(object_->IsNull(isolate_)),
seen_proxies_(0) {}
explicit PrototypeIterator(Handle<Map> receiver_map)
: object_(NULL),
handle_(handle(receiver_map->prototype(), receiver_map->GetIsolate())),
isolate_(receiver_map->GetIsolate()),
: isolate_(receiver_map->GetIsolate()),
object_(NULL),
handle_(receiver_map->GetPrototypeChainRootMap(isolate_)->prototype(),
isolate_),
where_to_end_(END_AT_NULL),
is_at_end_(handle_->IsNull(isolate_)),
seen_proxies_(0) {}
@ -161,9 +162,9 @@ class PrototypeIterator {
bool IsAtEnd() const { return is_at_end_; }
private:
Isolate* isolate_;
Object* object_;
Handle<Object> handle_;
Isolate* isolate_;
WhereToEnd where_to_end_;
bool is_at_end_;
int seen_proxies_;

View File

@ -533,7 +533,7 @@ void StringStream::PrintPrototype(JSFunction* fun, Object* receiver) {
print_name = true;
} else if (isolate->context() != nullptr) {
if (!receiver->IsJSObject()) {
receiver = receiver->GetRootMap(isolate)->prototype();
receiver = receiver->GetPrototypeChainRootMap(isolate)->prototype();
}
for (PrototypeIterator iter(isolate, JSObject::cast(receiver),