| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 | 462 |
| 463 Operand LCodeGen::ToOperand(LOperand* op) const { | 463 Operand LCodeGen::ToOperand(LOperand* op) const { |
| 464 // Does not handle registers. In X64 assembler, plain registers are not | 464 // Does not handle registers. In X64 assembler, plain registers are not |
| 465 // representable as an Operand. | 465 // representable as an Operand. |
| 466 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 466 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 467 return Operand(rbp, StackSlotOffset(op->index())); | 467 return Operand(rbp, StackSlotOffset(op->index())); |
| 468 } | 468 } |
| 469 | 469 |
| 470 | 470 |
| 471 void LCodeGen::WriteTranslation(LEnvironment* environment, | 471 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 472 Translation* translation) { | 472 Translation* translation, |
| 473 int* pushed_arguments_index, |
| 474 int* pushed_arguments_count) { |
| 473 if (environment == NULL) return; | 475 if (environment == NULL) return; |
| 474 | 476 |
| 475 // The translation includes one command per value in the environment. | 477 // The translation includes one command per value in the environment. |
| 476 int translation_size = environment->translation_size(); | 478 int translation_size = environment->values()->length(); |
| 477 // The output frame height does not include the parameters. | 479 // The output frame height does not include the parameters. |
| 478 int height = translation_size - environment->parameter_count(); | 480 int height = translation_size - environment->parameter_count(); |
| 479 | 481 |
| 480 WriteTranslation(environment->outer(), translation); | 482 // Function parameters are arguments to the outermost environment. The |
| 483 // arguments index points to the first element of a sequence of tagged |
| 484 // values on the stack that represent the arguments. This needs to be |
| 485 // kept in sync with the LArgumentsElements implementation. |
| 486 *pushed_arguments_index = -environment->parameter_count(); |
| 487 *pushed_arguments_count = environment->parameter_count(); |
| 488 |
| 489 WriteTranslation(environment->outer(), |
| 490 translation, |
| 491 pushed_arguments_index, |
| 492 pushed_arguments_count); |
| 481 bool has_closure_id = !info()->closure().is_null() && | 493 bool has_closure_id = !info()->closure().is_null() && |
| 482 !info()->closure().is_identical_to(environment->closure()); | 494 !info()->closure().is_identical_to(environment->closure()); |
| 483 int closure_id = has_closure_id | 495 int closure_id = has_closure_id |
| 484 ? DefineDeoptimizationLiteral(environment->closure()) | 496 ? DefineDeoptimizationLiteral(environment->closure()) |
| 485 : Translation::kSelfLiteralId; | 497 : Translation::kSelfLiteralId; |
| 486 | 498 |
| 487 switch (environment->frame_type()) { | 499 switch (environment->frame_type()) { |
| 488 case JS_FUNCTION: | 500 case JS_FUNCTION: |
| 489 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 501 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
| 490 break; | 502 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 502 translation->BeginSetterStubFrame(closure_id); | 514 translation->BeginSetterStubFrame(closure_id); |
| 503 break; | 515 break; |
| 504 case ARGUMENTS_ADAPTOR: | 516 case ARGUMENTS_ADAPTOR: |
| 505 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 517 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
| 506 break; | 518 break; |
| 507 case STUB: | 519 case STUB: |
| 508 translation->BeginCompiledStubFrame(); | 520 translation->BeginCompiledStubFrame(); |
| 509 break; | 521 break; |
| 510 } | 522 } |
| 511 | 523 |
| 524 // Inlined frames which push their arguments cause the index to be |
| 525 // bumped and another stack area to be used for materialization, |
| 526 // otherwise actual argument values are unknown for inlined frames. |
| 527 bool arguments_known = true; |
| 528 int arguments_index = *pushed_arguments_index; |
| 529 int arguments_count = *pushed_arguments_count; |
| 530 if (environment->entry() != NULL) { |
| 531 arguments_known = environment->entry()->arguments_pushed(); |
| 532 arguments_index = arguments_index < 0 |
| 533 ? GetStackSlotCount() : arguments_index + arguments_count; |
| 534 arguments_count = environment->entry()->arguments_count() + 1; |
| 535 if (environment->entry()->arguments_pushed()) { |
| 536 *pushed_arguments_index = arguments_index; |
| 537 *pushed_arguments_count = arguments_count; |
| 538 } |
| 539 } |
| 540 |
| 512 for (int i = 0; i < translation_size; ++i) { | 541 for (int i = 0; i < translation_size; ++i) { |
| 513 LOperand* value = environment->values()->at(i); | 542 LOperand* value = environment->values()->at(i); |
| 514 // spilled_registers_ and spilled_double_registers_ are either | 543 // spilled_registers_ and spilled_double_registers_ are either |
| 515 // both NULL or both set. | 544 // both NULL or both set. |
| 516 if (environment->spilled_registers() != NULL && value != NULL) { | 545 if (environment->spilled_registers() != NULL && value != NULL) { |
| 517 if (value->IsRegister() && | 546 if (value->IsRegister() && |
| 518 environment->spilled_registers()[value->index()] != NULL) { | 547 environment->spilled_registers()[value->index()] != NULL) { |
| 519 translation->MarkDuplicate(); | 548 translation->MarkDuplicate(); |
| 520 AddToTranslation(translation, | 549 AddToTranslation(translation, |
| 521 environment->spilled_registers()[value->index()], | 550 environment->spilled_registers()[value->index()], |
| 522 environment->HasTaggedValueAt(i), | 551 environment->HasTaggedValueAt(i), |
| 523 environment->HasUint32ValueAt(i)); | 552 environment->HasUint32ValueAt(i), |
| 553 arguments_known, |
| 554 arguments_index, |
| 555 arguments_count); |
| 524 } else if ( | 556 } else if ( |
| 525 value->IsDoubleRegister() && | 557 value->IsDoubleRegister() && |
| 526 environment->spilled_double_registers()[value->index()] != NULL) { | 558 environment->spilled_double_registers()[value->index()] != NULL) { |
| 527 translation->MarkDuplicate(); | 559 translation->MarkDuplicate(); |
| 528 AddToTranslation( | 560 AddToTranslation( |
| 529 translation, | 561 translation, |
| 530 environment->spilled_double_registers()[value->index()], | 562 environment->spilled_double_registers()[value->index()], |
| 531 false, | 563 false, |
| 532 false); | 564 false, |
| 565 arguments_known, |
| 566 arguments_index, |
| 567 arguments_count); |
| 533 } | 568 } |
| 534 } | 569 } |
| 535 | 570 |
| 536 // TODO(mstarzinger): Introduce marker operands to indicate that this value | |
| 537 // is not present and must be reconstructed from the deoptimizer. Currently | |
| 538 // this is only used for the arguments object. | |
| 539 if (value == NULL) { | |
| 540 int arguments_count = environment->values()->length() - translation_size; | |
| 541 translation->BeginArgumentsObject(arguments_count); | |
| 542 for (int i = 0; i < arguments_count; ++i) { | |
| 543 LOperand* value = environment->values()->at(translation_size + i); | |
| 544 ASSERT(environment->spilled_registers() == NULL || | |
| 545 !value->IsRegister() || | |
| 546 environment->spilled_registers()[value->index()] == NULL); | |
| 547 ASSERT(environment->spilled_registers() == NULL || | |
| 548 !value->IsDoubleRegister() || | |
| 549 environment->spilled_double_registers()[value->index()] == NULL); | |
| 550 AddToTranslation(translation, | |
| 551 value, | |
| 552 environment->HasTaggedValueAt(translation_size + i), | |
| 553 environment->HasUint32ValueAt(translation_size + i)); | |
| 554 } | |
| 555 continue; | |
| 556 } | |
| 557 | |
| 558 AddToTranslation(translation, | 571 AddToTranslation(translation, |
| 559 value, | 572 value, |
| 560 environment->HasTaggedValueAt(i), | 573 environment->HasTaggedValueAt(i), |
| 561 environment->HasUint32ValueAt(i)); | 574 environment->HasUint32ValueAt(i), |
| 575 arguments_known, |
| 576 arguments_index, |
| 577 arguments_count); |
| 562 } | 578 } |
| 563 } | 579 } |
| 564 | 580 |
| 565 | 581 |
| 566 void LCodeGen::AddToTranslation(Translation* translation, | 582 void LCodeGen::AddToTranslation(Translation* translation, |
| 567 LOperand* op, | 583 LOperand* op, |
| 568 bool is_tagged, | 584 bool is_tagged, |
| 569 bool is_uint32) { | 585 bool is_uint32, |
| 570 if (op->IsStackSlot()) { | 586 bool arguments_known, |
| 587 int arguments_index, |
| 588 int arguments_count) { |
| 589 if (op == NULL) { |
| 590 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
| 591 // is not present and must be reconstructed from the deoptimizer. Currently |
| 592 // this is only used for the arguments object. |
| 593 translation->StoreArgumentsObject( |
| 594 arguments_known, arguments_index, arguments_count); |
| 595 } else if (op->IsStackSlot()) { |
| 571 if (is_tagged) { | 596 if (is_tagged) { |
| 572 translation->StoreStackSlot(op->index()); | 597 translation->StoreStackSlot(op->index()); |
| 573 } else if (is_uint32) { | 598 } else if (is_uint32) { |
| 574 translation->StoreUint32StackSlot(op->index()); | 599 translation->StoreUint32StackSlot(op->index()); |
| 575 } else { | 600 } else { |
| 576 translation->StoreInt32StackSlot(op->index()); | 601 translation->StoreInt32StackSlot(op->index()); |
| 577 } | 602 } |
| 578 } else if (op->IsDoubleStackSlot()) { | 603 } else if (op->IsDoubleStackSlot()) { |
| 579 translation->StoreDoubleStackSlot(op->index()); | 604 translation->StoreDoubleStackSlot(op->index()); |
| 580 } else if (op->IsArgument()) { | 605 } else if (op->IsArgument()) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 // 0 ..................................................... size-1 | 690 // 0 ..................................................... size-1 |
| 666 // [parameters] [locals] [expression stack including arguments] | 691 // [parameters] [locals] [expression stack including arguments] |
| 667 | 692 |
| 668 // Layout of the translation: | 693 // Layout of the translation: |
| 669 // 0 ........................................................ size - 1 + 4 | 694 // 0 ........................................................ size - 1 + 4 |
| 670 // [expression stack including arguments] [locals] [4 words] [parameters] | 695 // [expression stack including arguments] [locals] [4 words] [parameters] |
| 671 // |>------------ translation_size ------------<| | 696 // |>------------ translation_size ------------<| |
| 672 | 697 |
| 673 int frame_count = 0; | 698 int frame_count = 0; |
| 674 int jsframe_count = 0; | 699 int jsframe_count = 0; |
| 700 int args_index = 0; |
| 701 int args_count = 0; |
| 675 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { | 702 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { |
| 676 ++frame_count; | 703 ++frame_count; |
| 677 if (e->frame_type() == JS_FUNCTION) { | 704 if (e->frame_type() == JS_FUNCTION) { |
| 678 ++jsframe_count; | 705 ++jsframe_count; |
| 679 } | 706 } |
| 680 } | 707 } |
| 681 Translation translation(&translations_, frame_count, jsframe_count, zone()); | 708 Translation translation(&translations_, frame_count, jsframe_count, zone()); |
| 682 WriteTranslation(environment, &translation); | 709 WriteTranslation(environment, &translation, &args_index, &args_count); |
| 683 int deoptimization_index = deoptimizations_.length(); | 710 int deoptimization_index = deoptimizations_.length(); |
| 684 int pc_offset = masm()->pc_offset(); | 711 int pc_offset = masm()->pc_offset(); |
| 685 environment->Register(deoptimization_index, | 712 environment->Register(deoptimization_index, |
| 686 translation.index(), | 713 translation.index(), |
| 687 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 714 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 688 deoptimizations_.Add(environment, environment->zone()); | 715 deoptimizations_.Add(environment, environment->zone()); |
| 689 } | 716 } |
| 690 } | 717 } |
| 691 | 718 |
| 692 | 719 |
| (...skipping 4911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5604 FixedArray::kHeaderSize - kPointerSize)); | 5631 FixedArray::kHeaderSize - kPointerSize)); |
| 5605 __ bind(&done); | 5632 __ bind(&done); |
| 5606 } | 5633 } |
| 5607 | 5634 |
| 5608 | 5635 |
| 5609 #undef __ | 5636 #undef __ |
| 5610 | 5637 |
| 5611 } } // namespace v8::internal | 5638 } } // namespace v8::internal |
| 5612 | 5639 |
| 5613 #endif // V8_TARGET_ARCH_X64 | 5640 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |