| 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) { | |
| 475 if (environment == NULL) return; | 473 if (environment == NULL) return; |
| 476 | 474 |
| 477 // The translation includes one command per value in the environment. | 475 // The translation includes one command per value in the environment. |
| 478 int translation_size = environment->values()->length(); | 476 int translation_size = environment->translation_size(); |
| 479 // The output frame height does not include the parameters. | 477 // The output frame height does not include the parameters. |
| 480 int height = translation_size - environment->parameter_count(); | 478 int height = translation_size - environment->parameter_count(); |
| 481 | 479 |
| 482 // Function parameters are arguments to the outermost environment. The | 480 WriteTranslation(environment->outer(), translation); |
| 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); | |
| 493 bool has_closure_id = !info()->closure().is_null() && | 481 bool has_closure_id = !info()->closure().is_null() && |
| 494 !info()->closure().is_identical_to(environment->closure()); | 482 !info()->closure().is_identical_to(environment->closure()); |
| 495 int closure_id = has_closure_id | 483 int closure_id = has_closure_id |
| 496 ? DefineDeoptimizationLiteral(environment->closure()) | 484 ? DefineDeoptimizationLiteral(environment->closure()) |
| 497 : Translation::kSelfLiteralId; | 485 : Translation::kSelfLiteralId; |
| 498 | 486 |
| 499 switch (environment->frame_type()) { | 487 switch (environment->frame_type()) { |
| 500 case JS_FUNCTION: | 488 case JS_FUNCTION: |
| 501 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 489 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
| 502 break; | 490 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 514 translation->BeginSetterStubFrame(closure_id); | 502 translation->BeginSetterStubFrame(closure_id); |
| 515 break; | 503 break; |
| 516 case ARGUMENTS_ADAPTOR: | 504 case ARGUMENTS_ADAPTOR: |
| 517 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 505 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
| 518 break; | 506 break; |
| 519 case STUB: | 507 case STUB: |
| 520 translation->BeginCompiledStubFrame(); | 508 translation->BeginCompiledStubFrame(); |
| 521 break; | 509 break; |
| 522 } | 510 } |
| 523 | 511 |
| 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 | |
| 541 for (int i = 0; i < translation_size; ++i) { | 512 for (int i = 0; i < translation_size; ++i) { |
| 542 LOperand* value = environment->values()->at(i); | 513 LOperand* value = environment->values()->at(i); |
| 543 // spilled_registers_ and spilled_double_registers_ are either | 514 // spilled_registers_ and spilled_double_registers_ are either |
| 544 // both NULL or both set. | 515 // both NULL or both set. |
| 545 if (environment->spilled_registers() != NULL && value != NULL) { | 516 if (environment->spilled_registers() != NULL && value != NULL) { |
| 546 if (value->IsRegister() && | 517 if (value->IsRegister() && |
| 547 environment->spilled_registers()[value->index()] != NULL) { | 518 environment->spilled_registers()[value->index()] != NULL) { |
| 548 translation->MarkDuplicate(); | 519 translation->MarkDuplicate(); |
| 549 AddToTranslation(translation, | 520 AddToTranslation(translation, |
| 550 environment->spilled_registers()[value->index()], | 521 environment->spilled_registers()[value->index()], |
| 551 environment->HasTaggedValueAt(i), | 522 environment->HasTaggedValueAt(i), |
| 552 environment->HasUint32ValueAt(i), | 523 environment->HasUint32ValueAt(i)); |
| 553 arguments_known, | |
| 554 arguments_index, | |
| 555 arguments_count); | |
| 556 } else if ( | 524 } else if ( |
| 557 value->IsDoubleRegister() && | 525 value->IsDoubleRegister() && |
| 558 environment->spilled_double_registers()[value->index()] != NULL) { | 526 environment->spilled_double_registers()[value->index()] != NULL) { |
| 559 translation->MarkDuplicate(); | 527 translation->MarkDuplicate(); |
| 560 AddToTranslation( | 528 AddToTranslation( |
| 561 translation, | 529 translation, |
| 562 environment->spilled_double_registers()[value->index()], | 530 environment->spilled_double_registers()[value->index()], |
| 563 false, | 531 false, |
| 564 false, | 532 false); |
| 565 arguments_known, | |
| 566 arguments_index, | |
| 567 arguments_count); | |
| 568 } | 533 } |
| 569 } | 534 } |
| 570 | 535 |
| 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 |
| 571 AddToTranslation(translation, | 558 AddToTranslation(translation, |
| 572 value, | 559 value, |
| 573 environment->HasTaggedValueAt(i), | 560 environment->HasTaggedValueAt(i), |
| 574 environment->HasUint32ValueAt(i), | 561 environment->HasUint32ValueAt(i)); |
| 575 arguments_known, | |
| 576 arguments_index, | |
| 577 arguments_count); | |
| 578 } | 562 } |
| 579 } | 563 } |
| 580 | 564 |
| 581 | 565 |
| 582 void LCodeGen::AddToTranslation(Translation* translation, | 566 void LCodeGen::AddToTranslation(Translation* translation, |
| 583 LOperand* op, | 567 LOperand* op, |
| 584 bool is_tagged, | 568 bool is_tagged, |
| 585 bool is_uint32, | 569 bool is_uint32) { |
| 586 bool arguments_known, | 570 if (op->IsStackSlot()) { |
| 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()) { | |
| 596 if (is_tagged) { | 571 if (is_tagged) { |
| 597 translation->StoreStackSlot(op->index()); | 572 translation->StoreStackSlot(op->index()); |
| 598 } else if (is_uint32) { | 573 } else if (is_uint32) { |
| 599 translation->StoreUint32StackSlot(op->index()); | 574 translation->StoreUint32StackSlot(op->index()); |
| 600 } else { | 575 } else { |
| 601 translation->StoreInt32StackSlot(op->index()); | 576 translation->StoreInt32StackSlot(op->index()); |
| 602 } | 577 } |
| 603 } else if (op->IsDoubleStackSlot()) { | 578 } else if (op->IsDoubleStackSlot()) { |
| 604 translation->StoreDoubleStackSlot(op->index()); | 579 translation->StoreDoubleStackSlot(op->index()); |
| 605 } else if (op->IsArgument()) { | 580 } else if (op->IsArgument()) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 // 0 ..................................................... size-1 | 665 // 0 ..................................................... size-1 |
| 691 // [parameters] [locals] [expression stack including arguments] | 666 // [parameters] [locals] [expression stack including arguments] |
| 692 | 667 |
| 693 // Layout of the translation: | 668 // Layout of the translation: |
| 694 // 0 ........................................................ size - 1 + 4 | 669 // 0 ........................................................ size - 1 + 4 |
| 695 // [expression stack including arguments] [locals] [4 words] [parameters] | 670 // [expression stack including arguments] [locals] [4 words] [parameters] |
| 696 // |>------------ translation_size ------------<| | 671 // |>------------ translation_size ------------<| |
| 697 | 672 |
| 698 int frame_count = 0; | 673 int frame_count = 0; |
| 699 int jsframe_count = 0; | 674 int jsframe_count = 0; |
| 700 int args_index = 0; | |
| 701 int args_count = 0; | |
| 702 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { | 675 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { |
| 703 ++frame_count; | 676 ++frame_count; |
| 704 if (e->frame_type() == JS_FUNCTION) { | 677 if (e->frame_type() == JS_FUNCTION) { |
| 705 ++jsframe_count; | 678 ++jsframe_count; |
| 706 } | 679 } |
| 707 } | 680 } |
| 708 Translation translation(&translations_, frame_count, jsframe_count, zone()); | 681 Translation translation(&translations_, frame_count, jsframe_count, zone()); |
| 709 WriteTranslation(environment, &translation, &args_index, &args_count); | 682 WriteTranslation(environment, &translation); |
| 710 int deoptimization_index = deoptimizations_.length(); | 683 int deoptimization_index = deoptimizations_.length(); |
| 711 int pc_offset = masm()->pc_offset(); | 684 int pc_offset = masm()->pc_offset(); |
| 712 environment->Register(deoptimization_index, | 685 environment->Register(deoptimization_index, |
| 713 translation.index(), | 686 translation.index(), |
| 714 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 687 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 715 deoptimizations_.Add(environment, environment->zone()); | 688 deoptimizations_.Add(environment, environment->zone()); |
| 716 } | 689 } |
| 717 } | 690 } |
| 718 | 691 |
| 719 | 692 |
| 720 void LCodeGen::DeoptimizeIf(Condition cc, | 693 void LCodeGen::DeoptimizeIf(Condition cc, |
| 721 LEnvironment* environment, | 694 LEnvironment* environment, |
| 722 Deoptimizer::BailoutType bailout_type) { | 695 Deoptimizer::BailoutType bailout_type) { |
| 723 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 696 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 724 ASSERT(environment->HasBeenRegistered()); | 697 ASSERT(environment->HasBeenRegistered()); |
| 725 int id = environment->deoptimization_index(); | 698 int id = environment->deoptimization_index(); |
| 726 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 699 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 727 Address entry = | 700 Address entry = |
| 728 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 701 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 729 if (entry == NULL) { | 702 if (entry == NULL) { |
| 730 Abort("bailout was not prepared"); | 703 Abort("bailout was not prepared"); |
| 731 return; | 704 return; |
| 732 } | 705 } |
| 733 | 706 |
| 734 ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64. | 707 ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64. |
| 735 | 708 |
| 736 if (FLAG_trap_on_deopt) { | 709 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { |
| 737 Label done; | 710 Label done; |
| 738 if (cc != no_condition) { | 711 if (cc != no_condition) { |
| 739 __ j(NegateCondition(cc), &done, Label::kNear); | 712 __ j(NegateCondition(cc), &done, Label::kNear); |
| 740 } | 713 } |
| 741 __ int3(); | 714 __ int3(); |
| 742 __ bind(&done); | 715 __ bind(&done); |
| 743 } | 716 } |
| 744 | 717 |
| 745 ASSERT(info()->IsStub() || frame_is_built_); | 718 ASSERT(info()->IsStub() || frame_is_built_); |
| 746 bool needs_lazy_deopt = info()->IsStub(); | 719 bool needs_lazy_deopt = info()->IsStub(); |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1737 } | 1710 } |
| 1738 | 1711 |
| 1739 | 1712 |
| 1740 void LCodeGen::DoAddI(LAddI* instr) { | 1713 void LCodeGen::DoAddI(LAddI* instr) { |
| 1741 LOperand* left = instr->left(); | 1714 LOperand* left = instr->left(); |
| 1742 LOperand* right = instr->right(); | 1715 LOperand* right = instr->right(); |
| 1743 | 1716 |
| 1744 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1717 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
| 1745 if (right->IsConstantOperand()) { | 1718 if (right->IsConstantOperand()) { |
| 1746 int32_t offset = ToInteger32(LConstantOperand::cast(right)); | 1719 int32_t offset = ToInteger32(LConstantOperand::cast(right)); |
| 1747 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); | 1720 __ leal(ToRegister(instr->result()), |
| 1721 MemOperand(ToRegister(left), offset)); |
| 1748 } else { | 1722 } else { |
| 1749 Operand address(ToRegister(left), ToRegister(right), times_1, 0); | 1723 Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
| 1750 __ lea(ToRegister(instr->result()), address); | 1724 __ leal(ToRegister(instr->result()), address); |
| 1751 } | 1725 } |
| 1752 } else { | 1726 } else { |
| 1753 if (right->IsConstantOperand()) { | 1727 if (right->IsConstantOperand()) { |
| 1754 __ addl(ToRegister(left), | 1728 __ addl(ToRegister(left), |
| 1755 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1729 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
| 1756 } else if (right->IsRegister()) { | 1730 } else if (right->IsRegister()) { |
| 1757 __ addl(ToRegister(left), ToRegister(right)); | 1731 __ addl(ToRegister(left), ToRegister(right)); |
| 1758 } else { | 1732 } else { |
| 1759 __ addl(ToRegister(left), ToOperand(right)); | 1733 __ addl(ToRegister(left), ToOperand(right)); |
| 1760 } | 1734 } |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 __ JumpIfSmi(object, &false_result); | 2444 __ JumpIfSmi(object, &false_result); |
| 2471 | 2445 |
| 2472 // This is the inlined call site instanceof cache. The two occurences of the | 2446 // This is the inlined call site instanceof cache. The two occurences of the |
| 2473 // hole value will be patched to the last map/result pair generated by the | 2447 // hole value will be patched to the last map/result pair generated by the |
| 2474 // instanceof stub. | 2448 // instanceof stub. |
| 2475 Label cache_miss; | 2449 Label cache_miss; |
| 2476 // Use a temp register to avoid memory operands with variable lengths. | 2450 // Use a temp register to avoid memory operands with variable lengths. |
| 2477 Register map = ToRegister(instr->temp()); | 2451 Register map = ToRegister(instr->temp()); |
| 2478 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 2452 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 2479 __ bind(deferred->map_check()); // Label for calculating code patching. | 2453 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 2480 Handle<JSGlobalPropertyCell> cache_cell = | 2454 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); |
| 2481 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); | 2455 __ movq(kScratchRegister, cache_cell, RelocInfo::CELL); |
| 2482 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); | |
| 2483 __ cmpq(map, Operand(kScratchRegister, 0)); | 2456 __ cmpq(map, Operand(kScratchRegister, 0)); |
| 2484 __ j(not_equal, &cache_miss, Label::kNear); | 2457 __ j(not_equal, &cache_miss, Label::kNear); |
| 2485 // Patched to load either true or false. | 2458 // Patched to load either true or false. |
| 2486 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2459 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
| 2487 #ifdef DEBUG | 2460 #ifdef DEBUG |
| 2488 // Check that the code size between patch label and patch sites is invariant. | 2461 // Check that the code size between patch label and patch sites is invariant. |
| 2489 Label end_of_patched_code; | 2462 Label end_of_patched_code; |
| 2490 __ bind(&end_of_patched_code); | 2463 __ bind(&end_of_patched_code); |
| 2491 ASSERT(true); | 2464 ASSERT(true); |
| 2492 #endif | 2465 #endif |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2641 __ Move(rcx, instr->name()); | 2614 __ Move(rcx, instr->name()); |
| 2642 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 2615 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
| 2643 RelocInfo::CODE_TARGET_CONTEXT; | 2616 RelocInfo::CODE_TARGET_CONTEXT; |
| 2644 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2617 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2645 CallCode(ic, mode, instr); | 2618 CallCode(ic, mode, instr); |
| 2646 } | 2619 } |
| 2647 | 2620 |
| 2648 | 2621 |
| 2649 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2622 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 2650 Register value = ToRegister(instr->value()); | 2623 Register value = ToRegister(instr->value()); |
| 2651 Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); | 2624 Handle<Cell> cell_handle = instr->hydrogen()->cell(); |
| 2652 | 2625 |
| 2653 // If the cell we are storing to contains the hole it could have | 2626 // If the cell we are storing to contains the hole it could have |
| 2654 // been deleted from the property dictionary. In that case, we need | 2627 // been deleted from the property dictionary. In that case, we need |
| 2655 // to update the property details in the property dictionary to mark | 2628 // to update the property details in the property dictionary to mark |
| 2656 // it as no longer deleted. We deoptimize in that case. | 2629 // it as no longer deleted. We deoptimize in that case. |
| 2657 if (instr->hydrogen()->RequiresHoleCheck()) { | 2630 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2658 // We have a temp because CompareRoot might clobber kScratchRegister. | 2631 // We have a temp because CompareRoot might clobber kScratchRegister. |
| 2659 Register cell = ToRegister(instr->temp()); | 2632 Register cell = ToRegister(instr->temp()); |
| 2660 ASSERT(!value.is(cell)); | 2633 ASSERT(!value.is(cell)); |
| 2661 __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2634 __ movq(cell, cell_handle, RelocInfo::CELL); |
| 2662 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); | 2635 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); |
| 2663 DeoptimizeIf(equal, instr->environment()); | 2636 DeoptimizeIf(equal, instr->environment()); |
| 2664 // Store the value. | 2637 // Store the value. |
| 2665 __ movq(Operand(cell, 0), value); | 2638 __ movq(Operand(cell, 0), value); |
| 2666 } else { | 2639 } else { |
| 2667 // Store the value. | 2640 // Store the value. |
| 2668 __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2641 __ movq(kScratchRegister, cell_handle, RelocInfo::CELL); |
| 2669 __ movq(Operand(kScratchRegister, 0), value); | 2642 __ movq(Operand(kScratchRegister, 0), value); |
| 2670 } | 2643 } |
| 2671 // Cells are always rescanned, so no write barrier here. | 2644 // Cells are always rescanned, so no write barrier here. |
| 2672 } | 2645 } |
| 2673 | 2646 |
| 2674 | 2647 |
| 2675 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2648 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 2676 ASSERT(ToRegister(instr->global_object()).is(rdx)); | 2649 ASSERT(ToRegister(instr->global_object()).is(rdx)); |
| 2677 ASSERT(ToRegister(instr->value()).is(rax)); | 2650 ASSERT(ToRegister(instr->value()).is(rax)); |
| 2678 | 2651 |
| (...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3944 __ Set(rax, instr->arity()); | 3917 __ Set(rax, instr->arity()); |
| 3945 __ Move(rbx, instr->hydrogen()->property_cell()); | 3918 __ Move(rbx, instr->hydrogen()->property_cell()); |
| 3946 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3919 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 3947 bool disable_allocation_sites = | 3920 bool disable_allocation_sites = |
| 3948 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); | 3921 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); |
| 3949 | 3922 |
| 3950 if (instr->arity() == 0) { | 3923 if (instr->arity() == 0) { |
| 3951 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); | 3924 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); |
| 3952 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3925 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3953 } else if (instr->arity() == 1) { | 3926 } else if (instr->arity() == 1) { |
| 3927 Label done; |
| 3928 if (IsFastPackedElementsKind(kind)) { |
| 3929 Label packed_case; |
| 3930 // We might need a change here |
| 3931 // look at the first argument |
| 3932 __ movq(rcx, Operand(rsp, 0)); |
| 3933 __ testq(rcx, rcx); |
| 3934 __ j(zero, &packed_case); |
| 3935 |
| 3936 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 3937 ArraySingleArgumentConstructorStub stub(holey_kind, |
| 3938 disable_allocation_sites); |
| 3939 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3940 __ jmp(&done); |
| 3941 __ bind(&packed_case); |
| 3942 } |
| 3943 |
| 3954 ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites); | 3944 ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites); |
| 3955 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3945 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3946 __ bind(&done); |
| 3956 } else { | 3947 } else { |
| 3957 ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites); | 3948 ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites); |
| 3958 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3949 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3959 } | 3950 } |
| 3960 } | 3951 } |
| 3961 | 3952 |
| 3962 | 3953 |
| 3963 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3954 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3964 CallRuntime(instr->function(), instr->arity(), instr); | 3955 CallRuntime(instr->function(), instr->arity(), instr); |
| 3965 } | 3956 } |
| (...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5614 FixedArray::kHeaderSize - kPointerSize)); | 5605 FixedArray::kHeaderSize - kPointerSize)); |
| 5615 __ bind(&done); | 5606 __ bind(&done); |
| 5616 } | 5607 } |
| 5617 | 5608 |
| 5618 | 5609 |
| 5619 #undef __ | 5610 #undef __ |
| 5620 | 5611 |
| 5621 } } // namespace v8::internal | 5612 } } // namespace v8::internal |
| 5622 | 5613 |
| 5623 #endif // V8_TARGET_ARCH_X64 | 5614 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |