From 986b04a62a5e3617f7c951ff91b83bcd1daa6f85 Mon Sep 17 00:00:00 2001 From: bmeurer Date: Sun, 31 Jul 2016 23:17:21 -0700 Subject: [PATCH] [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} --- src/compiler/ast-graph-builder.cc | 30 ++++++++----------- test/mjsunit/compiler/accessor-exceptions1.js | 21 +++++++++++++ test/mjsunit/compiler/accessor-exceptions2.js | 21 +++++++++++++ test/mjsunit/compiler/deopt-accessors1.js | 28 +++++++++++++++++ test/mjsunit/compiler/deopt-accessors2.js | 28 +++++++++++++++++ test/mjsunit/compiler/deopt-accessors3.js | 29 ++++++++++++++++++ test/mjsunit/compiler/deopt-accessors4.js | 29 ++++++++++++++++++ test/mjsunit/compiler/deopt-accessors5.js | 23 ++++++++++++++ test/mjsunit/compiler/deopt-accessors6.js | 24 +++++++++++++++ test/mjsunit/compiler/deopt-accessors7.js | 30 +++++++++++++++++++ 10 files changed, 245 insertions(+), 18 deletions(-) create mode 100644 test/mjsunit/compiler/accessor-exceptions1.js create mode 100644 test/mjsunit/compiler/accessor-exceptions2.js create mode 100644 test/mjsunit/compiler/deopt-accessors1.js create mode 100644 test/mjsunit/compiler/deopt-accessors2.js create mode 100644 test/mjsunit/compiler/deopt-accessors3.js create mode 100644 test/mjsunit/compiler/deopt-accessors4.js create mode 100644 test/mjsunit/compiler/deopt-accessors5.js create mode 100644 test/mjsunit/compiler/deopt-accessors6.js create mode 100644 test/mjsunit/compiler/deopt-accessors7.js diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 3251b943a5..3668ff8c01 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -2240,14 +2240,16 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) { Node* object = environment()->Pop(); Handle name = property->key()->AsLiteral()->AsPropertyName(); Node* store = BuildNamedStore(object, name, value, feedback); - PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(store, expr->AssignmentId(), + OutputFrameStateCombine::Push()); break; } case KEYED_PROPERTY: { Node* key = environment()->Pop(); Node* object = environment()->Pop(); Node* store = BuildKeyedStore(object, key, value, feedback); - PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(store, expr->AssignmentId(), + OutputFrameStateCombine::Push()); break; } case NAMED_SUPER_PROPERTY: { @@ -2300,7 +2302,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) { Node* object = environment()->Pop(); Handle name = expr->key()->AsLiteral()->AsPropertyName(); value = BuildNamedLoad(object, name, pair); - PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push()); break; } case KEYED_PROPERTY: { @@ -2309,7 +2311,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) { Node* key = environment()->Pop(); Node* object = environment()->Pop(); value = BuildKeyedLoad(object, key, pair); - PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push()); break; } case NAMED_SUPER_PROPERTY: { @@ -2319,7 +2321,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) { Node* receiver = environment()->Pop(); Handle name = expr->key()->AsLiteral()->AsPropertyName(); value = BuildNamedSuperLoad(receiver, home_object, name, pair); - PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push()); break; } case KEYED_SUPER_PROPERTY: { @@ -2330,7 +2332,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) { Node* home_object = environment()->Pop(); Node* receiver = environment()->Pop(); value = BuildKeyedSuperLoad(receiver, home_object, key, pair); - PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); + PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push()); break; } } @@ -2754,20 +2756,16 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { Node* object = environment()->Pop(); Handle name = property->key()->AsLiteral()->AsPropertyName(); Node* store = BuildNamedStore(object, name, value, feedback); - environment()->Push(value); PrepareFrameState(store, expr->AssignmentId(), - OutputFrameStateCombine::Ignore()); - environment()->Pop(); + OutputFrameStateCombine::Push()); break; } case KEYED_PROPERTY: { Node* key = environment()->Pop(); Node* object = environment()->Pop(); Node* store = BuildKeyedStore(object, key, value, feedback); - environment()->Push(value); PrepareFrameState(store, expr->AssignmentId(), - OutputFrameStateCombine::Ignore()); - environment()->Pop(); + OutputFrameStateCombine::Push()); break; } case NAMED_SUPER_PROPERTY: { @@ -2775,10 +2773,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { Node* receiver = environment()->Pop(); Handle name = property->key()->AsLiteral()->AsPropertyName(); Node* store = BuildNamedSuperStore(receiver, home_object, name, value); - environment()->Push(value); PrepareFrameState(store, expr->AssignmentId(), - OutputFrameStateCombine::Ignore()); - environment()->Pop(); + OutputFrameStateCombine::Push()); break; } case KEYED_SUPER_PROPERTY: { @@ -2786,10 +2782,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { Node* home_object = environment()->Pop(); Node* receiver = environment()->Pop(); Node* store = BuildKeyedSuperStore(receiver, home_object, key, value); - environment()->Push(value); PrepareFrameState(store, expr->AssignmentId(), - OutputFrameStateCombine::Ignore()); - environment()->Pop(); + OutputFrameStateCombine::Push()); break; } } diff --git a/test/mjsunit/compiler/accessor-exceptions1.js b/test/mjsunit/compiler/accessor-exceptions1.js new file mode 100644 index 0000000000..716d229aba --- /dev/null +++ b/test/mjsunit/compiler/accessor-exceptions1.js @@ -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)); diff --git a/test/mjsunit/compiler/accessor-exceptions2.js b/test/mjsunit/compiler/accessor-exceptions2.js new file mode 100644 index 0000000000..ed6e3e21c0 --- /dev/null +++ b/test/mjsunit/compiler/accessor-exceptions2.js @@ -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)); diff --git a/test/mjsunit/compiler/deopt-accessors1.js b/test/mjsunit/compiler/deopt-accessors1.js new file mode 100644 index 0000000000..3589258656 --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors1.js @@ -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)); diff --git a/test/mjsunit/compiler/deopt-accessors2.js b/test/mjsunit/compiler/deopt-accessors2.js new file mode 100644 index 0000000000..74d41397bf --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors2.js @@ -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)); diff --git a/test/mjsunit/compiler/deopt-accessors3.js b/test/mjsunit/compiler/deopt-accessors3.js new file mode 100644 index 0000000000..035cf2b359 --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors3.js @@ -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)); diff --git a/test/mjsunit/compiler/deopt-accessors4.js b/test/mjsunit/compiler/deopt-accessors4.js new file mode 100644 index 0000000000..5a8453f237 --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors4.js @@ -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)); diff --git a/test/mjsunit/compiler/deopt-accessors5.js b/test/mjsunit/compiler/deopt-accessors5.js new file mode 100644 index 0000000000..1b23c532dc --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors5.js @@ -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(); diff --git a/test/mjsunit/compiler/deopt-accessors6.js b/test/mjsunit/compiler/deopt-accessors6.js new file mode 100644 index 0000000000..16fb4ddf64 --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors6.js @@ -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(); diff --git a/test/mjsunit/compiler/deopt-accessors7.js b/test/mjsunit/compiler/deopt-accessors7.js new file mode 100644 index 0000000000..8c7d7a1e3c --- /dev/null +++ b/test/mjsunit/compiler/deopt-accessors7.js @@ -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"));