From d6ff45afadf1931ebd88d23f7e8f418ada1ba02e Mon Sep 17 00:00:00 2001 From: bmeurer Date: Sun, 6 Nov 2016 22:38:50 -0800 Subject: [PATCH] [crankshaft] Fix deoptimization loop w/ non-monomorphic arguments access. In Crankshaft we unconditionally assume that accesses to arguments[i] will be in-bounds and don't take into account IC feedback that would eventually teach us about out-of-bounds accesses that have happened in the past, so there's no real guard to protect the bounds check in optimized code. TEST=mjsunit/compiler/deopt-arguments-oob R=jarin@chromium.org BUG=v8:5606 Review-Url: https://codereview.chromium.org/2481053002 Cr-Commit-Position: refs/heads/master@{#40787} --- src/crankshaft/hydrogen.cc | 3 +++ test/mjsunit/compiler/deopt-arguments-oob.js | 27 ++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/mjsunit/compiler/deopt-arguments-oob.js diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc index 2e0695dfdf..4cdf74782e 100644 --- a/src/crankshaft/hydrogen.cc +++ b/src/crankshaft/hydrogen.cc @@ -7452,6 +7452,9 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { result = New(argument_count); } } else { + // We need to take into account the KEYED_LOAD_IC feedback to guard the + // HBoundsCheck instructions below. + if (!expr->IsMonomorphic()) return false; CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true); CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true); HValue* key = Pop(); diff --git a/test/mjsunit/compiler/deopt-arguments-oob.js b/test/mjsunit/compiler/deopt-arguments-oob.js new file mode 100644 index 0000000000..6995af6fc3 --- /dev/null +++ b/test/mjsunit/compiler/deopt-arguments-oob.js @@ -0,0 +1,27 @@ +// 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 + +function foo() { return arguments[0]; } + +// Warm up with monomorphic access. +foo(0); +foo(1); +%BaselineFunctionOnNextCall(foo); +foo(2); +foo(3); +%OptimizeFunctionOnNextCall(foo); + +// Mess with out-of-bounds accesses. +for (var i = 0; i < 50000; ++i) { + foo(); +} + +// Optimization shall stabilize now. +var count = %GetOptimizationCount(foo); +for (var i = 0; i < 50000; ++i) { + foo(); +} +assertEquals(count, %GetOptimizationCount(foo));