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 |