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

Unified Diff: src/compiler/bytecode-analysis.cc

Issue 2523893003: Reland of [ignition/turbo] Perform liveness analysis on the bytecodes (Closed)
Patch Set: Created 4 years, 1 month 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
Index: src/compiler/bytecode-analysis.cc
diff --git a/src/compiler/bytecode-analysis.cc b/src/compiler/bytecode-analysis.cc
index ea5d71a7da1c0cefdcb2d4c5ad4296353d82901b..86b12017057ff5570d622c6ef4bbcd91d2000829 100644
--- a/src/compiler/bytecode-analysis.cc
+++ b/src/compiler/bytecode-analysis.cc
@@ -11,30 +11,286 @@ namespace v8 {
namespace internal {
namespace compiler {
+using namespace interpreter;
+
BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
Zone* zone)
: bytecode_array_(bytecode_array),
zone_(zone),
loop_stack_(zone),
end_to_header_(zone),
- header_to_parent_(zone) {}
+ header_to_parent_(zone),
+ liveness_(
+ base::bits::RoundUpToPowerOfTwo32(bytecode_array->length() / 4 + 1),
+ base::KeyEqualityMatcher<int>(), ZoneAllocationPolicy(zone)) {}
+
+namespace {
+
+uint32_t OffsetHash(int offset) { return offset; }
+
+const BitVector* GetInLiveness(
+ int offset, const BytecodeAnalysis::LivenessMap& liveness_map) {
+ return liveness_map.Lookup(offset, OffsetHash(offset))->value.in;
+}
+
+const BitVector* GetOutLiveness(
+ int offset, const BytecodeAnalysis::LivenessMap& liveness_map) {
+ return liveness_map.Lookup(offset, OffsetHash(offset))->value.out;
+}
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper;
+
+template <int index, OperandType otherOperandType, OperandType... operandTypes>
+struct LivenessHelper<index, otherOperandType, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index>
+struct LivenessHelper<index> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {}
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {}
+};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kReg, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ liveness.Add(r.index());
+ }
+
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegList, OperandType::kRegCount,
+ operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ int count = accessor.GetRegisterCountOperand(index + 1);
+ for (int i = 0; i < count; ++i) {
+ liveness.Add(r.index() + i);
+ }
+ }
+
+ LivenessHelper<index + 2, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 2, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index, OperandType otherOperandType, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegList, otherOperandType,
+ operandTypes...> {};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegPair, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ liveness.Add(r.index());
+ liveness.Add(r.index() + 1);
+ }
+
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegOut, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ liveness.Remove(r.index());
+ }
+
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegOutPair, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ liveness.Remove(r.index());
+ liveness.Remove(r.index() + 1);
+ }
+
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <int index, OperandType... operandTypes>
+struct LivenessHelper<index, OperandType::kRegOutTriple, operandTypes...> {
+ static void AddReads(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ LivenessHelper<index + 1, operandTypes...>::AddReads(liveness, accessor);
+ }
+ static void KillWrites(BitVector& liveness,
+ const BytecodeArrayAccessor& accessor) {
+ interpreter::Register r = accessor.GetRegisterOperand(index);
+ if (!r.is_parameter()) {
+ liveness.Remove(r.index());
+ liveness.Remove(r.index() + 1);
+ liveness.Remove(r.index() + 2);
+ }
+
+ LivenessHelper<index + 1, operandTypes...>::KillWrites(liveness, accessor);
+ }
+};
+
+template <Bytecode bytecode, AccumulatorUse accumulatorUse,
+ OperandType... operandsTypes>
Jarin 2016/11/24 12:47:17 Oh, my eyes, my eyes! Does the heavy use of templ
Leszek Swirski 2016/11/25 17:31:27 Beauty is in the eye of the beholder ;) Unfortuna
+void UpdateLiveness(BytecodeAnalysis::Liveness liveness,
+ const BytecodeArrayAccessor& accessor,
+ const BytecodeAnalysis::LivenessMap& liveness_map) {
+ int current_offset = accessor.current_offset();
+ const Handle<BytecodeArray>& bytecode_array = accessor.bytecode_array();
+
+ BitVector& in_liveness = *liveness.in;
+ BitVector& out_liveness = *liveness.out;
+
+ if (Bytecodes::IsJump(bytecode)) {
+ int target_offset = accessor.GetJumpTargetOffset();
+ out_liveness.Union(*GetInLiveness(target_offset, liveness_map));
+ }
+
+ if (!Bytecodes::IsJump(bytecode) || Bytecodes::IsConditionalJump(bytecode)) {
+ int next_offset = current_offset + accessor.current_bytecode_size();
+ if (next_offset < bytecode_array->length()) {
+ out_liveness.Union(*GetInLiveness(next_offset, liveness_map));
+ }
+ }
+
+ if (!interpreter::Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
+ int handler_context;
+ int handler_offset = bytecode_array->LookupRangeInHandlerTable(
+ current_offset, &handler_context, nullptr);
+
+ if (handler_offset != -1) {
+ out_liveness.Union(*GetInLiveness(handler_offset, liveness_map));
+ out_liveness.Add(handler_context);
+ }
+ }
+
+ in_liveness.CopyFrom(out_liveness);
+
+ if (accumulatorUse == AccumulatorUse::kWrite) {
+ in_liveness.Remove(in_liveness.length() - 1);
+ }
+ LivenessHelper<0, operandsTypes...>::KillWrites(in_liveness, accessor);
+
+ if (accumulatorUse == AccumulatorUse::kRead) {
+ in_liveness.Add(in_liveness.length() - 1);
+ }
+ LivenessHelper<0, operandsTypes...>::AddReads(in_liveness, accessor);
+}
+} // namespace
+
+BytecodeAnalysis::Liveness::Liveness(int size, Zone* zone)
+ : in(new (zone) BitVector(size, zone)),
+ out(new (zone) BitVector(size, zone)) {}
void BytecodeAnalysis::Analyze() {
loop_stack_.push(-1);
- interpreter::BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
+ BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
while (!iterator.done()) {
- interpreter::Bytecode bytecode = iterator.current_bytecode();
- if (bytecode == interpreter::Bytecode::kJumpLoop) {
- PushLoop(iterator.GetJumpTargetOffset(), iterator.current_offset());
- } else if (iterator.current_offset() == loop_stack_.top()) {
+ Bytecode bytecode = iterator.current_bytecode();
+ int current_offset = iterator.current_offset();
+
+ if (bytecode == Bytecode::kJumpLoop) {
+ PushLoop(iterator.GetJumpTargetOffset(), current_offset);
+ } else if (current_offset == loop_stack_.top()) {
loop_stack_.pop();
}
+
+ liveness_.LookupOrInsert(
+ current_offset, OffsetHash(current_offset),
+ [&]() {
+ return Liveness(bytecode_array()->register_count() + 1, zone());
+ },
+ ZoneAllocationPolicy(zone()));
+
iterator.Advance();
}
DCHECK_EQ(loop_stack_.size(), 1u);
DCHECK_EQ(loop_stack_.top(), -1);
+
+ // Hoist previous_in_liveness out of the loop so that we don't trash the zone
+ // with allocations.
+ BitVector previous_in_liveness(bytecode_array()->register_count() + 1,
+ zone());
+
+ bool liveness_changed = true;
+ while (liveness_changed) {
+ liveness_changed = false;
+ iterator.Reset();
+ while (!iterator.done()) {
+ Liveness current_liveness =
+ liveness_
+ .Lookup(iterator.current_offset(),
+ OffsetHash(iterator.current_offset()))
+ ->value;
+ previous_in_liveness.CopyFrom(*current_liveness.in);
+
+ switch (iterator.current_bytecode()) {
+#define CASE(NAME, ...) \
+ case Bytecode::k##NAME: { \
+ UpdateLiveness<Bytecode::k##NAME, __VA_ARGS__>(current_liveness, iterator, \
+ liveness_); \
+ break; \
+ }
+
+ BYTECODE_LIST(CASE)
+#undef CASE
+ }
+
+ if (!liveness_changed &&
+ !current_liveness.in->Equals(previous_in_liveness)) {
+ liveness_changed = true;
+ }
+
+ iterator.Advance();
+ }
+ }
}
void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) {
@@ -92,6 +348,14 @@ int BytecodeAnalysis::GetParentLoopFor(int header_offset) const {
return header_to_parent_.find(header_offset)->second;
}
+const BitVector* BytecodeAnalysis::GetInLivenessFor(int offset) const {
+ return GetInLiveness(offset, liveness_);
+}
+
+const BitVector* BytecodeAnalysis::GetOutLivenessFor(int offset) const {
+ return GetOutLiveness(offset, liveness_);
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698