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 |