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

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

Issue 1998203002: [Interpreter] Preserve source positions in peephole optimizer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Nitlet on last 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
« 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
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) { 97 void BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(
98 BytecodeNode* current) {
98 if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) && 99 if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
99 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) { 100 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
100 // Conditional jumps with boolean conditions are emitted in 101 // Conditional jumps with boolean conditions are emitted in
101 // ToBoolean form by the bytecode array builder, 102 // ToBoolean form by the bytecode array builder,
102 // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element 103 // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element
103 // can be removed if the previous bytecode put a boolean value in 104 // can be removed if the previous bytecode put a boolean value in
104 // the accumulator. 105 // the accumulator.
105 Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode()); 106 Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
106 current->set_bytecode(jump, current->operand(0), current->operand_scale()); 107 current->set_bytecode(jump, current->operand(0), current->operand_scale());
107 } else if (current->bytecode() == Bytecode::kToBooleanLogicalNot && 108 } else if (current->bytecode() == Bytecode::kToBooleanLogicalNot &&
108 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) { 109 Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
109 // Logical-nots are emitted in ToBoolean form by the bytecode array 110 // Logical-nots are emitted in ToBoolean form by the bytecode array
110 // builder, The ToBoolean element can be removed if the previous bytecode 111 // builder, The ToBoolean element can be removed if the previous bytecode
111 // put a boolean value in the accumulator. 112 // put a boolean value in the accumulator.
112 current->set_bytecode(Bytecode::kLogicalNot); 113 current->set_bytecode(Bytecode::kLogicalNot);
113 } 114 }
115
116 if (current->source_info().is_statement() &&
117 last_.source_info().is_expression() &&
118 Bytecodes::IsWithoutExternalSideEffects(last_.bytecode())) {
119 // The last bytecode has been marked as expression. It has no
120 // external effects so can't throw and the current bytecode is a
121 // source position. Remove the expression position on the last
122 // bytecode to open up potential peephole optimizations and to
123 // save the memory and perf cost of storing the unneeded
124 // expression position.
125 last_.source_info().set_invalid();
126 }
114 } 127 }
115 128
116 bool BytecodePeepholeOptimizer::CanElideCurrent( 129 bool BytecodePeepholeOptimizer::CanElideCurrent(
117 const BytecodeNode* const current) const { 130 const BytecodeNode* const current) const {
118 if (Bytecodes::IsLdarOrStar(last_.bytecode()) && 131 if (Bytecodes::IsLdarOrStar(last_.bytecode()) &&
119 Bytecodes::IsLdarOrStar(current->bytecode()) && 132 Bytecodes::IsLdarOrStar(current->bytecode()) &&
120 current->operand(0) == last_.operand(0)) { 133 current->operand(0) == last_.operand(0)) {
121 // Ldar and Star make the accumulator and register hold equivalent 134 // Ldar and Star make the accumulator and register hold equivalent
122 // values. Only the first bytecode is needed if there's a sequence 135 // values. Only the first bytecode is needed if there's a sequence
123 // of back-to-back Ldar and Star bytecodes with the same operand. 136 // of back-to-back Ldar and Star bytecodes with the same operand.
124 return true; 137 return true;
125 } else if (current->bytecode() == Bytecode::kToName && 138 } else if (current->bytecode() == Bytecode::kToName &&
126 LastBytecodePutsNameInAccumulator()) { 139 LastBytecodePutsNameInAccumulator()) {
127 // If the previous bytecode ensured a name was in the accumulator, 140 // If the previous bytecode ensured a name was in the accumulator,
128 // the type coercion ToName() can be elided. 141 // the type coercion ToName() can be elided.
129 return true; 142 return true;
130 } else { 143 } else {
131 // Additional candidates for eliding current: 144 // Additional candidates for eliding current:
132 // (i) ToNumber if the last puts a number in the accumulator. 145 // (i) ToNumber if the last puts a number in the accumulator.
133 return false; 146 return false;
134 } 147 }
135 } 148 }
136 149
150 bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition(
151 const BytecodeNode* const current) const {
152 //
153 // The rules for allowing the elision of the last bytecode based
154 // on source position are:
155 //
156 // C U R R E N T
157 // +--------+--------+--------+
158 // | None | Expr | Stmt |
159 // L +--------+--------+--------+--------+
160 // | None | YES | YES | YES |
161 // A +--------+--------+--------+--------+
162 // | Expr | YES | MAYBE | MAYBE |
163 // S +--------+--------+--------+--------+
164 // | Stmt | YES | NO | NO |
165 // T +--------+--------+--------+--------+
166 //
167 // The goal is not lose any statement positions and not lose useful
168 // expression positions. Whenever the last bytecode is elided it's
169 // source position information is applied to the current node
170 // updating it if necessary.
171 //
172 //
173 // The last bytecode can be elided for the MAYBE cases if the last
174 // bytecode is known not to throw. If it throws, the system would
175 // not have correct stack trace information. The appropriate check
176 // for this would be Bytecodes::IsWithoutExternalSideEffects(), which
177 // is checked in BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes()
178 // to keep the check here simple.
179 //
180 // In rare cases, bytecode generation produces consecutive bytecodes
181 // with the same expression positions. In principle, the latter of
182 // these can be elided, but would make this function more expensive.
183 //
184 return (!last_.source_info().is_valid() ||
185 !current->source_info().is_valid());
186 }
187
137 bool BytecodePeepholeOptimizer::CanElideLast( 188 bool BytecodePeepholeOptimizer::CanElideLast(
138 const BytecodeNode* const current) const { 189 const BytecodeNode* const current) const {
139 if (!last_is_discardable_) { 190 if (!last_is_discardable_) {
140 return false; 191 return false;
141 } 192 }
142 193
143 if (last_.bytecode() == Bytecode::kNop) { 194 if (last_.bytecode() == Bytecode::kNop) {
144 // Nop are placeholders for holding source position information 195 // Nop are placeholders for holding source position information.
145 // and can be elided.
146 return true; 196 return true;
147 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) && 197 } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
148 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) { 198 Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
149 // The accumulator is invisible to the debugger. If there is a sequence of 199 // The accumulator is invisible to the debugger. If there is a sequence of
150 // consecutive accumulator loads (that don't have side effects) then only 200 // consecutive accumulator loads (that don't have side effects) then only
151 // the final load is potentially visible. 201 // the final load is potentially visible.
152 return true; 202 return true;
153 } else { 203 } else {
154 return false; 204 return false;
155 } 205 }
156 } 206 }
157 207
158 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) { 208 BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
159 UpdateCurrentBytecode(current); 209 UpdateLastAndCurrentBytecodes(current);
160
161 if (CanElideCurrent(current)) { 210 if (CanElideCurrent(current)) {
162 if (current->source_info().is_valid()) { 211 if (current->source_info().is_valid()) {
163 current->set_bytecode(Bytecode::kNop); 212 current->set_bytecode(Bytecode::kNop);
164 } else { 213 } else {
165 current = nullptr; 214 current = nullptr;
166 } 215 }
167 } else if (CanElideLast(current)) { 216 } else if (CanElideLast(current) &&
168 if (last_.source_info().is_valid()) { 217 CanElideLastBasedOnSourcePosition(current)) {
169 current->source_info().Update(last_.source_info()); 218 current->source_info().Update(last_.source_info());
170 }
171 InvalidateLast(); 219 InvalidateLast();
172 } 220 }
173 return current; 221 return current;
174 } 222 }
175 223
176 } // namespace interpreter 224 } // namespace interpreter
177 } // namespace internal 225 } // namespace internal
178 } // namespace v8 226 } // 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