Commit 47fb39e4 authored by bmeurer's avatar bmeurer Committed by Commit bot

Revert of [turbofan] Properly handle dictionary maps in the prototype chain....

Revert of [turbofan] Properly handle dictionary maps in the prototype chain. (patchset #1 id:1 of https://codereview.chromium.org/2067423003/ )

Reason for revert:
As discussed offline with Toon, this is not the correct fix here.

Original issue's description:
> [turbofan] Properly handle dictionary maps in the prototype chain.
>
> Dictionary prototypes don't have stable maps, but still don't matter for
> element access. Generalized the JSNativeContextSpecialization a bit to
> handle everything that Crankshaft can handle in this regard.
>
> R=jarin@chromium.org
> BUG=chromium:616709
>
> Committed: https://crrev.com/1c7bdc7f6f4d9512f4982590bd949f265ee9c8c3
> Cr-Commit-Position: refs/heads/master@{#37019}

TBR=jarin@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=chromium:616709

Review-Url: https://codereview.chromium.org/2076493002
Cr-Commit-Position: refs/heads/master@{#37029}
parent 175fc180
......@@ -124,6 +124,20 @@ void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
}
void CompilationDependencies::AssumePrototypeMapsStable(
Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
Handle<JSReceiver> const current =
PrototypeIterator::GetCurrent<JSReceiver>(i);
AssumeMapStable(handle(current->map()));
Handle<JSReceiver> last;
if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
break;
}
}
}
void CompilationDependencies::AssumeTransitionStable(
Handle<AllocationSite> site) {
// Do nothing if the object doesn't have any useful element transitions left.
......
......@@ -32,6 +32,9 @@ class CompilationDependencies {
Insert(DependentCode::kFieldTypeGroup, map);
}
void AssumeMapStable(Handle<Map> map);
void AssumePrototypeMapsStable(
Handle<Map> map,
MaybeHandle<JSReceiver> prototype = MaybeHandle<JSReceiver>());
void AssumeMapNotDeprecated(Handle<Map> map);
void AssumePropertyCell(Handle<PropertyCell> cell) {
Insert(DependentCode::kPropertyCellChangedGroup, cell);
......
......@@ -225,8 +225,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Determine actual holder and perform prototype chain checks.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
this_effect = CheckPrototypeMaps(receiver_type, native_context, holder,
this_effect, this_control);
AssumePrototypesStable(receiver_type, native_context, holder);
}
// Generate the actual property access.
......@@ -669,8 +668,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// not compatible with (monomorphic) keyed stores.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
this_effect = CheckPrototypeMaps(receiver_type, native_context, holder,
this_effect, this_control);
AssumePrototypesStable(receiver_type, native_context, holder);
}
// TODO(bmeurer): We currently specialize based on elements kind. We should
......@@ -755,9 +753,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
if (receiver_type->NowIs(initial_holey_array_type) &&
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
// Add a code dependency on the array protector cell.
this_effect = CheckPrototypeMaps(
receiver_type, native_context,
isolate()->initial_object_prototype(), this_effect, this_control);
AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector());
// Turn the hole into undefined.
mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
......@@ -775,9 +772,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
if (receiver_type->NowIs(initial_holey_array_type) &&
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
// Add a code dependency on the array protector cell.
this_effect = CheckPrototypeMaps(
receiver_type, native_context,
isolate()->initial_object_prototype(), this_effect, this_control);
AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector());
// Return the signaling NaN hole directly if all uses are truncating.
mode = CheckFloat64HoleMode::kAllowReturnHole;
......@@ -960,9 +956,10 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
p.language_mode(), store_mode);
}
Node* JSNativeContextSpecialization::CheckPrototypeMaps(
void JSNativeContextSpecialization::AssumePrototypesStable(
Type* receiver_type, Handle<Context> native_context,
Handle<JSObject> holder, Node* effect, Node* control) {
Handle<JSObject> holder) {
// Determine actual holder and perform prototype chain checks.
for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) {
Handle<Map> map = i.Current();
......@@ -973,28 +970,8 @@ Node* JSNativeContextSpecialization::CheckPrototypeMaps(
.ToHandle(&constructor)) {
map = handle(constructor->initial_map(), isolate());
}
for (PrototypeIterator j(map); !j.IsAtEnd(); j.Advance()) {
Handle<JSReceiver> const current =
PrototypeIterator::GetCurrent<JSReceiver>(j);
Handle<Map> current_map(current->map(), isolate());
if (current_map->is_stable()) {
dependencies()->AssumeMapStable(current_map);
} else {
// TODO(bmeurer): Introduce a dedicated CheckMaps operator.
Node* prototype = jsgraph()->HeapConstant(current);
Node* prototype_map = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
prototype, effect, control);
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Internal()), prototype_map,
jsgraph()->HeapConstant(current_map));
effect =
graph()->NewNode(simplified()->CheckIf(), check, effect, control);
}
if (holder.is_identical_to(current)) break;
}
dependencies()->AssumePrototypeMapsStable(map, holder);
}
return effect;
}
bool JSNativeContextSpecialization::ExtractReceiverMaps(
......
......@@ -80,12 +80,10 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
Reduction ReduceSoftDeoptimize(Node* node);
// Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder} if the maps
// are stable, otherwise falls back to inserting runtime map checks
// on the prototypes.
Node* CheckPrototypeMaps(Type* receiver_type, Handle<Context> native_context,
Handle<JSObject> holder, Node* effect,
Node* control);
// {receiver_type} up to (and including) the {holder}.
void AssumePrototypesStable(Type* receiver_type,
Handle<Context> native_context,
Handle<JSObject> holder);
// Extract receiver maps from {nexus} and filter based on {receiver} if
// possible.
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Make the Object prototype have dictionary properties.
for (var i = 0; i < 2000; i++) {
Object.prototype['X'+i] = true;
}
function boom(a1) {
return a1[0];
}
var a = new Array(1);
a[0] = 0.1;
boom(a);
boom(a);
%OptimizeFunctionOnNextCall(boom);
boom(a);
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