| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug.h" | 10 #include "src/debug.h" |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 } | 311 } |
| 312 | 312 |
| 313 | 313 |
| 314 static void Generate_Runtime_NewObject(MacroAssembler* masm, | 314 static void Generate_Runtime_NewObject(MacroAssembler* masm, |
| 315 bool create_memento, | 315 bool create_memento, |
| 316 Register original_constructor, | 316 Register original_constructor, |
| 317 Label* count_incremented, | 317 Label* count_incremented, |
| 318 Label* allocated) { | 318 Label* allocated) { |
| 319 if (create_memento) { | 319 if (create_memento) { |
| 320 // Get the cell or allocation site. | 320 // Get the cell or allocation site. |
| 321 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); | 321 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); |
| 322 __ push(r2); | 322 __ push(r2); |
| 323 } | 323 } |
| 324 | 324 |
| 325 __ push(r1); // argument for Runtime_NewObject | 325 __ push(r1); // argument for Runtime_NewObject |
| 326 __ push(original_constructor); // original constructor | 326 __ push(original_constructor); // original constructor |
| 327 if (create_memento) { | 327 if (create_memento) { |
| 328 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | 328 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); |
| 329 } else { | 329 } else { |
| 330 __ CallRuntime(Runtime::kNewObject, 2); | 330 __ CallRuntime(Runtime::kNewObject, 2); |
| 331 } | 331 } |
| 332 __ mov(r4, r0); | 332 __ mov(r4, r0); |
| 333 | 333 |
| 334 // Runtime_NewObjectWithAllocationSite increments allocation count. | 334 // Runtime_NewObjectWithAllocationSite increments allocation count. |
| 335 // Skip the increment. | 335 // Skip the increment. |
| 336 if (create_memento) { | 336 if (create_memento) { |
| 337 __ jmp(count_incremented); | 337 __ jmp(count_incremented); |
| 338 } else { | 338 } else { |
| 339 __ jmp(allocated); | 339 __ jmp(allocated); |
| 340 } | 340 } |
| 341 } | 341 } |
| 342 | 342 |
| 343 | 343 |
| 344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 345 bool is_api_function, | 345 bool is_api_function, |
| 346 bool use_new_target, | |
| 347 bool create_memento) { | 346 bool create_memento) { |
| 348 // ----------- S t a t e ------------- | 347 // ----------- S t a t e ------------- |
| 349 // -- r0 : number of arguments | 348 // -- r0 : number of arguments |
| 350 // -- r1 : constructor function | 349 // -- r1 : constructor function |
| 351 // -- r2 : allocation site or undefined | 350 // -- r2 : allocation site or undefined |
| 352 // -- r3 : original constructor | 351 // -- r3 : original constructor |
| 353 // -- lr : return address | 352 // -- lr : return address |
| 354 // -- sp[...]: constructor arguments | 353 // -- sp[...]: constructor arguments |
| 355 // ----------------------------------- | 354 // ----------------------------------- |
| 356 | 355 |
| 357 // Should never create mementos for api functions. | 356 // Should never create mementos for api functions. |
| 358 DCHECK(!is_api_function || !create_memento); | 357 DCHECK(!is_api_function || !create_memento); |
| 359 | 358 |
| 360 Isolate* isolate = masm->isolate(); | 359 Isolate* isolate = masm->isolate(); |
| 361 | 360 |
| 362 // Enter a construct frame. | 361 // Enter a construct frame. |
| 363 { | 362 { |
| 364 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 363 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
| 365 | 364 |
| 366 if (create_memento) { | 365 if (create_memento) { |
| 367 __ AssertUndefinedOrAllocationSite(r2, r4); | 366 __ AssertUndefinedOrAllocationSite(r2, r4); |
| 368 __ push(r2); | 367 __ push(r2); |
| 369 } | 368 } |
| 370 | 369 |
| 371 // Preserve the incoming parameters on the stack. | 370 // Preserve the incoming parameters on the stack. |
| 372 __ SmiTag(r0); | 371 __ SmiTag(r0); |
| 373 __ push(r0); | 372 __ push(r0); |
| 374 __ push(r1); | 373 __ push(r1); |
| 375 if (use_new_target) { | 374 __ push(r3); |
| 376 __ push(r3); | |
| 377 } | |
| 378 | 375 |
| 379 Label rt_call, allocated, normal_new, count_incremented; | 376 Label rt_call, allocated, normal_new, count_incremented; |
| 380 __ cmp(r1, r3); | 377 __ cmp(r1, r3); |
| 381 __ b(eq, &normal_new); | 378 __ b(eq, &normal_new); |
| 382 | 379 |
| 383 // Original constructor and function are different. | 380 // Original constructor and function are different. |
| 384 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, | 381 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, |
| 385 &allocated); | 382 &allocated); |
| 386 __ bind(&normal_new); | 383 __ bind(&normal_new); |
| 387 | 384 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 // r1: constructor function | 604 // r1: constructor function |
| 608 __ bind(&rt_call); | 605 __ bind(&rt_call); |
| 609 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, | 606 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, |
| 610 &allocated); | 607 &allocated); |
| 611 | 608 |
| 612 // Receiver for constructor call allocated. | 609 // Receiver for constructor call allocated. |
| 613 // r4: JSObject | 610 // r4: JSObject |
| 614 __ bind(&allocated); | 611 __ bind(&allocated); |
| 615 | 612 |
| 616 if (create_memento) { | 613 if (create_memento) { |
| 617 int offset = (use_new_target ? 3 : 2) * kPointerSize; | 614 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); |
| 618 __ ldr(r2, MemOperand(sp, offset)); | |
| 619 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 615 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 620 __ cmp(r2, r5); | 616 __ cmp(r2, r5); |
| 621 __ b(eq, &count_incremented); | 617 __ b(eq, &count_incremented); |
| 622 // r2 is an AllocationSite. We are creating a memento from it, so we | 618 // r2 is an AllocationSite. We are creating a memento from it, so we |
| 623 // need to increment the memento create count. | 619 // need to increment the memento create count. |
| 624 __ ldr(r3, FieldMemOperand(r2, | 620 __ ldr(r3, FieldMemOperand(r2, |
| 625 AllocationSite::kPretenureCreateCountOffset)); | 621 AllocationSite::kPretenureCreateCountOffset)); |
| 626 __ add(r3, r3, Operand(Smi::FromInt(1))); | 622 __ add(r3, r3, Operand(Smi::FromInt(1))); |
| 627 __ str(r3, FieldMemOperand(r2, | 623 __ str(r3, FieldMemOperand(r2, |
| 628 AllocationSite::kPretenureCreateCountOffset)); | 624 AllocationSite::kPretenureCreateCountOffset)); |
| 629 __ bind(&count_incremented); | 625 __ bind(&count_incremented); |
| 630 } | 626 } |
| 631 | 627 |
| 632 // Restore the parameters. | 628 // Restore the parameters. |
| 633 if (use_new_target) { | 629 __ pop(r3); |
| 634 __ pop(r3); | |
| 635 } | |
| 636 __ pop(r1); | 630 __ pop(r1); |
| 637 | 631 |
| 638 // Retrieve smi-tagged arguments count from the stack. | 632 // Retrieve smi-tagged arguments count from the stack. |
| 639 __ ldr(r0, MemOperand(sp)); | 633 __ ldr(r0, MemOperand(sp)); |
| 640 __ SmiUntag(r0); | 634 __ SmiUntag(r0); |
| 641 | 635 |
| 642 // Push new.target onto the construct frame. This is stored just below the | 636 // Push new.target onto the construct frame. This is stored just below the |
| 643 // receiver on the stack. | 637 // receiver on the stack. |
| 644 if (use_new_target) { | 638 __ push(r3); |
| 645 __ push(r3); | |
| 646 } | |
| 647 __ push(r4); | 639 __ push(r4); |
| 648 __ push(r4); | 640 __ push(r4); |
| 649 | 641 |
| 650 // Set up pointer to last argument. | 642 // Set up pointer to last argument. |
| 651 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 643 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 652 | 644 |
| 653 // Copy arguments and receiver to the expression stack. | 645 // Copy arguments and receiver to the expression stack. |
| 654 // r0: number of arguments | 646 // r0: number of arguments |
| 655 // r1: constructor function | 647 // r1: constructor function |
| 656 // r2: address of last argument (caller sp) | 648 // r2: address of last argument (caller sp) |
| 657 // r3: number of arguments (smi-tagged) | 649 // r3: number of arguments (smi-tagged) |
| 658 // sp[0]: receiver | 650 // sp[0]: receiver |
| 659 // sp[1]: receiver | 651 // sp[1]: receiver |
| 660 // sp[2]: new.target (if used) | 652 // sp[2]: new.target |
| 661 // sp[2/3]: number of arguments (smi-tagged) | 653 // sp[3]: number of arguments (smi-tagged) |
| 662 Label loop, entry; | 654 Label loop, entry; |
| 663 __ SmiTag(r3, r0); | 655 __ SmiTag(r3, r0); |
| 664 __ b(&entry); | 656 __ b(&entry); |
| 665 __ bind(&loop); | 657 __ bind(&loop); |
| 666 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); | 658 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); |
| 667 __ push(ip); | 659 __ push(ip); |
| 668 __ bind(&entry); | 660 __ bind(&entry); |
| 669 __ sub(r3, r3, Operand(2), SetCC); | 661 __ sub(r3, r3, Operand(2), SetCC); |
| 670 __ b(ge, &loop); | 662 __ b(ge, &loop); |
| 671 | 663 |
| 672 // Call the function. | 664 // Call the function. |
| 673 // r0: number of arguments | 665 // r0: number of arguments |
| 674 // r1: constructor function | 666 // r1: constructor function |
| 675 if (is_api_function) { | 667 if (is_api_function) { |
| 676 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 668 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 677 Handle<Code> code = | 669 Handle<Code> code = |
| 678 masm->isolate()->builtins()->HandleApiCallConstruct(); | 670 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 679 __ Call(code, RelocInfo::CODE_TARGET); | 671 __ Call(code, RelocInfo::CODE_TARGET); |
| 680 } else { | 672 } else { |
| 681 ParameterCount actual(r0); | 673 ParameterCount actual(r0); |
| 682 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); | 674 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); |
| 683 } | 675 } |
| 684 | 676 |
| 685 // Store offset of return address for deoptimizer. | 677 // Store offset of return address for deoptimizer. |
| 686 // TODO(arv): Remove the "!use_new_target" before supporting optimization | 678 if (!is_api_function) { |
| 687 // of functions that reference new.target | |
| 688 if (!is_api_function && !use_new_target) { | |
| 689 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 679 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
| 690 } | 680 } |
| 691 | 681 |
| 692 // Restore context from the frame. | 682 // Restore context from the frame. |
| 693 // r0: result | 683 // r0: result |
| 694 // sp[0]: receiver | 684 // sp[0]: receiver |
| 695 // sp[1]: new.target (if used) | 685 // sp[1]: new.target |
| 696 // sp[1/2]: number of arguments (smi-tagged) | 686 // sp[2]: number of arguments (smi-tagged) |
| 697 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 687 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 698 | 688 |
| 699 // If the result is an object (in the ECMA sense), we should get rid | 689 // If the result is an object (in the ECMA sense), we should get rid |
| 700 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 690 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
| 701 // on page 74. | 691 // on page 74. |
| 702 Label use_receiver, exit; | 692 Label use_receiver, exit; |
| 703 | 693 |
| 704 // If the result is a smi, it is *not* an object in the ECMA sense. | 694 // If the result is a smi, it is *not* an object in the ECMA sense. |
| 705 // r0: result | 695 // r0: result |
| 706 // sp[0]: receiver (newly allocated object) | 696 // sp[0]: receiver (newly allocated object) |
| 707 // sp[1]: new.target (if used) | 697 // sp[1]: new.target (if used) |
| 708 // sp[1/2]: number of arguments (smi-tagged) | 698 // sp[1/2]: number of arguments (smi-tagged) |
| 709 __ JumpIfSmi(r0, &use_receiver); | 699 __ JumpIfSmi(r0, &use_receiver); |
| 710 | 700 |
| 711 // If the type of the result (stored in its map) is less than | 701 // If the type of the result (stored in its map) is less than |
| 712 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 702 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
| 713 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); | 703 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); |
| 714 __ b(ge, &exit); | 704 __ b(ge, &exit); |
| 715 | 705 |
| 716 // Throw away the result of the constructor invocation and use the | 706 // Throw away the result of the constructor invocation and use the |
| 717 // on-stack receiver as the result. | 707 // on-stack receiver as the result. |
| 718 __ bind(&use_receiver); | 708 __ bind(&use_receiver); |
| 719 __ ldr(r0, MemOperand(sp)); | 709 __ ldr(r0, MemOperand(sp)); |
| 720 | 710 |
| 721 // Remove receiver from the stack, remove caller arguments, and | 711 // Remove receiver from the stack, remove caller arguments, and |
| 722 // return. | 712 // return. |
| 723 __ bind(&exit); | 713 __ bind(&exit); |
| 724 // r0: result | 714 // r0: result |
| 725 // sp[0]: receiver (newly allocated object) | 715 // sp[0]: receiver (newly allocated object) |
| 726 // sp[1]: new.target (if used) | 716 // sp[1]: new.target (original constructor) |
| 727 // sp[1/2]: number of arguments (smi-tagged) | 717 // sp[2]: number of arguments (smi-tagged) |
| 728 int offset = (use_new_target ? 2 : 1) * kPointerSize; | 718 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
| 729 __ ldr(r1, MemOperand(sp, offset)); | |
| 730 | 719 |
| 731 // Leave construct frame. | 720 // Leave construct frame. |
| 732 } | 721 } |
| 733 | 722 |
| 734 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 723 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
| 735 __ add(sp, sp, Operand(kPointerSize)); | 724 __ add(sp, sp, Operand(kPointerSize)); |
| 736 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 725 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
| 737 __ Jump(lr); | 726 __ Jump(lr); |
| 738 } | 727 } |
| 739 | 728 |
| 740 | 729 |
| 741 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 730 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 742 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); | 731 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); |
| 743 } | 732 } |
| 744 | 733 |
| 745 | 734 |
| 746 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 735 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 747 Generate_JSConstructStubHelper(masm, true, false, false); | 736 Generate_JSConstructStubHelper(masm, true, false); |
| 748 } | 737 } |
| 749 | 738 |
| 750 | 739 |
| 751 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { | |
| 752 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); | |
| 753 } | |
| 754 | |
| 755 | |
| 756 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 740 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 757 // ----------- S t a t e ------------- | 741 // ----------- S t a t e ------------- |
| 758 // -- r0 : number of arguments | 742 // -- r0 : number of arguments |
| 759 // -- r1 : constructor function | 743 // -- r1 : constructor function |
| 760 // -- r2 : allocation site or undefined | 744 // -- r2 : allocation site or undefined |
| 761 // -- r3 : original constructor | 745 // -- r3 : original constructor |
| 762 // -- lr : return address | 746 // -- lr : return address |
| 763 // -- sp[...]: constructor arguments | 747 // -- sp[...]: constructor arguments |
| 764 // ----------------------------------- | 748 // ----------------------------------- |
| 765 | 749 |
| (...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1829 } | 1813 } |
| 1830 } | 1814 } |
| 1831 | 1815 |
| 1832 | 1816 |
| 1833 #undef __ | 1817 #undef __ |
| 1834 | 1818 |
| 1835 } // namespace internal | 1819 } // namespace internal |
| 1836 } // namespace v8 | 1820 } // namespace v8 |
| 1837 | 1821 |
| 1838 #endif // V8_TARGET_ARCH_ARM | 1822 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |