Chromium Code Reviews| Index: src/interpreter/bytecode-peephole-optimizer.cc | 
| diff --git a/src/interpreter/bytecode-peephole-optimizer.cc b/src/interpreter/bytecode-peephole-optimizer.cc | 
| index 6b6589af41f544ecffea19a1615d6cdf88b0a811..e4105d326415bda213b705e1d85535149dc05c0e 100644 | 
| --- a/src/interpreter/bytecode-peephole-optimizer.cc | 
| +++ b/src/interpreter/bytecode-peephole-optimizer.cc | 
| @@ -94,21 +94,8 @@ bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const { | 
| GetConstantForIndexOperand(&last_, 0)->IsName())); | 
| } | 
| -void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) { | 
| - // Conditional jumps with boolean conditions are emiitted in | 
| - // ToBoolean form by the bytecode array builder, | 
| - // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element | 
| - // can be removed if the previous bytecode put a boolean value in | 
| - // the accumulator. | 
| - if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) && | 
| - Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) { | 
| - Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode()); | 
| - current->set_bytecode(jump, current->operand(0), current->operand_scale()); | 
| - } | 
| -} | 
| - | 
| bool BytecodePeepholeOptimizer::CanElideCurrent( | 
| - const BytecodeNode* const current) const { | 
| 
 
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
 
 | 
| + const BytecodeNode* const current) { | 
| if (Bytecodes::IsLdarOrStar(last_.bytecode()) && | 
| Bytecodes::IsLdarOrStar(current->bytecode()) && | 
| current->operand(0) == last_.operand(0)) { | 
| @@ -128,6 +115,76 @@ bool BytecodePeepholeOptimizer::CanElideCurrent( | 
| } | 
| } | 
| +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.
 
 | 
| + BytecodeNode* const current) { | 
| + bool can_simplify = last_.bytecode() == Bytecode::kLdar && | 
| + current->bytecode() == Bytecode::kMov && | 
| + last_.operand(0) == current->operand(0); | 
| + if (can_simplify) { | 
| + current->set_bytecode(Bytecode::kStar, current->operand(1), | 
| + current->operand_scale()); | 
| + } | 
| + return can_simplify; | 
| +} | 
| + | 
| +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
 
 | 
| + Bytecode new_bytecode, BytecodeNode* const current) { | 
| + last_.Transform(new_bytecode, current->operand(0), current->operand_scale()); | 
| + current->set_bytecode(Bytecode::kLdar, current->operand(0), | 
| + current->operand_scale()); | 
| + if (current->source_info().is_valid()) { | 
| + last_.source_info().Update(current->source_info()); | 
| + current->source_info().set_invalid(); | 
| + } | 
| +} | 
| + | 
| +bool BytecodePeepholeOptimizer::ChangeLdaToLdr(BytecodeNode* const current) { | 
| + if (current->bytecode() == Bytecode::kStar) { | 
| + switch (last_.bytecode()) { | 
| + case Bytecode::kLdaNamedProperty: | 
| + RewriteLastLoadAndStar(Bytecode::kLdrNamedProperty, current); | 
| + return true; | 
| + case Bytecode::kLdaKeyedProperty: | 
| + RewriteLastLoadAndStar(Bytecode::kLdrKeyedProperty, current); | 
| + return true; | 
| + case Bytecode::kLdaGlobal: | 
| + RewriteLastLoadAndStar(Bytecode::kLdrGlobal, current); | 
| + return true; | 
| + case Bytecode::kLdaContextSlot: | 
| + RewriteLastLoadAndStar(Bytecode::kLdrContextSlot, current); | 
| + return true; | 
| + case Bytecode::kLdaUndefined: | 
| + RewriteLastLoadAndStar(Bytecode::kLdrUndefined, current); | 
| + return true; | 
| + default: | 
| + break; | 
| + } | 
| + } | 
| + return false; | 
| +} | 
| + | 
| +bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump( | 
| + BytecodeNode* const current) { | 
| + bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) && | 
| + Bytecodes::WritesBooleanToAccumulator(last_.bytecode()); | 
| + if (can_remove) { | 
| + // Conditional jumps with boolean conditions are emiitted in | 
| + // ToBoolean form by the bytecode array builder, | 
| + // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean | 
| + // element can be removed if the previous bytecode put a boolean | 
| + // value in the accumulator. | 
| + Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode()); | 
| + current->set_bytecode(jump, current->operand(0), current->operand_scale()); | 
| + } | 
| + return can_remove; | 
| +} | 
| + | 
| +bool BytecodePeepholeOptimizer::SimpleSubstitution( | 
| + BytecodeNode* const current) { | 
| + 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.
 
 | 
| + ChangeLdarMovToLdarStar(current); | 
| +} | 
| + | 
| bool BytecodePeepholeOptimizer::CanElideLast( | 
| const BytecodeNode* const current) const { | 
| if (!last_is_discardable_) { | 
| @@ -144,25 +201,35 @@ bool BytecodePeepholeOptimizer::CanElideLast( | 
| // consecutive accumulator loads (that don't have side effects) then only | 
| // the final load is potentially visible. | 
| return true; | 
| + } else if (Bytecodes::GetAccumulatorUse(current->bytecode()) == | 
| + AccumulatorUse::kWrite && | 
| + Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { | 
| + // The current instruction clobbers the accumulator without reading it. The | 
| + // load in the last instruction can be elided as it has no effect. | 
| + return true; | 
| } else { | 
| return false; | 
| } | 
| } | 
| BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { | 
| - UpdateCurrentBytecode(current); | 
| - | 
| - if (CanElideCurrent(current)) { | 
| - if (current->source_info().is_valid()) { | 
| - current->set_bytecode(Bytecode::kNop); | 
| - } else { | 
| - current = nullptr; | 
| + 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.
 
 | 
| + if (CanElideCurrent(current)) { | 
| + if (current->source_info().is_valid()) { | 
| + if (current->source_info().is_statement()) { | 
| + current->set_bytecode(Bytecode::kNop); | 
| + } | 
| + } else { | 
| + return nullptr; | 
| + } | 
| } | 
| - } else if (CanElideLast(current)) { | 
| - if (last_.source_info().is_valid()) { | 
| - current->source_info().Update(last_.source_info()); | 
| + | 
| + if (CanElideLast(current)) { | 
| + if (last_.source_info().is_valid()) { | 
| + current->source_info().Update(last_.source_info()); | 
| + } | 
| + InvalidateLast(); | 
| } | 
| - InvalidateLast(); | 
| } | 
| return current; | 
| } |