[cleanup] Drop FLAG_eliminate_prototype_chain_checks

This flag has been on by default for a while, along with
FLAG_track_prototype_users which provides the prerequisite
infrastructure. We are now sure that this is the direction
we want to go in, so in order to simplify the code, this CL
drops the respective flag-off code paths.

Review-Url: https://codereview.chromium.org/1993913002
Cr-Commit-Position: refs/heads/master@{#36445}
This commit is contained in:
jkummerow 2016-05-23 07:25:43 -07:00 committed by Commit bot
parent 1292721f92
commit eac1b38d9a
10 changed files with 193 additions and 453 deletions

View File

@ -785,13 +785,8 @@ DEFINE_INT(random_seed, 0,
// objects.cc
DEFINE_BOOL(trace_weak_arrays, false, "Trace WeakFixedArray usage")
DEFINE_BOOL(track_prototype_users, false,
"Keep track of which maps refer to a given prototype object")
DEFINE_BOOL(trace_prototype_users, false,
"Trace updates to prototype user tracking")
DEFINE_BOOL(eliminate_prototype_chain_checks, true,
"Collapse prototype chain checks into single-cell checks")
DEFINE_IMPLICATION(eliminate_prototype_chain_checks, track_prototype_users)
DEFINE_BOOL(use_verbose_printer, true, "allows verbose printing")
DEFINE_BOOL(trace_for_in_enumerate, false, "Trace for-in enumerate slow-paths")
#if TRACE_MAPS

View File

@ -437,28 +437,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ mov(scratch1, Operand(validity_cell));
__ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
__ b(ne, miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ mov(scratch1, Operand(validity_cell));
__ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
__ 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);
}
// 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.
@ -494,8 +491,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -505,33 +504,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
__ ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ b(ne, miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -545,17 +523,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ b(ne, miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -467,28 +467,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!AreAliased(object_reg, scratch1, scratch2));
DCHECK(!AreAliased(holder_reg, scratch1, scratch2));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ Mov(scratch1, Operand(validity_cell));
__ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
__ B(ne, miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ Mov(scratch1, Operand(validity_cell));
__ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
__ 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);
}
// 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.
@ -525,8 +522,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -535,34 +534,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(current.is_null() || (current->property_dictionary()->FindEntry(
name) == NameDictionary::kNotFound));
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
__ Ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ Ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ B(ne, miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ Ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -576,17 +553,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ B(ne, miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -439,28 +439,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
// Operand::ForCell(...) points to the cell's payload!
__ cmp(Operand::ForCell(validity_cell),
Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
__ j(not_equal, miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
// Operand::ForCell(...) points to the cell's payload!
__ cmp(Operand::ForCell(validity_cell),
Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
__ 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);
}
// 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.
@ -496,8 +493,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -507,34 +506,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
__ mov(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ j(not_equal, miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -548,17 +525,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -423,28 +423,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ li(scratch1, Operand(validity_cell));
__ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Branch(miss, ne, scratch1,
Operand(Smi::FromInt(Map::kPrototypeChainValid)));
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ li(scratch1, Operand(validity_cell));
__ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Branch(miss, ne, scratch1,
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));
}
// 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.
@ -480,8 +477,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -491,33 +490,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
__ lw(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch2, Operand(map_reg));
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ lw(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -531,17 +509,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch2, Operand(scratch1));
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -423,28 +423,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ li(scratch1, Operand(validity_cell));
__ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Branch(miss, ne, scratch1,
Operand(Smi::FromInt(Map::kPrototypeChainValid)));
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ li(scratch1, Operand(validity_cell));
__ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ Branch(miss, ne, scratch1,
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));
}
// 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.
@ -480,8 +477,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -491,33 +490,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
__ ld(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch2, Operand(map_reg));
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ ld(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -531,17 +509,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ GetWeakValue(scratch2, cell);
__ Branch(miss, ne, scratch2, Operand(scratch1));
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -432,28 +432,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ mov(scratch1, Operand(validity_cell));
__ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
__ bne(miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ mov(scratch1, Operand(validity_cell));
__ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
__ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
__ 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);
}
// 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.
@ -488,8 +485,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -499,33 +498,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
__ LoadP(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ bne(miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ LoadP(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -539,17 +517,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ bne(miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -440,29 +440,26 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
__ Move(scratch1, validity_cell, RelocInfo::CELL);
// Move(..., CELL) loads the payload's address!
__ SmiCompare(Operand(scratch1, 0),
Smi::FromInt(Map::kPrototypeChainValid));
__ j(not_equal, miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
__ Move(scratch1, validity_cell, RelocInfo::CELL);
// Move(..., CELL) loads the payload's address!
__ SmiCompare(Operand(scratch1, 0),
Smi::FromInt(Map::kPrototypeChainValid));
__ 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);
}
// 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
@ -500,8 +497,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -511,34 +510,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
__ movp(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ movp(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ j(not_equal, miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ movp(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -552,17 +529,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -439,28 +439,25 @@ Register PropertyHandlerCompiler::CheckPrototypes(
DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
!scratch2.is(scratch1));
if (FLAG_eliminate_prototype_chain_checks) {
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
validity_cell->value());
// Operand::ForCell(...) points to the cell's payload!
__ cmp(Operand::ForCell(validity_cell),
Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
__ j(not_equal, miss);
}
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (!validity_cell.is_null()) {
DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
// Operand::ForCell(...) points to the cell's payload!
__ cmp(Operand::ForCell(validity_cell),
Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
__ 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);
}
// 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.
@ -496,8 +493,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
!current_map->is_access_check_needed());
prototype = handle(JSObject::cast(current_map->prototype()));
if (current_map->is_dictionary_map() &&
!current_map->IsJSGlobalObjectMap()) {
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
if (!name->IsUniqueName()) {
DCHECK(name->IsString());
@ -507,34 +506,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
current->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound);
if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
if (depth > 1) {
// TODO(jkummerow): Cache and re-use weak cell.
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
scratch2);
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
__ mov(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
}
} else {
Register map_reg = scratch1;
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
}
if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
} else if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 1 || check == CHECK_ALL_MAPS)) {
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(map_reg, cell, scratch2);
__ j(not_equal, miss);
}
if (!FLAG_eliminate_prototype_chain_checks) {
__ mov(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
}
}
reg = holder_reg; // From now on the object will be in holder_reg.
@ -548,17 +525,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (!FLAG_eliminate_prototype_chain_checks &&
(depth != 0 || check == CHECK_ALL_MAPS)) {
// Check the holder map.
__ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
__ CmpWeakValue(scratch1, cell, scratch2);
__ j(not_equal, miss);
}
bool return_holder = return_what == RETURN_HOLDER;
if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
if (return_holder && depth != 0) {
__ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
}

View File

@ -2797,7 +2797,6 @@ bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
Handle<Map> new_map,
Isolate* isolate) {
if (!FLAG_track_prototype_users) return;
if (!old_map->is_prototype_map()) return;
DCHECK(new_map->is_prototype_map());
bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
@ -11598,7 +11597,6 @@ void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
// static
void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
DCHECK(FLAG_track_prototype_users);
// Contract: In line with InvalidatePrototypeChains()'s requirements,
// leaf maps don't need to register as users, only prototypes do.
DCHECK(user->is_prototype_map());
@ -11704,7 +11702,6 @@ static void InvalidatePrototypeChainsInternal(Map* map) {
// static
void JSObject::InvalidatePrototypeChains(Map* map) {
if (!FLAG_eliminate_prototype_chain_checks) return;
DisallowHeapAllocation no_gc;
InvalidatePrototypeChainsInternal(map);
}