OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 ExternalReference ref = ExternalReference( | 548 ExternalReference ref = ExternalReference( |
549 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); | 549 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
550 __ TailCallExternalReference(ref, 5, 1); | 550 __ TailCallExternalReference(ref, 5, 1); |
551 } | 551 } |
552 | 552 |
553 private: | 553 private: |
554 Register name_; | 554 Register name_; |
555 }; | 555 }; |
556 | 556 |
557 | 557 |
| 558 // Reserves space for the extra arguments to FastHandleApiCall in the |
| 559 // caller's frame. |
| 560 // |
| 561 // These arguments are set by CheckPrototypes and GenerateFastApiCall. |
| 562 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 563 // ----------- S t a t e ------------- |
| 564 // -- rsp[0] : return address |
| 565 // -- rsp[8] : last argument in the internal frame of the caller |
| 566 // ----------------------------------- |
| 567 __ pop(scratch); |
| 568 __ Push(Smi::FromInt(0)); |
| 569 __ Push(Smi::FromInt(0)); |
| 570 __ Push(Smi::FromInt(0)); |
| 571 __ Push(Smi::FromInt(0)); |
| 572 __ push(scratch); |
| 573 } |
| 574 |
| 575 |
| 576 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 577 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 578 // ----------- S t a t e ------------- |
| 579 // -- rsp[0] : return address |
| 580 // -- rsp[8] : last fast api call extra argument |
| 581 // -- ... |
| 582 // -- rsp[32] : first fast api call extra argument |
| 583 // -- rsp[40] : last argument in the internal frame |
| 584 // ----------------------------------- |
| 585 __ pop(scratch); |
| 586 __ Drop(4); |
| 587 __ push(scratch); |
| 588 } |
| 589 |
| 590 |
| 591 // Generates call to FastHandleApiCall builtin. |
| 592 static void GenerateFastApiCall(MacroAssembler* masm, |
| 593 const CallOptimization& optimization, |
| 594 int argc) { |
| 595 // ----------- S t a t e ------------- |
| 596 // -- rsp[0] : return address |
| 597 // -- rsp[8] : object passing the type check |
| 598 // (last fast api call extra argument, |
| 599 // set by CheckPrototypes) |
| 600 // -- rsp[16] : api call data |
| 601 // -- rsp[24] : api callback |
| 602 // -- rsp[32] : api function |
| 603 // (first fast api call extra argument) |
| 604 // -- rsp[40] : last argument |
| 605 // -- ... |
| 606 // -- rsp[(argc + 5) * 8] : first argument |
| 607 // -- rsp[(argc + 6) * 8] : receiver |
| 608 // ----------------------------------- |
| 609 |
| 610 // Get the function and setup the context. |
| 611 JSFunction* function = optimization.constant_function(); |
| 612 __ Move(rdi, Handle<JSFunction>(function)); |
| 613 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 614 |
| 615 // Pass the additional arguments FastHandleApiCall expects. |
| 616 __ movq(Operand(rsp, 4 * kPointerSize), rdi); |
| 617 bool info_loaded = false; |
| 618 Object* callback = optimization.api_call_info()->callback(); |
| 619 if (Heap::InNewSpace(callback)) { |
| 620 info_loaded = true; |
| 621 __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 622 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kCallbackOffset)); |
| 623 __ movq(Operand(rsp, 3 * kPointerSize), rbx); |
| 624 } else { |
| 625 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(callback)); |
| 626 } |
| 627 Object* call_data = optimization.api_call_info()->data(); |
| 628 if (Heap::InNewSpace(call_data)) { |
| 629 if (!info_loaded) { |
| 630 __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 631 } |
| 632 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); |
| 633 __ movq(Operand(rsp, 2 * kPointerSize), rbx); |
| 634 } else { |
| 635 __ Move(Operand(rsp, 2 * kPointerSize), Handle<Object>(call_data)); |
| 636 } |
| 637 |
| 638 // Set the number of arguments. |
| 639 __ movq(rax, Immediate(argc + 4)); |
| 640 |
| 641 // Jump to the fast api call builtin (tail call). |
| 642 Handle<Code> code = Handle<Code>( |
| 643 Builtins::builtin(Builtins::FastHandleApiCall)); |
| 644 ParameterCount expected(0); |
| 645 __ InvokeCode(code, expected, expected, |
| 646 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
| 647 } |
| 648 |
| 649 |
558 class CallInterceptorCompiler BASE_EMBEDDED { | 650 class CallInterceptorCompiler BASE_EMBEDDED { |
559 public: | 651 public: |
560 CallInterceptorCompiler(const ParameterCount& arguments, Register name) | 652 CallInterceptorCompiler(StubCompiler* stub_compiler, |
561 : arguments_(arguments), name_(name) {} | 653 const ParameterCount& arguments, |
562 | 654 Register name) |
| 655 : stub_compiler_(stub_compiler), |
| 656 arguments_(arguments), |
| 657 name_(name) {} |
| 658 |
| 659 void Compile(MacroAssembler* masm, |
| 660 JSObject* object, |
| 661 JSObject* holder, |
| 662 String* name, |
| 663 LookupResult* lookup, |
| 664 Register receiver, |
| 665 Register scratch1, |
| 666 Register scratch2, |
| 667 Label* miss) { |
| 668 ASSERT(holder->HasNamedInterceptor()); |
| 669 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 670 |
| 671 // Check that the receiver isn't a smi. |
| 672 __ JumpIfSmi(receiver, miss); |
| 673 |
| 674 CallOptimization optimization(lookup); |
| 675 |
| 676 if (optimization.is_constant_call()) { |
| 677 CompileCacheable(masm, |
| 678 object, |
| 679 receiver, |
| 680 scratch1, |
| 681 scratch2, |
| 682 holder, |
| 683 lookup, |
| 684 name, |
| 685 optimization, |
| 686 miss); |
| 687 } else { |
| 688 CompileRegular(masm, |
| 689 object, |
| 690 receiver, |
| 691 scratch1, |
| 692 scratch2, |
| 693 name, |
| 694 holder, |
| 695 miss); |
| 696 } |
| 697 } |
| 698 |
| 699 private: |
563 void CompileCacheable(MacroAssembler* masm, | 700 void CompileCacheable(MacroAssembler* masm, |
564 StubCompiler* stub_compiler, | 701 JSObject* object, |
565 Register receiver, | 702 Register receiver, |
566 Register holder, | |
567 Register scratch1, | 703 Register scratch1, |
568 Register scratch2, | 704 Register scratch2, |
569 JSObject* holder_obj, | 705 JSObject* holder_obj, |
570 LookupResult* lookup, | 706 LookupResult* lookup, |
571 String* name, | 707 String* name, |
| 708 const CallOptimization& optimization, |
572 Label* miss_label) { | 709 Label* miss_label) { |
573 JSFunction* function = 0; | 710 ASSERT(optimization.is_constant_call()); |
574 bool optimize = false; | 711 ASSERT(!lookup->holder()->IsGlobalObject()); |
575 // So far the most popular case for failed interceptor is | 712 |
576 // CONSTANT_FUNCTION sitting below. | 713 int depth1 = kInvalidProtoDepth; |
577 if (lookup->type() == CONSTANT_FUNCTION) { | 714 int depth2 = kInvalidProtoDepth; |
578 function = lookup->GetConstantFunction(); | 715 bool can_do_fast_api_call = false; |
579 // JSArray holder is a special case for call constant function | 716 if (optimization.is_simple_api_call() && |
580 // (see the corresponding code). | 717 !lookup->holder()->IsGlobalObject()) { |
581 if (function->is_compiled() && !holder_obj->IsJSArray()) { | 718 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); |
582 optimize = true; | 719 if (depth1 == kInvalidProtoDepth) { |
| 720 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, |
| 721 lookup->holder()); |
583 } | 722 } |
584 } | 723 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || |
585 | 724 (depth2 != kInvalidProtoDepth); |
586 if (!optimize) { | 725 } |
587 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 726 |
588 return; | 727 __ IncrementCounter(&Counters::call_const_interceptor, 1); |
589 } | 728 |
590 | 729 if (can_do_fast_api_call) { |
591 ASSERT(!lookup->holder()->IsGlobalObject()); | 730 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); |
592 | 731 ReserveSpaceForFastApiCall(masm, scratch1); |
593 __ EnterInternalFrame(); | 732 } |
594 __ push(holder); // Save the holder. | 733 |
595 __ push(name_); // Save the name. | 734 Label miss_cleanup; |
596 | 735 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
597 CompileCallLoadPropertyWithInterceptor(masm, | 736 Register holder = |
598 receiver, | 737 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, |
599 holder, | 738 scratch1, scratch2, name, |
600 name_, | 739 depth1, miss); |
601 holder_obj); | 740 |
602 | 741 Label regular_invoke; |
603 __ pop(name_); // Restore the name. | 742 LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke); |
604 __ pop(receiver); // Restore the holder. | 743 |
605 __ LeaveInternalFrame(); | 744 // Generate code for the failed interceptor case. |
606 | 745 |
607 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 746 // Check the lookup is still valid. |
608 Label invoke; | 747 stub_compiler_->CheckPrototypes(holder_obj, receiver, |
609 __ j(not_equal, &invoke); | 748 lookup->holder(), |
610 | 749 scratch1, scratch2, name, |
611 stub_compiler->CheckPrototypes(holder_obj, receiver, | 750 depth2, miss); |
612 lookup->holder(), scratch1, | 751 |
613 scratch2, | 752 if (can_do_fast_api_call) { |
614 name, | 753 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
615 miss_label); | 754 } else { |
616 | 755 __ InvokeFunction(optimization.constant_function(), arguments_, |
617 __ InvokeFunction(function, arguments_, JUMP_FUNCTION); | 756 JUMP_FUNCTION); |
618 | 757 } |
619 __ bind(&invoke); | 758 |
| 759 if (can_do_fast_api_call) { |
| 760 __ bind(&miss_cleanup); |
| 761 FreeSpaceForFastApiCall(masm, scratch1); |
| 762 __ jmp(miss_label); |
| 763 } |
| 764 |
| 765 __ bind(®ular_invoke); |
| 766 if (can_do_fast_api_call) { |
| 767 FreeSpaceForFastApiCall(masm, scratch1); |
| 768 } |
620 } | 769 } |
621 | 770 |
622 void CompileRegular(MacroAssembler* masm, | 771 void CompileRegular(MacroAssembler* masm, |
| 772 JSObject* object, |
623 Register receiver, | 773 Register receiver, |
624 Register holder, | 774 Register scratch1, |
625 Register scratch, | 775 Register scratch2, |
| 776 String* name, |
626 JSObject* holder_obj, | 777 JSObject* holder_obj, |
627 Label* miss_label) { | 778 Label* miss_label) { |
| 779 Register holder = |
| 780 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, |
| 781 scratch1, scratch2, name, |
| 782 miss_label); |
| 783 |
628 __ EnterInternalFrame(); | 784 __ EnterInternalFrame(); |
629 // Save the name_ register across the call. | 785 // Save the name_ register across the call. |
630 __ push(name_); | 786 __ push(name_); |
631 | 787 |
632 PushInterceptorArguments(masm, | 788 PushInterceptorArguments(masm, |
633 receiver, | 789 receiver, |
634 holder, | 790 holder, |
635 name_, | 791 name_, |
636 holder_obj); | 792 holder_obj); |
637 | 793 |
638 __ CallExternalReference( | 794 __ CallExternalReference( |
639 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), | 795 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
640 5); | 796 5); |
641 | 797 |
| 798 // Restore the name_ register. |
642 __ pop(name_); | 799 __ pop(name_); |
643 __ LeaveInternalFrame(); | 800 __ LeaveInternalFrame(); |
644 } | 801 } |
645 | 802 |
646 private: | 803 void LoadWithInterceptor(MacroAssembler* masm, |
| 804 Register receiver, |
| 805 Register holder, |
| 806 JSObject* holder_obj, |
| 807 Label* interceptor_succeeded) { |
| 808 __ EnterInternalFrame(); |
| 809 __ push(holder); // Save the holder. |
| 810 __ push(name_); // Save the name. |
| 811 |
| 812 CompileCallLoadPropertyWithInterceptor(masm, |
| 813 receiver, |
| 814 holder, |
| 815 name_, |
| 816 holder_obj); |
| 817 |
| 818 __ pop(name_); // Restore the name. |
| 819 __ pop(receiver); // Restore the holder. |
| 820 __ LeaveInternalFrame(); |
| 821 |
| 822 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 823 __ j(not_equal, interceptor_succeeded); |
| 824 } |
| 825 |
| 826 StubCompiler* stub_compiler_; |
647 const ParameterCount& arguments_; | 827 const ParameterCount& arguments_; |
648 Register name_; | 828 Register name_; |
649 }; | 829 }; |
650 | 830 |
651 | 831 |
652 // Generate code to check that a global property cell is empty. Create | 832 // Generate code to check that a global property cell is empty. Create |
653 // the property cell at compilation time if no cell exists for the | 833 // the property cell at compilation time if no cell exists for the |
654 // property. | 834 // property. |
655 static Object* GenerateCheckPropertyCell(MacroAssembler* masm, | 835 static Object* GenerateCheckPropertyCell(MacroAssembler* masm, |
656 GlobalObject* global, | 836 GlobalObject* global, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 // rsp[(argc + 1) * 8] : argument 0 = receiver | 981 // rsp[(argc + 1) * 8] : argument 0 = receiver |
802 // ----------------------------------- | 982 // ----------------------------------- |
803 | 983 |
804 SharedFunctionInfo* function_info = function->shared(); | 984 SharedFunctionInfo* function_info = function->shared(); |
805 if (function_info->HasCustomCallGenerator()) { | 985 if (function_info->HasCustomCallGenerator()) { |
806 CustomCallGenerator generator = | 986 CustomCallGenerator generator = |
807 ToCData<CustomCallGenerator>(function_info->function_data()); | 987 ToCData<CustomCallGenerator>(function_info->function_data()); |
808 return generator(this, object, holder, function, name, check); | 988 return generator(this, object, holder, function, name, check); |
809 } | 989 } |
810 | 990 |
811 Label miss; | 991 Label miss_in_smi_check; |
812 | 992 |
813 // Get the receiver from the stack. | 993 // Get the receiver from the stack. |
814 const int argc = arguments().immediate(); | 994 const int argc = arguments().immediate(); |
815 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 995 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
816 | 996 |
817 // Check that the receiver isn't a smi. | 997 // Check that the receiver isn't a smi. |
818 if (check != NUMBER_CHECK) { | 998 if (check != NUMBER_CHECK) { |
819 __ JumpIfSmi(rdx, &miss); | 999 __ JumpIfSmi(rdx, &miss_in_smi_check); |
820 } | 1000 } |
821 | 1001 |
822 // Make sure that it's okay not to patch the on stack receiver | 1002 // Make sure that it's okay not to patch the on stack receiver |
823 // unless we're doing a receiver map check. | 1003 // unless we're doing a receiver map check. |
824 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 1004 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
825 | 1005 |
| 1006 CallOptimization optimization(function); |
| 1007 int depth = kInvalidProtoDepth; |
| 1008 Label miss; |
| 1009 |
826 switch (check) { | 1010 switch (check) { |
827 case RECEIVER_MAP_CHECK: | 1011 case RECEIVER_MAP_CHECK: |
| 1012 __ IncrementCounter(&Counters::call_const, 1); |
| 1013 |
| 1014 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { |
| 1015 depth = optimization.GetPrototypeDepthOfExpectedType( |
| 1016 JSObject::cast(object), holder); |
| 1017 } |
| 1018 |
| 1019 if (depth != kInvalidProtoDepth) { |
| 1020 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 1021 ReserveSpaceForFastApiCall(masm(), rax); |
| 1022 } |
| 1023 |
828 // Check that the maps haven't changed. | 1024 // Check that the maps haven't changed. |
829 CheckPrototypes(JSObject::cast(object), rdx, holder, | 1025 CheckPrototypes(JSObject::cast(object), rdx, holder, |
830 rbx, rax, name, &miss); | 1026 rbx, rax, name, depth, &miss); |
831 | 1027 |
832 // Patch the receiver on the stack with the global proxy if | 1028 // Patch the receiver on the stack with the global proxy if |
833 // necessary. | 1029 // necessary. |
834 if (object->IsGlobalObject()) { | 1030 if (object->IsGlobalObject()) { |
| 1031 ASSERT(depth == kInvalidProtoDepth); |
835 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1032 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
836 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1033 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
837 } | 1034 } |
838 break; | 1035 break; |
839 | 1036 |
840 case STRING_CHECK: | 1037 case STRING_CHECK: |
841 if (!function->IsBuiltin()) { | 1038 if (!function->IsBuiltin()) { |
842 // Calling non-builtins with a value as receiver requires boxing. | 1039 // Calling non-builtins with a value as receiver requires boxing. |
843 __ jmp(&miss); | 1040 __ jmp(&miss); |
844 } else { | 1041 } else { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 1091 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
895 rbx, rdx, name, &miss); | 1092 rbx, rdx, name, &miss); |
896 } | 1093 } |
897 break; | 1094 break; |
898 } | 1095 } |
899 | 1096 |
900 default: | 1097 default: |
901 UNREACHABLE(); | 1098 UNREACHABLE(); |
902 } | 1099 } |
903 | 1100 |
904 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 1101 if (depth != kInvalidProtoDepth) { |
| 1102 GenerateFastApiCall(masm(), optimization, argc); |
| 1103 } else { |
| 1104 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 1105 } |
905 | 1106 |
906 // Handle call cache miss. | 1107 // Handle call cache miss. |
907 __ bind(&miss); | 1108 __ bind(&miss); |
| 1109 if (depth != kInvalidProtoDepth) { |
| 1110 FreeSpaceForFastApiCall(masm(), rax); |
| 1111 } |
| 1112 |
| 1113 // Handle call cache miss. |
| 1114 __ bind(&miss_in_smi_check); |
908 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1115 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
909 __ Jump(ic, RelocInfo::CODE_TARGET); | 1116 __ Jump(ic, RelocInfo::CODE_TARGET); |
910 | 1117 |
911 // Return the generated code. | 1118 // Return the generated code. |
912 String* function_name = NULL; | 1119 String* function_name = NULL; |
913 if (function->shared()->name()->IsString()) { | 1120 if (function->shared()->name()->IsString()) { |
914 function_name = String::cast(function->shared()->name()); | 1121 function_name = String::cast(function->shared()->name()); |
915 } | 1122 } |
916 return GetCode(CONSTANT_FUNCTION, function_name); | 1123 return GetCode(CONSTANT_FUNCTION, function_name); |
917 } | 1124 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 | 1192 |
986 // Get the number of arguments. | 1193 // Get the number of arguments. |
987 const int argc = arguments().immediate(); | 1194 const int argc = arguments().immediate(); |
988 | 1195 |
989 LookupResult lookup; | 1196 LookupResult lookup; |
990 LookupPostInterceptor(holder, name, &lookup); | 1197 LookupPostInterceptor(holder, name, &lookup); |
991 | 1198 |
992 // Get the receiver from the stack. | 1199 // Get the receiver from the stack. |
993 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1200 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
994 | 1201 |
995 CallInterceptorCompiler compiler(arguments(), rcx); | 1202 CallInterceptorCompiler compiler(this, arguments(), rcx); |
996 CompileLoadInterceptor(&compiler, | 1203 compiler.Compile(masm(), |
997 this, | 1204 object, |
998 masm(), | 1205 holder, |
999 object, | 1206 name, |
1000 holder, | 1207 &lookup, |
1001 name, | 1208 rdx, |
1002 &lookup, | 1209 rbx, |
1003 rdx, | 1210 rdi, |
1004 rbx, | 1211 &miss); |
1005 rdi, | |
1006 &miss); | |
1007 | 1212 |
1008 // Restore receiver. | 1213 // Restore receiver. |
1009 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1214 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
1010 | 1215 |
1011 // Check that the function really is a function. | 1216 // Check that the function really is a function. |
1012 __ JumpIfSmi(rax, &miss); | 1217 __ JumpIfSmi(rax, &miss); |
1013 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 1218 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
1014 __ j(not_equal, &miss); | 1219 __ j(not_equal, &miss); |
1015 | 1220 |
1016 // Patch the receiver on the stack with the global proxy if | 1221 // Patch the receiver on the stack with the global proxy if |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 | 2017 |
1813 | 2018 |
1814 Register StubCompiler::CheckPrototypes(JSObject* object, | 2019 Register StubCompiler::CheckPrototypes(JSObject* object, |
1815 Register object_reg, | 2020 Register object_reg, |
1816 JSObject* holder, | 2021 JSObject* holder, |
1817 Register holder_reg, | 2022 Register holder_reg, |
1818 Register scratch, | 2023 Register scratch, |
1819 String* name, | 2024 String* name, |
1820 int save_at_depth, | 2025 int save_at_depth, |
1821 Label* miss) { | 2026 Label* miss) { |
1822 // TODO(602): support object saving. | |
1823 ASSERT(save_at_depth == kInvalidProtoDepth); | |
1824 | |
1825 // Check that the maps haven't changed. | 2027 // Check that the maps haven't changed. |
1826 Register result = | 2028 Register result = |
1827 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); | 2029 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, |
| 2030 save_at_depth, miss); |
1828 | 2031 |
1829 // If we've skipped any global objects, it's not enough to verify | 2032 // If we've skipped any global objects, it's not enough to verify |
1830 // that their maps haven't changed. We also need to check that the | 2033 // that their maps haven't changed. We also need to check that the |
1831 // property cell for the property is still empty. | 2034 // property cell for the property is still empty. |
1832 while (object != holder) { | 2035 while (object != holder) { |
1833 if (object->IsGlobalObject()) { | 2036 if (object->IsGlobalObject()) { |
1834 Object* cell = GenerateCheckPropertyCell(masm(), | 2037 Object* cell = GenerateCheckPropertyCell(masm(), |
1835 GlobalObject::cast(object), | 2038 GlobalObject::cast(object), |
1836 name, | 2039 name, |
1837 scratch, | 2040 scratch, |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2019 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 2222 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
2020 | 2223 |
2021 // Return the generated code. | 2224 // Return the generated code. |
2022 return GetCode(); | 2225 return GetCode(); |
2023 } | 2226 } |
2024 | 2227 |
2025 | 2228 |
2026 #undef __ | 2229 #undef __ |
2027 | 2230 |
2028 } } // namespace v8::internal | 2231 } } // namespace v8::internal |
OLD | NEW |