[turbofan] Fix various bailout points for AstGraphBuilder.
This introduces a bunch of new tests that test various aspects of accessor inlining in TurboFan (without the actual inlining), and does the appropriate fixes to the AstGraphBuilder. The actual inlining CL will land separately (so we don't need to revert the tests and fixes if the accessor CL has to be reverted). R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2197913002 Cr-Commit-Position: refs/heads/master@{#38191}
This commit is contained in:
parent
3e3ff89d4b
commit
986b04a62a
@ -2240,14 +2240,16 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
|||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||||
Node* store = BuildNamedStore(object, name, value, feedback);
|
Node* store = BuildNamedStore(object, name, value, feedback);
|
||||||
PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
|
OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEYED_PROPERTY: {
|
case KEYED_PROPERTY: {
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Node* store = BuildKeyedStore(object, key, value, feedback);
|
Node* store = BuildKeyedStore(object, key, value, feedback);
|
||||||
PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
|
OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_SUPER_PROPERTY: {
|
case NAMED_SUPER_PROPERTY: {
|
||||||
@ -2300,7 +2302,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
|||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||||
value = BuildNamedLoad(object, name, pair);
|
value = BuildNamedLoad(object, name, pair);
|
||||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEYED_PROPERTY: {
|
case KEYED_PROPERTY: {
|
||||||
@ -2309,7 +2311,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
|||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
value = BuildKeyedLoad(object, key, pair);
|
value = BuildKeyedLoad(object, key, pair);
|
||||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_SUPER_PROPERTY: {
|
case NAMED_SUPER_PROPERTY: {
|
||||||
@ -2319,7 +2321,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
|||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||||
value = BuildNamedSuperLoad(receiver, home_object, name, pair);
|
value = BuildNamedSuperLoad(receiver, home_object, name, pair);
|
||||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEYED_SUPER_PROPERTY: {
|
case KEYED_SUPER_PROPERTY: {
|
||||||
@ -2330,7 +2332,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
|||||||
Node* home_object = environment()->Pop();
|
Node* home_object = environment()->Pop();
|
||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
|
value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
|
||||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2754,20 +2756,16 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
|||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||||
Node* store = BuildNamedStore(object, name, value, feedback);
|
Node* store = BuildNamedStore(object, name, value, feedback);
|
||||||
environment()->Push(value);
|
|
||||||
PrepareFrameState(store, expr->AssignmentId(),
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Push());
|
||||||
environment()->Pop();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEYED_PROPERTY: {
|
case KEYED_PROPERTY: {
|
||||||
Node* key = environment()->Pop();
|
Node* key = environment()->Pop();
|
||||||
Node* object = environment()->Pop();
|
Node* object = environment()->Pop();
|
||||||
Node* store = BuildKeyedStore(object, key, value, feedback);
|
Node* store = BuildKeyedStore(object, key, value, feedback);
|
||||||
environment()->Push(value);
|
|
||||||
PrepareFrameState(store, expr->AssignmentId(),
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Push());
|
||||||
environment()->Pop();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NAMED_SUPER_PROPERTY: {
|
case NAMED_SUPER_PROPERTY: {
|
||||||
@ -2775,10 +2773,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
|||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||||
Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
|
Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
|
||||||
environment()->Push(value);
|
|
||||||
PrepareFrameState(store, expr->AssignmentId(),
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Push());
|
||||||
environment()->Pop();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEYED_SUPER_PROPERTY: {
|
case KEYED_SUPER_PROPERTY: {
|
||||||
@ -2786,10 +2782,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
|||||||
Node* home_object = environment()->Pop();
|
Node* home_object = environment()->Pop();
|
||||||
Node* receiver = environment()->Pop();
|
Node* receiver = environment()->Pop();
|
||||||
Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
|
Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
|
||||||
environment()->Push(value);
|
|
||||||
PrepareFrameState(store, expr->AssignmentId(),
|
PrepareFrameState(store, expr->AssignmentId(),
|
||||||
OutputFrameStateCombine::Ignore());
|
OutputFrameStateCombine::Push());
|
||||||
environment()->Pop();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
test/mjsunit/compiler/accessor-exceptions1.js
Normal file
21
test/mjsunit/compiler/accessor-exceptions1.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {}
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() { throw 7; }
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
var x = 1;
|
||||||
|
try { o.x; } catch (e) { x = e; }
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(7, foo(o));
|
||||||
|
assertEquals(7, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
assertEquals(7, foo(o));
|
21
test/mjsunit/compiler/accessor-exceptions2.js
Normal file
21
test/mjsunit/compiler/accessor-exceptions2.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {}
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
set: function(v) { throw 7; }
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
var x = 1;
|
||||||
|
try { o.x = 2; } catch (e) { x = e; }
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(7, foo(o));
|
||||||
|
assertEquals(7, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
assertEquals(7, foo(o));
|
28
test/mjsunit/compiler/deopt-accessors1.js
Normal file
28
test/mjsunit/compiler/deopt-accessors1.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {v:1};
|
||||||
|
var deopt = false;
|
||||||
|
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() { return this.v; },
|
||||||
|
set: function(v) {
|
||||||
|
this.v = v;
|
||||||
|
if (deopt) {
|
||||||
|
%DeoptimizeFunction(foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
return o.x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, foo(o));
|
||||||
|
assertEquals(2, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
deopt = true;
|
||||||
|
assertEquals(3, foo(o));
|
28
test/mjsunit/compiler/deopt-accessors2.js
Normal file
28
test/mjsunit/compiler/deopt-accessors2.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {v:1};
|
||||||
|
var deopt = false;
|
||||||
|
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() { return this.v; },
|
||||||
|
set: function(v) {
|
||||||
|
this.v = v;
|
||||||
|
if (deopt) {
|
||||||
|
%DeoptimizeFunction(foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
return ++o.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(2, foo(o));
|
||||||
|
assertEquals(3, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
deopt = true;
|
||||||
|
assertEquals(4, foo(o));
|
29
test/mjsunit/compiler/deopt-accessors3.js
Normal file
29
test/mjsunit/compiler/deopt-accessors3.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {v:1};
|
||||||
|
var deopt = false;
|
||||||
|
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() { return this.v; },
|
||||||
|
set: function(v) {
|
||||||
|
this.v = v;
|
||||||
|
if (deopt) {
|
||||||
|
%DeoptimizeFunction(foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
var x = "x";
|
||||||
|
return o[x]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, foo(o));
|
||||||
|
assertEquals(2, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
deopt = true;
|
||||||
|
assertEquals(3, foo(o));
|
29
test/mjsunit/compiler/deopt-accessors4.js
Normal file
29
test/mjsunit/compiler/deopt-accessors4.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {v:1};
|
||||||
|
var deopt = false;
|
||||||
|
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() { return this.v; },
|
||||||
|
set: function(v) {
|
||||||
|
this.v = v;
|
||||||
|
if (deopt) {
|
||||||
|
%DeoptimizeFunction(foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function foo(o) {
|
||||||
|
var x = "x";
|
||||||
|
return ++o[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(2, foo(o));
|
||||||
|
assertEquals(3, foo(o));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
deopt = true;
|
||||||
|
assertEquals(4, foo(o));
|
23
test/mjsunit/compiler/deopt-accessors5.js
Normal file
23
test/mjsunit/compiler/deopt-accessors5.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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 --harmony-tailcalls
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function f(v) {
|
||||||
|
%DeoptimizeFunction(test);
|
||||||
|
return 153;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
var o = {};
|
||||||
|
o.__defineSetter__('q', f);
|
||||||
|
assertEquals(1, o.q = 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
||||||
|
test();
|
||||||
|
%OptimizeFunctionOnNextCall(test);
|
||||||
|
test();
|
24
test/mjsunit/compiler/deopt-accessors6.js
Normal file
24
test/mjsunit/compiler/deopt-accessors6.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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 --harmony-tailcalls
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function f(v) {
|
||||||
|
%DeoptimizeFunction(test);
|
||||||
|
return 153;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
var o = {};
|
||||||
|
var q = "q";
|
||||||
|
o.__defineSetter__(q, f);
|
||||||
|
assertEquals(1, o[q] = 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
||||||
|
test();
|
||||||
|
%OptimizeFunctionOnNextCall(test);
|
||||||
|
test();
|
30
test/mjsunit/compiler/deopt-accessors7.js
Normal file
30
test/mjsunit/compiler/deopt-accessors7.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
var o = {v:1};
|
||||||
|
var deopt = false;
|
||||||
|
Object.defineProperty(o, "x", {
|
||||||
|
get: function() {
|
||||||
|
if (deopt) %DeoptimizeFunction(foo);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function bar(x, y, z) {
|
||||||
|
return x + z;
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo(o, x) {
|
||||||
|
return bar(1, (o[x], 2), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(4, foo(o, "v"));
|
||||||
|
assertEquals(4, foo(o, "v"));
|
||||||
|
assertEquals(4, foo(o, "x"));
|
||||||
|
assertEquals(4, foo(o, "x"));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
deopt = true;
|
||||||
|
assertEquals(4, foo(o, "x"));
|
Loading…
Reference in New Issue
Block a user