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

Side by Side Diff: src/interpreter/bytecode-peephole-optimizer.cc

Issue 1985753002: [interpreter] Introduce fused bytecodes for common sequences. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-peephole-optimizer.h" 5 #include "src/interpreter/bytecode-peephole-optimizer.h"
6 6
7 #include "src/interpreter/constant-array-builder.h" 7 #include "src/interpreter/constant-array-builder.h"
8 #include "src/objects-inl.h" 8 #include "src/objects-inl.h"
9 #include "src/objects.h" 9 #include "src/objects.h"
10 10
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 87 }
88 88
89 bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const { 89 bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const {
90 DCHECK(LastIsValid()); 90 DCHECK(LastIsValid());
91 return (last_.bytecode() == Bytecode::kTypeOf || 91 return (last_.bytecode() == Bytecode::kTypeOf ||
92 last_.bytecode() == Bytecode::kToName || 92 last_.bytecode() == Bytecode::kToName ||
93 (last_.bytecode() == Bytecode::kLdaConstant && 93 (last_.bytecode() == Bytecode::kLdaConstant &&
94 GetConstantForIndexOperand(&last_, 0)->IsName())); 94 GetConstantForIndexOperand(&last_, 0)->IsName()));
95 } 95 }
96 96
97 void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) {
98 // Conditional jumps with boolean conditions are emiitted in
99 // ToBoolean form by the bytecode array builder,
100 // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element
101 // can be removed if the previous bytecode put a boolean value in
102 // the accumulator.
103 if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
104 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
105 Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
106 current->set_bytecode(jump, current->operand(0), current->operand_scale());
107 }
108 }
109
110 bool BytecodePeepholeOptimizer::CanElideCurrent( 97 bool BytecodePeepholeOptimizer::CanElideCurrent(
111 const BytecodeNode* const current) const { 98 const BytecodeNode* const current) {
rmcilroy 2016/05/17 15:49:33 Still const?
oth 2016/05/18 20:22:25 Done. Oops, lost const when it incorporated the ch
112 if (Bytecodes::IsLdarOrStar(last_.bytecode()) && 99 if (Bytecodes::IsLdarOrStar(last_.bytecode()) &&
113 Bytecodes::IsLdarOrStar(current->bytecode()) && 100 Bytecodes::IsLdarOrStar(current->bytecode()) &&
114 current->operand(0) == last_.operand(0)) { 101 current->operand(0) == last_.operand(0)) {
115 // Ldar and Star make the accumulator and register hold equivalent 102 // Ldar and Star make the accumulator and register hold equivalent
116 // values. Only the first bytecode is needed if there's a sequence 103 // values. Only the first bytecode is needed if there's a sequence
117 // of back-to-back Ldar and Star bytecodes with the same operand. 104 // of back-to-back Ldar and Star bytecodes with the same operand.
118 return true; 105 return true;
119 } else if (current->bytecode() == Bytecode::kToName && 106 } else if (current->bytecode() == Bytecode::kToName &&
120 LastBytecodePutsNameInAccumulator()) { 107 LastBytecodePutsNameInAccumulator()) {
121 // If the previous bytecode ensured a name was in the accumulator, 108 // If the previous bytecode ensured a name was in the accumulator,
122 // the type coercion ToName() can be elided. 109 // the type coercion ToName() can be elided.
123 return true; 110 return true;
124 } else { 111 } else {
125 // Additional candidates for eliding current: 112 // Additional candidates for eliding current:
126 // (i) ToNumber if the last puts a number in the accumulator. 113 // (i) ToNumber if the last puts a number in the accumulator.
127 return false; 114 return false;
128 } 115 }
129 } 116 }
130 117
118 bool BytecodePeepholeOptimizer::ChangeLdarMovToLdarStar(
rmcilroy 2016/05/17 15:49:33 This seems unrelated to the other optimizations. C
oth 2016/05/18 20:22:25 Done.
119 BytecodeNode* const current) {
120 bool can_simplify = last_.bytecode() == Bytecode::kLdar &&
121 current->bytecode() == Bytecode::kMov &&
122 last_.operand(0) == current->operand(0);
123 if (can_simplify) {
124 current->set_bytecode(Bytecode::kStar, current->operand(1),
125 current->operand_scale());
126 }
127 return can_simplify;
128 }
129
130 void BytecodePeepholeOptimizer::RewriteLastLoadAndStar(
rmcilroy 2016/05/17 15:49:33 The name confuses me. How about RewriteLdaToLdr.
oth 2016/05/18 20:22:25 Changed to ChangeLoadStarToLdrLdar() which describ
131 Bytecode new_bytecode, BytecodeNode* const current) {
132 last_.Transform(new_bytecode, current->operand(0), current->operand_scale());
133 current->set_bytecode(Bytecode::kLdar, current->operand(0),
134 current->operand_scale());
135 if (current->source_info().is_valid()) {
136 last_.source_info().Update(current->source_info());
137 current->source_info().set_invalid();
138 }
139 }
140
141 bool BytecodePeepholeOptimizer::ChangeLdaToLdr(BytecodeNode* const current) {
142 if (current->bytecode() == Bytecode::kStar) {
143 switch (last_.bytecode()) {
144 case Bytecode::kLdaNamedProperty:
145 RewriteLastLoadAndStar(Bytecode::kLdrNamedProperty, current);
146 return true;
147 case Bytecode::kLdaKeyedProperty:
148 RewriteLastLoadAndStar(Bytecode::kLdrKeyedProperty, current);
149 return true;
150 case Bytecode::kLdaGlobal:
151 RewriteLastLoadAndStar(Bytecode::kLdrGlobal, current);
152 return true;
153 case Bytecode::kLdaContextSlot:
154 RewriteLastLoadAndStar(Bytecode::kLdrContextSlot, current);
155 return true;
156 case Bytecode::kLdaUndefined:
157 RewriteLastLoadAndStar(Bytecode::kLdrUndefined, current);
158 return true;
159 default:
160 break;
161 }
162 }
163 return false;
164 }
165
166 bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump(
167 BytecodeNode* const current) {
168 bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
169 Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
170 if (can_remove) {
171 // Conditional jumps with boolean conditions are emiitted in
172 // ToBoolean form by the bytecode array builder,
173 // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean
174 // element can be removed if the previous bytecode put a boolean
175 // value in the accumulator.
176 Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
177 current->set_bytecode(jump, current->operand(0), current->operand_scale());
178 }
179 return can_remove;
180 }
181
182 bool BytecodePeepholeOptimizer::SimpleSubstitution(
183 BytecodeNode* const current) {
184 return RemoveToBooleanFromJump(current) || ChangeLdaToLdr(current) ||
rmcilroy 2016/05/17 15:49:33 I think ChangeLdaToLdr should really be in CanElid
oth 2016/05/18 20:22:25 This was actually implemented during the construct
rmcilroy 2016/05/19 10:01:02 Acknowledged.
185 ChangeLdarMovToLdarStar(current);
186 }
187
131 bool BytecodePeepholeOptimizer::CanElideLast( 188 bool BytecodePeepholeOptimizer::CanElideLast(
132 const BytecodeNode* const current) const { 189 const BytecodeNode* const current) const {
133 if (!last_is_discardable_) { 190 if (!last_is_discardable_) {
134 return false; 191 return false;
135 } 192 }
136 193
137 if (last_.bytecode() == Bytecode::kNop) { 194 if (last_.bytecode() == Bytecode::kNop) {
138 // Nop are placeholders for holding source position information 195 // Nop are placeholders for holding source position information
139 // and can be elided. 196 // and can be elided.
140 return true; 197 return true;
141 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) && 198 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
142 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { 199 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
143 // The accumulator is invisible to the debugger. If there is a sequence of 200 // The accumulator is invisible to the debugger. If there is a sequence of
144 // consecutive accumulator loads (that don't have side effects) then only 201 // consecutive accumulator loads (that don't have side effects) then only
145 // the final load is potentially visible. 202 // the final load is potentially visible.
146 return true; 203 return true;
204 } else if (Bytecodes::GetAccumulatorUse(current->bytecode()) ==
205 AccumulatorUse::kWrite &&
206 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
207 // The current instruction clobbers the accumulator without reading it. The
208 // load in the last instruction can be elided as it has no effect.
209 return true;
147 } else { 210 } else {
148 return false; 211 return false;
149 } 212 }
150 } 213 }
151 214
152 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { 215 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
153 UpdateCurrentBytecode(current); 216 if (!SimpleSubstitution(current)) {
rmcilroy 2016/05/17 15:49:33 Why the change in behaviour here? I think it makes
oth 2016/05/18 20:22:25 As discussed above, this is not appealing. There i
rmcilroy 2016/05/19 10:01:02 Acknowledged.
217 if (CanElideCurrent(current)) {
218 if (current->source_info().is_valid()) {
219 if (current->source_info().is_statement()) {
220 current->set_bytecode(Bytecode::kNop);
221 }
222 } else {
223 return nullptr;
224 }
225 }
154 226
155 if (CanElideCurrent(current)) { 227 if (CanElideLast(current)) {
156 if (current->source_info().is_valid()) { 228 if (last_.source_info().is_valid()) {
157 current->set_bytecode(Bytecode::kNop); 229 current->source_info().Update(last_.source_info());
158 } else { 230 }
159 current = nullptr; 231 InvalidateLast();
160 } 232 }
161 } else if (CanElideLast(current)) {
162 if (last_.source_info().is_valid()) {
163 current->source_info().Update(last_.source_info());
164 }
165 InvalidateLast();
166 } 233 }
167 return current; 234 return current;
168 } 235 }
169 236
170 } // namespace interpreter 237 } // namespace interpreter
171 } // namespace internal 238 } // namespace internal
172 } // namespace v8 239 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698