From 673e434714ae3e71bb9b99ec6828ba921f361954 Mon Sep 17 00:00:00 2001 From: Benjamin Coe Date: Sat, 26 Jan 2019 10:06:01 -0800 Subject: [PATCH] deps: v8, cherry-pick 9365d09, aac2f8c, 47d34a3 Original commit message 9365d09: [coverage] Rework continuation counter handling This changes a few bits about how continuation counters are handled. It introduces a new mechanism that allows removal of a continuation range after it has been created. If coverage is enabled, we run a first post-processing pass on the AST immediately after parsing, which removes problematic continuation ranges in two situations: 1. nested continuation counters - only the outermost stays alive. 2. trailing continuation counters within a block-like structure are removed if the containing structure itself has a continuation. R=bmeurer@chromium.org, jgruber@chromium.org, yangguo@chromium.org Bug: v8:8381, v8:8539 Change-Id: I6bcaea5060d8c481d7bae099f6db9f993cc30ee3 Reviewed-on: https://chromium-review.googlesource.com/c/1339119 Reviewed-by: Yang Guo Reviewed-by: Leszek Swirski Reviewed-by: Georg Neis Commit-Queue: Jakob Gruber Cr-Commit-Position: refs/heads/master@{#58443} Refs: v8/v8@9365d09 Original commit message aac2f8c: [coverage] Filter out singleton ranges that alias full ranges Block coverage is based on a system of ranges that can either have both a start and end position, or only a start position (so-called singleton ranges). When formatting coverage information, singletons are expanded until the end of the immediate full parent range. E.g. in: {0, 10} // Full range. {5, -1} // Singleton range. the singleton range is expanded to {5, 10}. Singletons are produced mostly for continuation counters that track whether we execute past a specific language construct. Unfortunately, continuation counters can turn up in spots that confuse our post-processing. For example: if (true) { ... block1 ... } else { ... block2 ... } If block1 produces a continuation counter, it could end up with the same start position as the else-branch counter. Since we merge identical blocks, the else-branch could incorrectly end up with an execution count of one. We need to avoid merging such cases. A full range should always take precedence over a singleton range; a singleton range should never expand to completely fill a full range. An additional post-processing pass ensures this. Bug: v8:8237 Change-Id: Idb3ec7b2feddc0585313810b9c8be1e9f4ec64bf Reviewed-on: https://chromium-review.googlesource.com/c/1273095 Reviewed-by: Georg Neis Reviewed-by: Yang Guo Commit-Queue: Jakob Gruber Cr-Commit-Position: refs/heads/master@{#56531} Refs: v8/v8@aac2f8c deps: V8: backport 47d34a3 Original commit message: Revert "[coverage] change block range to avoid ambiguity." This reverts commit 471fef0469d04d7c487f3a08e81f3d77566a2f50. Reason for revert: A more general fix incoming at https://crrev.com/c/1273095. Original change's description: > [coverage] change block range to avoid ambiguity. > > By moving the block range end to left of closing bracket, > we can avoid ambiguity where an open-ended singleton range > could be both interpreted as inside the parent range, or > next to it. > > R=verwaest@chromium.org > > Bug: v8:8237 > Change-Id: Ibc9412b31efe900b6d8bff0d8fa8c52ddfbf460a > Reviewed-on: https://chromium-review.googlesource.com/1254127 > Reviewed-by: Georg Neis > Commit-Queue: Yang Guo > Cr-Commit-Position: refs/heads/master@{#56347} TBR=yangguo@chromium.org,neis@chromium.org,verwaest@chromium.org # Not skipping CQ checks because original CL landed > 1 day ago. Bug: v8:8237 Change-Id: I39310cf3c2f06a0d98ff314740aaeefbfffc0834 Reviewed-on: https://chromium-review.googlesource.com/c/1273096 Reviewed-by: Jakob Gruber Reviewed-by: Toon Verwaest Reviewed-by: Yang Guo Commit-Queue: Jakob Gruber Cr-Commit-Position: refs/heads/master@{#56513} Refs: https://github.com/v8/v8/commit/47d34a317e47bad86b68326607cd2e6de3901f3e PR-URL: https://github.com/nodejs/node/pull/25429 Backport-PR-URL: https://github.com/nodejs/node/pull/25728 Reviewed-By: Yang Guo Reviewed-By: Michael Dawson Reviewed-By: Anna Henningsen --- deps/v8/BUILD.gn | 2 + deps/v8/gypfiles/v8.gyp | 2 + deps/v8/src/ast/ast-source-ranges.h | 88 +++++++++- deps/v8/src/ast/source-range-ast-visitor.cc | 68 ++++++++ deps/v8/src/ast/source-range-ast-visitor.h | 49 ++++++ deps/v8/src/debug/debug-coverage.cc | 29 +--- deps/v8/src/interpreter/bytecode-generator.cc | 1 - .../src/interpreter/control-flow-builders.cc | 2 +- .../src/interpreter/control-flow-builders.h | 7 - deps/v8/src/parsing/parser.cc | 12 ++ .../cpu-profiler/coverage-block-expected.txt | 138 ++++------------ .../test/mjsunit/code-coverage-block-opt.js | 4 +- deps/v8/test/mjsunit/code-coverage-block.js | 156 +++++++++++++++--- 13 files changed, 392 insertions(+), 166 deletions(-) create mode 100644 deps/v8/src/ast/source-range-ast-visitor.cc create mode 100644 deps/v8/src/ast/source-range-ast-visitor.h diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index 712249eea5c428..b52d0325258a57 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -1570,6 +1570,8 @@ v8_source_set("v8_base") { "src/ast/prettyprinter.h", "src/ast/scopes.cc", "src/ast/scopes.h", + "src/ast/source-range-ast-visitor.cc", + "src/ast/source-range-ast-visitor.h", "src/ast/variables.cc", "src/ast/variables.h", "src/bailout-reason.cc", diff --git a/deps/v8/gypfiles/v8.gyp b/deps/v8/gypfiles/v8.gyp index 0c257025caeae4..9793d5cab5497c 100644 --- a/deps/v8/gypfiles/v8.gyp +++ b/deps/v8/gypfiles/v8.gyp @@ -548,6 +548,8 @@ '../src/ast/prettyprinter.h', '../src/ast/scopes.cc', '../src/ast/scopes.h', + '../src/ast/source-range-ast-visitor.cc', + '../src/ast/source-range-ast-visitor.h', '../src/ast/variables.cc', '../src/ast/variables.h', '../src/bailout-reason.cc', diff --git a/deps/v8/src/ast/ast-source-ranges.h b/deps/v8/src/ast/ast-source-ranges.h index cf7bab53daa607..b27c13945cde96 100644 --- a/deps/v8/src/ast/ast-source-ranges.h +++ b/deps/v8/src/ast/ast-source-ranges.h @@ -58,6 +58,8 @@ class AstNodeSourceRanges : public ZoneObject { public: virtual ~AstNodeSourceRanges() {} virtual SourceRange GetRange(SourceRangeKind kind) = 0; + virtual bool HasRange(SourceRangeKind kind) = 0; + virtual void RemoveContinuationRange() { UNREACHABLE(); } }; class BinaryOperationSourceRanges final : public AstNodeSourceRanges { @@ -65,11 +67,15 @@ class BinaryOperationSourceRanges final : public AstNodeSourceRanges { explicit BinaryOperationSourceRanges(const SourceRange& right_range) : right_range_(right_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { DCHECK_EQ(kind, SourceRangeKind::kRight); return right_range_; } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kRight; + } + private: SourceRange right_range_; }; @@ -79,11 +85,20 @@ class ContinuationSourceRanges : public AstNodeSourceRanges { explicit ContinuationSourceRanges(int32_t continuation_position) : continuation_position_(continuation_position) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { DCHECK_EQ(kind, SourceRangeKind::kContinuation); return SourceRange::OpenEnded(continuation_position_); } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kContinuation; + } + + void RemoveContinuationRange() override { + DCHECK(HasRange(SourceRangeKind::kContinuation)); + continuation_position_ = kNoSourcePosition; + } + private: int32_t continuation_position_; }; @@ -99,11 +114,15 @@ class CaseClauseSourceRanges final : public AstNodeSourceRanges { explicit CaseClauseSourceRanges(const SourceRange& body_range) : body_range_(body_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { DCHECK_EQ(kind, SourceRangeKind::kBody); return body_range_; } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kBody; + } + private: SourceRange body_range_; }; @@ -114,7 +133,7 @@ class ConditionalSourceRanges final : public AstNodeSourceRanges { const SourceRange& else_range) : then_range_(then_range), else_range_(else_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { switch (kind) { case SourceRangeKind::kThen: return then_range_; @@ -125,6 +144,10 @@ class ConditionalSourceRanges final : public AstNodeSourceRanges { } } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse; + } + private: SourceRange then_range_; SourceRange else_range_; @@ -136,13 +159,14 @@ class IfStatementSourceRanges final : public AstNodeSourceRanges { const SourceRange& else_range) : then_range_(then_range), else_range_(else_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { switch (kind) { case SourceRangeKind::kElse: return else_range_; case SourceRangeKind::kThen: return then_range_; case SourceRangeKind::kContinuation: { + if (!has_continuation_) return SourceRange::Empty(); const SourceRange& trailing_range = else_range_.IsEmpty() ? then_range_ : else_range_; return SourceRange::ContinuationOf(trailing_range); @@ -152,9 +176,20 @@ class IfStatementSourceRanges final : public AstNodeSourceRanges { } } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse || + kind == SourceRangeKind::kContinuation; + } + + void RemoveContinuationRange() override { + DCHECK(HasRange(SourceRangeKind::kContinuation)); + has_continuation_ = false; + } + private: SourceRange then_range_; SourceRange else_range_; + bool has_continuation_ = true; }; class IterationStatementSourceRanges final : public AstNodeSourceRanges { @@ -162,19 +197,31 @@ class IterationStatementSourceRanges final : public AstNodeSourceRanges { explicit IterationStatementSourceRanges(const SourceRange& body_range) : body_range_(body_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { switch (kind) { case SourceRangeKind::kBody: return body_range_; case SourceRangeKind::kContinuation: + if (!has_continuation_) return SourceRange::Empty(); return SourceRange::ContinuationOf(body_range_); default: UNREACHABLE(); } } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kBody || + kind == SourceRangeKind::kContinuation; + } + + void RemoveContinuationRange() override { + DCHECK(HasRange(SourceRangeKind::kContinuation)); + has_continuation_ = false; + } + private: SourceRange body_range_; + bool has_continuation_ = true; }; class JumpStatementSourceRanges final : public ContinuationSourceRanges { @@ -199,6 +246,7 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges { size_t RangeCount() const { return ranges_.size(); } SourceRange GetRange(SourceRangeKind kind) { UNREACHABLE(); } + bool HasRange(SourceRangeKind kind) { return false; } private: ZoneVector ranges_; @@ -227,19 +275,31 @@ class TryCatchStatementSourceRanges final : public AstNodeSourceRanges { explicit TryCatchStatementSourceRanges(const SourceRange& catch_range) : catch_range_(catch_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { switch (kind) { case SourceRangeKind::kCatch: return catch_range_; case SourceRangeKind::kContinuation: + if (!has_continuation_) return SourceRange::Empty(); return SourceRange::ContinuationOf(catch_range_); default: UNREACHABLE(); } } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kCatch || + kind == SourceRangeKind::kContinuation; + } + + void RemoveContinuationRange() override { + DCHECK(HasRange(SourceRangeKind::kContinuation)); + has_continuation_ = false; + } + private: SourceRange catch_range_; + bool has_continuation_ = true; }; class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges { @@ -247,19 +307,31 @@ class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges { explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range) : finally_range_(finally_range) {} - SourceRange GetRange(SourceRangeKind kind) { + SourceRange GetRange(SourceRangeKind kind) override { switch (kind) { case SourceRangeKind::kFinally: return finally_range_; case SourceRangeKind::kContinuation: + if (!has_continuation_) return SourceRange::Empty(); return SourceRange::ContinuationOf(finally_range_); default: UNREACHABLE(); } } + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kFinally || + kind == SourceRangeKind::kContinuation; + } + + void RemoveContinuationRange() override { + DCHECK(HasRange(SourceRangeKind::kContinuation)); + has_continuation_ = false; + } + private: SourceRange finally_range_; + bool has_continuation_ = true; }; // Maps ast node pointers to associated source ranges. The parser creates these diff --git a/deps/v8/src/ast/source-range-ast-visitor.cc b/deps/v8/src/ast/source-range-ast-visitor.cc new file mode 100644 index 00000000000000..b6acbddf0a6a5a --- /dev/null +++ b/deps/v8/src/ast/source-range-ast-visitor.cc @@ -0,0 +1,68 @@ +// 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. + +#include "src/ast/source-range-ast-visitor.h" + +#include "src/ast/ast-source-ranges.h" + +namespace v8 { +namespace internal { + +SourceRangeAstVisitor::SourceRangeAstVisitor(uintptr_t stack_limit, + Expression* root, + SourceRangeMap* source_range_map) + : AstTraversalVisitor(stack_limit, root), + source_range_map_(source_range_map) {} + +void SourceRangeAstVisitor::VisitBlock(Block* stmt) { + AstTraversalVisitor::VisitBlock(stmt); + ZonePtrList* stmts = stmt->statements(); + AstNodeSourceRanges* enclosingSourceRanges = source_range_map_->Find(stmt); + if (enclosingSourceRanges != nullptr) { + CHECK(enclosingSourceRanges->HasRange(SourceRangeKind::kContinuation)); + MaybeRemoveLastContinuationRange(stmts); + } +} + +void SourceRangeAstVisitor::VisitFunctionLiteral(FunctionLiteral* expr) { + AstTraversalVisitor::VisitFunctionLiteral(expr); + ZonePtrList* stmts = expr->body(); + MaybeRemoveLastContinuationRange(stmts); +} + +bool SourceRangeAstVisitor::VisitNode(AstNode* node) { + AstNodeSourceRanges* range = source_range_map_->Find(node); + + if (range == nullptr) return true; + if (!range->HasRange(SourceRangeKind::kContinuation)) return true; + + // Called in pre-order. In case of conflicting continuation ranges, only the + // outermost range may survive. + + SourceRange continuation = range->GetRange(SourceRangeKind::kContinuation); + if (continuation_positions_.find(continuation.start) != + continuation_positions_.end()) { + range->RemoveContinuationRange(); + } else { + continuation_positions_.emplace(continuation.start); + } + + return true; +} + +void SourceRangeAstVisitor::MaybeRemoveLastContinuationRange( + ZonePtrList* statements) { + if (statements == nullptr || statements->is_empty()) return; + + Statement* last_statement = statements->last(); + AstNodeSourceRanges* last_range = source_range_map_->Find(last_statement); + if (last_range == nullptr) return; + + if (last_range->HasRange(SourceRangeKind::kContinuation)) { + last_range->RemoveContinuationRange(); + } +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/ast/source-range-ast-visitor.h b/deps/v8/src/ast/source-range-ast-visitor.h new file mode 100644 index 00000000000000..4ea36a947f58e6 --- /dev/null +++ b/deps/v8/src/ast/source-range-ast-visitor.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef V8_AST_SOURCE_RANGE_AST_VISITOR_H_ +#define V8_AST_SOURCE_RANGE_AST_VISITOR_H_ + +#include + +#include "src/ast/ast-traversal-visitor.h" + +namespace v8 { +namespace internal { + +class SourceRangeMap; + +// Post-processes generated source ranges while the AST structure still exists. +// +// In particular, SourceRangeAstVisitor +// +// 1. deduplicates continuation source ranges, only keeping the outermost one. +// See also: https://crbug.com/v8/8539. +// +// 2. removes the source range associated with the final statement in a block +// or function body if the parent itself has a source range associated with it. +// See also: https://crbug.com/v8/8381. +class SourceRangeAstVisitor final + : public AstTraversalVisitor { + public: + SourceRangeAstVisitor(uintptr_t stack_limit, Expression* root, + SourceRangeMap* source_range_map); + + private: + friend class AstTraversalVisitor; + + void VisitBlock(Block* stmt); + void VisitFunctionLiteral(FunctionLiteral* expr); + bool VisitNode(AstNode* node); + + void MaybeRemoveLastContinuationRange(ZonePtrList* stmts); + + SourceRangeMap* source_range_map_ = nullptr; + std::unordered_set continuation_positions_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_AST_SOURCE_RANGE_AST_VISITOR_H_ diff --git a/deps/v8/src/debug/debug-coverage.cc b/deps/v8/src/debug/debug-coverage.cc index f8b716f7c910e9..d53dcf707579ff 100644 --- a/deps/v8/src/debug/debug-coverage.cc +++ b/deps/v8/src/debug/debug-coverage.cc @@ -233,25 +233,6 @@ bool HaveSameSourceRange(const CoverageBlock& lhs, const CoverageBlock& rhs) { return lhs.start == rhs.start && lhs.end == rhs.end; } -void MergeDuplicateSingletons(CoverageFunction* function) { - CoverageBlockIterator iter(function); - - while (iter.Next() && iter.HasNext()) { - CoverageBlock& block = iter.GetBlock(); - CoverageBlock& next_block = iter.GetNextBlock(); - - // Identical ranges should only occur through singleton ranges. Consider the - // ranges for `for (.) break;`: continuation ranges for both the `break` and - // `for` statements begin after the trailing semicolon. - // Such ranges are merged and keep the maximal execution count. - if (!HaveSameSourceRange(block, next_block)) continue; - - DCHECK_EQ(kNoSourcePosition, block.end); // Singleton range. - next_block.count = std::max(block.count, next_block.count); - iter.DeleteBlock(); - } -} - void MergeDuplicateRanges(CoverageFunction* function) { CoverageBlockIterator iter(function); @@ -424,8 +405,14 @@ void CollectBlockCoverage(CoverageFunction* function, SharedFunctionInfo* info, // If in binary mode, only report counts of 0/1. if (mode == debug::Coverage::kBlockBinary) ClampToBinary(function); - // Remove duplicate singleton ranges, keeping the max count. - MergeDuplicateSingletons(function); + // Remove singleton ranges with the same start position as a full range and + // throw away their counts. + // Singleton ranges are only intended to split existing full ranges and should + // never expand into a full range. Consider 'if (cond) { ... } else { ... }' + // as a problematic example; if the then-block produces a continuation + // singleton, it would incorrectly expand into the else range. + // For more context, see https://crbug.com/v8/8237. + FilterAliasedSingletons(function); // Remove singleton ranges with the same start position as a full range and // throw away their counts. diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc index 11a19443e11c26..25b1df08a8eee4 100644 --- a/deps/v8/src/interpreter/bytecode-generator.cc +++ b/deps/v8/src/interpreter/bytecode-generator.cc @@ -368,7 +368,6 @@ class BytecodeGenerator::ControlScopeForBreakable final protected: bool Execute(Command command, Statement* statement, int source_position) override { - control_builder_->set_needs_continuation_counter(); if (statement != statement_) return false; switch (command) { case CMD_BREAK: diff --git a/deps/v8/src/interpreter/control-flow-builders.cc b/deps/v8/src/interpreter/control-flow-builders.cc index bada935e4a22fb..6b1bdc34240d83 100644 --- a/deps/v8/src/interpreter/control-flow-builders.cc +++ b/deps/v8/src/interpreter/control-flow-builders.cc @@ -13,7 +13,7 @@ namespace interpreter { BreakableControlFlowBuilder::~BreakableControlFlowBuilder() { BindBreakTarget(); DCHECK(break_labels_.empty() || break_labels_.is_bound()); - if (block_coverage_builder_ != nullptr && needs_continuation_counter()) { + if (block_coverage_builder_ != nullptr) { block_coverage_builder_->IncrementBlockCounter( node_, SourceRangeKind::kContinuation); } diff --git a/deps/v8/src/interpreter/control-flow-builders.h b/deps/v8/src/interpreter/control-flow-builders.h index 405e81bc7632da..0bdcb615acaf1f 100644 --- a/deps/v8/src/interpreter/control-flow-builders.h +++ b/deps/v8/src/interpreter/control-flow-builders.h @@ -58,11 +58,6 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder BytecodeLabels* break_labels() { return &break_labels_; } - void set_needs_continuation_counter() { needs_continuation_counter_ = true; } - bool needs_continuation_counter() const { - return needs_continuation_counter_; - } - protected: void EmitJump(BytecodeLabels* labels); void EmitJumpIfTrue(BytecodeArrayBuilder::ToBooleanMode mode, @@ -81,7 +76,6 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder // A continuation counter (for block coverage) is needed e.g. when // encountering a break statement. AstNode* node_; - bool needs_continuation_counter_ = false; BlockCoverageBuilder* block_coverage_builder_; }; @@ -107,7 +101,6 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder { : BreakableControlFlowBuilder(builder, block_coverage_builder, node), continue_labels_(builder->zone()) { if (block_coverage_builder_ != nullptr) { - set_needs_continuation_counter(); block_coverage_body_slot_ = block_coverage_builder_->AllocateBlockCoverageSlot( node, SourceRangeKind::kBody); diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 41ff551091a1c6..831611b327fa3b 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -10,6 +10,7 @@ #include "src/ast/ast-function-literal-id-reindexer.h" #include "src/ast/ast-traversal-visitor.h" #include "src/ast/ast.h" +#include "src/ast/source-range-ast-visitor.h" #include "src/bailout-reason.h" #include "src/base/platform/platform.h" #include "src/char-predicates-inl.h" @@ -487,6 +488,15 @@ void MaybeResetCharacterStream(ParseInfo* info, FunctionLiteral* literal) { } } +void MaybeProcessSourceRanges(ParseInfo* parse_info, Expression* root, + uintptr_t stack_limit_) { + if (root != nullptr && parse_info->source_range_map() != nullptr) { + SourceRangeAstVisitor visitor(stack_limit_, root, + parse_info->source_range_map()); + visitor.Run(); + } +} + } // namespace FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { @@ -511,6 +521,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { scanner_.Initialize(); FunctionLiteral* result = DoParseProgram(isolate, info); MaybeResetCharacterStream(info, result); + MaybeProcessSourceRanges(info, result, stack_limit_); HandleSourceURLComments(isolate, info->script()); @@ -707,6 +718,7 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, FunctionLiteral* result = DoParseFunction(isolate, info, info->function_name()); MaybeResetCharacterStream(info, result); + MaybeProcessSourceRanges(info, result, stack_limit_); if (result != nullptr) { Handle inferred_name(shared_info->inferred_name(), isolate); result->set_inferred_name(inferred_name); diff --git a/deps/v8/test/inspector/cpu-profiler/coverage-block-expected.txt b/deps/v8/test/inspector/cpu-profiler/coverage-block-expected.txt index a631e72c69c8f7..cc48cfa85b320f 100644 --- a/deps/v8/test/inspector/cpu-profiler/coverage-block-expected.txt +++ b/deps/v8/test/inspector/cpu-profiler/coverage-block-expected.txt @@ -34,7 +34,7 @@ Running test: testPreciseCountCoverage [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -60,13 +60,8 @@ Running test: testPreciseCountCoverage } [2] : { count : 7 - endOffset : 71 - startOffset : 41 - } - [3] : { - count : 0 endOffset : 72 - startOffset : 71 + startOffset : 41 } ] } @@ -90,11 +85,6 @@ Running test: testPreciseCountCoverage endOffset : 208 startOffset : 177 } - [1] : { - count : 0 - endOffset : 207 - startOffset : 206 - } ] } ] @@ -104,7 +94,7 @@ Running test: testPreciseCountCoverage [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -116,7 +106,7 @@ Running test: testPreciseCountCoverage } ] scriptId : - url : + url : } ] } @@ -147,7 +137,7 @@ Running test: testPreciseCountCoverageIncremental [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -173,13 +163,8 @@ Running test: testPreciseCountCoverageIncremental } [2] : { count : 7 - endOffset : 71 - startOffset : 41 - } - [3] : { - count : 0 endOffset : 72 - startOffset : 71 + startOffset : 41 } ] } @@ -203,11 +188,6 @@ Running test: testPreciseCountCoverageIncremental endOffset : 208 startOffset : 177 } - [1] : { - count : 0 - endOffset : 207 - startOffset : 206 - } ] } ] @@ -267,13 +247,8 @@ Running test: testPreciseCountCoverageIncremental } [2] : { count : 10945 - endOffset : 71 - startOffset : 41 - } - [3] : { - count : 0 endOffset : 72 - startOffset : 71 + startOffset : 41 } ] } @@ -291,11 +266,6 @@ Running test: testPreciseCountCoverageIncremental endOffset : 156 startOffset : 143 } - [2] : { - count : 0 - endOffset : 174 - startOffset : 173 - } ] } ] @@ -305,7 +275,7 @@ Running test: testPreciseCountCoverageIncremental [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -317,12 +287,12 @@ Running test: testPreciseCountCoverageIncremental } ] scriptId : - url : + url : } [2] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -334,7 +304,7 @@ Running test: testPreciseCountCoverageIncremental } ] scriptId : - url : + url : } ] } @@ -403,7 +373,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -453,7 +423,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -465,7 +435,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled } ] scriptId : - url : + url : } ] } @@ -477,7 +447,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -527,7 +497,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -539,7 +509,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled } ] scriptId : - url : + url : } ] } @@ -563,7 +533,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -613,7 +583,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -625,7 +595,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled } ] scriptId : - url : + url : } ] } @@ -637,7 +607,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -687,7 +657,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : false ranges : [ [0] : { @@ -699,7 +669,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled } ] scriptId : - url : + url : } ] } @@ -721,7 +691,7 @@ Running test: testEnablePreciseCountCoverageAtPause [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -733,7 +703,7 @@ Running test: testEnablePreciseCountCoverageAtPause } ] scriptId : - url : + url : } ] } @@ -757,7 +727,7 @@ Running test: testPreciseBinaryCoverage [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -776,11 +746,6 @@ Running test: testPreciseBinaryCoverage endOffset : 73 startOffset : 1 } - [1] : { - count : 0 - endOffset : 72 - startOffset : 71 - } ] } [2] : { @@ -803,11 +768,6 @@ Running test: testPreciseBinaryCoverage endOffset : 208 startOffset : 177 } - [1] : { - count : 0 - endOffset : 207 - startOffset : 206 - } ] } ] @@ -862,7 +822,7 @@ Running test: testPreciseBinaryCoverage } [1] : { count : 1 - endOffset : 71 + endOffset : 72 startOffset : 32 } ] @@ -876,11 +836,6 @@ Running test: testPreciseBinaryCoverage endOffset : 175 startOffset : 74 } - [1] : { - count : 0 - endOffset : 174 - startOffset : 173 - } ] } ] @@ -890,7 +845,7 @@ Running test: testPreciseBinaryCoverage [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -902,12 +857,12 @@ Running test: testPreciseBinaryCoverage } ] scriptId : - url : + url : } [2] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -919,7 +874,7 @@ Running test: testPreciseBinaryCoverage } ] scriptId : - url : + url : } ] } @@ -950,7 +905,7 @@ Running test: testPreciseCountCoveragePartial [0] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -969,11 +924,6 @@ Running test: testPreciseCountCoveragePartial endOffset : 224 startOffset : 10 } - [1] : { - count : 0 - endOffset : 223 - startOffset : 222 - } ] } [2] : { @@ -985,11 +935,6 @@ Running test: testPreciseCountCoveragePartial endOffset : 176 startOffset : 31 } - [1] : { - count : 0 - endOffset : 175 - startOffset : 172 - } ] } [3] : { @@ -1001,11 +946,6 @@ Running test: testPreciseCountCoveragePartial endOffset : 172 startOffset : 64 } - [1] : { - count : 0 - endOffset : 171 - startOffset : 166 - } ] } [4] : { @@ -1017,11 +957,6 @@ Running test: testPreciseCountCoveragePartial endOffset : 166 startOffset : 99 } - [1] : { - count : 0 - endOffset : 165 - startOffset : 158 - } ] } [5] : { @@ -1068,11 +1003,6 @@ Running test: testPreciseCountCoveragePartial endOffset : 172 startOffset : 64 } - [1] : { - count : 0 - endOffset : 171 - startOffset : 166 - } ] } [1] : { @@ -1093,7 +1023,7 @@ Running test: testPreciseCountCoveragePartial [1] : { functions : [ [0] : { - functionName : + functionName : isBlockCoverage : true ranges : [ [0] : { @@ -1105,7 +1035,7 @@ Running test: testPreciseCountCoveragePartial } ] scriptId : - url : + url : } ] } diff --git a/deps/v8/test/mjsunit/code-coverage-block-opt.js b/deps/v8/test/mjsunit/code-coverage-block-opt.js index e02775bd45e234..5477a18dd5eac1 100644 --- a/deps/v8/test/mjsunit/code-coverage-block-opt.js +++ b/deps/v8/test/mjsunit/code-coverage-block-opt.js @@ -17,7 +17,7 @@ f(); f(); f(); f(); f(); f(); // 0150 `, [{"start":0,"end":199,"count":1}, {"start":0,"end":33,"count":4}, // TODO(jgruber): Invocation count is off. - {"start":25,"end":32,"count":16}, + {"start":25,"end":31,"count":16}, {"start":50,"end":76,"count":2}] // TODO(jgruber): Invocation count is off. ); @@ -39,7 +39,7 @@ TestCoverage("Partial coverage collection", }(); // 0400 `, [{"start":52,"end":153,"count":0}, - {"start":121,"end":152,"count":1}] + {"start":121,"end":137,"count":1}] ); %DebugToggleBlockCoverage(false); diff --git a/deps/v8/test/mjsunit/code-coverage-block.js b/deps/v8/test/mjsunit/code-coverage-block.js index 8cbb2969f7d050..1291a50d978ceb 100644 --- a/deps/v8/test/mjsunit/code-coverage-block.js +++ b/deps/v8/test/mjsunit/code-coverage-block.js @@ -246,8 +246,7 @@ function g() {} // 0000 {"start":224,"end":237,"count":12}, {"start":273,"end":277,"count":0}, {"start":412,"end":416,"count":12}, - {"start":462,"end":475,"count":12}, - {"start":620,"end":622,"count":0}] + {"start":462,"end":475,"count":12}] ); TestCoverage( @@ -357,7 +356,7 @@ TestCoverage( {"start":219,"end":222,"count":0}, {"start":254,"end":274,"count":0}, {"start":369,"end":372,"count":0}, - {"start":390,"end":404,"count":0}, + {"start":403,"end":404,"count":0}, {"start":513,"end":554,"count":0}] ); @@ -376,10 +375,10 @@ TestCoverage("try/catch/finally statements with early return", [{"start":0,"end":449,"count":1}, {"start":1,"end":151,"count":1}, {"start":67,"end":70,"count":0}, - {"start":89,"end":150,"count":0}, + {"start":91,"end":150,"count":0}, {"start":201,"end":401,"count":1}, {"start":267,"end":270,"count":0}, - {"start":319,"end":400,"count":0}] + {"start":321,"end":400,"count":0}] ); TestCoverage( @@ -411,11 +410,11 @@ TestCoverage( [{"start":0,"end":1099,"count":1}, {"start":1,"end":151,"count":1}, {"start":67,"end":70,"count":0}, - {"start":89,"end":150,"count":0}, + {"start":91,"end":150,"count":0}, {"start":201,"end":351,"count":1}, - {"start":284,"end":350,"count":0}, + {"start":286,"end":350,"count":0}, {"start":401,"end":701,"count":1}, - {"start":569,"end":700,"count":0}, + {"start":603,"end":700,"count":0}, {"start":561,"end":568,"count":0}, // TODO(jgruber): Sorting. {"start":751,"end":1051,"count":1}, {"start":817,"end":820,"count":0}, @@ -437,7 +436,7 @@ TestCoverage( [{"start":0,"end":399,"count":1}, {"start":1,"end":351,"count":1}, {"start":154,"end":204,"count":0}, - {"start":226,"end":303,"count":0}] + {"start":226,"end":350,"count":0}] ); TestCoverage( @@ -467,11 +466,7 @@ TestCoverage( [{"start":0,"end":999,"count":1}, {"start":1,"end":951,"count":1}, {"start":152,"end":202,"count":0}, - {"start":285,"end":353,"count":0}, - {"start":472,"end":503,"count":0}, - {"start":626,"end":653,"count":0}, - {"start":768,"end":803,"count":0}, - {"start":867,"end":869,"count":0}] + {"start":285,"end":353,"count":0}] ); TestCoverage( @@ -496,11 +491,8 @@ TestCoverage( [{"start":0,"end":749,"count":1}, {"start":1,"end":701,"count":1}, {"start":87,"end":153,"count":2}, - {"start":125,"end":153,"count":0}, {"start":271,"end":403,"count":2}, - {"start":379,"end":403,"count":0}, - {"start":509,"end":653,"count":2}, - {"start":621,"end":653,"count":0}] + {"start":509,"end":653,"count":2}] ); TestCoverage( @@ -570,6 +562,7 @@ try { // 0200 } catch (e) {} // 0450 `, [{"start":0,"end":499,"count":1}, + {"start":451,"end":452,"count":0}, {"start":12,"end":101,"count":3}, {"start":60,"end":100,"count":0}, {"start":264,"end":353,"count":3}, @@ -648,6 +641,7 @@ try { // 0200 } catch (e) {} // 0450 `, [{"start":0,"end":499,"count":1}, + {"start":451,"end":452,"count":0}, {"start":12,"end":101,"count":3}, {"start":65,"end":100,"count":0}, {"start":264,"end":353,"count":3}, @@ -846,8 +840,7 @@ Util.escape("foo.bar"); // 0400 `, [{"start":0,"end":449,"count":1}, {"start":64,"end":351,"count":1}, - {"start":112,"end":203,"count":0}, - {"start":268,"end":350,"count":0}] + {"start":112,"end":203,"count":0}] ); TestCoverage( @@ -879,17 +872,136 @@ TestCoverage( {"start":1,"end":151,"count":1}, {"start":118,"end":137,"count":0}, {"start":201,"end":351,"count":1}, - {"start":277,"end":318,"count":0}, + {"start":279,"end":318,"count":0}, {"start":401,"end":525,"count":1}, {"start":475,"end":486,"count":0}, {"start":503,"end":523,"count":0}, {"start":551,"end":651,"count":1}, {"start":622,"end":639,"count":0}, {"start":701,"end":801,"count":1}, - {"start":773,"end":791,"count":0}, + {"start":774,"end":791,"count":0}, {"start":851,"end":1001,"count":1}, {"start":920,"end":928,"count":0}, {"start":929,"end":965,"count":0}] ); +TestCoverage( +"terminal break statement", +` +while (true) { // 0000 + const b = false // 0050 + break // 0100 +} // 0150 +let stop = false // 0200 +while (true) { // 0250 + if (stop) { // 0300 + break // 0350 + } // 0400 + stop = true // 0450 +} // 0500 +`, +[{"start":0,"end":549,"count":1}, + {"start":263,"end":501,"count":2}, + {"start":312,"end":501,"count":1}] +); + +TestCoverage( +"terminal return statement", +` +function a () { // 0000 + const b = false // 0050 + return 1 // 0100 +} // 0150 +const b = (early) => { // 0200 + if (early) { // 0250 + return 2 // 0300 + } // 0350 + return 3 // 0400 +} // 0450 +const c = () => { // 0500 + if (true) { // 0550 + return // 0600 + } // 0650 +} // 0700 +a(); b(false); b(true); c() // 0750 +`, +[{"start":0,"end":799,"count":1}, + {"start":0,"end":151,"count":1}, + {"start":210,"end":451,"count":2}, + {"start":263,"end":450,"count":1}, + {"start":510,"end":701,"count":1}] +); + +TestCoverage( +"terminal blocks", +` +function a () { // 0000 + { // 0050 + return 'a' // 0100 + } // 0150 +} // 0200 +function b () { // 0250 + { // 0300 + { // 0350 + return 'b' // 0400 + } // 0450 + } // 0500 +} // 0550 +a(); b() // 0600 +`, +[{"start":0,"end":649,"count":1}, + {"start":0,"end":201,"count":1}, + {"start":250,"end":551,"count":1}] +); + +TestCoverage( +"terminal if statements", +` +function a (branch) { // 0000 + if (branch) { // 0050 + return 'a' // 0100 + } else { // 0150 + return 'b' // 0200 + } // 0250 +} // 0300 +function b (branch) { // 0350 + if (branch) { // 0400 + if (branch) { // 0450 + return 'c' // 0500 + } // 0550 + } // 0600 +} // 0650 +function c (branch) { // 0700 + if (branch) { // 0750 + return 'c' // 0800 + } else { // 0850 + return 'd' // 0900 + } // 0950 +} // 1000 +function d (branch) { // 1050 + if (branch) { // 1100 + if (!branch) { // 1150 + return 'e' // 1200 + } else { // 1250 + return 'f' // 1300 + } // 1350 + } else { // 1400 + // noop // 1450 + } // 1500 +} // 1550 +a(true); a(false); b(true); b(false) // 1600 +c(true); d(true); // 1650 +`, +[{"start":0,"end":1699,"count":1}, + {"start":0,"end":301,"count":2}, + {"start":64,"end":253,"count":1}, + {"start":350,"end":651,"count":2}, + {"start":414,"end":603,"count":1}, + {"start":700,"end":1001,"count":1}, + {"start":853,"end":953,"count":0}, + {"start":1050,"end":1551,"count":1}, + {"start":1167,"end":1255,"count":0}, + {"start":1403,"end":1503,"count":0}] +); + %DebugToggleBlockCoverage(false);