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 803fc23089927faf47fe893deb178dd479265d6f..cff15f6f8050c93f1826832b7c187b3ed9a4f905 100644 |
| --- a/src/interpreter/bytecode-peephole-optimizer.cc |
| +++ b/src/interpreter/bytecode-peephole-optimizer.cc |
| @@ -94,7 +94,8 @@ bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const { |
| GetConstantForIndexOperand(&last_, 0)->IsName())); |
| } |
| -void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) { |
| +void BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes( |
| + BytecodeNode* current) { |
| if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) && |
| Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) { |
| // Conditional jumps with boolean conditions are emitted in |
| @@ -111,6 +112,18 @@ void BytecodePeepholeOptimizer::UpdateCurrentBytecode(BytecodeNode* current) { |
| // put a boolean value in the accumulator. |
| current->set_bytecode(Bytecode::kLogicalNot); |
| } |
| + |
| + if (current->source_info().is_statement() && |
| + last_.source_info().is_expression() && |
| + Bytecodes::IsWithoutExternalSideEffects(last_.bytecode())) { |
| + // The last bytecode has been marked as expression. It has no |
| + // external effects so can't throw and the current bytecode is a |
| + // source position. Remove the expression position on the last |
| + // bytecode to open up potential peephole optimizations and to |
| + // save the memory and perf cost of storing the unneeded |
| + // expression position. |
| + last_.source_info().set_invalid(); |
| + } |
| } |
| bool BytecodePeepholeOptimizer::CanElideCurrent( |
| @@ -134,6 +147,38 @@ bool BytecodePeepholeOptimizer::CanElideCurrent( |
| } |
| } |
| +bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition( |
| + const BytecodeNode* const current) const { |
| + // |
| + // The rules for allowing the elision of the last bytecode based |
| + // on source position are: |
| + // |
| + // C U R R E N T |
| + // +--------+--------+--------+ |
| + // | None | Expr | Stmt | |
| + // L +--------+--------+--------+--------+ |
| + // | None | YES | YES | YES | |
| + // A +--------+--------+--------+--------+ |
| + // | Expr | YES | MAYBE | MAYBE | |
| + // S +--------+--------+--------+--------+ |
| + // | Stmt | YES | NO | NO | |
| + // T +--------+--------+--------+--------+ |
| + // |
| + // The goal is not lose any statement positions and not lose useful |
| + // expression positions. Whenever the last bytecode is elided it's |
| + // source position information is applied to the current node |
| + // updating it if necessary. |
| + // |
| + // The last bytecode can be elided for the MAYBE cases if the last |
| + // bytecode is known not to throw. If it throws, the system would |
| + // not have correct stack trace information. The appropriate check |
| + // for this would be Bytecodes::IsWithoutExternalSideEffects(), but |
| + // this is not performed here to keep the check simple. |
|
rmcilroy
2016/05/23 10:59:26
nit - /s/but this is not.../which is checked in Up
oth
2016/05/23 11:22:42
Done.
|
| + // |
| + return (!last_.source_info().is_valid() || |
| + !current->source_info().is_valid()); |
| +} |
| + |
| bool BytecodePeepholeOptimizer::CanElideLast( |
| const BytecodeNode* const current) const { |
| if (!last_is_discardable_) { |
| @@ -141,8 +186,7 @@ bool BytecodePeepholeOptimizer::CanElideLast( |
| } |
| if (last_.bytecode() == Bytecode::kNop) { |
| - // Nop are placeholders for holding source position information |
| - // and can be elided. |
| + // Nop are placeholders for holding source position information. |
| return true; |
| } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) && |
| Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { |
| @@ -156,18 +200,16 @@ bool BytecodePeepholeOptimizer::CanElideLast( |
| } |
| BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { |
| - UpdateCurrentBytecode(current); |
| - |
| + UpdateLastAndCurrentBytecodes(current); |
| if (CanElideCurrent(current)) { |
| if (current->source_info().is_valid()) { |
| current->set_bytecode(Bytecode::kNop); |
| } else { |
| current = nullptr; |
| } |
| - } else if (CanElideLast(current)) { |
| - if (last_.source_info().is_valid()) { |
| - current->source_info().Update(last_.source_info()); |
| - } |
| + } else if (CanElideLast(current) && |
| + CanElideLastBasedOnSourcePosition(current)) { |
| + current->source_info().Update(last_.source_info()); |
| InvalidateLast(); |
| } |
| return current; |