| 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 |