OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/interpreter/bytecode-array-builder.h" | 8 #include "src/interpreter/bytecode-array-builder.h" |
9 #include "src/interpreter/bytecode-array-iterator.h" | 9 #include "src/interpreter/bytecode-array-iterator.h" |
10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
11 #include "src/interpreter/bytecode-register-allocator.h" | 11 #include "src/interpreter/bytecode-register-allocator.h" |
12 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
13 #include "test/unittests/test-utils.h" | 13 #include "test/unittests/test-utils.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace interpreter { | 17 namespace interpreter { |
18 | 18 |
19 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { | 19 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { |
20 public: | 20 public: |
21 BytecodeArrayBuilderTest() {} | 21 BytecodeArrayBuilderTest() {} |
22 ~BytecodeArrayBuilderTest() override {} | 22 ~BytecodeArrayBuilderTest() override {} |
23 }; | 23 }; |
24 | 24 |
| 25 using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode; |
| 26 |
25 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { | 27 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { |
26 CanonicalHandleScope canonical(isolate()); | 28 CanonicalHandleScope canonical(isolate()); |
27 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); | 29 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); |
28 Factory* factory = isolate()->factory(); | 30 Factory* factory = isolate()->factory(); |
29 AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(), | 31 AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(), |
30 isolate()->heap()->HashSeed()); | 32 isolate()->heap()->HashSeed()); |
31 DeclarationScope scope(zone(), &ast_factory); | 33 DeclarationScope scope(zone(), &ast_factory); |
32 | 34 |
33 CHECK_EQ(builder.locals_count(), 131); | 35 CHECK_EQ(builder.locals_count(), 131); |
34 CHECK_EQ(builder.context_count(), 1); | 36 CHECK_EQ(builder.context_count(), 1); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 .BinaryOperation(Token::Value::SHL, reg, 5) | 190 .BinaryOperation(Token::Value::SHL, reg, 5) |
189 .LoadLiteral(Smi::FromInt(6)) | 191 .LoadLiteral(Smi::FromInt(6)) |
190 .BinaryOperation(Token::Value::SAR, reg, 6); | 192 .BinaryOperation(Token::Value::SAR, reg, 6); |
191 | 193 |
192 // Emit count operatior invocations | 194 // Emit count operatior invocations |
193 builder.CountOperation(Token::Value::ADD, 1) | 195 builder.CountOperation(Token::Value::ADD, 1) |
194 .CountOperation(Token::Value::SUB, 1); | 196 .CountOperation(Token::Value::SUB, 1); |
195 | 197 |
196 // Emit unary operator invocations. | 198 // Emit unary operator invocations. |
197 builder | 199 builder |
198 .LogicalNot() // ToBooleanLogicalNot | 200 .LogicalNot(ToBooleanMode::kConvertToBoolean) |
199 .LogicalNot() // non-ToBoolean LogicalNot | 201 .LogicalNot(ToBooleanMode::kAlreadyBoolean) |
200 .TypeOf(); | 202 .TypeOf(); |
201 | 203 |
202 // Emit delete | 204 // Emit delete |
203 builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT); | 205 builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT); |
204 | 206 |
205 // Emit construct. | 207 // Emit construct. |
206 builder.Construct(reg, reg_list, 1).ConstructWithSpread(reg, reg_list); | 208 builder.Construct(reg, reg_list, 1).ConstructWithSpread(reg, reg_list); |
207 | 209 |
208 // Emit test operator invocations. | 210 // Emit test operator invocations. |
209 builder.CompareOperation(Token::Value::EQ, reg, 1) | 211 builder.CompareOperation(Token::Value::EQ, reg, 1) |
(...skipping 24 matching lines...) Expand all Loading... |
234 builder.ConvertAccumulatorToNumber(reg) | 236 builder.ConvertAccumulatorToNumber(reg) |
235 .ConvertAccumulatorToObject(reg) | 237 .ConvertAccumulatorToObject(reg) |
236 .ConvertAccumulatorToName(reg); | 238 .ConvertAccumulatorToName(reg); |
237 | 239 |
238 // Emit GetSuperConstructor. | 240 // Emit GetSuperConstructor. |
239 builder.GetSuperConstructor(reg); | 241 builder.GetSuperConstructor(reg); |
240 | 242 |
241 // Short jumps with Imm8 operands | 243 // Short jumps with Imm8 operands |
242 { | 244 { |
243 BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, | 245 BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, |
244 after_jump5, after_jump6, after_jump7; | 246 after_jump5, after_jump6, after_jump7, after_jump8, after_jump9, |
| 247 after_jump10, after_jump11; |
245 builder.Bind(&start) | 248 builder.Bind(&start) |
246 .Jump(&after_jump1) | 249 .Jump(&after_jump1) |
247 .Bind(&after_jump1) | 250 .Bind(&after_jump1) |
248 .JumpIfNull(&after_jump2) | 251 .JumpIfNull(&after_jump2) |
249 .Bind(&after_jump2) | 252 .Bind(&after_jump2) |
250 .JumpIfNotNull(&after_jump3) | 253 .JumpIfNotNull(&after_jump3) |
251 .Bind(&after_jump3) | 254 .Bind(&after_jump3) |
252 .JumpIfUndefined(&after_jump4) | 255 .JumpIfUndefined(&after_jump4) |
253 .Bind(&after_jump4) | 256 .Bind(&after_jump4) |
254 .JumpIfNotUndefined(&after_jump5) | 257 .JumpIfNotUndefined(&after_jump5) |
255 .Bind(&after_jump5) | 258 .Bind(&after_jump5) |
256 .JumpIfNotHole(&after_jump6) | 259 .JumpIfNotHole(&after_jump6) |
257 .Bind(&after_jump6) | 260 .Bind(&after_jump6) |
258 .JumpIfJSReceiver(&after_jump7) | 261 .JumpIfJSReceiver(&after_jump7) |
259 .Bind(&after_jump7) | 262 .Bind(&after_jump7) |
| 263 .JumpIfTrue(ToBoolean::kConvertToBoolean, &after_jump8) |
| 264 .Bind(&after_jump8) |
| 265 .JumpIfTrue(ToBoolean::kAlreadyBoolean, &after_jump9) |
| 266 .Bind(&after_jump9) |
| 267 .JumpIfFalse(ToBoolean::kConvertToBoolean, &after_jump10) |
| 268 .Bind(&after_jump10) |
| 269 .JumpIfFalse(ToBoolean::kAlreadyBoolean, &after_jump11) |
| 270 .Bind(&after_jump11) |
260 .JumpLoop(&start, 0); | 271 .JumpLoop(&start, 0); |
261 } | 272 } |
262 | 273 |
263 // Longer jumps with constant operands | 274 // Longer jumps with constant operands |
264 BytecodeLabel end[11]; | 275 BytecodeLabel end[11]; |
265 { | 276 { |
266 BytecodeLabel after_jump; | 277 BytecodeLabel after_jump; |
267 builder.Jump(&end[0]) | 278 builder.Jump(&end[0]) |
268 .Bind(&after_jump) | 279 .Bind(&after_jump) |
269 .LoadTrue() | 280 .JumpIfTrue(ToBoolean::kConvertToBoolean, &end[1]) |
270 .JumpIfTrue(&end[1]) | 281 .JumpIfTrue(ToBoolean::kAlreadyBoolean, &end[2]) |
271 .LoadTrue() | 282 .JumpIfFalse(ToBoolean::kConvertToBoolean, &end[3]) |
272 .JumpIfFalse(&end[2]) | 283 .JumpIfFalse(ToBoolean::kAlreadyBoolean, &end[4]) |
273 .LoadLiteral(Smi::kZero) | |
274 .JumpIfTrue(&end[3]) | |
275 .LoadLiteral(Smi::kZero) | |
276 .JumpIfFalse(&end[4]) | |
277 .JumpIfNull(&end[5]) | 284 .JumpIfNull(&end[5]) |
278 .JumpIfNotNull(&end[6]) | 285 .JumpIfNotNull(&end[6]) |
279 .JumpIfUndefined(&end[7]) | 286 .JumpIfUndefined(&end[7]) |
280 .JumpIfNotUndefined(&end[8]) | 287 .JumpIfNotUndefined(&end[8]) |
281 .JumpIfNotHole(&end[9]) | 288 .JumpIfNotHole(&end[9]) |
282 .LoadLiteral(ast_factory.prototype_string()) | 289 .LoadLiteral(ast_factory.prototype_string()) |
283 .JumpIfJSReceiver(&end[10]); | 290 .JumpIfJSReceiver(&end[10]); |
284 } | 291 } |
285 | 292 |
286 // Perform an operation that returns boolean value to | |
287 // generate JumpIfTrue/False | |
288 { | |
289 BytecodeLabel after_jump1, after_jump2; | |
290 builder.CompareOperation(Token::Value::EQ, reg, 1) | |
291 .JumpIfTrue(&after_jump1) | |
292 .Bind(&after_jump1) | |
293 .CompareOperation(Token::Value::EQ, reg, 2) | |
294 .JumpIfFalse(&after_jump2) | |
295 .Bind(&after_jump2); | |
296 } | |
297 | |
298 // Perform an operation that returns a non-boolean operation to | |
299 // generate JumpIfToBooleanTrue/False. | |
300 { | |
301 BytecodeLabel after_jump1, after_jump2; | |
302 builder.BinaryOperation(Token::Value::ADD, reg, 1) | |
303 .JumpIfTrue(&after_jump1) | |
304 .Bind(&after_jump1) | |
305 .BinaryOperation(Token::Value::ADD, reg, 2) | |
306 .JumpIfFalse(&after_jump2) | |
307 .Bind(&after_jump2); | |
308 } | |
309 | |
310 // Emit set pending message bytecode. | 293 // Emit set pending message bytecode. |
311 builder.SetPendingMessage(); | 294 builder.SetPendingMessage(); |
312 | 295 |
313 // Emit stack check bytecode. | 296 // Emit stack check bytecode. |
314 builder.StackCheck(0); | 297 builder.StackCheck(0); |
315 | 298 |
316 // Emit throw and re-throw in it's own basic block so that the rest of the | 299 // Emit throw and re-throw in it's own basic block so that the rest of the |
317 // code isn't omitted due to being dead. | 300 // code isn't omitted due to being dead. |
318 BytecodeLabel after_throw; | 301 BytecodeLabel after_throw; |
319 builder.Throw().Bind(&after_throw); | 302 builder.Throw().Bind(&after_throw); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 } | 415 } |
433 | 416 |
434 // Insert entry for illegal bytecode as this is never willingly emitted. | 417 // Insert entry for illegal bytecode as this is never willingly emitted. |
435 scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1; | 418 scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1; |
436 | 419 |
437 // Insert entry for nop bytecode as this often gets optimized out. | 420 // Insert entry for nop bytecode as this often gets optimized out. |
438 scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1; | 421 scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1; |
439 | 422 |
440 if (!FLAG_ignition_peephole) { | 423 if (!FLAG_ignition_peephole) { |
441 // Insert entries for bytecodes only emitted by peephole optimizer. | 424 // Insert entries for bytecodes only emitted by peephole optimizer. |
442 scorecard[Bytecodes::ToByte(Bytecode::kLogicalNot)] = 1; | |
443 scorecard[Bytecodes::ToByte(Bytecode::kJump)] = 1; | |
444 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrue)] = 1; | |
445 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalse)] = 1; | |
446 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrueConstant)] = 1; | |
447 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalseConstant)] = 1; | |
448 scorecard[Bytecodes::ToByte(Bytecode::kAddSmi)] = 1; | 425 scorecard[Bytecodes::ToByte(Bytecode::kAddSmi)] = 1; |
449 scorecard[Bytecodes::ToByte(Bytecode::kSubSmi)] = 1; | 426 scorecard[Bytecodes::ToByte(Bytecode::kSubSmi)] = 1; |
450 scorecard[Bytecodes::ToByte(Bytecode::kBitwiseAndSmi)] = 1; | 427 scorecard[Bytecodes::ToByte(Bytecode::kBitwiseAndSmi)] = 1; |
451 scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1; | 428 scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1; |
452 scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 1; | 429 scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 1; |
453 scorecard[Bytecodes::ToByte(Bytecode::kShiftRightSmi)] = 1; | 430 scorecard[Bytecodes::ToByte(Bytecode::kShiftRightSmi)] = 1; |
454 } | 431 } |
455 | 432 |
456 if (!FLAG_type_profile) { | 433 if (!FLAG_type_profile) { |
457 // Bytecode for CollectTypeProfile is only emitted when | 434 // Bytecode for CollectTypeProfile is only emitted when |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 iterator.Advance(); | 771 iterator.Advance(); |
795 } | 772 } |
796 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 773 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
797 iterator.Advance(); | 774 iterator.Advance(); |
798 CHECK(iterator.done()); | 775 CHECK(iterator.done()); |
799 } | 776 } |
800 | 777 |
801 } // namespace interpreter | 778 } // namespace interpreter |
802 } // namespace internal | 779 } // namespace internal |
803 } // namespace v8 | 780 } // namespace v8 |
OLD | NEW |