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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 Object* object, | 369 Object* object, |
370 const ParameterCount& arguments, | 370 const ParameterCount& arguments, |
371 Label* miss) { | 371 Label* miss) { |
372 // ----------- S t a t e ------------- | 372 // ----------- S t a t e ------------- |
373 // -- r0: receiver | 373 // -- r0: receiver |
374 // -- r1: function to call | 374 // -- r1: function to call |
375 // ----------------------------------- | 375 // ----------------------------------- |
376 | 376 |
377 // Check that the function really is a function. | 377 // Check that the function really is a function. |
378 __ BranchOnSmi(r1, miss); | 378 __ BranchOnSmi(r1, miss); |
379 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 379 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
380 __ b(ne, miss); | 380 __ b(ne, miss); |
381 | 381 |
382 // Patch the receiver on the stack with the global proxy if | 382 // Patch the receiver on the stack with the global proxy if |
383 // necessary. | 383 // necessary. |
384 if (object->IsGlobalObject()) { | 384 if (object->IsGlobalObject()) { |
385 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 385 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
386 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); | 386 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); |
387 } | 387 } |
388 | 388 |
389 // Invoke the function. | 389 // Invoke the function. |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 | 796 |
797 return GetCodeWithFlags(flags, "LazyCompileStub"); | 797 return GetCodeWithFlags(flags, "LazyCompileStub"); |
798 } | 798 } |
799 | 799 |
800 | 800 |
801 Object* CallStubCompiler::CompileCallField(Object* object, | 801 Object* CallStubCompiler::CompileCallField(Object* object, |
802 JSObject* holder, | 802 JSObject* holder, |
803 int index, | 803 int index, |
804 String* name) { | 804 String* name) { |
805 // ----------- S t a t e ------------- | 805 // ----------- S t a t e ------------- |
806 // -- lr: return address | 806 // -- r2 : name |
| 807 // -- lr : return address |
807 // ----------------------------------- | 808 // ----------------------------------- |
808 Label miss; | 809 Label miss; |
809 | 810 |
810 const int argc = arguments().immediate(); | 811 const int argc = arguments().immediate(); |
811 | 812 |
812 // Get the receiver of the function from the stack into r0. | 813 // Get the receiver of the function from the stack into r0. |
813 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 814 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
814 // Check that the receiver isn't a smi. | 815 // Check that the receiver isn't a smi. |
815 __ tst(r0, Operand(kSmiTagMask)); | 816 __ tst(r0, Operand(kSmiTagMask)); |
816 __ b(eq, &miss); | 817 __ b(eq, &miss); |
817 | 818 |
818 // Do the right check and compute the holder register. | 819 // Do the right check and compute the holder register. |
819 Register reg = | 820 Register reg = |
820 CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name, &miss); | 821 CheckPrototypes(JSObject::cast(object), r0, holder, r1, r3, name, &miss); |
821 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); | 822 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); |
822 | 823 |
823 GenerateCallFunction(masm(), object, arguments(), &miss); | 824 GenerateCallFunction(masm(), object, arguments(), &miss); |
824 | 825 |
825 // Handle call cache miss. | 826 // Handle call cache miss. |
826 __ bind(&miss); | 827 __ bind(&miss); |
827 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 828 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
828 __ Jump(ic, RelocInfo::CODE_TARGET); | 829 __ Jump(ic, RelocInfo::CODE_TARGET); |
829 | 830 |
830 // Return the generated code. | 831 // Return the generated code. |
831 return GetCode(FIELD, name); | 832 return GetCode(FIELD, name); |
832 } | 833 } |
833 | 834 |
834 | 835 |
835 Object* CallStubCompiler::CompileCallConstant(Object* object, | 836 Object* CallStubCompiler::CompileCallConstant(Object* object, |
836 JSObject* holder, | 837 JSObject* holder, |
837 JSFunction* function, | 838 JSFunction* function, |
838 String* name, | 839 String* name, |
839 CheckType check) { | 840 CheckType check) { |
840 // ----------- S t a t e ------------- | 841 // ----------- S t a t e ------------- |
841 // -- lr: return address | 842 // -- r2 : name |
| 843 // -- lr : return address |
842 // ----------------------------------- | 844 // ----------------------------------- |
843 Label miss; | 845 Label miss; |
844 | 846 |
845 // Get the receiver from the stack | 847 // Get the receiver from the stack |
846 const int argc = arguments().immediate(); | 848 const int argc = arguments().immediate(); |
847 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 849 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
848 | 850 |
849 // Check that the receiver isn't a smi. | 851 // Check that the receiver isn't a smi. |
850 if (check != NUMBER_CHECK) { | 852 if (check != NUMBER_CHECK) { |
851 __ tst(r1, Operand(kSmiTagMask)); | 853 __ tst(r1, Operand(kSmiTagMask)); |
852 __ b(eq, &miss); | 854 __ b(eq, &miss); |
853 } | 855 } |
854 | 856 |
855 // Make sure that it's okay not to patch the on stack receiver | 857 // Make sure that it's okay not to patch the on stack receiver |
856 // unless we're doing a receiver map check. | 858 // unless we're doing a receiver map check. |
857 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 859 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
858 | 860 |
859 switch (check) { | 861 switch (check) { |
860 case RECEIVER_MAP_CHECK: | 862 case RECEIVER_MAP_CHECK: |
861 // Check that the maps haven't changed. | 863 // Check that the maps haven't changed. |
862 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); | 864 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss); |
863 | 865 |
864 // Patch the receiver on the stack with the global proxy if | 866 // Patch the receiver on the stack with the global proxy if |
865 // necessary. | 867 // necessary. |
866 if (object->IsGlobalObject()) { | 868 if (object->IsGlobalObject()) { |
867 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 869 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
868 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 870 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
869 } | 871 } |
870 break; | 872 break; |
871 | 873 |
872 case STRING_CHECK: | 874 case STRING_CHECK: |
873 if (!function->IsBuiltin()) { | 875 if (!function->IsBuiltin()) { |
874 // Calling non-builtins with a value as receiver requires boxing. | 876 // Calling non-builtins with a value as receiver requires boxing. |
875 __ jmp(&miss); | 877 __ jmp(&miss); |
876 } else { | 878 } else { |
877 // Check that the object is a two-byte string or a symbol. | 879 // Check that the object is a two-byte string or a symbol. |
878 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); | 880 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
879 __ b(hs, &miss); | 881 __ b(hs, &miss); |
880 // Check that the maps starting from the prototype haven't changed. | 882 // Check that the maps starting from the prototype haven't changed. |
881 GenerateLoadGlobalFunctionPrototype(masm(), | 883 GenerateLoadGlobalFunctionPrototype(masm(), |
882 Context::STRING_FUNCTION_INDEX, | 884 Context::STRING_FUNCTION_INDEX, |
883 r2); | 885 r0); |
884 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, | 886 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
885 r1, name, &miss); | 887 r1, name, &miss); |
886 } | 888 } |
887 break; | 889 break; |
888 | 890 |
889 case NUMBER_CHECK: { | 891 case NUMBER_CHECK: { |
890 if (!function->IsBuiltin()) { | 892 if (!function->IsBuiltin()) { |
891 // Calling non-builtins with a value as receiver requires boxing. | 893 // Calling non-builtins with a value as receiver requires boxing. |
892 __ jmp(&miss); | 894 __ jmp(&miss); |
893 } else { | 895 } else { |
894 Label fast; | 896 Label fast; |
895 // Check that the object is a smi or a heap number. | 897 // Check that the object is a smi or a heap number. |
896 __ tst(r1, Operand(kSmiTagMask)); | 898 __ tst(r1, Operand(kSmiTagMask)); |
897 __ b(eq, &fast); | 899 __ b(eq, &fast); |
898 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 900 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
899 __ b(ne, &miss); | 901 __ b(ne, &miss); |
900 __ bind(&fast); | 902 __ bind(&fast); |
901 // Check that the maps starting from the prototype haven't changed. | 903 // Check that the maps starting from the prototype haven't changed. |
902 GenerateLoadGlobalFunctionPrototype(masm(), | 904 GenerateLoadGlobalFunctionPrototype(masm(), |
903 Context::NUMBER_FUNCTION_INDEX, | 905 Context::NUMBER_FUNCTION_INDEX, |
904 r2); | 906 r0); |
905 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, | 907 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
906 r1, name, &miss); | 908 r1, name, &miss); |
907 } | 909 } |
908 break; | 910 break; |
909 } | 911 } |
910 | 912 |
911 case BOOLEAN_CHECK: { | 913 case BOOLEAN_CHECK: { |
912 if (!function->IsBuiltin()) { | 914 if (!function->IsBuiltin()) { |
913 // Calling non-builtins with a value as receiver requires boxing. | 915 // Calling non-builtins with a value as receiver requires boxing. |
914 __ jmp(&miss); | 916 __ jmp(&miss); |
915 } else { | 917 } else { |
916 Label fast; | 918 Label fast; |
917 // Check that the object is a boolean. | 919 // Check that the object is a boolean. |
918 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 920 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
919 __ cmp(r1, ip); | 921 __ cmp(r1, ip); |
920 __ b(eq, &fast); | 922 __ b(eq, &fast); |
921 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 923 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
922 __ cmp(r1, ip); | 924 __ cmp(r1, ip); |
923 __ b(ne, &miss); | 925 __ b(ne, &miss); |
924 __ bind(&fast); | 926 __ bind(&fast); |
925 // Check that the maps starting from the prototype haven't changed. | 927 // Check that the maps starting from the prototype haven't changed. |
926 GenerateLoadGlobalFunctionPrototype(masm(), | 928 GenerateLoadGlobalFunctionPrototype(masm(), |
927 Context::BOOLEAN_FUNCTION_INDEX, | 929 Context::BOOLEAN_FUNCTION_INDEX, |
928 r2); | 930 r0); |
929 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, | 931 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
930 r1, name, &miss); | 932 r1, name, &miss); |
931 } | 933 } |
932 break; | 934 break; |
933 } | 935 } |
934 | 936 |
935 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: | 937 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: |
936 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); | 938 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss); |
937 // Make sure object->HasFastElements(). | 939 // Make sure object->HasFastElements(). |
938 // Get the elements array of the object. | 940 // Get the elements array of the object. |
939 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset)); | 941 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset)); |
940 // Check that the object is in fast mode (not dictionary). | 942 // Check that the object is in fast mode (not dictionary). |
941 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); | 943 __ ldr(r0, FieldMemOperand(r3, HeapObject::kMapOffset)); |
942 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 944 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
943 __ cmp(r2, ip); | 945 __ cmp(r0, ip); |
944 __ b(ne, &miss); | 946 __ b(ne, &miss); |
945 break; | 947 break; |
946 | 948 |
947 default: | 949 default: |
948 UNREACHABLE(); | 950 UNREACHABLE(); |
949 } | 951 } |
950 | 952 |
951 GenerateCallConstFunction(masm(), function, arguments()); | 953 GenerateCallConstFunction(masm(), function, arguments()); |
952 | 954 |
953 // Handle call cache miss. | 955 // Handle call cache miss. |
954 __ bind(&miss); | 956 __ bind(&miss); |
955 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 957 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
956 __ Jump(ic, RelocInfo::CODE_TARGET); | 958 __ Jump(ic, RelocInfo::CODE_TARGET); |
957 | 959 |
958 // Return the generated code. | 960 // Return the generated code. |
959 String* function_name = NULL; | 961 String* function_name = NULL; |
960 if (function->shared()->name()->IsString()) { | 962 if (function->shared()->name()->IsString()) { |
961 function_name = String::cast(function->shared()->name()); | 963 function_name = String::cast(function->shared()->name()); |
962 } | 964 } |
963 return GetCode(CONSTANT_FUNCTION, function_name); | 965 return GetCode(CONSTANT_FUNCTION, function_name); |
964 } | 966 } |
965 | 967 |
966 | 968 |
967 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 969 Object* CallStubCompiler::CompileCallInterceptor(Object* object, |
968 JSObject* holder, | 970 JSObject* holder, |
969 String* name) { | 971 String* name) { |
970 // ----------- S t a t e ------------- | 972 // ----------- S t a t e ------------- |
971 // -- lr: return address | 973 // -- r2 : name |
| 974 // -- lr : return address |
972 // ----------------------------------- | 975 // ----------------------------------- |
973 ASSERT(holder->HasNamedInterceptor()); | 976 ASSERT(holder->HasNamedInterceptor()); |
974 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 977 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
975 Label miss; | 978 Label miss; |
976 | 979 |
977 const Register receiver = r0; | 980 const Register receiver = r0; |
978 const Register name_reg = r1; | 981 const Register holder_reg = r1; |
979 const Register holder_reg = r2; | 982 const Register name_reg = r2; |
980 const Register scratch = r3; | 983 const Register scratch = r3; |
981 | 984 |
982 // Get the number of arguments. | 985 // Get the number of arguments. |
983 const int argc = arguments().immediate(); | 986 const int argc = arguments().immediate(); |
984 | 987 |
985 LookupResult lookup; | 988 LookupResult lookup; |
986 LookupPostInterceptor(holder, name, &lookup); | 989 LookupPostInterceptor(holder, name, &lookup); |
987 | 990 |
988 // Load the receiver from the stack. | 991 // Get the receiver from the stack into r0. |
989 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 992 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
990 // Load the name from the stack. | |
991 __ ldr(name_reg, MemOperand(sp, (argc + 1) * kPointerSize)); | |
992 | 993 |
993 // Check that the receiver isn't a smi. | 994 // Check that the receiver isn't a smi. |
994 __ BranchOnSmi(receiver, &miss); | 995 __ BranchOnSmi(receiver, &miss); |
995 | 996 |
996 // Check that the maps haven't changed. | 997 // Check that the maps haven't changed. |
997 Register reg = | 998 Register reg = |
998 CheckPrototypes(JSObject::cast(object), receiver, holder, | 999 CheckPrototypes(JSObject::cast(object), receiver, holder, |
999 holder_reg, scratch, name, &miss); | 1000 holder_reg, scratch, name, &miss); |
1000 if (!reg.is(holder_reg)) { | 1001 if (!reg.is(holder_reg)) { |
1001 __ mov(holder_reg, reg); | 1002 __ mov(holder_reg, reg); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 __ mov(r0, Operand(5)); | 1055 __ mov(r0, Operand(5)); |
1055 __ mov(r1, Operand(ref)); | 1056 __ mov(r1, Operand(ref)); |
1056 | 1057 |
1057 CEntryStub stub(1); | 1058 CEntryStub stub(1); |
1058 __ CallStub(&stub); | 1059 __ CallStub(&stub); |
1059 | 1060 |
1060 __ pop(name_reg); | 1061 __ pop(name_reg); |
1061 __ LeaveInternalFrame(); | 1062 __ LeaveInternalFrame(); |
1062 } | 1063 } |
1063 | 1064 |
1064 | |
1065 // Move returned value, the function to call, to r1. | 1065 // Move returned value, the function to call, to r1. |
1066 // Neither receiver nor name contain their original value at this point. | |
1067 __ mov(r1, r0); | 1066 __ mov(r1, r0); |
1068 // Restore receiver. | 1067 // Restore receiver. |
1069 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1068 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
1070 | 1069 |
1071 GenerateCallFunction(masm(), object, arguments(), &miss); | 1070 GenerateCallFunction(masm(), object, arguments(), &miss); |
1072 | 1071 |
1073 // Handle call cache miss. | 1072 // Handle call cache miss. |
1074 __ bind(&miss); | 1073 __ bind(&miss); |
1075 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1074 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
1076 __ Jump(ic, RelocInfo::CODE_TARGET); | 1075 __ Jump(ic, RelocInfo::CODE_TARGET); |
1077 | 1076 |
1078 // Return the generated code. | 1077 // Return the generated code. |
1079 return GetCode(INTERCEPTOR, name); | 1078 return GetCode(INTERCEPTOR, name); |
1080 } | 1079 } |
1081 | 1080 |
1082 | 1081 |
1083 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, | 1082 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, |
1084 GlobalObject* holder, | 1083 GlobalObject* holder, |
1085 JSGlobalPropertyCell* cell, | 1084 JSGlobalPropertyCell* cell, |
1086 JSFunction* function, | 1085 JSFunction* function, |
1087 String* name) { | 1086 String* name) { |
1088 // ----------- S t a t e ------------- | 1087 // ----------- S t a t e ------------- |
1089 // -- lr: return address | 1088 // -- r2 : name |
| 1089 // -- lr : return address |
1090 // ----------------------------------- | 1090 // ----------------------------------- |
1091 Label miss; | 1091 Label miss; |
1092 | 1092 |
1093 // Get the number of arguments. | 1093 // Get the number of arguments. |
1094 const int argc = arguments().immediate(); | 1094 const int argc = arguments().immediate(); |
1095 | 1095 |
1096 // Get the receiver from the stack. | 1096 // Get the receiver from the stack. |
1097 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1097 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
1098 | 1098 |
1099 // If the object is the holder then we know that it's a global | 1099 // If the object is the holder then we know that it's a global |
1100 // object which can only happen for contextual calls. In this case, | 1100 // object which can only happen for contextual calls. In this case, |
1101 // the receiver cannot be a smi. | 1101 // the receiver cannot be a smi. |
1102 if (object != holder) { | 1102 if (object != holder) { |
1103 __ tst(r0, Operand(kSmiTagMask)); | 1103 __ tst(r0, Operand(kSmiTagMask)); |
1104 __ b(eq, &miss); | 1104 __ b(eq, &miss); |
1105 } | 1105 } |
1106 | 1106 |
1107 // Check that the maps haven't changed. | 1107 // Check that the maps haven't changed. |
1108 CheckPrototypes(object, r0, holder, r3, r2, name, &miss); | 1108 CheckPrototypes(object, r0, holder, r3, r1, name, &miss); |
1109 | 1109 |
1110 // Get the value from the cell. | 1110 // Get the value from the cell. |
1111 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1111 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
1112 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1112 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
1113 | 1113 |
1114 // Check that the cell contains the same function. | 1114 // Check that the cell contains the same function. |
1115 if (Heap::InNewSpace(function)) { | 1115 if (Heap::InNewSpace(function)) { |
1116 // We can't embed a pointer to a function in new space so we have | 1116 // We can't embed a pointer to a function in new space so we have |
1117 // to verify that the shared function info is unchanged. This has | 1117 // to verify that the shared function info is unchanged. This has |
1118 // the nice side effect that multiple closures based on the same | 1118 // the nice side effect that multiple closures based on the same |
1119 // function can all use this call IC. Before we load through the | 1119 // function can all use this call IC. Before we load through the |
1120 // function, we have to verify that it still is a function. | 1120 // function, we have to verify that it still is a function. |
1121 __ tst(r1, Operand(kSmiTagMask)); | 1121 __ tst(r1, Operand(kSmiTagMask)); |
1122 __ b(eq, &miss); | 1122 __ b(eq, &miss); |
1123 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 1123 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
1124 __ b(ne, &miss); | 1124 __ b(ne, &miss); |
1125 | 1125 |
1126 // Check the shared function info. Make sure it hasn't changed. | 1126 // Check the shared function info. Make sure it hasn't changed. |
1127 __ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared()))); | 1127 __ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared()))); |
1128 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1128 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1129 __ cmp(r2, r3); | 1129 __ cmp(r4, r3); |
1130 __ b(ne, &miss); | 1130 __ b(ne, &miss); |
1131 } else { | 1131 } else { |
1132 __ cmp(r1, Operand(Handle<JSFunction>(function))); | 1132 __ cmp(r1, Operand(Handle<JSFunction>(function))); |
1133 __ b(ne, &miss); | 1133 __ b(ne, &miss); |
1134 } | 1134 } |
1135 | 1135 |
1136 // Patch the receiver on the stack with the global proxy if | 1136 // Patch the receiver on the stack with the global proxy if |
1137 // necessary. | 1137 // necessary. |
1138 if (object->IsGlobalObject()) { | 1138 if (object->IsGlobalObject()) { |
1139 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 1139 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
1140 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 1140 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
1141 } | 1141 } |
1142 | 1142 |
1143 // Setup the context (function already in r1). | 1143 // Setup the context (function already in r1). |
1144 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1144 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1145 | 1145 |
1146 // Jump to the cached code (tail call). | 1146 // Jump to the cached code (tail call). |
1147 __ IncrementCounter(&Counters::call_global_inline, 1, r2, r3); | 1147 __ IncrementCounter(&Counters::call_global_inline, 1, r1, r3); |
1148 ASSERT(function->is_compiled()); | 1148 ASSERT(function->is_compiled()); |
1149 Handle<Code> code(function->code()); | 1149 Handle<Code> code(function->code()); |
1150 ParameterCount expected(function->shared()->formal_parameter_count()); | 1150 ParameterCount expected(function->shared()->formal_parameter_count()); |
1151 __ InvokeCode(code, expected, arguments(), | 1151 __ InvokeCode(code, expected, arguments(), |
1152 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 1152 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
1153 | 1153 |
1154 // Handle call cache miss. | 1154 // Handle call cache miss. |
1155 __ bind(&miss); | 1155 __ bind(&miss); |
1156 __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); | 1156 __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); |
1157 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1157 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1822 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 1822 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
1823 | 1823 |
1824 // Return the generated code. | 1824 // Return the generated code. |
1825 return GetCode(); | 1825 return GetCode(); |
1826 } | 1826 } |
1827 | 1827 |
1828 | 1828 |
1829 #undef __ | 1829 #undef __ |
1830 | 1830 |
1831 } } // namespace v8::internal | 1831 } } // namespace v8::internal |
OLD | NEW |