| 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 .StoreAccumulatorInRegister(reg) | 50 .StoreAccumulatorInRegister(reg) |
| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 } | 366 } |
| 364 | 367 |
| 365 | 368 |
| 366 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { | 369 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { |
| 367 for (int locals = 0; locals < 5; locals++) { | 370 for (int locals = 0; locals < 5; locals++) { |
| 368 for (int contexts = 0; contexts < 4; contexts++) { | 371 for (int contexts = 0; contexts < 4; contexts++) { |
| 369 for (int temps = 0; temps < 3; temps++) { | 372 for (int temps = 0; temps < 3; temps++) { |
| 370 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); | 373 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); |
| 371 BytecodeRegisterAllocator temporaries( | 374 BytecodeRegisterAllocator temporaries( |
| 372 zone(), builder.temporary_register_allocator()); | 375 zone(), builder.temporary_register_allocator()); |
| 376 for (int i = 0; i < locals + contexts; i++) { |
| 377 builder.LoadLiteral(Smi::FromInt(0)); |
| 378 builder.StoreAccumulatorInRegister(Register(i)); |
| 379 } |
| 373 for (int i = 0; i < temps; i++) { | 380 for (int i = 0; i < temps; i++) { |
| 381 builder.LoadLiteral(Smi::FromInt(0)); |
| 374 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); | 382 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); |
| 375 } | 383 } |
| 384 if (temps > 0) { |
| 385 // Ensure temporaries are used so not optimized away by the |
| 386 // register optimizer. |
| 387 builder.New(Register(locals + contexts), Register(locals + contexts), |
| 388 static_cast<size_t>(temps)); |
| 389 } |
| 376 builder.Return(); | 390 builder.Return(); |
| 377 | 391 |
| 378 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 392 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
| 379 int total_registers = locals + contexts + temps; | 393 int total_registers = locals + contexts + temps; |
| 380 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); | 394 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); |
| 381 } | 395 } |
| 382 } | 396 } |
| 383 } | 397 } |
| 384 } | 398 } |
| 385 | 399 |
| 386 | 400 |
| 387 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { | 401 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { |
| 388 int index = 1; | 402 int index = 1; |
| 389 | 403 |
| 390 Register the_register(index); | 404 Register the_register(index); |
| 391 CHECK_EQ(the_register.index(), index); | 405 CHECK_EQ(the_register.index(), index); |
| 392 | 406 |
| 393 int actual_operand = the_register.ToOperand(); | 407 int actual_operand = the_register.ToOperand(); |
| 394 int actual_index = Register::FromOperand(actual_operand).index(); | 408 int actual_index = Register::FromOperand(actual_operand).index(); |
| 395 CHECK_EQ(actual_index, index); | 409 CHECK_EQ(actual_index, index); |
| 396 } | 410 } |
| 397 | 411 |
| 398 | 412 |
| 399 TEST_F(BytecodeArrayBuilderTest, Parameters) { | 413 TEST_F(BytecodeArrayBuilderTest, Parameters) { |
| 400 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); | 414 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); |
| 415 |
| 401 Register param0(builder.Parameter(0)); | 416 Register param0(builder.Parameter(0)); |
| 402 Register param9(builder.Parameter(9)); | 417 Register param9(builder.Parameter(9)); |
| 403 CHECK_EQ(param9.index() - param0.index(), 9); | 418 CHECK_EQ(param9.index() - param0.index(), 9); |
| 404 } | 419 } |
| 405 | 420 |
| 406 | 421 |
| 407 TEST_F(BytecodeArrayBuilderTest, RegisterType) { | 422 TEST_F(BytecodeArrayBuilderTest, RegisterType) { |
| 408 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); | 423 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); |
| 409 BytecodeRegisterAllocator register_allocator( | 424 BytecodeRegisterAllocator register_allocator( |
| 410 zone(), builder.temporary_register_allocator()); | 425 zone(), builder.temporary_register_allocator()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 422 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); | 437 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); |
| 423 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); | 438 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); |
| 424 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); | 439 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); |
| 425 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); | 440 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); |
| 426 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); | 441 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); |
| 427 } | 442 } |
| 428 | 443 |
| 429 | 444 |
| 430 TEST_F(BytecodeArrayBuilderTest, Constants) { | 445 TEST_F(BytecodeArrayBuilderTest, Constants) { |
| 431 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 446 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 447 |
| 432 Factory* factory = isolate()->factory(); | 448 Factory* factory = isolate()->factory(); |
| 433 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); | 449 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); |
| 434 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); | 450 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); |
| 435 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); | 451 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); |
| 436 Handle<HeapObject> heap_num_2_copy(*heap_num_2); | 452 Handle<HeapObject> heap_num_2_copy(*heap_num_2); |
| 437 builder.LoadLiteral(heap_num_1) | 453 builder.LoadLiteral(heap_num_1) |
| 438 .LoadLiteral(heap_num_2) | 454 .LoadLiteral(heap_num_2) |
| 439 .LoadLiteral(large_smi) | 455 .LoadLiteral(large_smi) |
| 440 .LoadLiteral(heap_num_1) | 456 .LoadLiteral(heap_num_1) |
| 441 .LoadLiteral(heap_num_1) | 457 .LoadLiteral(heap_num_1) |
| 442 .LoadLiteral(heap_num_2_copy) | 458 .LoadLiteral(heap_num_2_copy) |
| 443 .Return(); | 459 .Return(); |
| 444 | 460 |
| 445 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 461 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
| 446 // Should only have one entry for each identical constant. | 462 // Should only have one entry for each identical constant. |
| 447 CHECK_EQ(array->constant_pool()->length(), 3); | 463 CHECK_EQ(array->constant_pool()->length(), 3); |
| 448 } | 464 } |
| 449 | 465 |
| 450 | 466 |
| 451 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 467 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
| 452 static const int kFarJumpDistance = 256; | 468 static const int kFarJumpDistance = 256; |
| 453 | 469 |
| 454 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 470 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 471 |
| 455 Register reg(0); | 472 Register reg(0); |
| 456 BytecodeLabel far0, far1, far2, far3, far4; | 473 BytecodeLabel far0, far1, far2, far3, far4; |
| 457 BytecodeLabel near0, near1, near2, near3, near4; | 474 BytecodeLabel near0, near1, near2, near3, near4; |
| 458 | 475 |
| 459 builder.Jump(&near0) | 476 builder.Jump(&near0) |
| 460 .CompareOperation(Token::Value::EQ, reg) | 477 .CompareOperation(Token::Value::EQ, reg) |
| 461 .JumpIfTrue(&near1) | 478 .JumpIfTrue(&near1) |
| 462 .CompareOperation(Token::Value::EQ, reg) | 479 .CompareOperation(Token::Value::EQ, reg) |
| 463 .JumpIfFalse(&near2) | 480 .JumpIfFalse(&near2) |
| 464 .BinaryOperation(Token::Value::ADD, reg) | 481 .BinaryOperation(Token::Value::ADD, reg) |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 CHECK_EQ(iterator.current_bytecode(), | 573 CHECK_EQ(iterator.current_bytecode(), |
| 557 Bytecode::kJumpIfToBooleanFalseConstant); | 574 Bytecode::kJumpIfToBooleanFalseConstant); |
| 558 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 575 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
| 559 Smi::FromInt(kFarJumpDistance - 16)); | 576 Smi::FromInt(kFarJumpDistance - 16)); |
| 560 iterator.Advance(); | 577 iterator.Advance(); |
| 561 } | 578 } |
| 562 | 579 |
| 563 | 580 |
| 564 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 581 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
| 565 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 582 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 583 |
| 566 Register reg(0); | 584 Register reg(0); |
| 567 | 585 |
| 568 BytecodeLabel label0, label1, label2, label3, label4; | 586 BytecodeLabel label0, label1, label2, label3, label4; |
| 569 builder.Bind(&label0) | 587 builder.Bind(&label0) |
| 570 .Jump(&label0) | 588 .Jump(&label0) |
| 571 .Bind(&label1) | 589 .Bind(&label1) |
| 572 .CompareOperation(Token::Value::EQ, reg) | 590 .CompareOperation(Token::Value::EQ, reg) |
| 573 .JumpIfTrue(&label1) | 591 .JumpIfTrue(&label1) |
| 574 .Bind(&label2) | 592 .Bind(&label2) |
| 575 .CompareOperation(Token::Value::EQ, reg) | 593 .CompareOperation(Token::Value::EQ, reg) |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 iterator.Advance(); | 738 iterator.Advance(); |
| 721 } | 739 } |
| 722 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 740 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 723 iterator.Advance(); | 741 iterator.Advance(); |
| 724 CHECK(iterator.done()); | 742 CHECK(iterator.done()); |
| 725 } | 743 } |
| 726 | 744 |
| 727 } // namespace interpreter | 745 } // namespace interpreter |
| 728 } // namespace internal | 746 } // namespace internal |
| 729 } // namespace v8 | 747 } // namespace v8 |
| OLD | NEW |