OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/objects-inl.h" | 7 #include "src/objects-inl.h" |
8 #include "src/objects.h" | 8 #include "src/objects.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 namespace interpreter { | 12 namespace interpreter { |
13 | 13 |
14 BytecodePeepholeOptimizer::BytecodePeepholeOptimizer( | 14 BytecodePeepholeOptimizer::BytecodePeepholeOptimizer( |
15 BytecodePipelineStage* next_stage) | 15 BytecodePipelineStage* next_stage) |
16 : next_stage_(next_stage), last_(Bytecode::kIllegal, BytecodeSourceInfo()) { | 16 : next_stage_(next_stage), |
| 17 last_(BytecodeNode::Create<Bytecode::kIllegal>()) { |
17 InvalidateLast(); | 18 InvalidateLast(); |
18 } | 19 } |
19 | 20 |
20 // override | 21 // override |
21 Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray( | 22 Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray( |
22 Isolate* isolate, int register_count, int parameter_count, | 23 Isolate* isolate, int register_count, int parameter_count, |
23 Handle<FixedArray> handler_table) { | 24 Handle<FixedArray> handler_table) { |
24 Flush(); | 25 Flush(); |
25 return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, | 26 return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, |
26 handler_table); | 27 handler_table); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 } | 59 } |
59 | 60 |
60 void BytecodePeepholeOptimizer::Flush() { | 61 void BytecodePeepholeOptimizer::Flush() { |
61 if (LastIsValid()) { | 62 if (LastIsValid()) { |
62 next_stage_->Write(&last_); | 63 next_stage_->Write(&last_); |
63 InvalidateLast(); | 64 InvalidateLast(); |
64 } | 65 } |
65 } | 66 } |
66 | 67 |
67 void BytecodePeepholeOptimizer::InvalidateLast() { | 68 void BytecodePeepholeOptimizer::InvalidateLast() { |
68 last_.set_bytecode(Bytecode::kIllegal); | 69 last_ = BytecodeNode::Create<Bytecode::kIllegal>(); |
69 } | 70 } |
70 | 71 |
71 bool BytecodePeepholeOptimizer::LastIsValid() const { | 72 bool BytecodePeepholeOptimizer::LastIsValid() const { |
72 return last_.bytecode() != Bytecode::kIllegal; | 73 return last_.bytecode() != Bytecode::kIllegal; |
73 } | 74 } |
74 | 75 |
75 void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) { | 76 void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) { |
76 // An action shouldn't leave a NOP as last bytecode unless it has | 77 // An action shouldn't leave a NOP as last bytecode unless it has |
77 // source position information. NOP without source information can | 78 // source position information. NOP without source information can |
78 // always be elided. | 79 // always be elided. |
(...skipping 30 matching lines...) Expand all Loading... |
109 // default, the upstream bytecode generator filters out unneeded | 110 // default, the upstream bytecode generator filters out unneeded |
110 // expression position information so there is neglible benefit to | 111 // expression position information so there is neglible benefit to |
111 // handling MAYBE specially. Hence MAYBE is treated the same as NO. | 112 // handling MAYBE specially. Hence MAYBE is treated the same as NO. |
112 // | 113 // |
113 return (!last_.source_info().is_valid() || | 114 return (!last_.source_info().is_valid() || |
114 !current->source_info().is_valid()); | 115 !current->source_info().is_valid()); |
115 } | 116 } |
116 | 117 |
117 namespace { | 118 namespace { |
118 | 119 |
119 void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, | 120 BytecodeNode TransformLdaSmiBinaryOpToBinaryOpWithSmi( |
120 BytecodeNode* const last, | 121 Bytecode new_bytecode, BytecodeNode* const last, |
121 BytecodeNode* const current) { | 122 BytecodeNode* const current) { |
122 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); | 123 DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi); |
123 current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), | 124 BytecodeNode node(new_bytecode, last->operand(0), current->operand(0), |
124 current->operand(1)); | 125 current->operand(1), current->source_info()); |
125 if (last->source_info().is_valid()) { | 126 if (last->source_info().is_valid()) { |
126 current->set_source_info(last->source_info()); | 127 node.set_source_info(last->source_info()); |
127 } | 128 } |
| 129 return node; |
128 } | 130 } |
129 | 131 |
130 void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, | 132 BytecodeNode TransformLdaZeroBinaryOpToBinaryOpWithZero( |
131 BytecodeNode* const last, | 133 Bytecode new_bytecode, BytecodeNode* const last, |
132 BytecodeNode* const current) { | 134 BytecodeNode* const current) { |
133 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); | 135 DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero); |
134 current->set_bytecode(new_bytecode, 0, current->operand(0), | 136 BytecodeNode node(new_bytecode, 0, current->operand(0), current->operand(1), |
135 current->operand(1)); | 137 current->source_info()); |
136 if (last->source_info().is_valid()) { | 138 if (last->source_info().is_valid()) { |
137 current->set_source_info(last->source_info()); | 139 node.set_source_info(last->source_info()); |
138 } | 140 } |
| 141 return node; |
139 } | 142 } |
140 | 143 |
141 } // namespace | 144 } // namespace |
142 | 145 |
143 void BytecodePeepholeOptimizer::DefaultAction( | 146 void BytecodePeepholeOptimizer::DefaultAction( |
144 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 147 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
145 DCHECK(LastIsValid()); | 148 DCHECK(LastIsValid()); |
146 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 149 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
147 | 150 |
148 next_stage()->Write(last()); | 151 next_stage()->Write(last()); |
(...skipping 19 matching lines...) Expand all Loading... |
168 } | 171 } |
169 | 172 |
170 void BytecodePeepholeOptimizer::ElideCurrentAction( | 173 void BytecodePeepholeOptimizer::ElideCurrentAction( |
171 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 174 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
172 DCHECK(LastIsValid()); | 175 DCHECK(LastIsValid()); |
173 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 176 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
174 | 177 |
175 if (node->source_info().is_valid()) { | 178 if (node->source_info().is_valid()) { |
176 // Preserve the source information by replacing the node bytecode | 179 // Preserve the source information by replacing the node bytecode |
177 // with a no op bytecode. | 180 // with a no op bytecode. |
178 node->set_bytecode(Bytecode::kNop); | 181 BytecodeNode new_node = |
179 DefaultAction(node); | 182 BytecodeNode::Create<Bytecode::kNop>(node->source_info()); |
| 183 DefaultAction(&new_node); |
180 } else { | 184 } else { |
181 // Nothing to do, keep last and wait for next bytecode to pair with it. | 185 // Nothing to do, keep last and wait for next bytecode to pair with it. |
182 } | 186 } |
183 } | 187 } |
184 | 188 |
185 void BytecodePeepholeOptimizer::ElideCurrentIfOperand0MatchesAction( | 189 void BytecodePeepholeOptimizer::ElideCurrentIfOperand0MatchesAction( |
186 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 190 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
187 DCHECK(LastIsValid()); | 191 DCHECK(LastIsValid()); |
188 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 192 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
189 | 193 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 DefaultAction(node); | 225 DefaultAction(node); |
222 } | 226 } |
223 | 227 |
224 void BytecodePeepholeOptimizer::TransformLdaSmiBinaryOpToBinaryOpWithSmiAction( | 228 void BytecodePeepholeOptimizer::TransformLdaSmiBinaryOpToBinaryOpWithSmiAction( |
225 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 229 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
226 DCHECK(LastIsValid()); | 230 DCHECK(LastIsValid()); |
227 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 231 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
228 | 232 |
229 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { | 233 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { |
230 // Fused last and current into current. | 234 // Fused last and current into current. |
231 TransformLdaSmiBinaryOpToBinaryOpWithSmi(action_data->bytecode, last(), | 235 BytecodeNode new_node(TransformLdaSmiBinaryOpToBinaryOpWithSmi( |
232 node); | 236 action_data->bytecode, last(), node)); |
233 SetLast(node); | 237 SetLast(&new_node); |
234 } else { | 238 } else { |
235 DefaultAction(node); | 239 DefaultAction(node); |
236 } | 240 } |
237 } | 241 } |
238 | 242 |
239 void BytecodePeepholeOptimizer:: | 243 void BytecodePeepholeOptimizer:: |
240 TransformLdaZeroBinaryOpToBinaryOpWithZeroAction( | 244 TransformLdaZeroBinaryOpToBinaryOpWithZeroAction( |
241 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 245 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
242 DCHECK(LastIsValid()); | 246 DCHECK(LastIsValid()); |
243 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 247 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
244 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { | 248 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { |
245 // Fused last and current into current. | 249 // Fused last and current into current. |
246 TransformLdaZeroBinaryOpToBinaryOpWithZero(action_data->bytecode, last(), | 250 BytecodeNode new_node(TransformLdaZeroBinaryOpToBinaryOpWithZero( |
247 node); | 251 action_data->bytecode, last(), node)); |
248 SetLast(node); | 252 SetLast(&new_node); |
249 } else { | 253 } else { |
250 DefaultAction(node); | 254 DefaultAction(node); |
251 } | 255 } |
252 } | 256 } |
253 | 257 |
254 void BytecodePeepholeOptimizer::DefaultJumpAction( | 258 void BytecodePeepholeOptimizer::DefaultJumpAction( |
255 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 259 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
256 DCHECK(LastIsValid()); | 260 DCHECK(LastIsValid()); |
257 DCHECK(Bytecodes::IsJump(node->bytecode())); | 261 DCHECK(Bytecodes::IsJump(node->bytecode())); |
258 | 262 |
259 next_stage()->Write(last()); | 263 next_stage()->Write(last()); |
260 InvalidateLast(); | 264 InvalidateLast(); |
261 } | 265 } |
262 | 266 |
263 void BytecodePeepholeOptimizer::UpdateLastJumpAction( | 267 void BytecodePeepholeOptimizer::UpdateLastJumpAction( |
264 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 268 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
265 DCHECK(!LastIsValid()); | 269 DCHECK(!LastIsValid()); |
266 DCHECK(Bytecodes::IsJump(node->bytecode())); | 270 DCHECK(Bytecodes::IsJump(node->bytecode())); |
267 } | 271 } |
268 | 272 |
269 void BytecodePeepholeOptimizer::ChangeJumpBytecodeAction( | 273 void BytecodePeepholeOptimizer::ChangeJumpBytecodeAction( |
270 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 274 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
271 DCHECK(LastIsValid()); | 275 DCHECK(LastIsValid()); |
272 DCHECK(Bytecodes::IsJump(node->bytecode())); | 276 DCHECK(Bytecodes::IsJump(node->bytecode())); |
273 | 277 |
274 next_stage()->Write(last()); | 278 next_stage()->Write(last()); |
275 InvalidateLast(); | 279 InvalidateLast(); |
276 node->set_bytecode(action_data->bytecode, node->operand(0)); | 280 node->replace_bytecode(action_data->bytecode); |
277 } | 281 } |
278 | 282 |
279 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( | 283 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( |
280 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 284 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
281 DCHECK(LastIsValid()); | 285 DCHECK(LastIsValid()); |
282 DCHECK(Bytecodes::IsJump(node->bytecode())); | 286 DCHECK(Bytecodes::IsJump(node->bytecode())); |
283 | 287 |
284 if (!CanElideLastBasedOnSourcePosition(node)) { | 288 if (!CanElideLastBasedOnSourcePosition(node)) { |
285 next_stage()->Write(last()); | 289 next_stage()->Write(last()); |
286 } else if (!node->source_info().is_valid()) { | 290 } else if (!node->source_info().is_valid()) { |
(...skipping 19 matching lines...) Expand all Loading... |
306 #undef CASE | 310 #undef CASE |
307 default: | 311 default: |
308 UNREACHABLE(); | 312 UNREACHABLE(); |
309 break; | 313 break; |
310 } | 314 } |
311 } | 315 } |
312 | 316 |
313 } // namespace interpreter | 317 } // namespace interpreter |
314 } // namespace internal | 318 } // namespace internal |
315 } // namespace v8 | 319 } // namespace v8 |
OLD | NEW |