| 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 |