[coverage] Move source ranges out of AST
This CL moves collected source range information out of AST nodes and into a side table stored on ParseInfo. The side table is only created if block coverage is enabled, so there's almost no memory overhead in the standard case. Change-Id: I41871b8425ebbc6217d82d3ad26b5fc9e5d68ecb Reviewed-on: https://chromium-review.googlesource.com/566808 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#46590}
This commit is contained in:
parent
f720d024dc
commit
645a1ea5dd
1
BUILD.gn
1
BUILD.gn
@ -1152,6 +1152,7 @@ v8_source_set("v8_base") {
|
||||
"src/ast/ast-function-literal-id-reindexer.h",
|
||||
"src/ast/ast-numbering.cc",
|
||||
"src/ast/ast-numbering.h",
|
||||
"src/ast/ast-source-ranges.h",
|
||||
"src/ast/ast-traversal-visitor.h",
|
||||
"src/ast/ast-value-factory.cc",
|
||||
"src/ast/ast-value-factory.h",
|
||||
|
206
src/ast/ast-source-ranges.h
Normal file
206
src/ast/ast-source-ranges.h
Normal file
@ -0,0 +1,206 @@
|
||||
// Copyright 2017 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_AST_SOURCE_RANGES_H_
|
||||
#define V8_AST_AST_SOURCE_RANGES_H_
|
||||
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Specifies a range within the source code. {start} is 0-based and inclusive,
|
||||
// {end} is 0-based and exclusive.
|
||||
struct SourceRange {
|
||||
SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {}
|
||||
SourceRange(int start, int end) : start(start), end(end) {}
|
||||
bool IsEmpty() const { return start == kNoSourcePosition; }
|
||||
static SourceRange Empty() { return SourceRange(); }
|
||||
static SourceRange OpenEnded(int32_t start) {
|
||||
return SourceRange(start, kNoSourcePosition);
|
||||
}
|
||||
static SourceRange ContinuationOf(const SourceRange& that) {
|
||||
return that.IsEmpty() ? Empty() : OpenEnded(that.end);
|
||||
}
|
||||
int32_t start, end;
|
||||
};
|
||||
|
||||
// The list of ast node kinds that have associated source ranges.
|
||||
#define AST_SOURCE_RANGE_LIST(V) \
|
||||
V(CaseClause) \
|
||||
V(IfStatement) \
|
||||
V(IterationStatement) \
|
||||
V(JumpStatement) \
|
||||
V(SwitchStatement) \
|
||||
V(Throw) \
|
||||
V(TryCatchStatement) \
|
||||
V(TryFinallyStatement)
|
||||
|
||||
enum class SourceRangeKind {
|
||||
kBody,
|
||||
kCatch,
|
||||
kContinuation,
|
||||
kElse,
|
||||
kFinally,
|
||||
kThen,
|
||||
};
|
||||
|
||||
class AstNodeSourceRanges : public ZoneObject {
|
||||
public:
|
||||
virtual ~AstNodeSourceRanges() {}
|
||||
virtual SourceRange GetRange(SourceRangeKind kind) = 0;
|
||||
};
|
||||
|
||||
class ContinuationSourceRanges : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit ContinuationSourceRanges(int32_t continuation_position)
|
||||
: continuation_position_(continuation_position) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
DCHECK(kind == SourceRangeKind::kContinuation);
|
||||
return SourceRange::OpenEnded(continuation_position_);
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t continuation_position_;
|
||||
};
|
||||
|
||||
class CaseClauseSourceRanges final : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit CaseClauseSourceRanges(const SourceRange& body_range)
|
||||
: body_range_(body_range) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
DCHECK(kind == SourceRangeKind::kBody);
|
||||
return body_range_;
|
||||
}
|
||||
|
||||
private:
|
||||
SourceRange body_range_;
|
||||
};
|
||||
|
||||
class IfStatementSourceRanges final : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit IfStatementSourceRanges(const SourceRange& then_range,
|
||||
const SourceRange& else_range)
|
||||
: then_range_(then_range), else_range_(else_range) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
switch (kind) {
|
||||
case SourceRangeKind::kElse:
|
||||
return else_range_;
|
||||
case SourceRangeKind::kThen:
|
||||
return then_range_;
|
||||
case SourceRangeKind::kContinuation: {
|
||||
const SourceRange& trailing_range =
|
||||
else_range_.IsEmpty() ? then_range_ : else_range_;
|
||||
return SourceRange::ContinuationOf(trailing_range);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SourceRange then_range_;
|
||||
SourceRange else_range_;
|
||||
};
|
||||
|
||||
class IterationStatementSourceRanges final : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit IterationStatementSourceRanges(const SourceRange& body_range)
|
||||
: body_range_(body_range) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
switch (kind) {
|
||||
case SourceRangeKind::kBody:
|
||||
return body_range_;
|
||||
case SourceRangeKind::kContinuation:
|
||||
return SourceRange::ContinuationOf(body_range_);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SourceRange body_range_;
|
||||
};
|
||||
|
||||
class JumpStatementSourceRanges final : public ContinuationSourceRanges {
|
||||
public:
|
||||
explicit JumpStatementSourceRanges(int32_t continuation_position)
|
||||
: ContinuationSourceRanges(continuation_position) {}
|
||||
};
|
||||
|
||||
class SwitchStatementSourceRanges final : public ContinuationSourceRanges {
|
||||
public:
|
||||
explicit SwitchStatementSourceRanges(int32_t continuation_position)
|
||||
: ContinuationSourceRanges(continuation_position) {}
|
||||
};
|
||||
|
||||
class ThrowSourceRanges final : public ContinuationSourceRanges {
|
||||
public:
|
||||
explicit ThrowSourceRanges(int32_t continuation_position)
|
||||
: ContinuationSourceRanges(continuation_position) {}
|
||||
};
|
||||
|
||||
class TryCatchStatementSourceRanges final : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit TryCatchStatementSourceRanges(const SourceRange& catch_range)
|
||||
: catch_range_(catch_range) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
DCHECK(kind == SourceRangeKind::kCatch);
|
||||
return catch_range_;
|
||||
}
|
||||
|
||||
private:
|
||||
SourceRange catch_range_;
|
||||
};
|
||||
|
||||
class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges {
|
||||
public:
|
||||
explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range)
|
||||
: finally_range_(finally_range) {}
|
||||
|
||||
SourceRange GetRange(SourceRangeKind kind) {
|
||||
DCHECK(kind == SourceRangeKind::kFinally);
|
||||
return finally_range_;
|
||||
}
|
||||
|
||||
private:
|
||||
SourceRange finally_range_;
|
||||
};
|
||||
|
||||
// Maps ast node pointers to associated source ranges. The parser creates these
|
||||
// mappings and the bytecode generator consumes them.
|
||||
class SourceRangeMap final : public ZoneObject {
|
||||
public:
|
||||
explicit SourceRangeMap(Zone* zone) : map_(zone) {}
|
||||
|
||||
AstNodeSourceRanges* Find(AstNode* node) {
|
||||
auto it = map_.find(node);
|
||||
if (it == map_.end()) return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Type-checked insertion.
|
||||
#define DEFINE_MAP_INSERT(type) \
|
||||
void Insert(type* node, type##SourceRanges* ranges) { \
|
||||
map_.emplace(node, ranges); \
|
||||
}
|
||||
AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT)
|
||||
#undef DEFINE_MAP_INSERT
|
||||
|
||||
private:
|
||||
ZoneMap<AstNode*, AstNodeSourceRanges*> map_;
|
||||
};
|
||||
|
||||
#undef AST_SOURCE_RANGE_LIST
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_AST_AST_SOURCE_RANGES_H_
|
@ -1068,11 +1068,8 @@ Call::CallType Call::GetCallType() const {
|
||||
}
|
||||
|
||||
CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
|
||||
int pos, const SourceRange& clause_range)
|
||||
: Expression(pos, kCaseClause),
|
||||
label_(label),
|
||||
statements_(statements),
|
||||
clause_range_(clause_range) {}
|
||||
int pos)
|
||||
: Expression(pos, kCaseClause), label_(label), statements_(statements) {}
|
||||
|
||||
void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
||||
LanguageMode language_mode,
|
||||
|
202
src/ast/ast.h
202
src/ast/ast.h
@ -182,22 +182,6 @@ class AstProperties final BASE_EMBEDDED {
|
||||
|
||||
DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags)
|
||||
|
||||
// Specifies a range within the source code. {start} is 0-based and inclusive,
|
||||
// {end} is 0-based and exclusive.
|
||||
struct SourceRange {
|
||||
SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {}
|
||||
SourceRange(int start, int end) : start(start), end(end) {}
|
||||
bool IsEmpty() const { return start == kNoSourcePosition; }
|
||||
static SourceRange Empty() { return SourceRange(); }
|
||||
static SourceRange OpenEnded(int32_t start) {
|
||||
return SourceRange(start, kNoSourcePosition);
|
||||
}
|
||||
static SourceRange ContinuationOf(const SourceRange& that) {
|
||||
return that.IsEmpty() ? Empty() : OpenEnded(that.end);
|
||||
}
|
||||
int32_t start, end;
|
||||
};
|
||||
|
||||
class AstNode: public ZoneObject {
|
||||
public:
|
||||
#define DECLARE_TYPE_ENUM(type) k##type,
|
||||
@ -502,13 +486,6 @@ class IterationStatement : public BreakableStatement {
|
||||
Statement* body() const { return body_; }
|
||||
void set_body(Statement* s) { body_ = s; }
|
||||
|
||||
SourceRange body_range() const { return body_range_; }
|
||||
|
||||
// The range starting after the iteration body, used for block coverage.
|
||||
SourceRange continuation_range() const {
|
||||
return SourceRange::ContinuationOf(body_range_);
|
||||
}
|
||||
|
||||
int suspend_count() const { return suspend_count_; }
|
||||
int first_suspend_id() const { return first_suspend_id_; }
|
||||
void set_suspend_count(int suspend_count) { suspend_count_ = suspend_count; }
|
||||
@ -530,10 +507,7 @@ class IterationStatement : public BreakableStatement {
|
||||
body_(NULL),
|
||||
suspend_count_(0),
|
||||
first_suspend_id_(0) {}
|
||||
void Initialize(Statement* body, const SourceRange& body_range = {}) {
|
||||
body_ = body;
|
||||
body_range_ = body_range;
|
||||
}
|
||||
void Initialize(Statement* body) { body_ = body; }
|
||||
|
||||
static const uint8_t kNextBitFieldIndex =
|
||||
BreakableStatement::kNextBitFieldIndex;
|
||||
@ -541,7 +515,6 @@ class IterationStatement : public BreakableStatement {
|
||||
private:
|
||||
BailoutId osr_id_;
|
||||
Statement* body_;
|
||||
SourceRange body_range_;
|
||||
int suspend_count_;
|
||||
int first_suspend_id_;
|
||||
};
|
||||
@ -549,9 +522,8 @@ class IterationStatement : public BreakableStatement {
|
||||
|
||||
class DoWhileStatement final : public IterationStatement {
|
||||
public:
|
||||
void Initialize(Expression* cond, Statement* body,
|
||||
const SourceRange& body_range = {}) {
|
||||
IterationStatement::Initialize(body, body_range);
|
||||
void Initialize(Expression* cond, Statement* body) {
|
||||
IterationStatement::Initialize(body);
|
||||
cond_ = cond;
|
||||
}
|
||||
|
||||
@ -570,9 +542,8 @@ class DoWhileStatement final : public IterationStatement {
|
||||
|
||||
class WhileStatement final : public IterationStatement {
|
||||
public:
|
||||
void Initialize(Expression* cond, Statement* body,
|
||||
const SourceRange& body_range = {}) {
|
||||
IterationStatement::Initialize(body, body_range);
|
||||
void Initialize(Expression* cond, Statement* body) {
|
||||
IterationStatement::Initialize(body);
|
||||
cond_ = cond;
|
||||
}
|
||||
|
||||
@ -592,8 +563,8 @@ class WhileStatement final : public IterationStatement {
|
||||
class ForStatement final : public IterationStatement {
|
||||
public:
|
||||
void Initialize(Statement* init, Expression* cond, Statement* next,
|
||||
Statement* body, const SourceRange& body_range = {}) {
|
||||
IterationStatement::Initialize(body, body_range);
|
||||
Statement* body) {
|
||||
IterationStatement::Initialize(body);
|
||||
init_ = init;
|
||||
cond_ = cond;
|
||||
next_ = next;
|
||||
@ -776,16 +747,8 @@ class JumpStatement : public Statement {
|
||||
public:
|
||||
bool IsJump() const { return true; }
|
||||
|
||||
// The range starting after the jump statement, used for block coverage.
|
||||
SourceRange continuation_range() const {
|
||||
return SourceRange::OpenEnded(continuation_pos_);
|
||||
}
|
||||
|
||||
protected:
|
||||
JumpStatement(int pos, NodeType type, int32_t continuation_pos)
|
||||
: Statement(pos, type), continuation_pos_(continuation_pos) {}
|
||||
|
||||
int32_t continuation_pos_;
|
||||
JumpStatement(int pos, NodeType type) : Statement(pos, type) {}
|
||||
};
|
||||
|
||||
|
||||
@ -796,9 +759,8 @@ class ContinueStatement final : public JumpStatement {
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
ContinueStatement(IterationStatement* target, int pos, int continuation_pos)
|
||||
: JumpStatement(pos, kContinueStatement, continuation_pos),
|
||||
target_(target) {}
|
||||
ContinueStatement(IterationStatement* target, int pos)
|
||||
: JumpStatement(pos, kContinueStatement), target_(target) {}
|
||||
|
||||
IterationStatement* target_;
|
||||
};
|
||||
@ -811,9 +773,8 @@ class BreakStatement final : public JumpStatement {
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
BreakStatement(BreakableStatement* target, int pos, int continuation_pos)
|
||||
: JumpStatement(pos, kBreakStatement, continuation_pos),
|
||||
target_(target) {}
|
||||
BreakStatement(BreakableStatement* target, int pos)
|
||||
: JumpStatement(pos, kBreakStatement), target_(target) {}
|
||||
|
||||
BreakableStatement* target_;
|
||||
};
|
||||
@ -831,10 +792,8 @@ class ReturnStatement final : public JumpStatement {
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
ReturnStatement(Expression* expression, Type type, int pos,
|
||||
int continuation_pos)
|
||||
: JumpStatement(pos, kReturnStatement, continuation_pos),
|
||||
expression_(expression) {
|
||||
ReturnStatement(Expression* expression, Type type, int pos)
|
||||
: JumpStatement(pos, kReturnStatement), expression_(expression) {
|
||||
bit_field_ |= TypeField::encode(type);
|
||||
}
|
||||
|
||||
@ -880,8 +839,6 @@ class CaseClause final : public Expression {
|
||||
Label* body_target() { return &body_target_; }
|
||||
ZoneList<Statement*>* statements() const { return statements_; }
|
||||
|
||||
SourceRange clause_range() const { return clause_range_; }
|
||||
|
||||
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
|
||||
FeedbackSlotCache* cache);
|
||||
|
||||
@ -890,24 +847,20 @@ class CaseClause final : public Expression {
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos,
|
||||
const SourceRange& clause_range);
|
||||
CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
|
||||
|
||||
FeedbackSlot feedback_slot_;
|
||||
Expression* label_;
|
||||
Label body_target_;
|
||||
ZoneList<Statement*>* statements_;
|
||||
SourceRange clause_range_;
|
||||
};
|
||||
|
||||
|
||||
class SwitchStatement final : public BreakableStatement {
|
||||
public:
|
||||
void Initialize(Expression* tag, ZoneList<CaseClause*>* cases,
|
||||
int32_t continuation_pos) {
|
||||
void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
|
||||
tag_ = tag;
|
||||
cases_ = cases;
|
||||
continuation_pos_ = continuation_pos;
|
||||
}
|
||||
|
||||
Expression* tag() const { return tag_; }
|
||||
@ -915,23 +868,16 @@ class SwitchStatement final : public BreakableStatement {
|
||||
|
||||
void set_tag(Expression* t) { tag_ = t; }
|
||||
|
||||
// The range starting after the switch body, used for block coverage.
|
||||
SourceRange continuation_range() const {
|
||||
return SourceRange::OpenEnded(continuation_pos_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
SwitchStatement(ZoneList<const AstRawString*>* labels, int pos)
|
||||
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, kSwitchStatement),
|
||||
tag_(NULL),
|
||||
cases_(NULL),
|
||||
continuation_pos_(kNoSourcePosition) {}
|
||||
cases_(NULL) {}
|
||||
|
||||
Expression* tag_;
|
||||
ZoneList<CaseClause*>* cases_;
|
||||
int32_t continuation_pos_;
|
||||
};
|
||||
|
||||
|
||||
@ -949,16 +895,6 @@ class IfStatement final : public Statement {
|
||||
Statement* then_statement() const { return then_statement_; }
|
||||
Statement* else_statement() const { return else_statement_; }
|
||||
|
||||
SourceRange then_range() const { return then_range_; }
|
||||
SourceRange else_range() const { return else_range_; }
|
||||
|
||||
// The range starting after the if body, used for block coverage.
|
||||
SourceRange continuation_range() const {
|
||||
SourceRange trailing_range =
|
||||
HasElseStatement() ? else_range() : then_range();
|
||||
return SourceRange::ContinuationOf(trailing_range);
|
||||
}
|
||||
|
||||
void set_condition(Expression* e) { condition_ = e; }
|
||||
void set_then_statement(Statement* s) { then_statement_ = s; }
|
||||
void set_else_statement(Statement* s) { else_statement_ = s; }
|
||||
@ -972,20 +908,15 @@ class IfStatement final : public Statement {
|
||||
friend class AstNodeFactory;
|
||||
|
||||
IfStatement(Expression* condition, Statement* then_statement,
|
||||
Statement* else_statement, int pos, SourceRange then_range,
|
||||
SourceRange else_range)
|
||||
Statement* else_statement, int pos)
|
||||
: Statement(pos, kIfStatement),
|
||||
condition_(condition),
|
||||
then_statement_(then_statement),
|
||||
else_statement_(else_statement),
|
||||
then_range_(then_range),
|
||||
else_range_(else_range) {}
|
||||
else_statement_(else_statement) {}
|
||||
|
||||
Expression* condition_;
|
||||
Statement* then_statement_;
|
||||
Statement* else_statement_;
|
||||
SourceRange then_range_;
|
||||
SourceRange else_range_;
|
||||
};
|
||||
|
||||
|
||||
@ -1009,8 +940,6 @@ class TryCatchStatement final : public TryStatement {
|
||||
Block* catch_block() const { return catch_block_; }
|
||||
void set_catch_block(Block* b) { catch_block_ = b; }
|
||||
|
||||
SourceRange catch_range() const { return catch_range_; }
|
||||
|
||||
// Prediction of whether exceptions thrown into the handler for this try block
|
||||
// will be caught.
|
||||
//
|
||||
@ -1063,18 +992,15 @@ class TryCatchStatement final : public TryStatement {
|
||||
friend class AstNodeFactory;
|
||||
|
||||
TryCatchStatement(Block* try_block, Scope* scope, Block* catch_block,
|
||||
HandlerTable::CatchPrediction catch_prediction, int pos,
|
||||
const SourceRange& catch_range)
|
||||
HandlerTable::CatchPrediction catch_prediction, int pos)
|
||||
: TryStatement(try_block, pos, kTryCatchStatement),
|
||||
scope_(scope),
|
||||
catch_block_(catch_block),
|
||||
catch_prediction_(catch_prediction),
|
||||
catch_range_(catch_range) {}
|
||||
catch_prediction_(catch_prediction) {}
|
||||
|
||||
Scope* scope_;
|
||||
Block* catch_block_;
|
||||
HandlerTable::CatchPrediction catch_prediction_;
|
||||
SourceRange catch_range_;
|
||||
};
|
||||
|
||||
|
||||
@ -1083,19 +1009,14 @@ class TryFinallyStatement final : public TryStatement {
|
||||
Block* finally_block() const { return finally_block_; }
|
||||
void set_finally_block(Block* b) { finally_block_ = b; }
|
||||
|
||||
SourceRange finally_range() const { return finally_range_; }
|
||||
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
TryFinallyStatement(Block* try_block, Block* finally_block, int pos,
|
||||
const SourceRange& finally_range)
|
||||
TryFinallyStatement(Block* try_block, Block* finally_block, int pos)
|
||||
: TryStatement(try_block, pos, kTryFinallyStatement),
|
||||
finally_block_(finally_block),
|
||||
finally_range_(finally_range) {}
|
||||
finally_block_(finally_block) {}
|
||||
|
||||
Block* finally_block_;
|
||||
SourceRange finally_range_;
|
||||
};
|
||||
|
||||
|
||||
@ -2455,21 +2376,13 @@ class Throw final : public Expression {
|
||||
Expression* exception() const { return exception_; }
|
||||
void set_exception(Expression* e) { exception_ = e; }
|
||||
|
||||
// The range starting after the throw statement, used for block coverage.
|
||||
SourceRange continuation_range() const {
|
||||
return SourceRange::OpenEnded(continuation_pos_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
Throw(Expression* exception, int pos, int32_t continuation_pos)
|
||||
: Expression(pos, kThrow),
|
||||
exception_(exception),
|
||||
continuation_pos_(continuation_pos) {}
|
||||
Throw(Expression* exception, int pos)
|
||||
: Expression(pos, kThrow), exception_(exception) {}
|
||||
|
||||
Expression* exception_;
|
||||
int32_t continuation_pos_;
|
||||
};
|
||||
|
||||
|
||||
@ -3206,29 +3119,22 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
return new (zone_) ExpressionStatement(expression, pos);
|
||||
}
|
||||
|
||||
ContinueStatement* NewContinueStatement(
|
||||
IterationStatement* target, int pos,
|
||||
int continuation_pos = kNoSourcePosition) {
|
||||
return new (zone_) ContinueStatement(target, pos, continuation_pos);
|
||||
ContinueStatement* NewContinueStatement(IterationStatement* target, int pos) {
|
||||
return new (zone_) ContinueStatement(target, pos);
|
||||
}
|
||||
|
||||
BreakStatement* NewBreakStatement(BreakableStatement* target, int pos,
|
||||
int continuation_pos = kNoSourcePosition) {
|
||||
return new (zone_) BreakStatement(target, pos, continuation_pos);
|
||||
BreakStatement* NewBreakStatement(BreakableStatement* target, int pos) {
|
||||
return new (zone_) BreakStatement(target, pos);
|
||||
}
|
||||
|
||||
ReturnStatement* NewReturnStatement(
|
||||
Expression* expression, int pos,
|
||||
int continuation_pos = kNoSourcePosition) {
|
||||
return new (zone_) ReturnStatement(expression, ReturnStatement::kNormal,
|
||||
pos, continuation_pos);
|
||||
ReturnStatement* NewReturnStatement(Expression* expression, int pos) {
|
||||
return new (zone_)
|
||||
ReturnStatement(expression, ReturnStatement::kNormal, pos);
|
||||
}
|
||||
|
||||
ReturnStatement* NewAsyncReturnStatement(
|
||||
Expression* expression, int pos,
|
||||
int continuation_pos = kNoSourcePosition) {
|
||||
return new (zone_) ReturnStatement(
|
||||
expression, ReturnStatement::kAsyncReturn, pos, continuation_pos);
|
||||
ReturnStatement* NewAsyncReturnStatement(Expression* expression, int pos) {
|
||||
return new (zone_)
|
||||
ReturnStatement(expression, ReturnStatement::kAsyncReturn, pos);
|
||||
}
|
||||
|
||||
WithStatement* NewWithStatement(Scope* scope,
|
||||
@ -3239,18 +3145,15 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
}
|
||||
|
||||
IfStatement* NewIfStatement(Expression* condition, Statement* then_statement,
|
||||
Statement* else_statement, int pos,
|
||||
SourceRange then_range = {},
|
||||
SourceRange else_range = {}) {
|
||||
return new (zone_) IfStatement(condition, then_statement, else_statement,
|
||||
pos, then_range, else_range);
|
||||
Statement* else_statement, int pos) {
|
||||
return new (zone_)
|
||||
IfStatement(condition, then_statement, else_statement, pos);
|
||||
}
|
||||
|
||||
TryCatchStatement* NewTryCatchStatement(Block* try_block, Scope* scope,
|
||||
Block* catch_block, int pos,
|
||||
const SourceRange catch_range = {}) {
|
||||
return new (zone_) TryCatchStatement(
|
||||
try_block, scope, catch_block, HandlerTable::CAUGHT, pos, catch_range);
|
||||
Block* catch_block, int pos) {
|
||||
return new (zone_) TryCatchStatement(try_block, scope, catch_block,
|
||||
HandlerTable::CAUGHT, pos);
|
||||
}
|
||||
|
||||
TryCatchStatement* NewTryCatchStatementForReThrow(Block* try_block,
|
||||
@ -3258,7 +3161,7 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
Block* catch_block,
|
||||
int pos) {
|
||||
return new (zone_) TryCatchStatement(try_block, scope, catch_block,
|
||||
HandlerTable::UNCAUGHT, pos, {});
|
||||
HandlerTable::UNCAUGHT, pos);
|
||||
}
|
||||
|
||||
TryCatchStatement* NewTryCatchStatementForDesugaring(Block* try_block,
|
||||
@ -3266,7 +3169,7 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
Block* catch_block,
|
||||
int pos) {
|
||||
return new (zone_) TryCatchStatement(try_block, scope, catch_block,
|
||||
HandlerTable::DESUGARING, pos, {});
|
||||
HandlerTable::DESUGARING, pos);
|
||||
}
|
||||
|
||||
TryCatchStatement* NewTryCatchStatementForAsyncAwait(Block* try_block,
|
||||
@ -3274,14 +3177,12 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
Block* catch_block,
|
||||
int pos) {
|
||||
return new (zone_) TryCatchStatement(try_block, scope, catch_block,
|
||||
HandlerTable::ASYNC_AWAIT, pos, {});
|
||||
HandlerTable::ASYNC_AWAIT, pos);
|
||||
}
|
||||
|
||||
TryFinallyStatement* NewTryFinallyStatement(
|
||||
Block* try_block, Block* finally_block, int pos,
|
||||
const SourceRange& finally_range = {}) {
|
||||
return new (zone_)
|
||||
TryFinallyStatement(try_block, finally_block, pos, finally_range);
|
||||
TryFinallyStatement* NewTryFinallyStatement(Block* try_block,
|
||||
Block* finally_block, int pos) {
|
||||
return new (zone_) TryFinallyStatement(try_block, finally_block, pos);
|
||||
}
|
||||
|
||||
DebuggerStatement* NewDebuggerStatement(int pos) {
|
||||
@ -3298,8 +3199,8 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
}
|
||||
|
||||
CaseClause* NewCaseClause(Expression* label, ZoneList<Statement*>* statements,
|
||||
int pos, const SourceRange& clause_range = {}) {
|
||||
return new (zone_) CaseClause(label, statements, pos, clause_range);
|
||||
int pos) {
|
||||
return new (zone_) CaseClause(label, statements, pos);
|
||||
}
|
||||
|
||||
Literal* NewStringLiteral(const AstRawString* string, int pos) {
|
||||
@ -3497,9 +3398,8 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
return new (zone_) YieldStar(expression, pos, flags);
|
||||
}
|
||||
|
||||
Throw* NewThrow(Expression* exception, int pos,
|
||||
int32_t continuation_pos = kNoSourcePosition) {
|
||||
return new (zone_) Throw(exception, pos, continuation_pos);
|
||||
Throw* NewThrow(Expression* exception, int pos) {
|
||||
return new (zone_) Throw(exception, pos);
|
||||
}
|
||||
|
||||
FunctionLiteral* NewFunctionLiteral(
|
||||
|
@ -516,6 +516,8 @@ bool CompileUnoptimizedInnerFunctions(
|
||||
parse_info.set_ast_value_factory(
|
||||
outer_info->parse_info()->ast_value_factory());
|
||||
parse_info.set_ast_value_factory_owned(false);
|
||||
parse_info.set_source_range_map(
|
||||
outer_info->parse_info()->source_range_map());
|
||||
|
||||
if (will_serialize) info.PrepareForSerializing();
|
||||
if (is_debug) info.MarkAsDebug();
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "src/accessors.h"
|
||||
#include "src/allocation-site-scopes.h"
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/bootstrapper.h"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef V8_INTERPRETER_BLOCK_COVERAGE_BUILDER_H_
|
||||
#define V8_INTERPRETER_BLOCK_COVERAGE_BUILDER_H_
|
||||
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/interpreter/bytecode-array-builder.h"
|
||||
|
||||
#include "src/zone/zone-containers.h"
|
||||
@ -18,13 +18,24 @@ namespace interpreter {
|
||||
// mapping for block coverage.
|
||||
class BlockCoverageBuilder final : public ZoneObject {
|
||||
public:
|
||||
BlockCoverageBuilder(Zone* zone, BytecodeArrayBuilder* builder)
|
||||
: slots_(0, zone), builder_(builder) {}
|
||||
BlockCoverageBuilder(Zone* zone, BytecodeArrayBuilder* builder,
|
||||
SourceRangeMap* source_range_map)
|
||||
: slots_(0, zone),
|
||||
builder_(builder),
|
||||
source_range_map_(source_range_map) {
|
||||
DCHECK_NOT_NULL(builder);
|
||||
DCHECK_NOT_NULL(source_range_map);
|
||||
}
|
||||
|
||||
static const int kNoCoverageArraySlot = -1;
|
||||
static constexpr int kNoCoverageArraySlot = -1;
|
||||
|
||||
int AllocateBlockCoverageSlot(SourceRange range) {
|
||||
int AllocateBlockCoverageSlot(AstNode* node, SourceRangeKind kind) {
|
||||
AstNodeSourceRanges* ranges = source_range_map_->Find(node);
|
||||
if (ranges == nullptr) return kNoCoverageArraySlot;
|
||||
|
||||
SourceRange range = ranges->GetRange(kind);
|
||||
if (range.IsEmpty()) return kNoCoverageArraySlot;
|
||||
|
||||
const int slot = static_cast<int>(slots_.size());
|
||||
slots_.emplace_back(range);
|
||||
return slot;
|
||||
@ -42,6 +53,7 @@ class BlockCoverageBuilder final : public ZoneObject {
|
||||
// slots. Slot i covers range slots_[i].
|
||||
ZoneVector<SourceRange> slots_;
|
||||
BytecodeArrayBuilder* builder_;
|
||||
SourceRangeMap* source_range_map_;
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "src/interpreter/bytecode-generator.h"
|
||||
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/ast/compile-time-value.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/builtins/builtins-constructor.h"
|
||||
@ -802,8 +803,8 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
||||
DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
|
||||
if (info->is_block_coverage_enabled()) {
|
||||
DCHECK(FLAG_block_coverage);
|
||||
block_coverage_builder_ =
|
||||
new (zone()) BlockCoverageBuilder(zone(), builder());
|
||||
block_coverage_builder_ = new (zone()) BlockCoverageBuilder(
|
||||
zone(), builder(), info->parse_info()->source_range_map());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1230,8 +1231,10 @@ void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
||||
builder()->SetStatementPosition(stmt);
|
||||
|
||||
int then_slot = AllocateBlockCoverageSlotIfEnabled(stmt->then_range());
|
||||
int else_slot = AllocateBlockCoverageSlotIfEnabled(stmt->else_range());
|
||||
int then_slot =
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kThen);
|
||||
int else_slot =
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kElse);
|
||||
|
||||
if (stmt->condition()->ToBooleanIsTrue()) {
|
||||
// Generate then block unconditionally as always true.
|
||||
@ -1266,7 +1269,8 @@ void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
||||
}
|
||||
builder()->Bind(&end_label);
|
||||
}
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt->continuation_range());
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt,
|
||||
SourceRangeKind::kContinuation);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
|
||||
@ -1275,19 +1279,19 @@ void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt->continuation_range());
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
|
||||
builder()->SetStatementPosition(stmt);
|
||||
execution_control()->Continue(stmt->target());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt->continuation_range());
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
|
||||
builder()->SetStatementPosition(stmt);
|
||||
execution_control()->Break(stmt->target());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt->continuation_range());
|
||||
AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
|
||||
builder()->SetStatementPosition(stmt);
|
||||
VisitForAccumulatorValue(stmt->expression());
|
||||
if (stmt->is_async_return()) {
|
||||
@ -1348,11 +1352,12 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
for (int i = 0; i < clauses->length(); i++) {
|
||||
CaseClause* clause = clauses->at(i);
|
||||
switch_builder.SetCaseTarget(i);
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(clause->clause_range());
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(clause, SourceRangeKind::kBody);
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
switch_builder.BindBreakTarget();
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt->continuation_range());
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt,
|
||||
SourceRangeKind::kContinuation);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
|
||||
@ -1370,8 +1375,7 @@ void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_,
|
||||
stmt->body_range(), stmt->continuation_range());
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
|
||||
if (stmt->cond()->ToBooleanIsFalse()) {
|
||||
VisitIterationBody(stmt, &loop_builder);
|
||||
} else if (stmt->cond()->ToBooleanIsTrue()) {
|
||||
@ -1391,8 +1395,7 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_,
|
||||
stmt->body_range(), stmt->continuation_range());
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
|
||||
|
||||
if (stmt->cond()->ToBooleanIsFalse()) {
|
||||
// If the condition is false there is no need to generate the loop.
|
||||
@ -1412,8 +1415,7 @@ void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_,
|
||||
stmt->body_range(), stmt->continuation_range());
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
|
||||
|
||||
if (stmt->init() != nullptr) {
|
||||
Visit(stmt->init());
|
||||
@ -1536,7 +1538,7 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// The loop
|
||||
{
|
||||
LoopBuilder loop_builder(builder());
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
|
||||
VisitIterationHeader(stmt, &loop_builder);
|
||||
builder()->SetExpressionAsStatementPosition(stmt->each());
|
||||
builder()->ForInContinue(index, cache_length);
|
||||
@ -1556,7 +1558,7 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
||||
LoopBuilder loop_builder(builder());
|
||||
LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
|
||||
|
||||
builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
|
||||
VisitForEffect(stmt->assign_iterator());
|
||||
@ -1610,7 +1612,7 @@ void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
builder()->LoadAccumulatorWithRegister(context);
|
||||
|
||||
// Evaluate the catch-block.
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt->catch_range());
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt, SourceRangeKind::kCatch);
|
||||
VisitInScope(stmt->catch_block(), stmt->scope());
|
||||
try_control_builder.EndCatch();
|
||||
}
|
||||
@ -1669,7 +1671,7 @@ void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
message);
|
||||
|
||||
// Evaluate the finally-block.
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt->finally_range());
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(stmt, SourceRangeKind::kFinally);
|
||||
Visit(stmt->finally_block());
|
||||
try_control_builder.EndFinally();
|
||||
|
||||
@ -2793,7 +2795,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
|
||||
.StoreAccumulatorInRegister(resume_mode);
|
||||
|
||||
{
|
||||
LoopBuilder loop(builder());
|
||||
LoopBuilder loop(builder(), block_coverage_builder_, expr);
|
||||
VisitIterationHeader(expr->suspend_id(), 1, &loop);
|
||||
|
||||
{
|
||||
@ -2951,7 +2953,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitThrow(Throw* expr) {
|
||||
AllocateBlockCoverageSlotIfEnabled(expr->continuation_range());
|
||||
AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kContinuation);
|
||||
VisitForAccumulatorValue(expr->exception());
|
||||
builder()->SetExpressionPosition(expr);
|
||||
builder()->Throw();
|
||||
@ -4154,10 +4156,18 @@ void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
|
||||
}
|
||||
|
||||
int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
|
||||
const SourceRange& range) {
|
||||
AstNode* node, SourceRangeKind kind) {
|
||||
return (block_coverage_builder_ == nullptr)
|
||||
? BlockCoverageBuilder::kNoCoverageArraySlot
|
||||
: block_coverage_builder_->AllocateBlockCoverageSlot(range);
|
||||
: block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
|
||||
AstNode* node, SourceRangeKind kind) {
|
||||
if (block_coverage_builder_ == nullptr) return;
|
||||
|
||||
int slot = block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
|
||||
block_coverage_builder_->IncrementBlockCounter(slot);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
|
||||
@ -4167,14 +4177,6 @@ void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
|
||||
const SourceRange& range) {
|
||||
if (block_coverage_builder_ != nullptr) {
|
||||
int slot = block_coverage_builder_->AllocateBlockCoverageSlot(range);
|
||||
block_coverage_builder_->IncrementBlockCounter(slot);
|
||||
}
|
||||
}
|
||||
|
||||
// Visits the expression |expr| and places the result in the accumulator.
|
||||
BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
|
||||
Expression* expr) {
|
||||
|
@ -14,8 +14,10 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class AstNodeSourceRanges;
|
||||
class AstStringConstants;
|
||||
class CompilationInfo;
|
||||
enum class SourceRangeKind;
|
||||
|
||||
namespace interpreter {
|
||||
|
||||
@ -192,9 +194,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
|
||||
void BuildLoadPropertyKey(LiteralProperty* property, Register out_reg);
|
||||
|
||||
int AllocateBlockCoverageSlotIfEnabled(const SourceRange& range);
|
||||
int AllocateBlockCoverageSlotIfEnabled(AstNode* node, SourceRangeKind kind);
|
||||
void BuildIncrementBlockCoverageCounterIfEnabled(AstNode* node,
|
||||
SourceRangeKind kind);
|
||||
void BuildIncrementBlockCoverageCounterIfEnabled(int coverage_array_slot);
|
||||
void BuildIncrementBlockCoverageCounterIfEnabled(const SourceRange& range);
|
||||
|
||||
void BuildTest(ToBooleanMode mode, BytecodeLabels* then_labels,
|
||||
BytecodeLabels* else_labels, TestFallthrough fallthrough);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "src/interpreter/bytecode-array-builder.h"
|
||||
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/interpreter/block-coverage-builder.h"
|
||||
#include "src/interpreter/bytecode-label.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
@ -89,9 +90,7 @@ class V8_EXPORT_PRIVATE BlockBuilder final
|
||||
class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
|
||||
public:
|
||||
LoopBuilder(BytecodeArrayBuilder* builder,
|
||||
BlockCoverageBuilder* block_coverage_builder = nullptr,
|
||||
const SourceRange& body_range = {},
|
||||
const SourceRange& continuation_range = {})
|
||||
BlockCoverageBuilder* block_coverage_builder, AstNode* node)
|
||||
: BreakableControlFlowBuilder(builder),
|
||||
continue_labels_(builder->zone()),
|
||||
generator_jump_table_location_(nullptr),
|
||||
@ -99,10 +98,11 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
|
||||
block_coverage_builder_(block_coverage_builder) {
|
||||
if (block_coverage_builder_ != nullptr) {
|
||||
block_coverage_body_slot_ =
|
||||
block_coverage_builder_->AllocateBlockCoverageSlot(body_range);
|
||||
block_coverage_builder_->AllocateBlockCoverageSlot(
|
||||
node, SourceRangeKind::kBody);
|
||||
block_coverage_continuation_slot_ =
|
||||
block_coverage_builder_->AllocateBlockCoverageSlot(
|
||||
continuation_range);
|
||||
node, SourceRangeKind::kContinuation);
|
||||
}
|
||||
}
|
||||
~LoopBuilder();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "src/parsing/parse-info.h"
|
||||
|
||||
#include "src/api.h"
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/ast/ast-value-factory.h"
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
@ -39,6 +40,7 @@ ParseInfo::ParseInfo(AccountingAllocator* zone_allocator)
|
||||
ast_string_constants_(nullptr),
|
||||
function_name_(nullptr),
|
||||
runtime_call_stats_(nullptr),
|
||||
source_range_map_(nullptr),
|
||||
literal_(nullptr),
|
||||
deferred_handles_(nullptr) {}
|
||||
|
||||
@ -162,6 +164,9 @@ void ParseInfo::InitFromIsolate(Isolate* isolate) {
|
||||
isolate->is_tail_call_elimination_enabled());
|
||||
set_runtime_call_stats(isolate->counters()->runtime_call_stats());
|
||||
set_ast_string_constants(isolate->ast_string_constants());
|
||||
if (FLAG_block_coverage && isolate->is_block_code_coverage()) {
|
||||
set_source_range_map(new (zone()) SourceRangeMap(zone()));
|
||||
}
|
||||
}
|
||||
|
||||
void ParseInfo::UpdateStatisticsAfterBackgroundParse(Isolate* isolate) {
|
||||
|
@ -31,6 +31,7 @@ class FunctionLiteral;
|
||||
class RuntimeCallStats;
|
||||
class ScriptData;
|
||||
class SharedFunctionInfo;
|
||||
class SourceRangeMap;
|
||||
class UnicodeCache;
|
||||
class Utf16CharacterStream;
|
||||
class Zone;
|
||||
@ -207,6 +208,11 @@ class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
|
||||
runtime_call_stats_ = runtime_call_stats;
|
||||
}
|
||||
|
||||
SourceRangeMap* source_range_map() const { return source_range_map_; }
|
||||
void set_source_range_map(SourceRangeMap* source_range_map) {
|
||||
source_range_map_ = source_range_map;
|
||||
}
|
||||
|
||||
// Getters for individual compiler hints.
|
||||
bool is_declaration() const;
|
||||
FunctionKind function_kind() const;
|
||||
@ -310,6 +316,7 @@ class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
|
||||
const class AstStringConstants* ast_string_constants_;
|
||||
const AstRawString* function_name_;
|
||||
RuntimeCallStats* runtime_call_stats_;
|
||||
SourceRangeMap* source_range_map_; // Used when block coverage is enabled.
|
||||
|
||||
//----------- Output of parsing and scope analysis ------------------------
|
||||
FunctionLiteral* literal_;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_PARSING_PARSER_BASE_H
|
||||
#define V8_PARSING_PARSER_BASE_H
|
||||
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/bailout-reason.h"
|
||||
@ -101,11 +102,12 @@ class SourceRangeScope final {
|
||||
|
||||
~SourceRangeScope() { Finalize(); }
|
||||
|
||||
void Finalize() {
|
||||
if (is_finalized_) return;
|
||||
const SourceRange& Finalize() {
|
||||
if (is_finalized_) return *range_;
|
||||
is_finalized_ = true;
|
||||
range_->end = GetPosition(post_kind_);
|
||||
DCHECK_NE(range_->end, kNoSourcePosition);
|
||||
return *range_;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1428,12 +1430,9 @@ class ParserBase {
|
||||
|
||||
// Convenience method which determines the type of return statement to emit
|
||||
// depending on the current function type.
|
||||
inline StatementT BuildReturnStatement(
|
||||
ExpressionT expr, int pos, int continuation_pos = kNoSourcePosition) {
|
||||
if (is_async_function()) {
|
||||
return factory()->NewAsyncReturnStatement(expr, pos, continuation_pos);
|
||||
}
|
||||
return factory()->NewReturnStatement(expr, pos, continuation_pos);
|
||||
inline StatementT BuildReturnStatement(ExpressionT expr, int pos) {
|
||||
return is_async_function() ? factory()->NewAsyncReturnStatement(expr, pos)
|
||||
: factory()->NewReturnStatement(expr, pos);
|
||||
}
|
||||
|
||||
inline SuspendExpressionT BuildSuspend(
|
||||
@ -5200,8 +5199,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement(
|
||||
} else {
|
||||
else_statement = factory()->NewEmptyStatement(kNoSourcePosition);
|
||||
}
|
||||
return factory()->NewIfStatement(condition, then_statement, else_statement,
|
||||
pos, then_range, else_range);
|
||||
StatementT stmt =
|
||||
factory()->NewIfStatement(condition, then_statement, else_statement, pos);
|
||||
impl()->RecordIfStatementSourceRange(stmt, then_range, else_range);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -5236,8 +5237,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement(
|
||||
return impl()->NullStatement();
|
||||
}
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
int continuation_pos = scanner_->location().end_pos;
|
||||
return factory()->NewContinueStatement(target, pos, continuation_pos);
|
||||
StatementT stmt = factory()->NewContinueStatement(target, pos);
|
||||
impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -5275,8 +5277,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement(
|
||||
return impl()->NullStatement();
|
||||
}
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
int continuation_pos = scanner_->location().end_pos;
|
||||
return factory()->NewBreakStatement(target, pos, continuation_pos);
|
||||
StatementT stmt = factory()->NewBreakStatement(target, pos);
|
||||
impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -5330,8 +5333,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
|
||||
}
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
return_value = impl()->RewriteReturn(return_value, loc.beg_pos);
|
||||
int continuation_pos = scanner_->location().end_pos;
|
||||
return BuildReturnStatement(return_value, loc.beg_pos, continuation_pos);
|
||||
StatementT stmt = BuildReturnStatement(return_value, loc.beg_pos);
|
||||
impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -5393,7 +5397,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
|
||||
// ExpectSemicolon() functionality here.
|
||||
Check(Token::SEMICOLON);
|
||||
|
||||
loop->Initialize(cond, body, body_range);
|
||||
loop->Initialize(cond, body);
|
||||
impl()->RecordIterationStatementSourceRange(loop, body_range);
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
@ -5418,7 +5424,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
|
||||
body = ParseStatement(nullptr, CHECK_OK);
|
||||
}
|
||||
|
||||
loop->Initialize(cond, body, body_range);
|
||||
loop->Initialize(cond, body);
|
||||
impl()->RecordIterationStatementSourceRange(loop, body_range);
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
@ -5437,9 +5445,11 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
|
||||
}
|
||||
ExpressionT exception = ParseExpression(true, CHECK_OK);
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
int continuation_pos = scanner_->location().end_pos;
|
||||
|
||||
return impl()->NewThrowStatement(exception, pos, continuation_pos);
|
||||
StatementT stmt = impl()->NewThrowStatement(exception, pos);
|
||||
impl()->RecordThrowSourceRange(stmt, scanner_->location().end_pos);
|
||||
|
||||
return stmt;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -5493,19 +5503,17 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
|
||||
StatementT stat = ParseStatementListItem(CHECK_OK);
|
||||
statements->Add(stat, zone());
|
||||
}
|
||||
range_scope.Finalize();
|
||||
auto clause =
|
||||
factory()->NewCaseClause(label, statements, clause_pos, clause_range);
|
||||
auto clause = factory()->NewCaseClause(label, statements, clause_pos);
|
||||
impl()->RecordCaseClauseSourceRange(clause, range_scope.Finalize());
|
||||
cases->Add(clause, zone());
|
||||
}
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
|
||||
int end_position = scanner()->location().end_pos;
|
||||
scope()->set_end_position(end_position);
|
||||
int continuation_pos = end_position;
|
||||
impl()->RecordSwitchStatementSourceRange(switch_statement, end_position);
|
||||
return impl()->RewriteSwitchStatement(tag, switch_statement, cases,
|
||||
scope()->FinalizeBlockScope(),
|
||||
continuation_pos);
|
||||
scope()->FinalizeBlockScope());
|
||||
}
|
||||
}
|
||||
|
||||
@ -5879,11 +5887,13 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop(
|
||||
}
|
||||
block->statements()->Add(loop, zone());
|
||||
block->set_scope(for_scope);
|
||||
loop->Initialize(init, cond, next, body, body_range);
|
||||
loop->Initialize(init, cond, next, body);
|
||||
impl()->RecordIterationStatementSourceRange(loop, body_range);
|
||||
return block;
|
||||
}
|
||||
|
||||
loop->Initialize(init, cond, next, body, body_range);
|
||||
loop->Initialize(init, cond, next, body);
|
||||
impl()->RecordIterationStatementSourceRange(loop, body_range);
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
@ -487,6 +487,7 @@ Parser::Parser(ParseInfo* info)
|
||||
scanner_(info->unicode_cache()),
|
||||
reusable_preparser_(nullptr),
|
||||
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
|
||||
source_range_map_(info->source_range_map()),
|
||||
target_stack_(nullptr),
|
||||
compile_options_(info->compile_options()),
|
||||
cached_parse_data_(nullptr),
|
||||
@ -1641,8 +1642,7 @@ Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
|
||||
Statement* Parser::RewriteSwitchStatement(Expression* tag,
|
||||
SwitchStatement* switch_statement,
|
||||
ZoneList<CaseClause*>* cases,
|
||||
Scope* scope,
|
||||
int32_t continuation_pos) {
|
||||
Scope* scope) {
|
||||
// In order to get the CaseClauses to execute in their own lexical scope,
|
||||
// but without requiring downstream code to have special scope handling
|
||||
// code for switch statements, desugar into blocks as follows:
|
||||
@ -1673,7 +1673,7 @@ Statement* Parser::RewriteSwitchStatement(Expression* tag,
|
||||
zone());
|
||||
|
||||
Expression* tag_read = factory()->NewVariableProxy(tag_variable);
|
||||
switch_statement->Initialize(tag_read, cases, continuation_pos);
|
||||
switch_statement->Initialize(tag_read, cases);
|
||||
Block* cases_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition);
|
||||
cases_block->statements()->Add(switch_statement, zone());
|
||||
cases_block->set_scope(scope);
|
||||
@ -1751,8 +1751,8 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
|
||||
DCHECK_NOT_NULL(catch_info.scope);
|
||||
TryCatchStatement* statement;
|
||||
statement = factory()->NewTryCatchStatement(try_block, catch_info.scope,
|
||||
catch_block, kNoSourcePosition,
|
||||
catch_range);
|
||||
catch_block, kNoSourcePosition);
|
||||
RecordTryCatchStatementSourceRange(statement, catch_range);
|
||||
|
||||
try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
|
||||
try_block->statements()->Add(statement, zone());
|
||||
@ -1767,12 +1767,16 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
|
||||
|
||||
DCHECK_NULL(finally_block);
|
||||
DCHECK_NOT_NULL(catch_info.scope);
|
||||
return factory()->NewTryCatchStatement(try_block, catch_info.scope,
|
||||
catch_block, pos, catch_range);
|
||||
TryCatchStatement* stmt = factory()->NewTryCatchStatement(
|
||||
try_block, catch_info.scope, catch_block, pos);
|
||||
RecordTryCatchStatementSourceRange(stmt, catch_range);
|
||||
return stmt;
|
||||
} else {
|
||||
DCHECK_NOT_NULL(finally_block);
|
||||
return factory()->NewTryFinallyStatement(try_block, finally_block, pos,
|
||||
finally_range);
|
||||
TryFinallyStatement* stmt =
|
||||
factory()->NewTryFinallyStatement(try_block, finally_block, pos);
|
||||
RecordTryFinallyStatementSourceRange(stmt, finally_range);
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2448,7 +2452,9 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
||||
inner_block->set_scope(inner_scope);
|
||||
}
|
||||
|
||||
outer_loop->Initialize(NULL, NULL, NULL, inner_block, body_range);
|
||||
outer_loop->Initialize(NULL, NULL, NULL, inner_block);
|
||||
RecordIterationStatementSourceRange(outer_loop, body_range);
|
||||
|
||||
return outer_block;
|
||||
}
|
||||
|
||||
@ -4616,8 +4622,7 @@ Expression* Parser::RewriteYieldStar(Expression* iterable, int pos) {
|
||||
cases->Add(factory()->NewCaseClause(kreturn, case_return, nopos), zone());
|
||||
cases->Add(factory()->NewCaseClause(kthrow, case_throw, nopos), zone());
|
||||
|
||||
switch_mode->Initialize(factory()->NewVariableProxy(var_mode), cases,
|
||||
kNoSourcePosition);
|
||||
switch_mode->Initialize(factory()->NewVariableProxy(var_mode), cases);
|
||||
}
|
||||
|
||||
// while (true) { ... }
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_PARSING_PARSER_H_
|
||||
#define V8_PARSING_PARSER_H_
|
||||
|
||||
#include "src/ast/ast-source-ranges.h"
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/base/compiler-specific.h"
|
||||
@ -340,8 +341,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
Expression* RewriteReturn(Expression* return_value, int pos);
|
||||
Statement* RewriteSwitchStatement(Expression* tag,
|
||||
SwitchStatement* switch_statement,
|
||||
ZoneList<CaseClause*>* cases, Scope* scope,
|
||||
int32_t continuation_pos);
|
||||
ZoneList<CaseClause*>* cases, Scope* scope);
|
||||
void RewriteCatchPattern(CatchInfo* catch_info, bool* ok);
|
||||
void ValidateCatchBlock(const CatchInfo& catch_info, bool* ok);
|
||||
Statement* RewriteTryStatement(Block* try_block, Block* catch_block,
|
||||
@ -1051,10 +1051,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
ZoneList<Expression*>* args, int pos,
|
||||
bool* ok);
|
||||
|
||||
V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos,
|
||||
int32_t continuation_pos) {
|
||||
V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos) {
|
||||
return factory()->NewExpressionStatement(
|
||||
factory()->NewThrow(exception, pos, continuation_pos), pos);
|
||||
factory()->NewThrow(exception, pos), pos);
|
||||
}
|
||||
|
||||
V8_INLINE void AddParameterInitializationBlock(
|
||||
@ -1147,6 +1146,68 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
return parameters_end_pos_ != kNoSourcePosition;
|
||||
}
|
||||
|
||||
V8_INLINE void RecordCaseClauseSourceRange(CaseClause* node,
|
||||
const SourceRange& body_range) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(node,
|
||||
new (zone()) CaseClauseSourceRanges(body_range));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordJumpStatementSourceRange(Statement* node,
|
||||
int32_t continuation_position) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
static_cast<JumpStatement*>(node),
|
||||
new (zone()) JumpStatementSourceRanges(continuation_position));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordIfStatementSourceRange(Statement* node,
|
||||
const SourceRange& then_range,
|
||||
const SourceRange& else_range) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
node->AsIfStatement(),
|
||||
new (zone()) IfStatementSourceRanges(then_range, else_range));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordIterationStatementSourceRange(
|
||||
IterationStatement* node, const SourceRange& body_range) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
node, new (zone()) IterationStatementSourceRanges(body_range));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordSwitchStatementSourceRange(
|
||||
Statement* node, int32_t continuation_position) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
node->AsSwitchStatement(),
|
||||
new (zone()) SwitchStatementSourceRanges(continuation_position));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordThrowSourceRange(Statement* node,
|
||||
int32_t continuation_position) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
ExpressionStatement* expr_stmt = static_cast<ExpressionStatement*>(node);
|
||||
Throw* throw_expr = expr_stmt->expression()->AsThrow();
|
||||
source_range_map_->Insert(
|
||||
throw_expr, new (zone()) ThrowSourceRanges(continuation_position));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordTryCatchStatementSourceRange(
|
||||
TryCatchStatement* node, const SourceRange& body_range) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
node, new (zone()) TryCatchStatementSourceRanges(body_range));
|
||||
}
|
||||
|
||||
V8_INLINE void RecordTryFinallyStatementSourceRange(
|
||||
TryFinallyStatement* node, const SourceRange& body_range) {
|
||||
if (source_range_map_ == nullptr) return;
|
||||
source_range_map_->Insert(
|
||||
node, new (zone()) TryFinallyStatementSourceRanges(body_range));
|
||||
}
|
||||
|
||||
// Parser's private field members.
|
||||
friend class DiscardableZoneScope; // Uses reusable_preparser_.
|
||||
// FIXME(marja): Make reusable_preparser_ always use its own temp Zone (call
|
||||
@ -1161,6 +1222,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
CompilerDispatcher* compiler_dispatcher_ = nullptr;
|
||||
ParseInfo* main_parse_info_ = nullptr;
|
||||
|
||||
SourceRangeMap* source_range_map_ = nullptr;
|
||||
|
||||
friend class ParserTarget;
|
||||
friend class ParserTargetScope;
|
||||
ParserTarget* target_stack_; // for break, continue statements
|
||||
|
@ -769,8 +769,7 @@ class PreParserFactory {
|
||||
}
|
||||
|
||||
PreParserStatement NewCaseClause(PreParserExpression label,
|
||||
PreParserStatementList statements, int pos,
|
||||
const SourceRange& clause_range) {
|
||||
PreParserStatementList statements, int pos) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
@ -1068,7 +1067,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
}
|
||||
V8_INLINE PreParserStatement RewriteSwitchStatement(
|
||||
PreParserExpression tag, PreParserStatement switch_statement,
|
||||
PreParserStatementList cases, Scope* scope, int32_t continuation_pos) {
|
||||
PreParserStatementList cases, Scope* scope) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
@ -1638,8 +1637,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
}
|
||||
|
||||
V8_INLINE PreParserStatement NewThrowStatement(PreParserExpression exception,
|
||||
int pos,
|
||||
int32_t continuation_pos) {
|
||||
int pos) {
|
||||
return PreParserStatement::Jump();
|
||||
}
|
||||
|
||||
@ -1745,6 +1743,25 @@ class PreParser : public ParserBase<PreParser> {
|
||||
|
||||
V8_INLINE bool ParsingDynamicFunctionDeclaration() const { return false; }
|
||||
|
||||
V8_INLINE void RecordCaseClauseSourceRange(PreParserStatement node,
|
||||
const SourceRange& body_range) {}
|
||||
V8_INLINE void RecordIfStatementSourceRange(PreParserStatement node,
|
||||
const SourceRange& then_range,
|
||||
const SourceRange& else_range) {}
|
||||
V8_INLINE void RecordJumpStatementSourceRange(PreParserStatement node,
|
||||
int32_t continuation_position) {
|
||||
}
|
||||
V8_INLINE void RecordIterationStatementSourceRange(
|
||||
PreParserStatement node, const SourceRange& body_range) {}
|
||||
V8_INLINE void RecordSwitchStatementSourceRange(
|
||||
PreParserStatement node, int32_t continuation_position) {}
|
||||
V8_INLINE void RecordThrowSourceRange(PreParserStatement node,
|
||||
int32_t continuation_position) {}
|
||||
V8_INLINE void RecordTryCatchStatementSourceRange(
|
||||
PreParserStatement node, const SourceRange& body_range) {}
|
||||
V8_INLINE void RecordTryFinallyStatementSourceRange(
|
||||
PreParserStatement node, const SourceRange& body_range) {}
|
||||
|
||||
// Preparser's private field members.
|
||||
|
||||
int* use_counts_;
|
||||
|
@ -593,6 +593,7 @@
|
||||
'ast/ast-function-literal-id-reindexer.h',
|
||||
'ast/ast-numbering.cc',
|
||||
'ast/ast-numbering.h',
|
||||
'ast/ast-source-ranges.h',
|
||||
'ast/ast-traversal-visitor.h',
|
||||
'ast/ast-value-factory.cc',
|
||||
'ast/ast-value-factory.h',
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --no-always-opt --block-coverage
|
||||
// Flags: --allow-natives-syntax --no-always-opt --ignition --block-coverage
|
||||
|
||||
// Test precise code coverage.
|
||||
|
||||
@ -342,6 +342,36 @@ TestCoverage(
|
||||
{"start":513,"end":564,"count":0}]
|
||||
);
|
||||
|
||||
TestCoverage(
|
||||
"early return in blocks",
|
||||
`
|
||||
!function() { // 0000
|
||||
try { throw 42; } catch (e) { return; } // 0050
|
||||
nop(); // 0100
|
||||
}(); // 0150
|
||||
!function() { // 0200
|
||||
try { nop(); } finally { return; } // 0250
|
||||
nop(); // 0300
|
||||
}(); // 0350
|
||||
!function() { // 0400
|
||||
{ // 0450
|
||||
let x = 42; // 0500
|
||||
return () => x; // 0550
|
||||
} // 0600
|
||||
nop(); // 0650
|
||||
}(); // 0700
|
||||
`,
|
||||
[{"start":0,"end":749,"count":1},
|
||||
{"start":1,"end":151,"count":1},
|
||||
{"start":67,"end":80,"count":0},
|
||||
{"start":89,"end":91,"count":0}, // TODO(jgruber): Missing continuation.
|
||||
{"start":201,"end":351,"count":1},
|
||||
{"start":284,"end":286,"count":0}, // TODO(jgruber): Missing continuation.
|
||||
{"start":401,"end":701,"count":1},
|
||||
{"start":569,"end":701,"count":0},
|
||||
{"start":561,"end":568,"count":0}] // TODO(jgruber): Sorting.
|
||||
);
|
||||
|
||||
TestCoverage(
|
||||
"switch statements",
|
||||
`
|
||||
|
@ -236,7 +236,7 @@ TEST_F(BytecodeAnalysisTest, SimpleLoop) {
|
||||
expected_liveness.emplace_back("..LL", "L.LL");
|
||||
|
||||
{
|
||||
interpreter::LoopBuilder loop_builder(&builder);
|
||||
interpreter::LoopBuilder loop_builder(&builder, nullptr, nullptr);
|
||||
loop_builder.LoopHeader();
|
||||
|
||||
builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
|
||||
@ -322,7 +322,7 @@ TEST_F(BytecodeAnalysisTest, DiamondInLoop) {
|
||||
expected_liveness.emplace_back("...L", "L..L");
|
||||
|
||||
{
|
||||
interpreter::LoopBuilder loop_builder(&builder);
|
||||
interpreter::LoopBuilder loop_builder(&builder, nullptr, nullptr);
|
||||
loop_builder.LoopHeader();
|
||||
|
||||
builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
|
||||
@ -371,7 +371,7 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) {
|
||||
expected_liveness.emplace_back(".L.L", "LL..");
|
||||
|
||||
{
|
||||
interpreter::LoopBuilder loop_builder(&builder);
|
||||
interpreter::LoopBuilder loop_builder(&builder, nullptr, nullptr);
|
||||
loop_builder.LoopHeader();
|
||||
|
||||
builder.LoadAccumulatorWithRegister(reg_0);
|
||||
@ -385,7 +385,7 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) {
|
||||
expected_liveness.emplace_back(".L.L", ".L.L");
|
||||
|
||||
{
|
||||
interpreter::LoopBuilder inner_loop_builder(&builder);
|
||||
interpreter::LoopBuilder inner_loop_builder(&builder, nullptr, nullptr);
|
||||
inner_loop_builder.LoopHeader();
|
||||
|
||||
builder.StoreAccumulatorInRegister(reg_0);
|
||||
|
Loading…
Reference in New Issue
Block a user