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/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "test/unittests/test-utils.h" | 10 #include "test/unittests/test-utils.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 .Debugger() // Prevent peephole optimization LdaNull, Star -> LdrNull. | 50 .Debugger() // Prevent peephole optimization LdaNull, Star -> LdrNull. |
51 .LoadNull() | 51 .LoadNull() |
52 .StoreAccumulatorInRegister(reg) | 52 .StoreAccumulatorInRegister(reg) |
53 .LoadTheHole() | 53 .LoadTheHole() |
54 .StoreAccumulatorInRegister(reg) | 54 .StoreAccumulatorInRegister(reg) |
55 .LoadTrue() | 55 .LoadTrue() |
56 .StoreAccumulatorInRegister(reg) | 56 .StoreAccumulatorInRegister(reg) |
57 .LoadFalse() | 57 .LoadFalse() |
58 .StoreAccumulatorInRegister(wide); | 58 .StoreAccumulatorInRegister(wide); |
59 | 59 |
| 60 // Emit Ldar and Star taking care to foil the register optimizer. |
60 builder.StackCheck(0) | 61 builder.StackCheck(0) |
61 .LoadAccumulatorWithRegister(other) | 62 .LoadAccumulatorWithRegister(other) |
| 63 .BinaryOperation(Token::ADD, reg) |
62 .StoreAccumulatorInRegister(reg) | 64 .StoreAccumulatorInRegister(reg) |
63 .LoadNull() | 65 .LoadNull(); |
64 .StoreAccumulatorInRegister(reg); | |
65 | 66 |
66 // Emit register-register transfer. | 67 // Emit register-register transfer. |
67 builder.MoveRegister(reg, other); | 68 builder.MoveRegister(reg, other); |
68 builder.MoveRegister(reg, wide); | 69 builder.MoveRegister(reg, wide); |
69 | 70 |
70 // Emit global load / store operations. | 71 // Emit global load / store operations. |
71 Handle<String> name = factory->NewStringFromStaticChars("var_name"); | 72 Handle<String> name = factory->NewStringFromStaticChars("var_name"); |
72 builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF) | 73 builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF) |
73 .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF) | 74 .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF) |
74 .StoreGlobal(name, 1, LanguageMode::SLOPPY) | 75 .StoreGlobal(name, 1, LanguageMode::SLOPPY) |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 | 285 |
285 // Emit wide variant of literal creation operations. | 286 // Emit wide variant of literal creation operations. |
286 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), | 287 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), |
287 0, 0) | 288 0, 0) |
288 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) | 289 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) |
289 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0); | 290 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0); |
290 | 291 |
291 // Longer jumps requiring ConstantWide operand | 292 // Longer jumps requiring ConstantWide operand |
292 builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole( | 293 builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole( |
293 &start); | 294 &start); |
| 295 |
294 // Perform an operation that returns boolean value to | 296 // Perform an operation that returns boolean value to |
295 // generate JumpIfTrue/False | 297 // generate JumpIfTrue/False |
296 builder.CompareOperation(Token::Value::EQ, reg) | 298 builder.CompareOperation(Token::Value::EQ, reg) |
297 .JumpIfTrue(&start) | 299 .JumpIfTrue(&start) |
298 .CompareOperation(Token::Value::EQ, reg) | 300 .CompareOperation(Token::Value::EQ, reg) |
299 .JumpIfFalse(&start); | 301 .JumpIfFalse(&start); |
| 302 |
300 // Perform an operation that returns a non-boolean operation to | 303 // Perform an operation that returns a non-boolean operation to |
301 // generate JumpIfToBooleanTrue/False. | 304 // generate JumpIfToBooleanTrue/False. |
302 builder.BinaryOperation(Token::Value::ADD, reg) | 305 builder.BinaryOperation(Token::Value::ADD, reg) |
303 .JumpIfTrue(&start) | 306 .JumpIfTrue(&start) |
304 .BinaryOperation(Token::Value::ADD, reg) | 307 .BinaryOperation(Token::Value::ADD, reg) |
305 .JumpIfFalse(&start); | 308 .JumpIfFalse(&start); |
306 | 309 |
307 // Emit generator operations | 310 // Emit generator operations |
308 builder.SuspendGenerator(reg) | 311 builder.SuspendGenerator(reg) |
309 .ResumeGenerator(reg); | 312 .ResumeGenerator(reg); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 } | 373 } |
371 | 374 |
372 | 375 |
373 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { | 376 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { |
374 for (int locals = 0; locals < 5; locals++) { | 377 for (int locals = 0; locals < 5; locals++) { |
375 for (int contexts = 0; contexts < 4; contexts++) { | 378 for (int contexts = 0; contexts < 4; contexts++) { |
376 for (int temps = 0; temps < 3; temps++) { | 379 for (int temps = 0; temps < 3; temps++) { |
377 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); | 380 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); |
378 BytecodeRegisterAllocator temporaries( | 381 BytecodeRegisterAllocator temporaries( |
379 zone(), builder.temporary_register_allocator()); | 382 zone(), builder.temporary_register_allocator()); |
| 383 for (int i = 0; i < locals + contexts; i++) { |
| 384 builder.LoadLiteral(Smi::FromInt(0)); |
| 385 builder.StoreAccumulatorInRegister(Register(i)); |
| 386 } |
380 for (int i = 0; i < temps; i++) { | 387 for (int i = 0; i < temps; i++) { |
| 388 builder.LoadLiteral(Smi::FromInt(0)); |
381 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); | 389 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); |
382 } | 390 } |
| 391 if (temps > 0) { |
| 392 // Ensure temporaries are used so not optimized away by the |
| 393 // register optimizer. |
| 394 builder.New(Register(locals + contexts), Register(locals + contexts), |
| 395 static_cast<size_t>(temps)); |
| 396 } |
383 builder.Return(); | 397 builder.Return(); |
384 | 398 |
385 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 399 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
386 int total_registers = locals + contexts + temps; | 400 int total_registers = locals + contexts + temps; |
387 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); | 401 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); |
388 } | 402 } |
389 } | 403 } |
390 } | 404 } |
391 } | 405 } |
392 | 406 |
393 | 407 |
394 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { | 408 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { |
395 int index = 1; | 409 int index = 1; |
396 | 410 |
397 Register the_register(index); | 411 Register the_register(index); |
398 CHECK_EQ(the_register.index(), index); | 412 CHECK_EQ(the_register.index(), index); |
399 | 413 |
400 int actual_operand = the_register.ToOperand(); | 414 int actual_operand = the_register.ToOperand(); |
401 int actual_index = Register::FromOperand(actual_operand).index(); | 415 int actual_index = Register::FromOperand(actual_operand).index(); |
402 CHECK_EQ(actual_index, index); | 416 CHECK_EQ(actual_index, index); |
403 } | 417 } |
404 | 418 |
405 | 419 |
406 TEST_F(BytecodeArrayBuilderTest, Parameters) { | 420 TEST_F(BytecodeArrayBuilderTest, Parameters) { |
407 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); | 421 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); |
| 422 |
408 Register param0(builder.Parameter(0)); | 423 Register param0(builder.Parameter(0)); |
409 Register param9(builder.Parameter(9)); | 424 Register param9(builder.Parameter(9)); |
410 CHECK_EQ(param9.index() - param0.index(), 9); | 425 CHECK_EQ(param9.index() - param0.index(), 9); |
411 } | 426 } |
412 | 427 |
413 | 428 |
414 TEST_F(BytecodeArrayBuilderTest, RegisterType) { | 429 TEST_F(BytecodeArrayBuilderTest, RegisterType) { |
415 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); | 430 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); |
416 BytecodeRegisterAllocator register_allocator( | 431 BytecodeRegisterAllocator register_allocator( |
417 zone(), builder.temporary_register_allocator()); | 432 zone(), builder.temporary_register_allocator()); |
(...skipping 11 matching lines...) Expand all Loading... |
429 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); | 444 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); |
430 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); | 445 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); |
431 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); | 446 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); |
432 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); | 447 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); |
433 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); | 448 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); |
434 } | 449 } |
435 | 450 |
436 | 451 |
437 TEST_F(BytecodeArrayBuilderTest, Constants) { | 452 TEST_F(BytecodeArrayBuilderTest, Constants) { |
438 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 453 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 454 |
439 Factory* factory = isolate()->factory(); | 455 Factory* factory = isolate()->factory(); |
440 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); | 456 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); |
441 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); | 457 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); |
442 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); | 458 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); |
443 Handle<HeapObject> heap_num_2_copy(*heap_num_2); | 459 Handle<HeapObject> heap_num_2_copy(*heap_num_2); |
444 builder.LoadLiteral(heap_num_1) | 460 builder.LoadLiteral(heap_num_1) |
445 .LoadLiteral(heap_num_2) | 461 .LoadLiteral(heap_num_2) |
446 .LoadLiteral(large_smi) | 462 .LoadLiteral(large_smi) |
447 .LoadLiteral(heap_num_1) | 463 .LoadLiteral(heap_num_1) |
448 .LoadLiteral(heap_num_1) | 464 .LoadLiteral(heap_num_1) |
449 .LoadLiteral(heap_num_2_copy) | 465 .LoadLiteral(heap_num_2_copy) |
450 .Return(); | 466 .Return(); |
451 | 467 |
452 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 468 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
453 // Should only have one entry for each identical constant. | 469 // Should only have one entry for each identical constant. |
454 CHECK_EQ(array->constant_pool()->length(), 3); | 470 CHECK_EQ(array->constant_pool()->length(), 3); |
455 } | 471 } |
456 | 472 |
457 | 473 |
458 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 474 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
459 static const int kFarJumpDistance = 256; | 475 static const int kFarJumpDistance = 256; |
460 | 476 |
461 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 477 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 478 |
462 Register reg(0); | 479 Register reg(0); |
463 BytecodeLabel far0, far1, far2, far3, far4; | 480 BytecodeLabel far0, far1, far2, far3, far4; |
464 BytecodeLabel near0, near1, near2, near3, near4; | 481 BytecodeLabel near0, near1, near2, near3, near4; |
465 | 482 |
466 builder.Jump(&near0) | 483 builder.Jump(&near0) |
467 .CompareOperation(Token::Value::EQ, reg) | 484 .CompareOperation(Token::Value::EQ, reg) |
468 .JumpIfTrue(&near1) | 485 .JumpIfTrue(&near1) |
469 .CompareOperation(Token::Value::EQ, reg) | 486 .CompareOperation(Token::Value::EQ, reg) |
470 .JumpIfFalse(&near2) | 487 .JumpIfFalse(&near2) |
471 .BinaryOperation(Token::Value::ADD, reg) | 488 .BinaryOperation(Token::Value::ADD, reg) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 CHECK_EQ(iterator.current_bytecode(), | 580 CHECK_EQ(iterator.current_bytecode(), |
564 Bytecode::kJumpIfToBooleanFalseConstant); | 581 Bytecode::kJumpIfToBooleanFalseConstant); |
565 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 582 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
566 Smi::FromInt(kFarJumpDistance - 16)); | 583 Smi::FromInt(kFarJumpDistance - 16)); |
567 iterator.Advance(); | 584 iterator.Advance(); |
568 } | 585 } |
569 | 586 |
570 | 587 |
571 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 588 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
572 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 589 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 590 |
573 Register reg(0); | 591 Register reg(0); |
574 | 592 |
575 BytecodeLabel label0, label1, label2, label3, label4; | 593 BytecodeLabel label0, label1, label2, label3, label4; |
576 builder.Bind(&label0) | 594 builder.Bind(&label0) |
577 .Jump(&label0) | 595 .Jump(&label0) |
578 .Bind(&label1) | 596 .Bind(&label1) |
579 .CompareOperation(Token::Value::EQ, reg) | 597 .CompareOperation(Token::Value::EQ, reg) |
580 .JumpIfTrue(&label1) | 598 .JumpIfTrue(&label1) |
581 .Bind(&label2) | 599 .Bind(&label2) |
582 .CompareOperation(Token::Value::EQ, reg) | 600 .CompareOperation(Token::Value::EQ, reg) |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 iterator.Advance(); | 745 iterator.Advance(); |
728 } | 746 } |
729 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 747 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
730 iterator.Advance(); | 748 iterator.Advance(); |
731 CHECK(iterator.done()); | 749 CHECK(iterator.done()); |
732 } | 750 } |
733 | 751 |
734 } // namespace interpreter | 752 } // namespace interpreter |
735 } // namespace internal | 753 } // namespace internal |
736 } // namespace v8 | 754 } // namespace v8 |
OLD | NEW |