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

Side by Side 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: Rebase 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 unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-peephole-optimizer.h ('k') | src/interpreter/bytecode-pipeline.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/interpreter/bytecode-peephole-optimizer.h"
6
7 #include "src/interpreter/constant-array-builder.h"
8 #include "src/objects-inl.h"
9 #include "src/objects.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace interpreter {
14
15 BytecodePeepholeOptimizer::BytecodePeepholeOptimizer(
16 ConstantArrayBuilder* constant_array_builder,
17 BytecodePipelineStage* next_stage)
18 : constant_array_builder_(constant_array_builder),
19 next_stage_(next_stage),
20 last_(Bytecode::kNop),
21 last_is_valid_(false),
22 last_is_discardable_(false) {
23 // TODO(oth): Remove last_is_valid_ and use kIllegal for last_ when
24 // not invalid. Currently blocked on bytecode generator emitting
25 // kIllegal for entry not found in jump table.
26 }
27
28 void BytecodePeepholeOptimizer::InvalidateLast() { last_is_valid_ = false; }
29
30 bool BytecodePeepholeOptimizer::LastIsValid() const { return last_is_valid_; }
31
32 void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) {
33 last_.Clone(node);
34 last_is_valid_ = true;
35 last_is_discardable_ = true;
36 }
37
38 // override
39 size_t BytecodePeepholeOptimizer::FlushForOffset() {
40 size_t buffered_size = next_stage_->FlushForOffset();
41 if (LastIsValid()) {
42 if (last_.bytecode() == Bytecode::kNop &&
43 !last_.source_info().is_statement()) {
44 // The Nop can be dropped as it doesn't have a statement
45 // position for the debugger and doesn't have any effects by
46 // definition.
47 InvalidateLast();
48 } else {
49 buffered_size += last_.Size();
50 last_is_discardable_ = false;
51 }
52 }
53 return buffered_size;
54 }
55
56 // override
57 void BytecodePeepholeOptimizer::FlushBasicBlock() {
58 if (LastIsValid()) {
59 next_stage_->Write(&last_);
60 InvalidateLast();
61 }
62 next_stage_->FlushBasicBlock();
63 }
64
65 // override
66 void BytecodePeepholeOptimizer::Write(BytecodeNode* node) {
67 // Attempt optimization if there is an earlier node to optimize with.
68 if (LastIsValid()) {
69 node = Optimize(node);
70 // Only output the last node if it wasn't invalidated by the optimization.
71 if (LastIsValid()) {
72 next_stage_->Write(&last_);
73 InvalidateLast();
74 }
75 }
76
77 if (node != nullptr) {
78 SetLast(node);
79 }
80 }
81
82 Handle<Object> BytecodePeepholeOptimizer::GetConstantForIndexOperand(
83 const BytecodeNode* const node, int index) const {
84 DCHECK_LE(index, node->operand_count());
85 DCHECK_EQ(Bytecodes::GetOperandType(node->bytecode(), 0), OperandType::kIdx);
86 uint32_t index_operand = node->operand(0);
87 return constant_array_builder_->At(index_operand);
88 }
89
90 bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const {
91 DCHECK(LastIsValid());
92 return (last_.bytecode() == Bytecode::kTypeOf ||
93 last_.bytecode() == Bytecode::kToName ||
94 (last_.bytecode() == Bytecode::kLdaConstant &&
95 GetConstantForIndexOperand(&last_, 0)->IsName()));
96 }
97
98 void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) {
99 // Conditional jumps with boolean conditions are emiitted in
100 // ToBoolean form by the bytecode array builder,
101 // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element
102 // can be removed if the previous bytecode put a boolean value in
103 // the accumulator.
104 if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
105 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
106 Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
107 current->set_bytecode(jump, current->operand(0), current->operand_scale());
108 }
109 }
110
111 bool BytecodePeepholeOptimizer::CanElideCurrent(
112 const BytecodeNode* const current) const {
113 if (Bytecodes::IsLdarOrStar(last_.bytecode()) &&
114 Bytecodes::IsLdarOrStar(current->bytecode()) &&
115 current->operand(0) == last_.operand(0)) {
116 // Ldar and Star make the accumulator and register hold equivalent
117 // values. Only the first bytecode is needed if there's a sequence
118 // of back-to-back Ldar and Star bytecodes with the same operand.
119 return true;
120 } else if (current->bytecode() == Bytecode::kToName &&
121 LastBytecodePutsNameInAccumulator()) {
122 // If the previous bytecode ensured a name was in the accumulator,
123 // the type coercion ToName() can be elided.
124 return true;
125 } else {
126 // Additional candidates for eliding current:
127 // (i) ToNumber if the last puts a number in the accumulator.
128 return false;
129 }
130 }
131
132 bool BytecodePeepholeOptimizer::CanElideLast(
133 const BytecodeNode* const current) const {
134 if (!last_is_discardable_) {
135 return false;
136 }
137
138 if (last_.bytecode() == Bytecode::kNop) {
139 // Nop are placeholders for holding source position information
140 // and can be elided.
141 return true;
142 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
143 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
144 // The accumulator is invisible to the debugger. If there is a sequence of
145 // consecutive accumulator loads (that don't have side effects) then only
146 // the final load is potentially visible.
147 return true;
148 } else {
149 return false;
150 }
151 }
152
153 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
154 UpdateCurrentBytecode(current);
155
156 if (CanElideCurrent(current)) {
157 if (current->source_info().is_valid()) {
158 current->set_bytecode(Bytecode::kNop);
159 } else {
160 current = nullptr;
161 }
162 } else if (CanElideLast(current)) {
163 if (last_.source_info().is_valid()) {
164 current->source_info().Update(last_.source_info());
165 }
166 InvalidateLast();
167 }
168 return current;
169 }
170
171 } // namespace interpreter
172 } // namespace internal
173 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-peephole-optimizer.h ('k') | src/interpreter/bytecode-pipeline.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698