Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(398)

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 2882973002: [coverage] Block coverage with support for IfStatements (Closed)
Patch Set: Address comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index b754897e759335c90ea8c4a94555f3d22d3e6a9f..59173891f0a14f63bfdc671ad8b958e01a06e707 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -737,6 +737,36 @@ class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
bool has_constant_pool_entry_;
};
+// Used to generate IncBlockCounter bytecodes and the {source range, slot}
+// mapping for block coverage.
+class BytecodeGenerator::BlockCoverageBuilder final : public ZoneObject {
+ public:
+ explicit BlockCoverageBuilder(Zone* zone, BytecodeArrayBuilder* builder)
+ : slots_(0, zone), builder_(builder) {}
+
+ static const int kNoCoverageArraySlot = -1;
+
+ int AllocateBlockCoverageSlot(SourceRange range) {
+ if (range.IsEmpty()) return kNoCoverageArraySlot;
+ const int slot = static_cast<int>(slots_.size());
+ slots_.emplace_back(range);
+ return slot;
+ }
+
+ void IncrementBlockCounter(int coverage_array_slot) {
+ if (coverage_array_slot == kNoCoverageArraySlot) return;
+ builder_->IncBlockCounter(coverage_array_slot);
+ }
+
+ const ZoneVector<SourceRange>& slots() const { return slots_; }
+
+ private:
+ // Contains source range information for allocated block coverage counter
+ // slots. Slot i covers range slots_[i].
+ ZoneVector<SourceRange> slots_;
+ BytecodeArrayBuilder* builder_;
+};
+
class BytecodeGenerator::CurrentScope final {
public:
CurrentScope(BytecodeGenerator* generator, Scope* scope)
@@ -767,6 +797,7 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
closure_scope_(info->scope()),
current_scope_(info->scope()),
globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())),
+ block_coverage_builder_(nullptr),
global_declarations_(0, info->zone()),
function_literals_(0, info->zone()),
native_function_literals_(0, info->zone()),
@@ -779,10 +810,23 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
generator_state_(),
loop_depth_(0) {
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());
+ }
}
Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) {
+ DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
+
AllocateDeferredConstants(isolate);
+
+ if (info()->is_block_coverage_enabled()) {
+ info()->set_coverage_info(
+ isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
+ }
+
if (HasStackOverflow()) return Handle<BytecodeArray>();
return builder()->ToBytecodeArray(isolate);
}
@@ -1184,12 +1228,18 @@ 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());
+
if (stmt->condition()->ToBooleanIsTrue()) {
// Generate then block unconditionally as always true.
+ BuildIncrementBlockCoverageCounterIfEnabled(then_slot);
Visit(stmt->then_statement());
} else if (stmt->condition()->ToBooleanIsFalse()) {
// Generate else block unconditionally if it exists.
if (stmt->HasElseStatement()) {
+ BuildIncrementBlockCoverageCounterIfEnabled(else_slot);
Visit(stmt->else_statement());
}
} else {
@@ -1202,11 +1252,13 @@ void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
TestFallthrough::kThen);
then_labels.Bind(builder());
+ BuildIncrementBlockCoverageCounterIfEnabled(then_slot);
Visit(stmt->then_statement());
if (stmt->HasElseStatement()) {
builder()->Jump(&end_label);
else_labels.Bind(builder());
+ BuildIncrementBlockCoverageCounterIfEnabled(else_slot);
Visit(stmt->else_statement());
} else {
else_labels.Bind(builder());
@@ -3851,6 +3903,19 @@ void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
}
}
+int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(SourceRange range) {
+ return (block_coverage_builder_ == nullptr)
+ ? BlockCoverageBuilder::kNoCoverageArraySlot
+ : block_coverage_builder_->AllocateBlockCoverageSlot(range);
+}
+
+void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
+ int coverage_array_slot) {
+ if (block_coverage_builder_ != nullptr) {
+ block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
+ }
+}
+
// Visits the expression |expr| for testing its boolean value and jumping to the
// |then| or |other| label depending on value and short-circuit semantics
void BytecodeGenerator::VisitForTest(Expression* expr,
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698