Commit 7c22a153 authored by ishell's avatar ishell Committed by Commit bot

[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}
parent 16310b2e
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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);
}
......
......@@ -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; }
......
......@@ -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());
}
......
......@@ -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
......
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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());
}
......
......@@ -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);
......
......@@ -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
......
......@@ -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(
......
......@@ -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_;
......
......@@ -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),
......
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