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::Illegal(BytecodeSourceInfo())) { |
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::Illegal(BytecodeSourceInfo()); |
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 void TransformEqualityWithNullOrUndefinedToTestUndetectable( | 144 BytecodeNode TransformEqualityWithNullOrUndefinedToTestUndetectable( |
142 BytecodeNode* const last, BytecodeNode* const current) { | 145 BytecodeNode* const last, BytecodeNode* const current) { |
143 DCHECK((last->bytecode() == Bytecode::kLdaNull) || | 146 DCHECK((last->bytecode() == Bytecode::kLdaNull) || |
144 (last->bytecode() == Bytecode::kLdaUndefined)); | 147 (last->bytecode() == Bytecode::kLdaUndefined)); |
145 DCHECK_EQ(current->bytecode(), Bytecode::kTestEqual); | 148 DCHECK_EQ(current->bytecode(), Bytecode::kTestEqual); |
146 current->set_bytecode(Bytecode::kTestUndetectable, current->operand(0)); | 149 BytecodeNode node(BytecodeNode::TestUndetectable(current->source_info(), |
| 150 current->operand(0))); |
147 if (last->source_info().is_valid()) { | 151 if (last->source_info().is_valid()) { |
148 current->set_source_info(last->source_info()); | 152 node.set_source_info(last->source_info()); |
149 } | 153 } |
| 154 return node; |
150 } | 155 } |
151 | 156 |
152 } // namespace | 157 } // namespace |
153 | 158 |
154 void BytecodePeepholeOptimizer::DefaultAction( | 159 void BytecodePeepholeOptimizer::DefaultAction( |
155 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 160 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
156 DCHECK(LastIsValid()); | 161 DCHECK(LastIsValid()); |
157 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 162 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
158 | 163 |
159 next_stage()->Write(last()); | 164 next_stage()->Write(last()); |
(...skipping 19 matching lines...) Expand all Loading... |
179 } | 184 } |
180 | 185 |
181 void BytecodePeepholeOptimizer::ElideCurrentAction( | 186 void BytecodePeepholeOptimizer::ElideCurrentAction( |
182 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 187 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
183 DCHECK(LastIsValid()); | 188 DCHECK(LastIsValid()); |
184 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 189 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
185 | 190 |
186 if (node->source_info().is_valid()) { | 191 if (node->source_info().is_valid()) { |
187 // Preserve the source information by replacing the node bytecode | 192 // Preserve the source information by replacing the node bytecode |
188 // with a no op bytecode. | 193 // with a no op bytecode. |
189 node->set_bytecode(Bytecode::kNop); | 194 BytecodeNode new_node(BytecodeNode::Nop(node->source_info())); |
190 DefaultAction(node); | 195 DefaultAction(&new_node); |
191 } else { | 196 } else { |
192 // Nothing to do, keep last and wait for next bytecode to pair with it. | 197 // Nothing to do, keep last and wait for next bytecode to pair with it. |
193 } | 198 } |
194 } | 199 } |
195 | 200 |
196 void BytecodePeepholeOptimizer::ElideCurrentIfOperand0MatchesAction( | 201 void BytecodePeepholeOptimizer::ElideCurrentIfOperand0MatchesAction( |
197 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 202 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
198 DCHECK(LastIsValid()); | 203 DCHECK(LastIsValid()); |
199 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 204 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
200 | 205 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 DefaultAction(node); | 237 DefaultAction(node); |
233 } | 238 } |
234 | 239 |
235 void BytecodePeepholeOptimizer::TransformLdaSmiBinaryOpToBinaryOpWithSmiAction( | 240 void BytecodePeepholeOptimizer::TransformLdaSmiBinaryOpToBinaryOpWithSmiAction( |
236 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 241 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
237 DCHECK(LastIsValid()); | 242 DCHECK(LastIsValid()); |
238 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 243 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
239 | 244 |
240 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { | 245 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { |
241 // Fused last and current into current. | 246 // Fused last and current into current. |
242 TransformLdaSmiBinaryOpToBinaryOpWithSmi(action_data->bytecode, last(), | 247 BytecodeNode new_node(TransformLdaSmiBinaryOpToBinaryOpWithSmi( |
243 node); | 248 action_data->bytecode, last(), node)); |
244 SetLast(node); | 249 SetLast(&new_node); |
245 } else { | 250 } else { |
246 DefaultAction(node); | 251 DefaultAction(node); |
247 } | 252 } |
248 } | 253 } |
249 | 254 |
250 void BytecodePeepholeOptimizer:: | 255 void BytecodePeepholeOptimizer:: |
251 TransformLdaZeroBinaryOpToBinaryOpWithZeroAction( | 256 TransformLdaZeroBinaryOpToBinaryOpWithZeroAction( |
252 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 257 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
253 DCHECK(LastIsValid()); | 258 DCHECK(LastIsValid()); |
254 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 259 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
255 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { | 260 if (!node->source_info().is_valid() || !last()->source_info().is_valid()) { |
256 // Fused last and current into current. | 261 // Fused last and current into current. |
257 TransformLdaZeroBinaryOpToBinaryOpWithZero(action_data->bytecode, last(), | 262 BytecodeNode new_node(TransformLdaZeroBinaryOpToBinaryOpWithZero( |
258 node); | 263 action_data->bytecode, last(), node)); |
259 SetLast(node); | 264 SetLast(&new_node); |
260 } else { | 265 } else { |
261 DefaultAction(node); | 266 DefaultAction(node); |
262 } | 267 } |
263 } | 268 } |
264 | 269 |
265 void BytecodePeepholeOptimizer:: | 270 void BytecodePeepholeOptimizer:: |
266 TransformEqualityWithNullOrUndefinedToTestUndetectableAction( | 271 TransformEqualityWithNullOrUndefinedToTestUndetectableAction( |
267 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 272 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
268 DCHECK(LastIsValid()); | 273 DCHECK(LastIsValid()); |
269 DCHECK(!Bytecodes::IsJump(node->bytecode())); | 274 DCHECK(!Bytecodes::IsJump(node->bytecode())); |
270 // Fused last and current into current. | 275 // Fused last and current into current. |
271 TransformEqualityWithNullOrUndefinedToTestUndetectable(last(), node); | 276 BytecodeNode new_node( |
272 SetLast(node); | 277 TransformEqualityWithNullOrUndefinedToTestUndetectable(last(), node)); |
| 278 SetLast(&new_node); |
273 } | 279 } |
274 | 280 |
275 void BytecodePeepholeOptimizer::DefaultJumpAction( | 281 void BytecodePeepholeOptimizer::DefaultJumpAction( |
276 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 282 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
277 DCHECK(LastIsValid()); | 283 DCHECK(LastIsValid()); |
278 DCHECK(Bytecodes::IsJump(node->bytecode())); | 284 DCHECK(Bytecodes::IsJump(node->bytecode())); |
279 | 285 |
280 next_stage()->Write(last()); | 286 next_stage()->Write(last()); |
281 InvalidateLast(); | 287 InvalidateLast(); |
282 } | 288 } |
283 | 289 |
284 void BytecodePeepholeOptimizer::UpdateLastJumpAction( | 290 void BytecodePeepholeOptimizer::UpdateLastJumpAction( |
285 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 291 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
286 DCHECK(!LastIsValid()); | 292 DCHECK(!LastIsValid()); |
287 DCHECK(Bytecodes::IsJump(node->bytecode())); | 293 DCHECK(Bytecodes::IsJump(node->bytecode())); |
288 } | 294 } |
289 | 295 |
290 void BytecodePeepholeOptimizer::ChangeJumpBytecodeAction( | 296 void BytecodePeepholeOptimizer::ChangeJumpBytecodeAction( |
291 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 297 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
292 DCHECK(LastIsValid()); | 298 DCHECK(LastIsValid()); |
293 DCHECK(Bytecodes::IsJump(node->bytecode())); | 299 DCHECK(Bytecodes::IsJump(node->bytecode())); |
294 | 300 |
295 next_stage()->Write(last()); | 301 next_stage()->Write(last()); |
296 InvalidateLast(); | 302 InvalidateLast(); |
297 node->set_bytecode(action_data->bytecode, node->operand(0)); | 303 node->replace_bytecode(action_data->bytecode); |
298 } | 304 } |
299 | 305 |
300 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( | 306 void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( |
301 BytecodeNode* const node, const PeepholeActionAndData* action_data) { | 307 BytecodeNode* const node, const PeepholeActionAndData* action_data) { |
302 DCHECK(LastIsValid()); | 308 DCHECK(LastIsValid()); |
303 DCHECK(Bytecodes::IsJump(node->bytecode())); | 309 DCHECK(Bytecodes::IsJump(node->bytecode())); |
304 | 310 |
305 if (!CanElideLastBasedOnSourcePosition(node)) { | 311 if (!CanElideLastBasedOnSourcePosition(node)) { |
306 next_stage()->Write(last()); | 312 next_stage()->Write(last()); |
307 } else if (!node->source_info().is_valid()) { | 313 } else if (!node->source_info().is_valid()) { |
(...skipping 19 matching lines...) Expand all Loading... |
327 #undef CASE | 333 #undef CASE |
328 default: | 334 default: |
329 UNREACHABLE(); | 335 UNREACHABLE(); |
330 break; | 336 break; |
331 } | 337 } |
332 } | 338 } |
333 | 339 |
334 } // namespace interpreter | 340 } // namespace interpreter |
335 } // namespace internal | 341 } // namespace internal |
336 } // namespace v8 | 342 } // namespace v8 |
OLD | NEW |