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

Unified Diff: src/interpreter/bytecode-peephole-optimizer.cc

Issue 1947403002: [interpreter] Introduce bytecode generation pipeline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix return type of BytecodeSourceInfo::is_statement() Created 4 years, 7 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/interpreter/bytecode-peephole-optimizer.cc
diff --git a/src/interpreter/bytecode-peephole-optimizer.cc b/src/interpreter/bytecode-peephole-optimizer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5621d2981b29699230c31ab995c1c7a4c0b452b2
--- /dev/null
+++ b/src/interpreter/bytecode-peephole-optimizer.cc
@@ -0,0 +1,123 @@
+// 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.
+
+#include "src/interpreter/bytecode-peephole-optimizer.h"
+
+#include "src/interpreter/constant-array-builder.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+BytecodePeepholeOptimizer::BytecodePeepholeOptimizer(
+ ConstantArrayBuilder* constant_array_builder, BytecodeWriter* output_writer)
+ : constant_array_builder_(constant_array_builder),
+ output_writer_(output_writer),
+ last_(nullptr),
+ last_is_discardable_(true) {}
+
+// override
+size_t BytecodePeepholeOptimizer::FlushForOffset() {
+ size_t buffered_size = output_writer_->FlushForOffset();
+ if (last_ != nullptr) {
+ if (last_->bytecode() == Bytecode::kNop &&
+ !last_->source_info().is_statement()) {
+ last_->Release();
+ last_ = nullptr;
+ } else {
+ buffered_size += last_->Size();
+ last_is_discardable_ = false;
+ }
+ }
+ return buffered_size;
+}
+
+// override
+void BytecodePeepholeOptimizer::LeaveBasicBlock() {
+ if (last_ != nullptr) {
+ output_writer_->Write(last_);
+ last_ = nullptr;
+ }
+ last_is_discardable_ = false;
+ output_writer_->LeaveBasicBlock();
+}
+
+// override
+void BytecodePeepholeOptimizer::Write(BytecodeNode* node) {
+ // Attempt optimization if there is an earlier node to optimize with.
+ if (last_ != nullptr) {
+ node = Optimize(node);
+ }
+
+ // Only output if optimization did not remove earlier node.
+ if (last_ != nullptr) {
+ output_writer_->Write(last_);
+ }
+
+ last_ = node;
+ last_is_discardable_ = true;
+}
+
+Handle<Object> BytecodePeepholeOptimizer::GetConstantForIndexOperand(
+ const BytecodeNode* const node, int index) const {
+ DCHECK_LE(index, node->operand_count());
+ DCHECK_EQ(Bytecodes::GetOperandType(node->bytecode(), 0), OperandType::kIdx);
+ uint32_t index_operand = node->operands()[0];
+ return constant_array_builder_->At(index_operand);
+}
+
+BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
rmcilroy 2016/05/06 15:25:48 This function is a bit hard for me to reason about
oth 2016/05/09 11:02:17 Done.
+ DCHECK_NE(current, last_);
+
+ // The current node can always be discarded here. The last node
+ // can only be discarded if last_is_discardable_ == true.
rmcilroy 2016/05/06 15:25:48 This comment isn't really true given the source po
oth 2016/05/09 11:02:17 Done.
+ if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
+ Bytecodes::WritesAccumulatorWithBoolean(last_->bytecode())) {
+ current->set_bytecode(
rmcilroy 2016/05/06 15:25:48 nit - could we have a replace_bytecode() in Byteco
oth 2016/05/09 11:02:17 Done.
+ Bytecodes::GetJumpWithoutToBoolean(current->bytecode()),
+ current->operands()[0], current->operand_scale());
+ return current;
+ } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
+ Bytecodes::IsAccumulatorLoadWithoutEffects(last_->bytecode()) &&
+ last_is_discardable_) {
+ last_->Release();
+ last_ = nullptr;
+ } else if ((last_->bytecode() == Bytecode::kLdar ||
+ last_->bytecode() == Bytecode::kStar) &&
+ (current->bytecode() == Bytecode::kLdar ||
+ current->bytecode() == Bytecode::kStar) &&
+ current->operands()[0] == last_->operands()[0]) {
+ // The current operation is moot as the last has performed desired effect.
+ // If current bytecode has a source position, change it to a nop, else it
+ // can be discarded. The next call to Optimize will try to remove the nop.
+ if (current->source_info().is_valid()) {
+ current->set_bytecode(Bytecode::kNop);
+ } else {
+ current->Release();
+ current = nullptr;
+ }
+ } else if (last_->bytecode() == Bytecode::kNop && last_is_discardable_) {
+ if (last_->source_info().is_valid()) {
+ current->source_info().Update(last_->source_info());
+ }
+ last_->Release();
+ last_ = nullptr;
+ } else if (current->bytecode() == Bytecode::kToName &&
+ !current->source_info().is_statement()) {
rmcilroy 2016/05/06 15:25:48 It's a bit weird that this is the only is_statemen
oth 2016/05/09 11:02:17 Cleaned-up in later CL. This is more oversight of
+ if (last_->bytecode() == Bytecode::kToName ||
+ last_->bytecode() == Bytecode::kTypeOf ||
+ (last_->bytecode() == Bytecode::kLdaConstant &&
+ GetConstantForIndexOperand(last_, 0)->IsName())) {
+ current->Release();
+ current = nullptr;
+ }
+ }
+ return current;
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698