c7ebc5814f
This is a reland of 35269f77f8
Switches on an expression that unconditionally throws would have all their
case statements dead, causing a DCHECK error in the SwitchBuilder. This
fixes up the DCHECK to allow dead labels.
Original change's description:
> [ignition] Skip binding dead labels
>
> BytecodeLabels for forward jumps may create a dead basic block if their
> corresponding jump was elided (due to it dead code elimination). We can
> avoid generating such dead basic blocks by skipping the label bind when
> no corresponding jump has been observed. This works because all jumps
> except JumpLoop are forward jumps, so we only have to special case one
> Bind for loop headers to bind unconditionally.
>
> Since Binds are now conditional on a jump existing, we can no longer rely
> on using Bind to get the current offset (e.g. at the beginning of a try
> block). Instead, we now expose the current offset in the bytecode array
> writer. Conveniently, this means that we can be a bit smarter about basic
> blocks around these statements.
>
> As a drive-by, remove the unused Bind(target,label) function.
>
> Bug: chromium:934166
> Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3
> Reviewed-on: https://chromium-review.googlesource.com/c/1488763
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#59942}
TBR=rmcilroy@chromium.org
Bug: chromium:934166
Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4
Reviewed-on: https://chromium-review.googlesource.com/c/1494535
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59948}
115 lines
2.9 KiB
C++
115 lines
2.9 KiB
C++
// Copyright 2015 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_INTERPRETER_BYTECODE_LABEL_H_
|
|
#define V8_INTERPRETER_BYTECODE_LABEL_H_
|
|
|
|
#include <algorithm>
|
|
|
|
#include "src/zone/zone-containers.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace interpreter {
|
|
|
|
class BytecodeArrayBuilder;
|
|
|
|
// A label representing a loop header in a bytecode array. It is bound before
|
|
// the jump is seen, so its position is always known by the time the jump is
|
|
// reached.
|
|
class V8_EXPORT_PRIVATE BytecodeLoopHeader final {
|
|
public:
|
|
BytecodeLoopHeader() : offset_(kInvalidOffset) {}
|
|
|
|
size_t offset() const {
|
|
DCHECK_NE(offset_, kInvalidOffset);
|
|
return offset_;
|
|
}
|
|
|
|
private:
|
|
static const size_t kInvalidOffset = static_cast<size_t>(-1);
|
|
|
|
void bind_to(size_t offset) {
|
|
DCHECK_NE(offset, kInvalidOffset);
|
|
DCHECK_EQ(offset_, kInvalidOffset);
|
|
offset_ = offset;
|
|
}
|
|
|
|
// The bytecode offset of the loop header.
|
|
size_t offset_;
|
|
|
|
friend class BytecodeArrayWriter;
|
|
};
|
|
|
|
// A label representing a forward branch target in a bytecode array. When a
|
|
// label is bound, it represents a known position in the bytecode array. A label
|
|
// can only have at most one referrer jump.
|
|
class V8_EXPORT_PRIVATE BytecodeLabel final {
|
|
public:
|
|
BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {}
|
|
|
|
bool is_bound() const { return bound_; }
|
|
size_t jump_offset() const {
|
|
DCHECK_NE(jump_offset_, kInvalidOffset);
|
|
return jump_offset_;
|
|
}
|
|
|
|
bool has_referrer_jump() const { return jump_offset_ != kInvalidOffset; }
|
|
|
|
private:
|
|
static const size_t kInvalidOffset = static_cast<size_t>(-1);
|
|
|
|
void bind() {
|
|
DCHECK(!bound_);
|
|
bound_ = true;
|
|
}
|
|
|
|
void set_referrer(size_t offset) {
|
|
DCHECK(!bound_);
|
|
DCHECK_NE(offset, kInvalidOffset);
|
|
DCHECK_EQ(jump_offset_, kInvalidOffset);
|
|
jump_offset_ = offset;
|
|
}
|
|
|
|
// Set when the label is bound (i.e. the start of the target basic block).
|
|
bool bound_;
|
|
// Set when the jump referrer is set (i.e. the location of the jump).
|
|
size_t jump_offset_;
|
|
|
|
friend class BytecodeArrayWriter;
|
|
};
|
|
|
|
// Class representing a branch target of multiple jumps.
|
|
class V8_EXPORT_PRIVATE BytecodeLabels {
|
|
public:
|
|
explicit BytecodeLabels(Zone* zone) : labels_(zone), is_bound_(false) {}
|
|
|
|
BytecodeLabel* New();
|
|
|
|
void Bind(BytecodeArrayBuilder* builder);
|
|
|
|
bool is_bound() const {
|
|
DCHECK_IMPLIES(
|
|
is_bound_,
|
|
std::all_of(labels_.begin(), labels_.end(), [](const BytecodeLabel& l) {
|
|
return !l.has_referrer_jump() || l.is_bound();
|
|
}));
|
|
return is_bound_;
|
|
}
|
|
|
|
bool empty() const { return labels_.empty(); }
|
|
|
|
private:
|
|
ZoneLinkedList<BytecodeLabel> labels_;
|
|
bool is_bound_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BytecodeLabels);
|
|
};
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_INTERPRETER_BYTECODE_LABEL_H_
|