OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 } | 302 } |
303 | 303 |
304 | 304 |
305 static void Generate_Runtime_NewObject(MacroAssembler* masm, | 305 static void Generate_Runtime_NewObject(MacroAssembler* masm, |
306 bool create_memento, | 306 bool create_memento, |
307 Register original_constructor, | 307 Register original_constructor, |
308 Label* count_incremented, | 308 Label* count_incremented, |
309 Label* allocated) { | 309 Label* allocated) { |
310 if (create_memento) { | 310 if (create_memento) { |
311 // Get the cell or allocation site. | 311 // Get the cell or allocation site. |
312 __ Peek(x4, 2 * kXRegSize); | 312 __ Peek(x4, 3 * kXRegSize); |
313 __ Push(x4); | 313 __ Push(x4); |
314 __ Push(x1); // Argument for Runtime_NewObject. | 314 __ Push(x1); // Argument for Runtime_NewObject. |
315 __ Push(original_constructor); | 315 __ Push(original_constructor); |
316 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | 316 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); |
317 __ Mov(x4, x0); | 317 __ Mov(x4, x0); |
318 // If we ended up using the runtime, and we want a memento, then the | 318 // If we ended up using the runtime, and we want a memento, then the |
319 // runtime call made it for us, and we shouldn't do create count | 319 // runtime call made it for us, and we shouldn't do create count |
320 // increment. | 320 // increment. |
321 __ jmp(count_incremented); | 321 __ jmp(count_incremented); |
322 } else { | 322 } else { |
323 __ Push(x1); // Argument for Runtime_NewObject. | 323 __ Push(x1); // Argument for Runtime_NewObject. |
324 __ Push(original_constructor); | 324 __ Push(original_constructor); |
325 __ CallRuntime(Runtime::kNewObject, 2); | 325 __ CallRuntime(Runtime::kNewObject, 2); |
326 __ Mov(x4, x0); | 326 __ Mov(x4, x0); |
327 __ jmp(allocated); | 327 __ jmp(allocated); |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
333 bool is_api_function, | 333 bool is_api_function, |
334 bool use_new_target, | |
335 bool create_memento) { | 334 bool create_memento) { |
336 // ----------- S t a t e ------------- | 335 // ----------- S t a t e ------------- |
337 // -- x0 : number of arguments | 336 // -- x0 : number of arguments |
338 // -- x1 : constructor function | 337 // -- x1 : constructor function |
339 // -- x2 : allocation site or undefined | 338 // -- x2 : allocation site or undefined |
340 // -- x3 : original constructor | 339 // -- x3 : original constructor |
341 // -- lr : return address | 340 // -- lr : return address |
342 // -- sp[...]: constructor arguments | 341 // -- sp[...]: constructor arguments |
343 // ----------------------------------- | 342 // ----------------------------------- |
344 | 343 |
(...skipping 12 matching lines...) Expand all Loading... |
357 __ AssertUndefinedOrAllocationSite(x2, x10); | 356 __ AssertUndefinedOrAllocationSite(x2, x10); |
358 __ Push(x2); | 357 __ Push(x2); |
359 } | 358 } |
360 | 359 |
361 Register argc = x0; | 360 Register argc = x0; |
362 Register constructor = x1; | 361 Register constructor = x1; |
363 Register original_constructor = x3; | 362 Register original_constructor = x3; |
364 | 363 |
365 // Preserve the incoming parameters on the stack. | 364 // Preserve the incoming parameters on the stack. |
366 __ SmiTag(argc); | 365 __ SmiTag(argc); |
367 if (use_new_target) { | 366 __ Push(argc, constructor, original_constructor); |
368 __ Push(argc, constructor, original_constructor); | 367 // sp[0]: new.target |
369 } else { | 368 // sp[1]: Constructor function. |
370 __ Push(argc, constructor); | 369 // sp[2]: number of arguments (smi-tagged) |
371 } | |
372 // sp[0]: new.target (if used) | |
373 // sp[0/1]: Constructor function. | |
374 // sp[1/2]: number of arguments (smi-tagged) | |
375 | 370 |
376 Label rt_call, count_incremented, allocated, normal_new; | 371 Label rt_call, count_incremented, allocated, normal_new; |
377 __ Cmp(constructor, original_constructor); | 372 __ Cmp(constructor, original_constructor); |
378 __ B(eq, &normal_new); | 373 __ B(eq, &normal_new); |
379 Generate_Runtime_NewObject(masm, create_memento, original_constructor, | 374 Generate_Runtime_NewObject(masm, create_memento, original_constructor, |
380 &count_incremented, &allocated); | 375 &count_incremented, &allocated); |
381 | 376 |
382 __ Bind(&normal_new); | 377 __ Bind(&normal_new); |
383 | 378 |
384 // Try to allocate the object without transitioning into C code. If any of | 379 // Try to allocate the object without transitioning into C code. If any of |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 // Allocate the new receiver object using the runtime call. | 575 // Allocate the new receiver object using the runtime call. |
581 __ Bind(&rt_call); | 576 __ Bind(&rt_call); |
582 Generate_Runtime_NewObject(masm, create_memento, constructor, | 577 Generate_Runtime_NewObject(masm, create_memento, constructor, |
583 &count_incremented, &allocated); | 578 &count_incremented, &allocated); |
584 | 579 |
585 // Receiver for constructor call allocated. | 580 // Receiver for constructor call allocated. |
586 // x4: JSObject | 581 // x4: JSObject |
587 __ Bind(&allocated); | 582 __ Bind(&allocated); |
588 | 583 |
589 if (create_memento) { | 584 if (create_memento) { |
590 int offset = (use_new_target ? 3 : 2) * kXRegSize; | 585 __ Peek(x10, 3 * kXRegSize); |
591 __ Peek(x10, offset); | |
592 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); | 586 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
593 // r2 is an AllocationSite. We are creating a memento from it, so we | 587 // r2 is an AllocationSite. We are creating a memento from it, so we |
594 // need to increment the memento create count. | 588 // need to increment the memento create count. |
595 __ Ldr(x5, FieldMemOperand(x10, | 589 __ Ldr(x5, FieldMemOperand(x10, |
596 AllocationSite::kPretenureCreateCountOffset)); | 590 AllocationSite::kPretenureCreateCountOffset)); |
597 __ Add(x5, x5, Operand(Smi::FromInt(1))); | 591 __ Add(x5, x5, Operand(Smi::FromInt(1))); |
598 __ Str(x5, FieldMemOperand(x10, | 592 __ Str(x5, FieldMemOperand(x10, |
599 AllocationSite::kPretenureCreateCountOffset)); | 593 AllocationSite::kPretenureCreateCountOffset)); |
600 __ bind(&count_incremented); | 594 __ bind(&count_incremented); |
601 } | 595 } |
602 | 596 |
603 // Restore the parameters. | 597 // Restore the parameters. |
604 if (use_new_target) { | 598 __ Pop(original_constructor); |
605 __ Pop(original_constructor); | |
606 } | |
607 __ Pop(constructor); | 599 __ Pop(constructor); |
608 | 600 |
609 // Reload the number of arguments from the stack. | 601 // Reload the number of arguments from the stack. |
610 // Set it up in x0 for the function call below. | 602 // Set it up in x0 for the function call below. |
611 // jssp[0]: number of arguments (smi-tagged) | 603 // jssp[0]: number of arguments (smi-tagged) |
612 __ Peek(argc, 0); // Load number of arguments. | 604 __ Peek(argc, 0); // Load number of arguments. |
613 __ SmiUntag(argc); | 605 __ SmiUntag(argc); |
614 | 606 |
615 if (use_new_target) { | 607 __ Push(original_constructor, x4, x4); |
616 __ Push(original_constructor, x4, x4); | |
617 } else { | |
618 __ Push(x4, x4); | |
619 } | |
620 | 608 |
621 // Set up pointer to last argument. | 609 // Set up pointer to last argument. |
622 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); | 610 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); |
623 | 611 |
624 // Copy arguments and receiver to the expression stack. | 612 // Copy arguments and receiver to the expression stack. |
625 // Copy 2 values every loop to use ldp/stp. | 613 // Copy 2 values every loop to use ldp/stp. |
626 // x0: number of arguments | 614 // x0: number of arguments |
627 // x1: constructor function | 615 // x1: constructor function |
628 // x2: address of last argument (caller sp) | 616 // x2: address of last argument (caller sp) |
629 // jssp[0]: receiver | 617 // jssp[0]: receiver |
630 // jssp[1]: receiver | 618 // jssp[1]: receiver |
631 // jssp[2]: new.target (if used) | 619 // jssp[2]: new.target |
632 // jssp[2/3]: number of arguments (smi-tagged) | 620 // jssp[3]: number of arguments (smi-tagged) |
633 // Compute the start address of the copy in x3. | 621 // Compute the start address of the copy in x3. |
634 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); | 622 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); |
635 Label loop, entry, done_copying_arguments; | 623 Label loop, entry, done_copying_arguments; |
636 __ B(&entry); | 624 __ B(&entry); |
637 __ Bind(&loop); | 625 __ Bind(&loop); |
638 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); | 626 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); |
639 __ Push(x11, x10); | 627 __ Push(x11, x10); |
640 __ Bind(&entry); | 628 __ Bind(&entry); |
641 __ Cmp(x3, x2); | 629 __ Cmp(x3, x2); |
642 __ B(gt, &loop); | 630 __ B(gt, &loop); |
(...skipping 10 matching lines...) Expand all Loading... |
653 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); | 641 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); |
654 Handle<Code> code = | 642 Handle<Code> code = |
655 masm->isolate()->builtins()->HandleApiCallConstruct(); | 643 masm->isolate()->builtins()->HandleApiCallConstruct(); |
656 __ Call(code, RelocInfo::CODE_TARGET); | 644 __ Call(code, RelocInfo::CODE_TARGET); |
657 } else { | 645 } else { |
658 ParameterCount actual(argc); | 646 ParameterCount actual(argc); |
659 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); | 647 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); |
660 } | 648 } |
661 | 649 |
662 // Store offset of return address for deoptimizer. | 650 // Store offset of return address for deoptimizer. |
663 // TODO(arv): Remove the "!use_new_target" before supporting optimization | 651 if (!is_api_function) { |
664 // of functions that reference new.target | |
665 if (!is_api_function && !use_new_target) { | |
666 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 652 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
667 } | 653 } |
668 | 654 |
669 // Restore the context from the frame. | 655 // Restore the context from the frame. |
670 // x0: result | 656 // x0: result |
671 // jssp[0]: receiver | 657 // jssp[0]: receiver |
672 // jssp[1]: new.target (if used) | 658 // jssp[1]: new.target |
673 // jssp[1/2]: number of arguments (smi-tagged) | 659 // jssp[2]: number of arguments (smi-tagged) |
674 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 660 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
675 | 661 |
676 // If the result is an object (in the ECMA sense), we should get rid | 662 // If the result is an object (in the ECMA sense), we should get rid |
677 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 663 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
678 // on page 74. | 664 // on page 74. |
679 Label use_receiver, exit; | 665 Label use_receiver, exit; |
680 | 666 |
681 // If the result is a smi, it is *not* an object in the ECMA sense. | 667 // If the result is a smi, it is *not* an object in the ECMA sense. |
682 // x0: result | 668 // x0: result |
683 // jssp[0]: receiver (newly allocated object) | 669 // jssp[0]: receiver (newly allocated object) |
684 // jssp[1]: number of arguments (smi-tagged) | 670 // jssp[1]: number of arguments (smi-tagged) |
685 __ JumpIfSmi(x0, &use_receiver); | 671 __ JumpIfSmi(x0, &use_receiver); |
686 | 672 |
687 // If the type of the result (stored in its map) is less than | 673 // If the type of the result (stored in its map) is less than |
688 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 674 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
689 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); | 675 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); |
690 | 676 |
691 // Throw away the result of the constructor invocation and use the | 677 // Throw away the result of the constructor invocation and use the |
692 // on-stack receiver as the result. | 678 // on-stack receiver as the result. |
693 __ Bind(&use_receiver); | 679 __ Bind(&use_receiver); |
694 __ Peek(x0, 0); | 680 __ Peek(x0, 0); |
695 | 681 |
696 // Remove the receiver from the stack, remove caller arguments, and | 682 // Remove the receiver from the stack, remove caller arguments, and |
697 // return. | 683 // return. |
698 __ Bind(&exit); | 684 __ Bind(&exit); |
699 // x0: result | 685 // x0: result |
700 // jssp[0]: receiver (newly allocated object) | 686 // jssp[0]: receiver (newly allocated object) |
701 // jssp[1]: new.target (if used) | 687 // jssp[1]: new.target (original constructor) |
702 // jssp[1/2]: number of arguments (smi-tagged) | 688 // jssp[2]: number of arguments (smi-tagged) |
703 int offset = (use_new_target ? 2 : 1) * kXRegSize; | 689 __ Peek(x1, 2 * kXRegSize); |
704 __ Peek(x1, offset); | |
705 | 690 |
706 // Leave construct frame. | 691 // Leave construct frame. |
707 } | 692 } |
708 | 693 |
709 __ DropBySMI(x1); | 694 __ DropBySMI(x1); |
710 __ Drop(1); | 695 __ Drop(1); |
711 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 696 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
712 __ Ret(); | 697 __ Ret(); |
713 } | 698 } |
714 | 699 |
715 | 700 |
716 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 701 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
717 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); | 702 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); |
718 } | 703 } |
719 | 704 |
720 | 705 |
721 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 706 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
722 Generate_JSConstructStubHelper(masm, true, false, false); | 707 Generate_JSConstructStubHelper(masm, true, false); |
723 } | 708 } |
724 | 709 |
725 | 710 |
726 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { | |
727 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); | |
728 } | |
729 | |
730 | |
731 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 711 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
732 // ----------- S t a t e ------------- | 712 // ----------- S t a t e ------------- |
733 // -- x0 : number of arguments | 713 // -- x0 : number of arguments |
734 // -- x1 : constructor function | 714 // -- x1 : constructor function |
735 // -- x2 : allocation site or undefined | 715 // -- x2 : allocation site or undefined |
736 // -- x3 : original constructor | 716 // -- x3 : original constructor |
737 // -- lr : return address | 717 // -- lr : return address |
738 // -- sp[...]: constructor arguments | 718 // -- sp[...]: constructor arguments |
739 // ----------------------------------- | 719 // ----------------------------------- |
740 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); | 720 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 } | 1839 } |
1860 } | 1840 } |
1861 | 1841 |
1862 | 1842 |
1863 #undef __ | 1843 #undef __ |
1864 | 1844 |
1865 } // namespace internal | 1845 } // namespace internal |
1866 } // namespace v8 | 1846 } // namespace v8 |
1867 | 1847 |
1868 #endif // V8_TARGET_ARCH_ARM | 1848 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |