OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 compiler->CompileRegular(masm, | 593 compiler->CompileRegular(masm, |
594 receiver, | 594 receiver, |
595 reg, | 595 reg, |
596 scratch2, | 596 scratch2, |
597 holder, | 597 holder, |
598 miss); | 598 miss); |
599 } | 599 } |
600 } | 600 } |
601 | 601 |
602 | 602 |
| 603 // Reserves space for the extra arguments to FastHandleApiCall in the |
| 604 // caller's frame. |
| 605 // |
| 606 // These arguments are set by CheckPrototypes and GenerateFastApiCall. |
| 607 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| 608 Register scratch) { |
| 609 __ mov(scratch, Operand(Smi::FromInt(0))); |
| 610 __ push(scratch); |
| 611 __ push(scratch); |
| 612 __ push(scratch); |
| 613 __ push(scratch); |
| 614 } |
| 615 |
| 616 |
| 617 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 618 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
| 619 __ Drop(4); |
| 620 } |
| 621 |
| 622 |
| 623 // Generates call to FastHandleApiCall builtin. |
| 624 static void GenerateFastApiCall(MacroAssembler* masm, |
| 625 const CallOptimization& optimization, |
| 626 int argc) { |
| 627 // Get the function and setup the context. |
| 628 JSFunction* function = optimization.constant_function(); |
| 629 __ mov(r7, Operand(Handle<JSFunction>(function))); |
| 630 __ ldr(cp, FieldMemOperand(r7, JSFunction::kContextOffset)); |
| 631 |
| 632 // Pass the additional arguments FastHandleApiCall expects. |
| 633 bool info_loaded = false; |
| 634 Object* callback = optimization.api_call_info()->callback(); |
| 635 if (Heap::InNewSpace(callback)) { |
| 636 info_loaded = true; |
| 637 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 638 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); |
| 639 } else { |
| 640 __ Move(r6, Handle<Object>(callback)); |
| 641 } |
| 642 Object* call_data = optimization.api_call_info()->data(); |
| 643 if (Heap::InNewSpace(call_data)) { |
| 644 if (!info_loaded) { |
| 645 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 646 } |
| 647 __ ldr(r5, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
| 648 } else { |
| 649 __ Move(r5, Handle<Object>(call_data)); |
| 650 } |
| 651 |
| 652 __ add(sp, sp, Operand(1 * kPointerSize)); |
| 653 __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); |
| 654 __ sub(sp, sp, Operand(1 * kPointerSize)); |
| 655 |
| 656 // Set the number of arguments. |
| 657 __ mov(r0, Operand(argc + 4)); |
| 658 |
| 659 // Jump to the fast api call builtin (tail call). |
| 660 Handle<Code> code = Handle<Code>( |
| 661 Builtins::builtin(Builtins::FastHandleApiCall)); |
| 662 ParameterCount expected(0); |
| 663 __ InvokeCode(code, expected, expected, |
| 664 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
| 665 } |
| 666 |
| 667 |
| 668 class CallInterceptorCompiler BASE_EMBEDDED { |
| 669 public: |
| 670 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 671 const ParameterCount& arguments, |
| 672 Register name) |
| 673 : stub_compiler_(stub_compiler), |
| 674 arguments_(arguments), |
| 675 name_(name) {} |
| 676 |
| 677 void Compile(MacroAssembler* masm, |
| 678 JSObject* object, |
| 679 JSObject* holder, |
| 680 String* name, |
| 681 LookupResult* lookup, |
| 682 Register receiver, |
| 683 Register scratch1, |
| 684 Register scratch2, |
| 685 Label* miss) { |
| 686 ASSERT(holder->HasNamedInterceptor()); |
| 687 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 688 |
| 689 // Check that the receiver isn't a smi. |
| 690 __ BranchOnSmi(receiver, miss); |
| 691 |
| 692 CallOptimization optimization(lookup); |
| 693 |
| 694 if (optimization.is_constant_call()) { |
| 695 CompileCacheable(masm, |
| 696 object, |
| 697 receiver, |
| 698 scratch1, |
| 699 scratch2, |
| 700 holder, |
| 701 lookup, |
| 702 name, |
| 703 optimization, |
| 704 miss); |
| 705 } else { |
| 706 CompileRegular(masm, |
| 707 object, |
| 708 receiver, |
| 709 scratch1, |
| 710 scratch2, |
| 711 name, |
| 712 holder, |
| 713 miss); |
| 714 } |
| 715 } |
| 716 |
| 717 private: |
| 718 void CompileCacheable(MacroAssembler* masm, |
| 719 JSObject* object, |
| 720 Register receiver, |
| 721 Register scratch1, |
| 722 Register scratch2, |
| 723 JSObject* holder_obj, |
| 724 LookupResult* lookup, |
| 725 String* name, |
| 726 const CallOptimization& optimization, |
| 727 Label* miss_label) { |
| 728 ASSERT(optimization.is_constant_call()); |
| 729 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 730 |
| 731 int depth1 = kInvalidProtoDepth; |
| 732 int depth2 = kInvalidProtoDepth; |
| 733 bool can_do_fast_api_call = false; |
| 734 if (optimization.is_simple_api_call() && |
| 735 !lookup->holder()->IsGlobalObject()) { |
| 736 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); |
| 737 if (depth1 == kInvalidProtoDepth) { |
| 738 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, |
| 739 lookup->holder()); |
| 740 } |
| 741 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || |
| 742 (depth2 != kInvalidProtoDepth); |
| 743 } |
| 744 |
| 745 __ IncrementCounter(&Counters::call_const_interceptor, 1, |
| 746 scratch1, scratch2); |
| 747 |
| 748 if (can_do_fast_api_call) { |
| 749 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1, |
| 750 scratch1, scratch2); |
| 751 ReserveSpaceForFastApiCall(masm, scratch1); |
| 752 } |
| 753 |
| 754 Label miss_cleanup; |
| 755 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 756 Register holder = |
| 757 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, scratch1, |
| 758 scratch2, name, depth1, miss); |
| 759 |
| 760 Label regular_invoke; |
| 761 LoadWithInterceptor(masm, receiver, holder, holder_obj, scratch2, |
| 762 ®ular_invoke); |
| 763 |
| 764 // Generate code for the failed interceptor case. |
| 765 |
| 766 // Check the lookup is still valid. |
| 767 stub_compiler_->CheckPrototypes(holder_obj, receiver, |
| 768 lookup->holder(), scratch1, |
| 769 scratch2, name, depth2, miss); |
| 770 |
| 771 if (can_do_fast_api_call) { |
| 772 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 773 } else { |
| 774 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 775 JUMP_FUNCTION); |
| 776 } |
| 777 |
| 778 if (can_do_fast_api_call) { |
| 779 __ bind(&miss_cleanup); |
| 780 FreeSpaceForFastApiCall(masm); |
| 781 __ b(miss_label); |
| 782 } |
| 783 |
| 784 __ bind(®ular_invoke); |
| 785 if (can_do_fast_api_call) { |
| 786 FreeSpaceForFastApiCall(masm); |
| 787 } |
| 788 } |
| 789 |
| 790 void CompileRegular(MacroAssembler* masm, |
| 791 JSObject* object, |
| 792 Register receiver, |
| 793 Register scratch1, |
| 794 Register scratch2, |
| 795 String* name, |
| 796 JSObject* holder_obj, |
| 797 Label* miss_label) { |
| 798 Register holder = |
| 799 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, |
| 800 scratch1, scratch2, name, |
| 801 miss_label); |
| 802 |
| 803 // Call a runtime function to load the interceptor property. |
| 804 __ EnterInternalFrame(); |
| 805 // Save the name_ register across the call. |
| 806 __ push(name_); |
| 807 |
| 808 PushInterceptorArguments(masm, |
| 809 receiver, |
| 810 holder, |
| 811 name_, |
| 812 holder_obj); |
| 813 |
| 814 __ CallExternalReference( |
| 815 ExternalReference( |
| 816 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
| 817 5); |
| 818 |
| 819 // Restore the name_ register. |
| 820 __ pop(name_); |
| 821 __ LeaveInternalFrame(); |
| 822 } |
| 823 |
| 824 void LoadWithInterceptor(MacroAssembler* masm, |
| 825 Register receiver, |
| 826 Register holder, |
| 827 JSObject* holder_obj, |
| 828 Register scratch, |
| 829 Label* interceptor_succeeded) { |
| 830 __ EnterInternalFrame(); |
| 831 __ push(holder); // Save the holder. |
| 832 __ push(name_); // Save the name. |
| 833 |
| 834 CompileCallLoadPropertyWithInterceptor(masm, |
| 835 receiver, |
| 836 holder, |
| 837 name_, |
| 838 holder_obj); |
| 839 |
| 840 __ pop(name_); // Restore the name. |
| 841 __ pop(receiver); // Restore the holder. |
| 842 __ LeaveInternalFrame(); |
| 843 |
| 844 // If interceptor returns no-result sentinel, call the constant function. |
| 845 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 846 __ cmp(r0, scratch); |
| 847 __ b(ne, interceptor_succeeded); |
| 848 } |
| 849 |
| 850 StubCompiler* stub_compiler_; |
| 851 const ParameterCount& arguments_; |
| 852 Register name_; |
| 853 }; |
| 854 |
| 855 |
603 // Generate code to check that a global property cell is empty. Create | 856 // Generate code to check that a global property cell is empty. Create |
604 // the property cell at compilation time if no cell exists for the | 857 // the property cell at compilation time if no cell exists for the |
605 // property. | 858 // property. |
606 static Object* GenerateCheckPropertyCell(MacroAssembler* masm, | 859 static Object* GenerateCheckPropertyCell(MacroAssembler* masm, |
607 GlobalObject* global, | 860 GlobalObject* global, |
608 String* name, | 861 String* name, |
609 Register scratch, | 862 Register scratch, |
610 Label* miss) { | 863 Label* miss) { |
611 Object* probe = global->EnsurePropertyCell(name); | 864 Object* probe = global->EnsurePropertyCell(name); |
612 if (probe->IsFailure()) return probe; | 865 if (probe->IsFailure()) return probe; |
(...skipping 14 matching lines...) Expand all Loading... |
627 | 880 |
628 | 881 |
629 Register StubCompiler::CheckPrototypes(JSObject* object, | 882 Register StubCompiler::CheckPrototypes(JSObject* object, |
630 Register object_reg, | 883 Register object_reg, |
631 JSObject* holder, | 884 JSObject* holder, |
632 Register holder_reg, | 885 Register holder_reg, |
633 Register scratch, | 886 Register scratch, |
634 String* name, | 887 String* name, |
635 int save_at_depth, | 888 int save_at_depth, |
636 Label* miss) { | 889 Label* miss) { |
637 // TODO(602): support object saving. | |
638 ASSERT(save_at_depth == kInvalidProtoDepth); | |
639 | |
640 // Check that the maps haven't changed. | 890 // Check that the maps haven't changed. |
641 Register result = | 891 Register result = |
642 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); | 892 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, |
| 893 save_at_depth, miss); |
643 | 894 |
644 // If we've skipped any global objects, it's not enough to verify | 895 // If we've skipped any global objects, it's not enough to verify |
645 // that their maps haven't changed. We also need to check that the | 896 // that their maps haven't changed. We also need to check that the |
646 // property cell for the property is still empty. | 897 // property cell for the property is still empty. |
647 while (object != holder) { | 898 while (object != holder) { |
648 if (object->IsGlobalObject()) { | 899 if (object->IsGlobalObject()) { |
649 Object* cell = GenerateCheckPropertyCell(masm(), | 900 Object* cell = GenerateCheckPropertyCell(masm(), |
650 GlobalObject::cast(object), | 901 GlobalObject::cast(object), |
651 name, | 902 name, |
652 scratch, | 903 scratch, |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 // -- r2 : name | 1190 // -- r2 : name |
940 // -- lr : return address | 1191 // -- lr : return address |
941 // ----------------------------------- | 1192 // ----------------------------------- |
942 SharedFunctionInfo* function_info = function->shared(); | 1193 SharedFunctionInfo* function_info = function->shared(); |
943 if (function_info->HasCustomCallGenerator()) { | 1194 if (function_info->HasCustomCallGenerator()) { |
944 CustomCallGenerator generator = | 1195 CustomCallGenerator generator = |
945 ToCData<CustomCallGenerator>(function_info->function_data()); | 1196 ToCData<CustomCallGenerator>(function_info->function_data()); |
946 return generator(this, object, holder, function, name, check); | 1197 return generator(this, object, holder, function, name, check); |
947 } | 1198 } |
948 | 1199 |
949 Label miss; | 1200 Label miss_in_smi_check; |
950 | 1201 |
951 // Get the receiver from the stack | 1202 // Get the receiver from the stack |
952 const int argc = arguments().immediate(); | 1203 const int argc = arguments().immediate(); |
953 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 1204 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
954 | 1205 |
955 // Check that the receiver isn't a smi. | 1206 // Check that the receiver isn't a smi. |
956 if (check != NUMBER_CHECK) { | 1207 if (check != NUMBER_CHECK) { |
957 __ tst(r1, Operand(kSmiTagMask)); | 1208 __ tst(r1, Operand(kSmiTagMask)); |
958 __ b(eq, &miss); | 1209 __ b(eq, &miss_in_smi_check); |
959 } | 1210 } |
960 | 1211 |
961 // Make sure that it's okay not to patch the on stack receiver | 1212 // Make sure that it's okay not to patch the on stack receiver |
962 // unless we're doing a receiver map check. | 1213 // unless we're doing a receiver map check. |
963 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 1214 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
964 | 1215 |
| 1216 CallOptimization optimization(function); |
| 1217 int depth = kInvalidProtoDepth; |
| 1218 Label miss; |
| 1219 |
965 switch (check) { | 1220 switch (check) { |
966 case RECEIVER_MAP_CHECK: | 1221 case RECEIVER_MAP_CHECK: |
| 1222 __ IncrementCounter(&Counters::call_const, 1, r0, r3); |
| 1223 |
| 1224 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { |
| 1225 depth = optimization.GetPrototypeDepthOfExpectedType( |
| 1226 JSObject::cast(object), holder); |
| 1227 } |
| 1228 |
| 1229 if (depth != kInvalidProtoDepth) { |
| 1230 __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3); |
| 1231 ReserveSpaceForFastApiCall(masm(), r0); |
| 1232 } |
| 1233 |
967 // Check that the maps haven't changed. | 1234 // Check that the maps haven't changed. |
968 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss); | 1235 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name, |
| 1236 depth, &miss); |
969 | 1237 |
970 // Patch the receiver on the stack with the global proxy if | 1238 // Patch the receiver on the stack with the global proxy if |
971 // necessary. | 1239 // necessary. |
972 if (object->IsGlobalObject()) { | 1240 if (object->IsGlobalObject()) { |
| 1241 ASSERT(depth == kInvalidProtoDepth); |
973 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1242 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
974 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 1243 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
975 } | 1244 } |
976 break; | 1245 break; |
977 | 1246 |
978 case STRING_CHECK: | 1247 case STRING_CHECK: |
979 if (!function->IsBuiltin()) { | 1248 if (!function->IsBuiltin()) { |
980 // Calling non-builtins with a value as receiver requires boxing. | 1249 // Calling non-builtins with a value as receiver requires boxing. |
981 __ jmp(&miss); | 1250 __ jmp(&miss); |
982 } else { | 1251 } else { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 1304 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
1036 r1, name, &miss); | 1305 r1, name, &miss); |
1037 } | 1306 } |
1038 break; | 1307 break; |
1039 } | 1308 } |
1040 | 1309 |
1041 default: | 1310 default: |
1042 UNREACHABLE(); | 1311 UNREACHABLE(); |
1043 } | 1312 } |
1044 | 1313 |
1045 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 1314 if (depth != kInvalidProtoDepth) { |
| 1315 GenerateFastApiCall(masm(), optimization, argc); |
| 1316 } else { |
| 1317 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 1318 } |
1046 | 1319 |
1047 // Handle call cache miss. | 1320 // Handle call cache miss. |
1048 __ bind(&miss); | 1321 __ bind(&miss); |
| 1322 if (depth != kInvalidProtoDepth) { |
| 1323 FreeSpaceForFastApiCall(masm()); |
| 1324 } |
| 1325 |
| 1326 __ bind(&miss_in_smi_check); |
1049 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1327 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
1050 __ Jump(ic, RelocInfo::CODE_TARGET); | 1328 __ Jump(ic, RelocInfo::CODE_TARGET); |
1051 | 1329 |
1052 // Return the generated code. | 1330 // Return the generated code. |
1053 String* function_name = NULL; | 1331 String* function_name = NULL; |
1054 if (function->shared()->name()->IsString()) { | 1332 if (function->shared()->name()->IsString()) { |
1055 function_name = String::cast(function->shared()->name()); | 1333 function_name = String::cast(function->shared()->name()); |
1056 } | 1334 } |
1057 return GetCode(CONSTANT_FUNCTION, function_name); | 1335 return GetCode(CONSTANT_FUNCTION, function_name); |
1058 } | 1336 } |
1059 | 1337 |
1060 | 1338 |
1061 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 1339 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
1062 JSObject* holder, | 1340 JSObject* holder, |
1063 String* name) { | 1341 String* name) { |
1064 // ----------- S t a t e ------------- | 1342 // ----------- S t a t e ------------- |
1065 // -- r2 : name | 1343 // -- r2 : name |
1066 // -- lr : return address | 1344 // -- lr : return address |
1067 // ----------------------------------- | 1345 // ----------------------------------- |
1068 ASSERT(holder->HasNamedInterceptor()); | 1346 |
1069 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | |
1070 Label miss; | 1347 Label miss; |
1071 | 1348 |
1072 const Register receiver = r0; | |
1073 const Register holder_reg = r1; | |
1074 const Register name_reg = r2; | |
1075 const Register scratch = r3; | |
1076 | |
1077 // Get the number of arguments. | 1349 // Get the number of arguments. |
1078 const int argc = arguments().immediate(); | 1350 const int argc = arguments().immediate(); |
1079 | 1351 |
1080 LookupResult lookup; | 1352 LookupResult lookup; |
1081 LookupPostInterceptor(holder, name, &lookup); | 1353 LookupPostInterceptor(holder, name, &lookup); |
1082 | 1354 |
1083 // Get the receiver from the stack into r0. | 1355 // Get the receiver from the stack. |
1084 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1356 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
1085 | 1357 |
1086 // Check that the receiver isn't a smi. | 1358 CallInterceptorCompiler compiler(this, arguments(), r2); |
1087 __ BranchOnSmi(receiver, &miss); | 1359 compiler.Compile(masm(), |
1088 | 1360 object, |
1089 // Check that the maps haven't changed. | 1361 holder, |
1090 Register reg = CheckPrototypes(object, receiver, holder, holder_reg, | 1362 name, |
1091 scratch, name, &miss); | 1363 &lookup, |
1092 if (!reg.is(holder_reg)) { | 1364 r1, |
1093 __ mov(holder_reg, reg); | 1365 r3, |
1094 } | 1366 r4, |
1095 | 1367 &miss); |
1096 // If we call a constant function when the interceptor returns | |
1097 // the no-result sentinel, generate code that optimizes this case. | |
1098 if (lookup.IsProperty() && | |
1099 lookup.IsCacheable() && | |
1100 lookup.type() == CONSTANT_FUNCTION && | |
1101 lookup.GetConstantFunction()->is_compiled() && | |
1102 !holder->IsJSArray()) { | |
1103 // Constant functions cannot sit on global object. | |
1104 ASSERT(!lookup.holder()->IsGlobalObject()); | |
1105 | |
1106 // Call the interceptor. | |
1107 __ EnterInternalFrame(); | |
1108 __ push(holder_reg); | |
1109 __ push(name_reg); | |
1110 CompileCallLoadPropertyWithInterceptor(masm(), | |
1111 receiver, | |
1112 holder_reg, | |
1113 name_reg, | |
1114 holder); | |
1115 __ pop(name_reg); | |
1116 __ pop(holder_reg); | |
1117 __ LeaveInternalFrame(); | |
1118 // r0 no longer contains the receiver. | |
1119 | |
1120 // If interceptor returns no-result sentinal, call the constant function. | |
1121 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | |
1122 __ cmp(r0, scratch); | |
1123 Label invoke; | |
1124 __ b(ne, &invoke); | |
1125 // Check the prototypes between the interceptor's holder and the | |
1126 // constant function's holder. | |
1127 CheckPrototypes(holder, holder_reg, | |
1128 lookup.holder(), r0, | |
1129 scratch, | |
1130 name, | |
1131 &miss); | |
1132 | |
1133 __ InvokeFunction(lookup.GetConstantFunction(), | |
1134 arguments(), | |
1135 JUMP_FUNCTION); | |
1136 | |
1137 __ bind(&invoke); | |
1138 | |
1139 } else { | |
1140 // Call a runtime function to load the interceptor property. | |
1141 __ EnterInternalFrame(); | |
1142 __ push(name_reg); | |
1143 | |
1144 PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder); | |
1145 | |
1146 __ CallExternalReference( | |
1147 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), | |
1148 5); | |
1149 | |
1150 __ pop(name_reg); | |
1151 __ LeaveInternalFrame(); | |
1152 } | |
1153 | 1368 |
1154 // Move returned value, the function to call, to r1. | 1369 // Move returned value, the function to call, to r1. |
1155 __ mov(r1, r0); | 1370 __ mov(r1, r0); |
1156 // Restore receiver. | 1371 // Restore receiver. |
1157 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1372 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
1158 | 1373 |
1159 GenerateCallFunction(masm(), object, arguments(), &miss); | 1374 GenerateCallFunction(masm(), object, arguments(), &miss); |
1160 | 1375 |
1161 // Handle call cache miss. | 1376 // Handle call cache miss. |
1162 __ bind(&miss); | 1377 __ bind(&miss); |
1163 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1378 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
1164 __ Jump(ic, RelocInfo::CODE_TARGET); | 1379 __ Jump(ic, RelocInfo::CODE_TARGET); |
1165 | 1380 |
1166 // Return the generated code. | 1381 // Return the generated code. |
1167 return GetCode(INTERCEPTOR, name); | 1382 return GetCode(INTERCEPTOR, name); |
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 2166 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
1952 | 2167 |
1953 // Return the generated code. | 2168 // Return the generated code. |
1954 return GetCode(); | 2169 return GetCode(); |
1955 } | 2170 } |
1956 | 2171 |
1957 | 2172 |
1958 #undef __ | 2173 #undef __ |
1959 | 2174 |
1960 } } // namespace v8::internal | 2175 } } // namespace v8::internal |
OLD | NEW |