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

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

Issue 2042633002: [interpreter] Ensure optimizations preserve source positions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 6 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/bytecodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 // 166 //
167 return (!last_.source_info().is_valid() || 167 return (!last_.source_info().is_valid() ||
168 !current->source_info().is_valid()); 168 !current->source_info().is_valid());
169 } 169 }
170 170
171 namespace { 171 namespace {
172 172
173 void TransformLdaStarToLdrLdar(Bytecode new_bytecode, BytecodeNode* const last, 173 void TransformLdaStarToLdrLdar(Bytecode new_bytecode, BytecodeNode* const last,
174 BytecodeNode* const current) { 174 BytecodeNode* const current) {
175 DCHECK_EQ(current->bytecode(), Bytecode::kStar); 175 DCHECK_EQ(current->bytecode(), Bytecode::kStar);
176
176 // 177 //
177 // An example transformation here would be: 178 // An example transformation here would be:
178 // 179 //
179 // LdaGlobal i0, i1 ____\ LdrGlobal i0, i1, R 180 // LdaGlobal i0, i1 ____\ LdrGlobal i0, i1, R
180 // Star R ====/ Ldar R 181 // Star R ====/ Ldar R
181 // 182 //
182 // which loads a global value into both a register and the 183 // which loads a global value into both a register and the
183 // accumulator. However, in the second form the Ldar can often be 184 // accumulator. However, in the second form the Ldar can often be
184 // peephole optimized away unlike the Star in the first form. 185 // peephole optimized away unlike the Star in the first form.
185 // 186 //
186 last->Transform(new_bytecode, current->operand(0), current->operand_scale()); 187 last->Transform(new_bytecode, current->operand(0), current->operand_scale());
187 current->set_bytecode(Bytecode::kLdar, current->operand(0), 188 current->set_bytecode(Bytecode::kLdar, current->operand(0),
188 current->operand_scale()); 189 current->operand_scale());
189
190 // If there was a source position on |current| transfer it to the
191 // updated |last| to maintain the debugger's causal view. ie. if an
192 // expression position LdrGlobal is the bytecode that could throw
193 // and if a statement position it needs to be placed before the
194 // store to R occurs.
195 last->source_info().Update(current->source_info());
196 current->source_info().set_invalid();
197 } 190 }
198 191
199 } // namespace 192 } // namespace
200 193
201 bool BytecodePeepholeOptimizer::ChangeLdaToLdr(BytecodeNode* const current) { 194 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes(
202 if (current->bytecode() == Bytecode::kStar) { 195 BytecodeNode* const current) {
196 if (current->bytecode() == Bytecode::kStar &&
197 !current->source_info().is_statement()) {
198 // Note: If the Star is tagged with a statement position, we can't
199 // perform this transform as the store to the register will
200 // have the wrong ordering for stepping in the debugger.
203 switch (last_.bytecode()) { 201 switch (last_.bytecode()) {
204 case Bytecode::kLdaNamedProperty: 202 case Bytecode::kLdaNamedProperty:
205 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current); 203 TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current);
206 return true; 204 return true;
207 case Bytecode::kLdaKeyedProperty: 205 case Bytecode::kLdaKeyedProperty:
208 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current); 206 TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current);
209 return true; 207 return true;
210 case Bytecode::kLdaGlobal: 208 case Bytecode::kLdaGlobal:
211 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current); 209 TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current);
212 return true; 210 return true;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); 243 Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
246 if (can_remove) { 244 if (can_remove) {
247 // Logical-nots are emitted in ToBoolean form by the bytecode array 245 // Logical-nots are emitted in ToBoolean form by the bytecode array
248 // builder, The ToBoolean element can be removed if the previous bytecode 246 // builder, The ToBoolean element can be removed if the previous bytecode
249 // put a boolean value in the accumulator. 247 // put a boolean value in the accumulator.
250 current->set_bytecode(Bytecode::kLogicalNot); 248 current->set_bytecode(Bytecode::kLogicalNot);
251 } 249 }
252 return can_remove; 250 return can_remove;
253 } 251 }
254 252
255 bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes( 253 bool BytecodePeepholeOptimizer::TransformCurrentBytecode(
256 BytecodeNode* const current) { 254 BytecodeNode* const current) {
257 return RemoveToBooleanFromJump(current) || 255 return RemoveToBooleanFromJump(current) ||
258 RemoveToBooleanFromLogicalNot(current) || ChangeLdaToLdr(current); 256 RemoveToBooleanFromLogicalNot(current);
259 } 257 }
260 258
261 bool BytecodePeepholeOptimizer::CanElideLast( 259 bool BytecodePeepholeOptimizer::CanElideLast(
262 const BytecodeNode* const current) const { 260 const BytecodeNode* const current) const {
263 if (last_.bytecode() == Bytecode::kNop) { 261 if (last_.bytecode() == Bytecode::kNop) {
264 // Nop are placeholders for holding source position information. 262 // Nop are placeholders for holding source position information.
265 return true; 263 return true;
266 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) && 264 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
267 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { 265 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
268 // The accumulator is invisible to the debugger. If there is a sequence of 266 // The accumulator is invisible to the debugger. If there is a sequence of
269 // consecutive accumulator loads (that don't have side effects) then only 267 // consecutive accumulator loads (that don't have side effects) then only
270 // the final load is potentially visible. 268 // the final load is potentially visible.
271 return true; 269 return true;
272 } else if (Bytecodes::GetAccumulatorUse(current->bytecode()) == 270 } else if (Bytecodes::GetAccumulatorUse(current->bytecode()) ==
273 AccumulatorUse::kWrite && 271 AccumulatorUse::kWrite &&
274 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { 272 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
275 // The current instruction clobbers the accumulator without reading it. The 273 // The current instruction clobbers the accumulator without reading it. The
276 // load in the last instruction can be elided as it has no effect. 274 // load in the last instruction can be elided as it has no effect.
277 return true; 275 return true;
278 } else { 276 } else {
279 return false; 277 return false;
280 } 278 }
281 } 279 }
282 280
283 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { 281 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
284 TryToRemoveLastExpressionPosition(current); 282 TryToRemoveLastExpressionPosition(current);
285 283
286 if (TransformLastAndCurrentBytecodes(current)) { 284 if (TransformCurrentBytecode(current) ||
285 TransformLastAndCurrentBytecodes(current)) {
287 return current; 286 return current;
288 } 287 }
289 288
290 if (CanElideCurrent(current)) { 289 if (CanElideCurrent(current)) {
291 if (current->source_info().is_valid()) { 290 if (current->source_info().is_valid()) {
292 // Preserve the source information by replacing the current bytecode 291 // Preserve the source information by replacing the current bytecode
293 // with a no op bytecode. 292 // with a no op bytecode.
294 current->set_bytecode(Bytecode::kNop); 293 current->set_bytecode(Bytecode::kNop);
295 } else { 294 } else {
296 current = nullptr; 295 current = nullptr;
(...skipping 20 matching lines...) Expand all
317 next_stage_->Write(&last_); 316 next_stage_->Write(&last_);
318 InvalidateLast(); 317 InvalidateLast();
319 } 318 }
320 } 319 }
321 return current; 320 return current;
322 } 321 }
323 322
324 } // namespace interpreter 323 } // namespace interpreter
325 } // namespace internal 324 } // namespace internal
326 } // namespace v8 325 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-peephole-optimizer.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698