[turbofan] Non-dictionary prototype maps are always stable.

We don't need to have an (untested) fallback for the case that a
prototype map is not stable when specializing a named property,
because prototype maps are always stable (which is now guarded
by a DCHECK in CompilationDependencies).  Less (dead) code is
better code.

R=verwaest@chromium.org
BUG=v8:4470
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#31524}
This commit is contained in:
bmeurer 2015-10-23 06:57:55 -07:00 committed by Commit bot
parent 22c5e464c9
commit daf76e6d14
2 changed files with 25 additions and 62 deletions

View File

@ -569,37 +569,7 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
this_value = jsgraph()->Constant(holder);
for (auto i = access_info.receiver_type()->Classes(); !i.Done();
i.Advance()) {
Handle<Map> map = i.Current();
PrototypeIterator j(map);
while (true) {
// Check that the {prototype} still has the same map. For stable
// maps, we can add a stability dependency on the prototype map;
// for everything else we need to perform a map check at runtime.
Handle<JSReceiver> prototype =
PrototypeIterator::GetCurrent<JSReceiver>(j);
if (prototype->map()->is_stable()) {
dependencies()->AssumeMapStable(
handle(prototype->map(), isolate()));
} else {
Node* prototype_map = this_effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMap()),
jsgraph()->Constant(prototype), this_effect, this_control);
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Internal()), prototype_map,
jsgraph()->Constant(handle(prototype->map(), isolate())));
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
check, this_control);
exit_controls.push_back(
graph()->NewNode(common()->IfFalse(), branch));
this_control = graph()->NewNode(common()->IfTrue(), branch);
}
// Stop once we get to the holder.
if (prototype.is_identical_to(holder)) break;
j.Advance();
}
}
AssumePrototypesStable(receiver_type, holder);
}
// Generate the actual property access.
@ -782,37 +752,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
// Determine actual holder and perform prototype chain checks.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
for (auto i = access_info.receiver_type()->Classes(); !i.Done();
i.Advance()) {
Handle<Map> map = i.Current();
PrototypeIterator j(map);
while (true) {
// Check that the {prototype} still has the same map. For stable
// maps, we can add a stability dependency on the prototype map;
// for everything else we need to perform a map check at runtime.
Handle<JSReceiver> prototype =
PrototypeIterator::GetCurrent<JSReceiver>(j);
if (prototype->map()->is_stable()) {
dependencies()->AssumeMapStable(
handle(prototype->map(), isolate()));
} else {
Node* prototype_map = this_effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMap()),
jsgraph()->Constant(prototype), this_effect, this_control);
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Internal()), prototype_map,
jsgraph()->Constant(handle(prototype->map(), isolate())));
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
check, this_control);
exit_controls.push_back(
graph()->NewNode(common()->IfFalse(), branch));
this_control = graph()->NewNode(common()->IfTrue(), branch);
}
// Stop once we get to the holder.
if (prototype.is_identical_to(holder)) break;
j.Advance();
}
}
AssumePrototypesStable(receiver_type, holder);
}
// Generate the actual property access.
@ -951,6 +891,25 @@ bool JSNativeContextSpecialization::LookupInScriptContextTable(
}
void JSNativeContextSpecialization::AssumePrototypesStable(
Type* receiver_type, Handle<JSObject> holder) {
// Determine actual holder and perform prototype chain checks.
for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) {
Handle<Map> const map = i.Current();
for (PrototypeIterator j(map);; j.Advance()) {
// Check that the {prototype} still has the same map. All prototype
// maps are guaranteed to be stable, so it's sufficient to add a
// stability dependency here.
Handle<JSReceiver> const prototype =
PrototypeIterator::GetCurrent<JSReceiver>(j);
dependencies()->AssumeMapStable(handle(prototype->map(), isolate()));
// Stop once we get to the holder.
if (prototype.is_identical_to(holder)) break;
}
}
}
Graph* JSNativeContextSpecialization::graph() const {
return jsgraph()->graph();
}

View File

@ -72,6 +72,10 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
bool LookupInScriptContextTable(Handle<Name> name,
ScriptContextTableLookupResult* result);
// Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}.
void AssumePrototypesStable(Type* receiver_type, Handle<JSObject> holder);
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const;