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

Unified Diff: src/compiler/liveness-analyzer.cc

Issue 949743002: [turbofan] Variable liveness analysis for deopt (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Test tweaks Created 5 years, 10 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
Index: src/compiler/liveness-analyzer.cc
diff --git a/src/compiler/liveness-analyzer.cc b/src/compiler/liveness-analyzer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c219ff6f33cd610e27a48c40d3d33a3fc3f14246
--- /dev/null
+++ b/src/compiler/liveness-analyzer.cc
@@ -0,0 +1,190 @@
+// Copyright 2014 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/compiler/liveness-analyzer.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/node.h"
+#include "src/compiler/node-matchers.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+
+LivenessAnalyzer::LivenessAnalyzer(size_t local_count, Zone* zone)
+ : zone_(zone), blocks_(zone), local_count_(local_count), queue_(zone) {}
+
+
+void LivenessAnalyzer::Print(std::ostream& os) {
+ for (auto block : blocks_) {
+ block->Print(os);
+ os << std::endl;
+ }
+}
+
+
+LivenessAnalyzerBlock* LivenessAnalyzer::New() {
+ LivenessAnalyzerBlock* result =
+ new (zone()) LivenessAnalyzerBlock(blocks_.size(), local_count_, zone());
+ blocks_.push_back(result);
+ return result;
+}
+
+
+LivenessAnalyzerBlock* LivenessAnalyzer::New(
+ LivenessAnalyzerBlock* predecessor) {
+ LivenessAnalyzerBlock* result = New();
+ result->AddPredecessor(predecessor);
+ return result;
+}
+
+
+void LivenessAnalyzer::Queue(LivenessAnalyzerBlock* block) {
+ if (!block->IsQueued()) {
+ block->SetQueued();
+ queue_.push(block);
+ }
+}
+
+
+void LivenessAnalyzer::Run(FrameStateRelaxer* relaxer) {
+ // Put all blocks into the queue.
+ DCHECK(queue_.empty());
+ for (auto block : blocks_) {
+ Queue(block);
+ }
+
+ // Compute the fix-point.
+ ZoneVector<bool> working_area(local_count_, false, zone_);
+ while (!queue_.empty()) {
+ LivenessAnalyzerBlock* block = queue_.front();
+ queue_.pop();
+ block->Process(&working_area, nullptr);
+
+ for (auto i = block->pred_begin(); i != block->pred_end(); i++) {
+ if ((*i)->UpdateLive(&working_area)) {
+ Queue(*i);
+ }
+ }
+ }
+
+ // Update the frame states according to the liveness.
+ for (auto block : blocks_) {
+ block->Process(&working_area, relaxer);
+ }
+}
+
+
+void LivenessAnalyzerBlock::Process(ZoneVector<bool>* result,
+ FrameStateRelaxer* relaxer) {
+ queued_ = false;
+
+ // Copy the bitvector to the target bit vector.
+ *result = live_;
+
+ for (auto i = entries_.rbegin(); i != entries_.rend(); i++) {
+ auto entry = *i;
+ switch (entry.kind()) {
+ case Entry::kLookup:
+ (*result)[entry.var()] = true;
+ break;
+ case Entry::kBind:
+ (*result)[entry.var()] = false;
+ break;
+ case Entry::kCheckpoint:
+ if (relaxer != nullptr) {
+ relaxer->RelaxFrameState(entry.node(), result);
+ }
+ break;
+ }
+ }
+}
+
+
+bool LivenessAnalyzerBlock::UpdateLive(ZoneVector<bool>* working_area) {
+ bool changed = false;
+ for (size_t i = 0; i < working_area->size(); i++) {
+ if ((*working_area)[i] && !live_[i]) {
+ // We can only make variables live during propagation.
+ live_[i] = true;
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+
+void FrameStateRelaxer::RelaxFrameState(Node* frame_state,
+ ZoneVector<bool>* liveness) {
+ DCHECK_EQ(frame_state->opcode(), IrOpcode::kFrameState);
+ Node* locals_state = frame_state->InputAt(1);
+ DCHECK_EQ(locals_state->opcode(), IrOpcode::kStateValues);
+ int count = locals_state->InputCount();
+ DCHECK_EQ(count, static_cast<int>(liveness->size()));
+ for (int i = 0; i < count; i++) {
+ bool live = (*liveness)[i] || blacklist_[i];
+ if (!live || locals_state->InputAt(i) != replacement_node_) {
+ Node* new_values = RelaxStateValues(locals_state, liveness);
+ frame_state->ReplaceInput(1, new_values);
+ break;
+ }
+ }
+}
+
+
+Node* FrameStateRelaxer::RelaxStateValues(Node* values,
+ ZoneVector<bool>* liveness) {
+ int count = values->InputCount();
+ ZoneVector<Node*> inputs(count, nullptr, local_zone());
+ for (int i = 0; i < count; i++) {
+ bool live = (*liveness)[i] || blacklist_[i];
+ inputs[i] = live ? values->InputAt(i) : replacement_node_;
+ }
+ const Operator* op = js_graph()->common()->StateValues(count);
+ return js_graph()->graph()->NewNode(op, count,
+ count == 0 ? nullptr : &(inputs.front()));
+}
+
+
+void LivenessAnalyzerBlock::Print(std::ostream& os) {
+ os << "Block " << id();
+ bool first = true;
+ for (LivenessAnalyzerBlock* pred : predecessors_) {
+ if (!first) {
+ os << ", ";
+ } else {
+ os << "; predecessors: ";
+ first = false;
+ }
+ os << pred->id();
+ }
+ os << std::endl;
+
+ for (auto entry : entries_) {
+ os << " ";
+ switch (entry.kind()) {
+ case Entry::kLookup:
+ os << "- Lookup " << entry.var() << std::endl;
+ break;
+ case Entry::kBind:
+ os << "- Bind " << entry.var() << std::endl;
+ break;
+ case Entry::kCheckpoint:
+ os << "- Checkpoint " << entry.node()->id() << std::endl;
+ break;
+ }
+ }
+
+ if (live_.size() > 0) {
+ os << " Live set: ";
+ for (bool live : live_) {
+ os << (live ? "L" : ".");
+ }
+ os << std::endl;
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698