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

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: Incorporate review comments. 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..c6ec096eb261f3ca470ddd9985478a7b94db83fe
--- /dev/null
+++ b/src/interpreter/bytecode-peephole-optimizer.cc
@@ -0,0 +1,138 @@
+// 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,
+ BytecodePipelineStage* next_stage)
+ : constant_array_builder_(constant_array_builder),
+ next_stage_(next_stage),
+ last_(nullptr),
+ last_is_discardable_(true) {}
+
+// override
+size_t BytecodePeepholeOptimizer::FlushForOffset() {
+ size_t buffered_size = next_stage_->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() {
rmcilroy 2016/05/10 11:14:09 How about FlushForNewBasicBlock()?
oth 2016/05/11 13:17:30 I hate to bikeshed, but it really is used at the e
rmcilroy 2016/05/12 12:15:13 Works for me, thanks!
+ if (last_ != nullptr) {
+ next_stage_->Write(last_);
+ last_ = nullptr;
+ }
+ last_is_discardable_ = false;
+ next_stage_->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) {
+ next_stage_->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);
+}
+
+void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) {
+ if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
+ Bytecodes::WritesAccumulatorWithBoolean(last_->bytecode())) {
+ Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
rmcilroy 2016/05/10 11:14:09 nit - comment.
oth 2016/05/11 13:17:31 Done.
+ current->replace_bytecode(jump);
+ }
+}
+
+bool BytecodePeepholeOptimizer::CanElideCurrent(
+ const BytecodeNode* const current) const {
+ if ((last_->bytecode() == Bytecode::kLdar ||
+ last_->bytecode() == Bytecode::kStar) &&
rmcilroy 2016/05/10 11:14:10 nit - add Bytecodes::IsLdarOrStar() helper
oth 2016/05/11 13:17:30 Done.
+ (current->bytecode() == Bytecode::kLdar ||
+ current->bytecode() == Bytecode::kStar) &&
+ current->operands()[0] == last_->operands()[0]) {
+ return true;
rmcilroy 2016/05/10 11:14:09 Comment on all branches with reasoning behind deci
oth 2016/05/11 13:17:31 Done.
+ } else if (current->bytecode() == Bytecode::kToName &&
+ (last_->bytecode() == Bytecode::kTypeOf ||
+ (last_->bytecode() == Bytecode::kLdaConstant &&
+ GetConstantForIndexOperand(last_, 0)->IsName()) ||
+ last_->bytecode() == Bytecode::kToName)) {
rmcilroy 2016/05/10 11:14:10 This if check is pretty difficult to parse. Could
oth 2016/05/11 13:17:30 Done.
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool BytecodePeepholeOptimizer::CanElideLast(
+ const BytecodeNode* const current) const {
+ if (!last_is_discardable_ || (last_->source_info().is_statement() &&
+ current->source_info().is_statement())) {
+ return false;
rmcilroy 2016/05/10 11:14:10 Comment on all branches with reasoning behind deci
oth 2016/05/11 13:17:30 Done.
+ } else if (last_->bytecode() == Bytecode::kNop) {
+ return true;
+ } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
+ Bytecodes::IsAccumulatorLoadWithoutEffects(last_->bytecode())) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
+ UpdateCurrentBytecode(current);
+
+ if (CanElideCurrent(current)) {
+ if (current->source_info().is_valid()) {
+ current->replace_bytecode(Bytecode::kNop);
+ } else {
+ current->Release();
+ current = nullptr;
+ }
+ } else if (CanElideLast(current)) {
+ if (last_->source_info().is_valid()) {
+ current->source_info().Update(last_->source_info());
+ }
+ last_->Release();
+ last_ = nullptr;
+ }
+
+ return current;
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698