diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc index c07c4826b6..2183068576 100644 --- a/src/interpreter/bytecode-array-builder.cc +++ b/src/interpreter/bytecode-array-builder.cc @@ -1342,6 +1342,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler( BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id, Register context) { + // TODO(leszeks): Do we need to start a new basic block here? Could we simply + // get the current bytecode offset from the array writer instead? BytecodeLabel try_begin; Bind(&try_begin); handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset()); diff --git a/src/interpreter/bytecode-array-builder.h b/src/interpreter/bytecode-array-builder.h index 08422d1f2a..87a99607c5 100644 --- a/src/interpreter/bytecode-array-builder.h +++ b/src/interpreter/bytecode-array-builder.h @@ -521,6 +521,9 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { } bool RequiresImplicitReturn() const { return !return_seen_in_block_; } + bool RemainderOfBlockIsDead() const { + return bytecode_array_writer_.RemainderOfBlockIsDead(); + } // Returns the raw operand value for the given register or register list. uint32_t GetInputRegisterOperand(Register reg); diff --git a/src/interpreter/bytecode-array-writer.h b/src/interpreter/bytecode-array-writer.h index 9700d2c1cf..e6db2fce22 100644 --- a/src/interpreter/bytecode-array-writer.h +++ b/src/interpreter/bytecode-array-writer.h @@ -45,6 +45,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final { int parameter_count, Handle handler_table); + bool RemainderOfBlockIsDead() const { return exit_seen_in_block_; } + private: // Maximum sized packed bytecode is comprised of a prefix bytecode, // plus the actual bytecode, plus the maximum number of operands times diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index bef3a0a276..b31bb82f44 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -1341,7 +1341,7 @@ void BytecodeGenerator::VisitStatements( RegisterAllocationScope allocation_scope(this); Statement* stmt = statements->at(i); Visit(stmt); - if (stmt->IsJump()) break; + if (builder()->RemainderOfBlockIsDead()) break; } } diff --git a/test/mjsunit/regress/regress-crbug-902395.js b/test/mjsunit/regress/regress-crbug-902395.js new file mode 100644 index 0000000000..79aaecf6fa --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-902395.js @@ -0,0 +1,37 @@ +// Copyright 2018 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 opt() { + try{ + Object.seal({}) + }finally{ + try{ + // Carefully crafted by clusterfuzz to alias the temporary object literal + // register with the below dead try block's context register. + ( + { + toString(){ + } + } + ).apply(-1).x( ) + } + finally{ + if(2.2) + { + return + } + // This code should be dead. + try{ + Reflect.construct + }finally{ + } + } + } +} + +opt(); +%OptimizeFunctionOnNextCall(opt); +opt();