OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 __ pop(offset); | 100 __ pop(offset); |
101 } | 101 } |
102 } | 102 } |
103 | 103 |
104 | 104 |
105 // Helper function used to check that the dictionary doesn't contain | 105 // Helper function used to check that the dictionary doesn't contain |
106 // the property. This function may return false negatives, so miss_label | 106 // the property. This function may return false negatives, so miss_label |
107 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
108 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
109 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
110 static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
111 Label* miss_label, | 111 Label* miss_label, |
112 Register receiver, | 112 Register receiver, |
113 String* name, | 113 Handle<String> name, |
114 Register r0, | 114 Register r0, |
115 Register r1) { | 115 Register r1) { |
116 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
117 Counters* counters = masm->isolate()->counters(); | 117 Counters* counters = masm->isolate()->counters(); |
118 __ IncrementCounter(counters->negative_lookups(), 1); | 118 __ IncrementCounter(counters->negative_lookups(), 1); |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 120 |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 |
| 123 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); |
| 129 __ j(not_zero, miss_label); |
| 130 |
| 131 // Check that receiver is a JSObject. |
| 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 133 __ j(below, miss_label); |
| 134 |
| 135 // Load properties array. |
| 136 Register properties = r0; |
| 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 138 |
| 139 // Check that the properties array is a dictionary. |
| 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 142 __ j(not_equal, miss_label); |
| 143 |
| 144 Label done; |
| 145 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 146 miss_label, |
| 147 &done, |
| 148 properties, |
| 149 name, |
| 150 r1); |
| 151 __ bind(&done); |
| 152 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 153 } |
| 154 |
| 155 |
| 156 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 157 // handlified. |
| 158 static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 159 Label* miss_label, |
| 160 Register receiver, |
| 161 String* name, |
| 162 Register r0, |
| 163 Register r1) { |
| 164 ASSERT(name->IsSymbol()); |
| 165 Counters* counters = masm->isolate()->counters(); |
| 166 __ IncrementCounter(counters->negative_lookups(), 1); |
119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 167 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
120 | 168 |
121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 169 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
122 | 170 |
123 const int kInterceptorOrAccessCheckNeededMask = | 171 const int kInterceptorOrAccessCheckNeededMask = |
124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 172 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
125 | 173 |
126 // Bail out if the receiver has a named interceptor or requires access checks. | 174 // Bail out if the receiver has a named interceptor or requires access checks. |
127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 175 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
128 kInterceptorOrAccessCheckNeededMask); | 176 kInterceptorOrAccessCheckNeededMask); |
129 __ j(not_zero, miss_label); | 177 __ j(not_zero, miss_label); |
130 | 178 |
131 // Check that receiver is a JSObject. | 179 // Check that receiver is a JSObject. |
132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | 180 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
133 __ j(below, miss_label); | 181 __ j(below, miss_label); |
134 | 182 |
135 // Load properties array. | 183 // Load properties array. |
136 Register properties = r0; | 184 Register properties = r0; |
137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 185 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
138 | 186 |
139 // Check that the properties array is a dictionary. | 187 // Check that the properties array is a dictionary. |
140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 188 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
141 Immediate(masm->isolate()->factory()->hash_table_map())); | 189 Immediate(masm->isolate()->factory()->hash_table_map())); |
142 __ j(not_equal, miss_label); | 190 __ j(not_equal, miss_label); |
143 | 191 |
144 Label done; | 192 Label done; |
145 MaybeObject* result = | 193 MaybeObject* result = |
146 StringDictionaryLookupStub::GenerateNegativeLookup(masm, | 194 StringDictionaryLookupStub::TryGenerateNegativeLookup(masm, |
147 miss_label, | 195 miss_label, |
148 &done, | 196 &done, |
149 properties, | 197 properties, |
150 name, | 198 name, |
151 r1); | 199 r1); |
152 if (result->IsFailure()) return result; | 200 if (result->IsFailure()) return result; |
153 | 201 |
154 __ bind(&done); | 202 __ bind(&done); |
155 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 203 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
156 | 204 |
157 return result; | 205 return result; |
158 } | 206 } |
159 | 207 |
160 | 208 |
161 void StubCache::GenerateProbe(MacroAssembler* masm, | 209 void StubCache::GenerateProbe(MacroAssembler* masm, |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
319 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
320 __ ret(0); | 368 __ ret(0); |
321 } | 369 } |
322 | 370 |
323 | 371 |
324 // Load a fast property out of a holder object (src). In-object properties | 372 // Load a fast property out of a holder object (src). In-object properties |
325 // are loaded directly otherwise the property is loaded from the properties | 373 // are loaded directly otherwise the property is loaded from the properties |
326 // fixed array. | 374 // fixed array. |
327 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
328 Register dst, Register src, | 376 Register dst, |
329 JSObject* holder, int index) { | 377 Register src, |
| 378 Handle<JSObject> holder, |
| 379 int index) { |
330 // Adjust for the number of properties stored in the holder. | 380 // Adjust for the number of properties stored in the holder. |
331 index -= holder->map()->inobject_properties(); | 381 index -= holder->map()->inobject_properties(); |
332 if (index < 0) { | 382 if (index < 0) { |
333 // Get the property straight out of the holder. | 383 // Get the property straight out of the holder. |
334 int offset = holder->map()->instance_size() + (index * kPointerSize); | 384 int offset = holder->map()->instance_size() + (index * kPointerSize); |
335 __ mov(dst, FieldOperand(src, offset)); | 385 __ mov(dst, FieldOperand(src, offset)); |
336 } else { | 386 } else { |
337 // Calculate the offset into the properties array. | 387 // Calculate the offset into the properties array. |
338 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 388 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
339 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 389 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 } | 861 } |
812 | 862 |
813 // Return the value (register eax). | 863 // Return the value (register eax). |
814 __ ret(0); | 864 __ ret(0); |
815 } | 865 } |
816 | 866 |
817 | 867 |
818 // Generate code to check that a global property cell is empty. Create | 868 // Generate code to check that a global property cell is empty. Create |
819 // the property cell at compilation time if no cell exists for the | 869 // the property cell at compilation time if no cell exists for the |
820 // property. | 870 // property. |
821 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 871 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 872 Handle<GlobalObject> global, |
| 873 Handle<String> name, |
| 874 Register scratch, |
| 875 Label* miss) { |
| 876 Handle<JSGlobalPropertyCell> cell = |
| 877 GlobalObject::EnsurePropertyCell(global, name); |
| 878 ASSERT(cell->value()->IsTheHole()); |
| 879 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
| 880 if (Serializer::enabled()) { |
| 881 __ mov(scratch, Immediate(cell)); |
| 882 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 883 Immediate(the_hole)); |
| 884 } else { |
| 885 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
| 886 } |
| 887 __ j(not_equal, miss); |
| 888 } |
| 889 |
| 890 |
| 891 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 892 // handlified. |
| 893 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
822 MacroAssembler* masm, | 894 MacroAssembler* masm, |
823 GlobalObject* global, | 895 GlobalObject* global, |
824 String* name, | 896 String* name, |
825 Register scratch, | 897 Register scratch, |
826 Label* miss) { | 898 Label* miss) { |
827 Object* probe; | 899 Object* probe; |
828 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 900 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
829 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 901 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
830 } | 902 } |
831 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 903 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
832 ASSERT(cell->value()->IsTheHole()); | 904 ASSERT(cell->value()->IsTheHole()); |
833 if (Serializer::enabled()) { | 905 if (Serializer::enabled()) { |
834 __ mov(scratch, Immediate(Handle<Object>(cell))); | 906 __ mov(scratch, Immediate(Handle<Object>(cell))); |
835 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 907 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
836 Immediate(masm->isolate()->factory()->the_hole_value())); | 908 Immediate(masm->isolate()->factory()->the_hole_value())); |
837 } else { | 909 } else { |
838 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 910 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
839 Immediate(masm->isolate()->factory()->the_hole_value())); | 911 Immediate(masm->isolate()->factory()->the_hole_value())); |
840 } | 912 } |
841 __ j(not_equal, miss); | 913 __ j(not_equal, miss); |
842 return cell; | 914 return cell; |
843 } | 915 } |
844 | 916 |
845 | 917 |
846 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 918 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
847 // from object to (but not including) holder. | 919 // from object to (but not including) holder. |
848 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 920 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 921 Handle<JSObject> object, |
| 922 Handle<JSObject> holder, |
| 923 Handle<String> name, |
| 924 Register scratch, |
| 925 Label* miss) { |
| 926 Handle<JSObject> current = object; |
| 927 while (!current.is_identical_to(holder)) { |
| 928 if (current->IsGlobalObject()) { |
| 929 GenerateCheckPropertyCell(masm, |
| 930 Handle<GlobalObject>::cast(current), |
| 931 name, |
| 932 scratch, |
| 933 miss); |
| 934 } |
| 935 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 936 } |
| 937 } |
| 938 |
| 939 |
| 940 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 941 // handlified. |
| 942 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
849 MacroAssembler* masm, | 943 MacroAssembler* masm, |
850 JSObject* object, | 944 JSObject* object, |
851 JSObject* holder, | 945 JSObject* holder, |
852 String* name, | 946 String* name, |
853 Register scratch, | 947 Register scratch, |
854 Label* miss) { | 948 Label* miss) { |
855 JSObject* current = object; | 949 JSObject* current = object; |
856 while (current != holder) { | 950 while (current != holder) { |
857 if (current->IsGlobalObject()) { | 951 if (current->IsGlobalObject()) { |
858 // Returns a cell or a failure. | 952 // Returns a cell or a failure. |
859 MaybeObject* result = GenerateCheckPropertyCell( | 953 MaybeObject* result = TryGenerateCheckPropertyCell( |
860 masm, | 954 masm, |
861 GlobalObject::cast(current), | 955 GlobalObject::cast(current), |
862 name, | 956 name, |
863 scratch, | 957 scratch, |
864 miss); | 958 miss); |
865 if (result->IsFailure()) return result; | 959 if (result->IsFailure()) return result; |
866 } | 960 } |
867 ASSERT(current->IsJSObject()); | 961 ASSERT(current->IsJSObject()); |
868 current = JSObject::cast(current->GetPrototype()); | 962 current = JSObject::cast(current->GetPrototype()); |
869 } | 963 } |
870 return NULL; | 964 return NULL; |
871 } | 965 } |
872 | 966 |
873 | 967 |
874 #undef __ | 968 #undef __ |
875 #define __ ACCESS_MASM(masm()) | 969 #define __ ACCESS_MASM(masm()) |
876 | 970 |
877 | 971 |
| 972 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 973 Register object_reg, |
| 974 Handle<JSObject> holder, |
| 975 Register holder_reg, |
| 976 Register scratch1, |
| 977 Register scratch2, |
| 978 Handle<String> name, |
| 979 int save_at_depth, |
| 980 Label* miss) { |
| 981 // Make sure there's no overlap between holder and object registers. |
| 982 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 983 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 984 && !scratch2.is(scratch1)); |
| 985 |
| 986 // Keep track of the current object in register reg. |
| 987 Register reg = object_reg; |
| 988 Handle<JSObject> current = object; |
| 989 int depth = 0; |
| 990 |
| 991 if (save_at_depth == depth) { |
| 992 __ mov(Operand(esp, kPointerSize), reg); |
| 993 } |
| 994 |
| 995 // Traverse the prototype chain and check the maps in the prototype chain for |
| 996 // fast and global objects or do negative lookup for normal objects. |
| 997 while (!current.is_identical_to(holder)) { |
| 998 ++depth; |
| 999 |
| 1000 // Only global objects and objects that do not require access |
| 1001 // checks are allowed in stubs. |
| 1002 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 1003 |
| 1004 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 1005 if (!current->HasFastProperties() && |
| 1006 !current->IsJSGlobalObject() && |
| 1007 !current->IsJSGlobalProxy()) { |
| 1008 if (!name->IsSymbol()) { |
| 1009 name = factory()->LookupSymbol(name); |
| 1010 } |
| 1011 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 1012 StringDictionary::kNotFound); |
| 1013 |
| 1014 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1015 scratch1, scratch2); |
| 1016 |
| 1017 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1018 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1019 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1020 } else { |
| 1021 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1022 Handle<Map> current_map(current->map()); |
| 1023 if (in_new_space) { |
| 1024 // Save the map in scratch1 for later. |
| 1025 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1026 __ cmp(scratch1, Immediate(current_map)); |
| 1027 } else { |
| 1028 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1029 Immediate(current_map)); |
| 1030 } |
| 1031 // Branch on the result of the map check. |
| 1032 __ j(not_equal, miss); |
| 1033 // Check access rights to the global object. This has to happen after |
| 1034 // the map check so that we know that the object is actually a global |
| 1035 // object. |
| 1036 if (current->IsJSGlobalProxy()) { |
| 1037 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1038 } |
| 1039 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1040 |
| 1041 if (in_new_space) { |
| 1042 // The prototype is in new space; we cannot store a reference to it |
| 1043 // in the code. Load it from the map. |
| 1044 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1045 } else { |
| 1046 // The prototype is in old space; load it directly. |
| 1047 __ mov(reg, prototype); |
| 1048 } |
| 1049 } |
| 1050 |
| 1051 if (save_at_depth == depth) { |
| 1052 __ mov(Operand(esp, kPointerSize), reg); |
| 1053 } |
| 1054 |
| 1055 // Go to the next object in the prototype chain. |
| 1056 current = prototype; |
| 1057 } |
| 1058 ASSERT(current.is_identical_to(holder)); |
| 1059 |
| 1060 // Log the check depth. |
| 1061 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1062 |
| 1063 // Check the holder map. |
| 1064 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1065 Immediate(Handle<Map>(holder->map()))); |
| 1066 __ j(not_equal, miss); |
| 1067 |
| 1068 // Perform security check for access to the global object. |
| 1069 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1070 if (holder->IsJSGlobalProxy()) { |
| 1071 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1072 } |
| 1073 |
| 1074 // If we've skipped any global objects, it's not enough to verify that |
| 1075 // their maps haven't changed. We also need to check that the property |
| 1076 // cell for the property is still empty. |
| 1077 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1078 |
| 1079 // Return the register containing the holder. |
| 1080 return reg; |
| 1081 } |
| 1082 |
| 1083 |
| 1084 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1085 // handlified. |
878 Register StubCompiler::CheckPrototypes(JSObject* object, | 1086 Register StubCompiler::CheckPrototypes(JSObject* object, |
879 Register object_reg, | 1087 Register object_reg, |
880 JSObject* holder, | 1088 JSObject* holder, |
881 Register holder_reg, | 1089 Register holder_reg, |
882 Register scratch1, | 1090 Register scratch1, |
883 Register scratch2, | 1091 Register scratch2, |
884 String* name, | 1092 String* name, |
885 int save_at_depth, | 1093 int save_at_depth, |
886 Label* miss) { | 1094 Label* miss) { |
887 // Make sure there's no overlap between holder and object registers. | 1095 // Make sure there's no overlap between holder and object registers. |
(...skipping 29 matching lines...) Expand all Loading... |
917 Object* lookup_result = NULL; // Initialization to please compiler. | 1125 Object* lookup_result = NULL; // Initialization to please compiler. |
918 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 1126 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
919 set_failure(Failure::cast(maybe_lookup_result)); | 1127 set_failure(Failure::cast(maybe_lookup_result)); |
920 return reg; | 1128 return reg; |
921 } | 1129 } |
922 name = String::cast(lookup_result); | 1130 name = String::cast(lookup_result); |
923 } | 1131 } |
924 ASSERT(current->property_dictionary()->FindEntry(name) == | 1132 ASSERT(current->property_dictionary()->FindEntry(name) == |
925 StringDictionary::kNotFound); | 1133 StringDictionary::kNotFound); |
926 | 1134 |
927 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1135 MaybeObject* negative_lookup = |
928 miss, | 1136 TryGenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
929 reg, | 1137 scratch1, scratch2); |
930 name, | |
931 scratch1, | |
932 scratch2); | |
933 if (negative_lookup->IsFailure()) { | 1138 if (negative_lookup->IsFailure()) { |
934 set_failure(Failure::cast(negative_lookup)); | 1139 set_failure(Failure::cast(negative_lookup)); |
935 return reg; | 1140 return reg; |
936 } | 1141 } |
937 | 1142 |
938 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1143 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
939 reg = holder_reg; // from now the object is in holder_reg | 1144 reg = holder_reg; // from now the object is in holder_reg |
940 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1145 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
941 } else if (heap()->InNewSpace(prototype)) { | 1146 } else if (heap()->InNewSpace(prototype)) { |
942 // Get the map of the current object. | 1147 // Get the map of the current object. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 | 1194 |
990 // Check the holder map. | 1195 // Check the holder map. |
991 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1196 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
992 Immediate(Handle<Map>(holder->map()))); | 1197 Immediate(Handle<Map>(holder->map()))); |
993 __ j(not_equal, miss); | 1198 __ j(not_equal, miss); |
994 | 1199 |
995 // Perform security check for access to the global object. | 1200 // Perform security check for access to the global object. |
996 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1201 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
997 if (holder->IsJSGlobalProxy()) { | 1202 if (holder->IsJSGlobalProxy()) { |
998 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1203 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
999 }; | 1204 } |
1000 | 1205 |
1001 // If we've skipped any global objects, it's not enough to verify | 1206 // If we've skipped any global objects, it's not enough to verify |
1002 // that their maps haven't changed. We also need to check that the | 1207 // that their maps haven't changed. We also need to check that the |
1003 // property cell for the property is still empty. | 1208 // property cell for the property is still empty. |
1004 MaybeObject* result = GenerateCheckPropertyCells(masm(), | 1209 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
1005 object, | 1210 object, |
1006 holder, | 1211 holder, |
1007 name, | 1212 name, |
1008 scratch1, | 1213 scratch1, |
1009 miss); | 1214 miss); |
1010 if (result->IsFailure()) set_failure(Failure::cast(result)); | 1215 if (result->IsFailure()) set_failure(Failure::cast(result)); |
1011 | 1216 |
1012 // Return the register containing the holder. | 1217 // Return the register containing the holder. |
1013 return reg; | 1218 return reg; |
1014 } | 1219 } |
1015 | 1220 |
1016 | 1221 |
1017 void StubCompiler::GenerateLoadField(JSObject* object, | 1222 void StubCompiler::GenerateLoadField(JSObject* object, |
1018 JSObject* holder, | 1223 JSObject* holder, |
1019 Register receiver, | 1224 Register receiver, |
1020 Register scratch1, | 1225 Register scratch1, |
1021 Register scratch2, | 1226 Register scratch2, |
1022 Register scratch3, | 1227 Register scratch3, |
1023 int index, | 1228 int index, |
1024 String* name, | 1229 String* name, |
1025 Label* miss) { | 1230 Label* miss) { |
1026 // Check that the receiver isn't a smi. | 1231 // Check that the receiver isn't a smi. |
1027 __ JumpIfSmi(receiver, miss); | 1232 __ JumpIfSmi(receiver, miss); |
1028 | 1233 |
1029 // Check the prototype chain. | 1234 // Check the prototype chain. |
1030 Register reg = | 1235 Register reg = |
1031 CheckPrototypes(object, receiver, holder, | 1236 CheckPrototypes(object, receiver, holder, |
1032 scratch1, scratch2, scratch3, name, miss); | 1237 scratch1, scratch2, scratch3, name, miss); |
1033 | 1238 |
1034 // Get the value from the properties. | 1239 // Get the value from the properties. |
1035 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1240 GenerateFastPropertyLoad(masm(), eax, reg, Handle<JSObject>(holder), index); |
1036 __ ret(0); | 1241 __ ret(0); |
1037 } | 1242 } |
1038 | 1243 |
1039 | 1244 |
1040 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1245 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
1041 JSObject* holder, | 1246 JSObject* holder, |
1042 Register receiver, | 1247 Register receiver, |
1043 Register name_reg, | 1248 Register name_reg, |
1044 Register scratch1, | 1249 Register scratch1, |
1045 Register scratch2, | 1250 Register scratch2, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 scratch2, | 1419 scratch2, |
1215 scratch3, | 1420 scratch3, |
1216 name, | 1421 name, |
1217 miss); | 1422 miss); |
1218 } | 1423 } |
1219 | 1424 |
1220 if (lookup->type() == FIELD) { | 1425 if (lookup->type() == FIELD) { |
1221 // We found FIELD property in prototype chain of interceptor's holder. | 1426 // We found FIELD property in prototype chain of interceptor's holder. |
1222 // Retrieve a field from field's holder. | 1427 // Retrieve a field from field's holder. |
1223 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1428 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
1224 lookup->holder(), lookup->GetFieldIndex()); | 1429 Handle<JSObject>(lookup->holder()), |
| 1430 lookup->GetFieldIndex()); |
1225 __ ret(0); | 1431 __ ret(0); |
1226 } else { | 1432 } else { |
1227 // We found CALLBACKS property in prototype chain of interceptor's | 1433 // We found CALLBACKS property in prototype chain of interceptor's |
1228 // holder. | 1434 // holder. |
1229 ASSERT(lookup->type() == CALLBACKS); | 1435 ASSERT(lookup->type() == CALLBACKS); |
1230 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1436 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
1231 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1437 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
1232 ASSERT(callback != NULL); | 1438 ASSERT(callback != NULL); |
1233 ASSERT(callback->getter() != NULL); | 1439 ASSERT(callback->getter() != NULL); |
1234 | 1440 |
(...skipping 26 matching lines...) Expand all Loading... |
1261 __ push(scratch2); // restore old return address | 1467 __ push(scratch2); // restore old return address |
1262 | 1468 |
1263 ExternalReference ref = | 1469 ExternalReference ref = |
1264 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1470 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1265 isolate()); | 1471 isolate()); |
1266 __ TailCallExternalReference(ref, 5, 1); | 1472 __ TailCallExternalReference(ref, 5, 1); |
1267 } | 1473 } |
1268 } | 1474 } |
1269 | 1475 |
1270 | 1476 |
1271 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1477 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
1272 if (kind_ == Code::KEYED_CALL_IC) { | 1478 if (kind_ == Code::KEYED_CALL_IC) { |
1273 __ cmp(ecx, Immediate(Handle<String>(name))); | 1479 __ cmp(ecx, Immediate(name)); |
1274 __ j(not_equal, miss); | 1480 __ j(not_equal, miss); |
1275 } | 1481 } |
1276 } | 1482 } |
1277 | 1483 |
1278 | 1484 |
1279 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1485 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
1280 JSObject* holder, | 1486 JSObject* holder, |
1281 String* name, | 1487 String* name, |
1282 Label* miss) { | 1488 Label* miss) { |
1283 ASSERT(holder->IsGlobalObject()); | 1489 ASSERT(holder->IsGlobalObject()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1532 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1327 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1533 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1328 __ j(not_equal, miss); | 1534 __ j(not_equal, miss); |
1329 } else { | 1535 } else { |
1330 __ cmp(edi, Immediate(Handle<JSFunction>(function))); | 1536 __ cmp(edi, Immediate(Handle<JSFunction>(function))); |
1331 __ j(not_equal, miss); | 1537 __ j(not_equal, miss); |
1332 } | 1538 } |
1333 } | 1539 } |
1334 | 1540 |
1335 | 1541 |
1336 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1542 void CallStubCompiler::GenerateMissBranch() { |
| 1543 Handle<Code> code = |
| 1544 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1545 kind_, |
| 1546 extra_state_); |
| 1547 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1548 } |
| 1549 |
| 1550 |
| 1551 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1552 // handlified. |
| 1553 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
1337 MaybeObject* maybe_obj = | 1554 MaybeObject* maybe_obj = |
1338 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | 1555 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
1339 kind_, | 1556 kind_, |
1340 extra_state_); | 1557 extra_state_); |
1341 Object* obj; | 1558 Object* obj; |
1342 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1559 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1343 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1560 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
1344 return obj; | 1561 return obj; |
1345 } | 1562 } |
1346 | 1563 |
1347 | 1564 |
1348 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1565 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1349 JSObject* object, | 1566 Handle<JSObject> holder, |
1350 JSObject* holder, | 1567 int index, |
1351 int index, | 1568 Handle<String> name) { |
1352 String* name) { | |
1353 // ----------- S t a t e ------------- | 1569 // ----------- S t a t e ------------- |
1354 // -- ecx : name | 1570 // -- ecx : name |
1355 // -- esp[0] : return address | 1571 // -- esp[0] : return address |
1356 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1572 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1357 // -- ... | 1573 // -- ... |
1358 // -- esp[(argc + 1) * 4] : receiver | 1574 // -- esp[(argc + 1) * 4] : receiver |
1359 // ----------------------------------- | 1575 // ----------------------------------- |
1360 Label miss; | 1576 Label miss; |
1361 | 1577 |
1362 GenerateNameCheck(name, &miss); | 1578 GenerateNameCheck(name, &miss); |
(...skipping 25 matching lines...) Expand all Loading... |
1388 | 1604 |
1389 // Invoke the function. | 1605 // Invoke the function. |
1390 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1606 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
1391 ? CALL_AS_FUNCTION | 1607 ? CALL_AS_FUNCTION |
1392 : CALL_AS_METHOD; | 1608 : CALL_AS_METHOD; |
1393 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 1609 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
1394 NullCallWrapper(), call_kind); | 1610 NullCallWrapper(), call_kind); |
1395 | 1611 |
1396 // Handle call cache miss. | 1612 // Handle call cache miss. |
1397 __ bind(&miss); | 1613 __ bind(&miss); |
1398 MaybeObject* maybe_result = GenerateMissBranch(); | 1614 GenerateMissBranch(); |
1399 if (maybe_result->IsFailure()) return maybe_result; | |
1400 | 1615 |
1401 // Return the generated code. | 1616 // Return the generated code. |
1402 return GetCode(FIELD, name); | 1617 return GetCode(FIELD, name); |
1403 } | 1618 } |
1404 | 1619 |
1405 | 1620 |
1406 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1621 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
1407 JSObject* holder, | 1622 JSObject* holder, |
1408 JSGlobalPropertyCell* cell, | 1623 JSGlobalPropertyCell* cell, |
1409 JSFunction* function, | 1624 JSFunction* function, |
1410 String* name) { | 1625 String* name) { |
1411 // ----------- S t a t e ------------- | 1626 // ----------- S t a t e ------------- |
1412 // -- ecx : name | 1627 // -- ecx : name |
1413 // -- esp[0] : return address | 1628 // -- esp[0] : return address |
1414 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1629 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1415 // -- ... | 1630 // -- ... |
1416 // -- esp[(argc + 1) * 4] : receiver | 1631 // -- esp[(argc + 1) * 4] : receiver |
1417 // ----------------------------------- | 1632 // ----------------------------------- |
1418 | 1633 |
1419 // If object is not an array, bail out to regular call. | 1634 // If object is not an array, bail out to regular call. |
1420 if (!object->IsJSArray() || cell != NULL) { | 1635 if (!object->IsJSArray() || cell != NULL) { |
1421 return isolate()->heap()->undefined_value(); | 1636 return isolate()->heap()->undefined_value(); |
1422 } | 1637 } |
1423 | 1638 |
1424 Label miss; | 1639 Label miss; |
1425 | 1640 |
1426 GenerateNameCheck(name, &miss); | 1641 GenerateNameCheck(Handle<String>(name), &miss); |
1427 | 1642 |
1428 // Get the receiver from the stack. | 1643 // Get the receiver from the stack. |
1429 const int argc = arguments().immediate(); | 1644 const int argc = arguments().immediate(); |
1430 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1645 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1431 | 1646 |
1432 // Check that the receiver isn't a smi. | 1647 // Check that the receiver isn't a smi. |
1433 __ JumpIfSmi(edx, &miss); | 1648 __ JumpIfSmi(edx, &miss); |
1434 | 1649 |
1435 CheckPrototypes(JSObject::cast(object), edx, | 1650 CheckPrototypes(JSObject::cast(object), edx, |
1436 holder, ebx, | 1651 holder, ebx, |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 } | 1788 } |
1574 | 1789 |
1575 __ bind(&call_builtin); | 1790 __ bind(&call_builtin); |
1576 __ TailCallExternalReference( | 1791 __ TailCallExternalReference( |
1577 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1792 ExternalReference(Builtins::c_ArrayPush, isolate()), |
1578 argc + 1, | 1793 argc + 1, |
1579 1); | 1794 1); |
1580 } | 1795 } |
1581 | 1796 |
1582 __ bind(&miss); | 1797 __ bind(&miss); |
1583 MaybeObject* maybe_result = GenerateMissBranch(); | 1798 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1584 if (maybe_result->IsFailure()) return maybe_result; | 1799 if (maybe_result->IsFailure()) return maybe_result; |
1585 | 1800 |
1586 // Return the generated code. | 1801 // Return the generated code. |
1587 return GetCode(function); | 1802 return TryGetCode(function); |
1588 } | 1803 } |
1589 | 1804 |
1590 | 1805 |
1591 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1806 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
1592 JSObject* holder, | 1807 JSObject* holder, |
1593 JSGlobalPropertyCell* cell, | 1808 JSGlobalPropertyCell* cell, |
1594 JSFunction* function, | 1809 JSFunction* function, |
1595 String* name) { | 1810 String* name) { |
1596 // ----------- S t a t e ------------- | 1811 // ----------- S t a t e ------------- |
1597 // -- ecx : name | 1812 // -- ecx : name |
1598 // -- esp[0] : return address | 1813 // -- esp[0] : return address |
1599 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1814 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1600 // -- ... | 1815 // -- ... |
1601 // -- esp[(argc + 1) * 4] : receiver | 1816 // -- esp[(argc + 1) * 4] : receiver |
1602 // ----------------------------------- | 1817 // ----------------------------------- |
1603 | 1818 |
1604 // If object is not an array, bail out to regular call. | 1819 // If object is not an array, bail out to regular call. |
1605 if (!object->IsJSArray() || cell != NULL) { | 1820 if (!object->IsJSArray() || cell != NULL) { |
1606 return heap()->undefined_value(); | 1821 return heap()->undefined_value(); |
1607 } | 1822 } |
1608 | 1823 |
1609 Label miss, return_undefined, call_builtin; | 1824 Label miss, return_undefined, call_builtin; |
1610 | 1825 |
1611 GenerateNameCheck(name, &miss); | 1826 GenerateNameCheck(Handle<String>(name), &miss); |
1612 | 1827 |
1613 // Get the receiver from the stack. | 1828 // Get the receiver from the stack. |
1614 const int argc = arguments().immediate(); | 1829 const int argc = arguments().immediate(); |
1615 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1830 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1616 | 1831 |
1617 // Check that the receiver isn't a smi. | 1832 // Check that the receiver isn't a smi. |
1618 __ JumpIfSmi(edx, &miss); | 1833 __ JumpIfSmi(edx, &miss); |
1619 CheckPrototypes(JSObject::cast(object), edx, | 1834 CheckPrototypes(JSObject::cast(object), edx, |
1620 holder, ebx, | 1835 holder, ebx, |
1621 eax, edi, name, &miss); | 1836 eax, edi, name, &miss); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1656 __ mov(eax, Immediate(factory()->undefined_value())); | 1871 __ mov(eax, Immediate(factory()->undefined_value())); |
1657 __ ret((argc + 1) * kPointerSize); | 1872 __ ret((argc + 1) * kPointerSize); |
1658 | 1873 |
1659 __ bind(&call_builtin); | 1874 __ bind(&call_builtin); |
1660 __ TailCallExternalReference( | 1875 __ TailCallExternalReference( |
1661 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1876 ExternalReference(Builtins::c_ArrayPop, isolate()), |
1662 argc + 1, | 1877 argc + 1, |
1663 1); | 1878 1); |
1664 | 1879 |
1665 __ bind(&miss); | 1880 __ bind(&miss); |
1666 MaybeObject* maybe_result = GenerateMissBranch(); | 1881 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1667 if (maybe_result->IsFailure()) return maybe_result; | 1882 if (maybe_result->IsFailure()) return maybe_result; |
1668 | 1883 |
1669 // Return the generated code. | 1884 // Return the generated code. |
1670 return GetCode(function); | 1885 return TryGetCode(function); |
1671 } | 1886 } |
1672 | 1887 |
1673 | 1888 |
1674 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1889 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
1675 Object* object, | 1890 Object* object, |
1676 JSObject* holder, | 1891 JSObject* holder, |
1677 JSGlobalPropertyCell* cell, | 1892 JSGlobalPropertyCell* cell, |
1678 JSFunction* function, | 1893 JSFunction* function, |
1679 String* name) { | 1894 String* name) { |
1680 // ----------- S t a t e ------------- | 1895 // ----------- S t a t e ------------- |
(...skipping 15 matching lines...) Expand all Loading... |
1696 Label name_miss; | 1911 Label name_miss; |
1697 Label index_out_of_range; | 1912 Label index_out_of_range; |
1698 Label* index_out_of_range_label = &index_out_of_range; | 1913 Label* index_out_of_range_label = &index_out_of_range; |
1699 | 1914 |
1700 if (kind_ == Code::CALL_IC && | 1915 if (kind_ == Code::CALL_IC && |
1701 (CallICBase::StringStubState::decode(extra_state_) == | 1916 (CallICBase::StringStubState::decode(extra_state_) == |
1702 DEFAULT_STRING_STUB)) { | 1917 DEFAULT_STRING_STUB)) { |
1703 index_out_of_range_label = &miss; | 1918 index_out_of_range_label = &miss; |
1704 } | 1919 } |
1705 | 1920 |
1706 GenerateNameCheck(name, &name_miss); | 1921 GenerateNameCheck(Handle<String>(name), &name_miss); |
1707 | 1922 |
1708 // Check that the maps starting from the prototype haven't changed. | 1923 // Check that the maps starting from the prototype haven't changed. |
1709 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1924 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1710 Context::STRING_FUNCTION_INDEX, | 1925 Context::STRING_FUNCTION_INDEX, |
1711 eax, | 1926 eax, |
1712 &miss); | 1927 &miss); |
1713 ASSERT(object != holder); | 1928 ASSERT(object != holder); |
1714 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1929 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1715 ebx, edx, edi, name, &miss); | 1930 ebx, edx, edi, name, &miss); |
1716 | 1931 |
(...skipping 25 matching lines...) Expand all Loading... |
1742 if (index_out_of_range.is_linked()) { | 1957 if (index_out_of_range.is_linked()) { |
1743 __ bind(&index_out_of_range); | 1958 __ bind(&index_out_of_range); |
1744 __ Set(eax, Immediate(factory()->nan_value())); | 1959 __ Set(eax, Immediate(factory()->nan_value())); |
1745 __ ret((argc + 1) * kPointerSize); | 1960 __ ret((argc + 1) * kPointerSize); |
1746 } | 1961 } |
1747 | 1962 |
1748 __ bind(&miss); | 1963 __ bind(&miss); |
1749 // Restore function name in ecx. | 1964 // Restore function name in ecx. |
1750 __ Set(ecx, Immediate(Handle<String>(name))); | 1965 __ Set(ecx, Immediate(Handle<String>(name))); |
1751 __ bind(&name_miss); | 1966 __ bind(&name_miss); |
1752 MaybeObject* maybe_result = GenerateMissBranch(); | 1967 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1753 if (maybe_result->IsFailure()) return maybe_result; | 1968 if (maybe_result->IsFailure()) return maybe_result; |
1754 | 1969 |
1755 // Return the generated code. | 1970 // Return the generated code. |
1756 return GetCode(function); | 1971 return TryGetCode(function); |
1757 } | 1972 } |
1758 | 1973 |
1759 | 1974 |
1760 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1975 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
1761 Object* object, | 1976 Object* object, |
1762 JSObject* holder, | 1977 JSObject* holder, |
1763 JSGlobalPropertyCell* cell, | 1978 JSGlobalPropertyCell* cell, |
1764 JSFunction* function, | 1979 JSFunction* function, |
1765 String* name) { | 1980 String* name) { |
1766 // ----------- S t a t e ------------- | 1981 // ----------- S t a t e ------------- |
(...skipping 15 matching lines...) Expand all Loading... |
1782 Label name_miss; | 1997 Label name_miss; |
1783 Label index_out_of_range; | 1998 Label index_out_of_range; |
1784 Label* index_out_of_range_label = &index_out_of_range; | 1999 Label* index_out_of_range_label = &index_out_of_range; |
1785 | 2000 |
1786 if (kind_ == Code::CALL_IC && | 2001 if (kind_ == Code::CALL_IC && |
1787 (CallICBase::StringStubState::decode(extra_state_) == | 2002 (CallICBase::StringStubState::decode(extra_state_) == |
1788 DEFAULT_STRING_STUB)) { | 2003 DEFAULT_STRING_STUB)) { |
1789 index_out_of_range_label = &miss; | 2004 index_out_of_range_label = &miss; |
1790 } | 2005 } |
1791 | 2006 |
1792 GenerateNameCheck(name, &name_miss); | 2007 GenerateNameCheck(Handle<String>(name), &name_miss); |
1793 | 2008 |
1794 // Check that the maps starting from the prototype haven't changed. | 2009 // Check that the maps starting from the prototype haven't changed. |
1795 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2010 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1796 Context::STRING_FUNCTION_INDEX, | 2011 Context::STRING_FUNCTION_INDEX, |
1797 eax, | 2012 eax, |
1798 &miss); | 2013 &miss); |
1799 ASSERT(object != holder); | 2014 ASSERT(object != holder); |
1800 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2015 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1801 ebx, edx, edi, name, &miss); | 2016 ebx, edx, edi, name, &miss); |
1802 | 2017 |
(...skipping 27 matching lines...) Expand all Loading... |
1830 if (index_out_of_range.is_linked()) { | 2045 if (index_out_of_range.is_linked()) { |
1831 __ bind(&index_out_of_range); | 2046 __ bind(&index_out_of_range); |
1832 __ Set(eax, Immediate(factory()->empty_string())); | 2047 __ Set(eax, Immediate(factory()->empty_string())); |
1833 __ ret((argc + 1) * kPointerSize); | 2048 __ ret((argc + 1) * kPointerSize); |
1834 } | 2049 } |
1835 | 2050 |
1836 __ bind(&miss); | 2051 __ bind(&miss); |
1837 // Restore function name in ecx. | 2052 // Restore function name in ecx. |
1838 __ Set(ecx, Immediate(Handle<String>(name))); | 2053 __ Set(ecx, Immediate(Handle<String>(name))); |
1839 __ bind(&name_miss); | 2054 __ bind(&name_miss); |
1840 MaybeObject* maybe_result = GenerateMissBranch(); | 2055 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1841 if (maybe_result->IsFailure()) return maybe_result; | 2056 if (maybe_result->IsFailure()) return maybe_result; |
1842 | 2057 |
1843 // Return the generated code. | 2058 // Return the generated code. |
1844 return GetCode(function); | 2059 return TryGetCode(function); |
1845 } | 2060 } |
1846 | 2061 |
1847 | 2062 |
1848 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2063 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
1849 Object* object, | 2064 Object* object, |
1850 JSObject* holder, | 2065 JSObject* holder, |
1851 JSGlobalPropertyCell* cell, | 2066 JSGlobalPropertyCell* cell, |
1852 JSFunction* function, | 2067 JSFunction* function, |
1853 String* name) { | 2068 String* name) { |
1854 // ----------- S t a t e ------------- | 2069 // ----------- S t a t e ------------- |
1855 // -- ecx : function name | 2070 // -- ecx : function name |
1856 // -- esp[0] : return address | 2071 // -- esp[0] : return address |
1857 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2072 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1858 // -- ... | 2073 // -- ... |
1859 // -- esp[(argc + 1) * 4] : receiver | 2074 // -- esp[(argc + 1) * 4] : receiver |
1860 // ----------------------------------- | 2075 // ----------------------------------- |
1861 | 2076 |
1862 const int argc = arguments().immediate(); | 2077 const int argc = arguments().immediate(); |
1863 | 2078 |
1864 // If the object is not a JSObject or we got an unexpected number of | 2079 // If the object is not a JSObject or we got an unexpected number of |
1865 // arguments, bail out to the regular call. | 2080 // arguments, bail out to the regular call. |
1866 if (!object->IsJSObject() || argc != 1) { | 2081 if (!object->IsJSObject() || argc != 1) { |
1867 return isolate()->heap()->undefined_value(); | 2082 return isolate()->heap()->undefined_value(); |
1868 } | 2083 } |
1869 | 2084 |
1870 Label miss; | 2085 Label miss; |
1871 GenerateNameCheck(name, &miss); | 2086 GenerateNameCheck(Handle<String>(name), &miss); |
1872 | 2087 |
1873 if (cell == NULL) { | 2088 if (cell == NULL) { |
1874 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2089 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1875 | 2090 |
1876 STATIC_ASSERT(kSmiTag == 0); | 2091 STATIC_ASSERT(kSmiTag == 0); |
1877 __ JumpIfSmi(edx, &miss); | 2092 __ JumpIfSmi(edx, &miss); |
1878 | 2093 |
1879 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2094 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1880 &miss); | 2095 &miss); |
1881 } else { | 2096 } else { |
(...skipping 25 matching lines...) Expand all Loading... |
1907 // because the function makes no use of it. | 2122 // because the function makes no use of it. |
1908 __ bind(&slow); | 2123 __ bind(&slow); |
1909 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2124 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
1910 ? CALL_AS_FUNCTION | 2125 ? CALL_AS_FUNCTION |
1911 : CALL_AS_METHOD; | 2126 : CALL_AS_METHOD; |
1912 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2127 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
1913 NullCallWrapper(), call_kind); | 2128 NullCallWrapper(), call_kind); |
1914 | 2129 |
1915 __ bind(&miss); | 2130 __ bind(&miss); |
1916 // ecx: function name. | 2131 // ecx: function name. |
1917 MaybeObject* maybe_result = GenerateMissBranch(); | 2132 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1918 if (maybe_result->IsFailure()) return maybe_result; | 2133 if (maybe_result->IsFailure()) return maybe_result; |
1919 | 2134 |
1920 // Return the generated code. | 2135 // Return the generated code. |
1921 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2136 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
1922 } | 2137 } |
1923 | 2138 |
1924 | 2139 |
1925 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2140 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
1926 JSObject* holder, | 2141 JSObject* holder, |
1927 JSGlobalPropertyCell* cell, | 2142 JSGlobalPropertyCell* cell, |
1928 JSFunction* function, | 2143 JSFunction* function, |
1929 String* name) { | 2144 String* name) { |
1930 // ----------- S t a t e ------------- | 2145 // ----------- S t a t e ------------- |
1931 // -- ecx : name | 2146 // -- ecx : name |
(...skipping 11 matching lines...) Expand all Loading... |
1943 | 2158 |
1944 const int argc = arguments().immediate(); | 2159 const int argc = arguments().immediate(); |
1945 | 2160 |
1946 // If the object is not a JSObject or we got an unexpected number of | 2161 // If the object is not a JSObject or we got an unexpected number of |
1947 // arguments, bail out to the regular call. | 2162 // arguments, bail out to the regular call. |
1948 if (!object->IsJSObject() || argc != 1) { | 2163 if (!object->IsJSObject() || argc != 1) { |
1949 return isolate()->heap()->undefined_value(); | 2164 return isolate()->heap()->undefined_value(); |
1950 } | 2165 } |
1951 | 2166 |
1952 Label miss; | 2167 Label miss; |
1953 GenerateNameCheck(name, &miss); | 2168 GenerateNameCheck(Handle<String>(name), &miss); |
1954 | 2169 |
1955 if (cell == NULL) { | 2170 if (cell == NULL) { |
1956 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2171 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1957 | 2172 |
1958 STATIC_ASSERT(kSmiTag == 0); | 2173 STATIC_ASSERT(kSmiTag == 0); |
1959 __ JumpIfSmi(edx, &miss); | 2174 __ JumpIfSmi(edx, &miss); |
1960 | 2175 |
1961 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2176 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1962 &miss); | 2177 &miss); |
1963 } else { | 2178 } else { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2036 __ ret(2 * kPointerSize); | 2251 __ ret(2 * kPointerSize); |
2037 | 2252 |
2038 // Tail call the full function. We do not have to patch the receiver | 2253 // Tail call the full function. We do not have to patch the receiver |
2039 // because the function makes no use of it. | 2254 // because the function makes no use of it. |
2040 __ bind(&slow); | 2255 __ bind(&slow); |
2041 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2256 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2042 NullCallWrapper(), CALL_AS_METHOD); | 2257 NullCallWrapper(), CALL_AS_METHOD); |
2043 | 2258 |
2044 __ bind(&miss); | 2259 __ bind(&miss); |
2045 // ecx: function name. | 2260 // ecx: function name. |
2046 MaybeObject* maybe_result = GenerateMissBranch(); | 2261 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2047 if (maybe_result->IsFailure()) return maybe_result; | 2262 if (maybe_result->IsFailure()) return maybe_result; |
2048 | 2263 |
2049 // Return the generated code. | 2264 // Return the generated code. |
2050 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2265 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
2051 } | 2266 } |
2052 | 2267 |
2053 | 2268 |
2054 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2269 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
2055 JSObject* holder, | 2270 JSObject* holder, |
2056 JSGlobalPropertyCell* cell, | 2271 JSGlobalPropertyCell* cell, |
2057 JSFunction* function, | 2272 JSFunction* function, |
2058 String* name) { | 2273 String* name) { |
2059 // ----------- S t a t e ------------- | 2274 // ----------- S t a t e ------------- |
2060 // -- ecx : name | 2275 // -- ecx : name |
2061 // -- esp[0] : return address | 2276 // -- esp[0] : return address |
2062 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2277 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2063 // -- ... | 2278 // -- ... |
2064 // -- esp[(argc + 1) * 4] : receiver | 2279 // -- esp[(argc + 1) * 4] : receiver |
2065 // ----------------------------------- | 2280 // ----------------------------------- |
2066 | 2281 |
2067 const int argc = arguments().immediate(); | 2282 const int argc = arguments().immediate(); |
2068 | 2283 |
2069 // If the object is not a JSObject or we got an unexpected number of | 2284 // If the object is not a JSObject or we got an unexpected number of |
2070 // arguments, bail out to the regular call. | 2285 // arguments, bail out to the regular call. |
2071 if (!object->IsJSObject() || argc != 1) { | 2286 if (!object->IsJSObject() || argc != 1) { |
2072 return isolate()->heap()->undefined_value(); | 2287 return isolate()->heap()->undefined_value(); |
2073 } | 2288 } |
2074 | 2289 |
2075 Label miss; | 2290 Label miss; |
2076 GenerateNameCheck(name, &miss); | 2291 GenerateNameCheck(Handle<String>(name), &miss); |
2077 | 2292 |
2078 if (cell == NULL) { | 2293 if (cell == NULL) { |
2079 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2294 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2080 | 2295 |
2081 STATIC_ASSERT(kSmiTag == 0); | 2296 STATIC_ASSERT(kSmiTag == 0); |
2082 __ JumpIfSmi(edx, &miss); | 2297 __ JumpIfSmi(edx, &miss); |
2083 | 2298 |
2084 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2299 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
2085 &miss); | 2300 &miss); |
2086 } else { | 2301 } else { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2140 __ ret(2 * kPointerSize); | 2355 __ ret(2 * kPointerSize); |
2141 | 2356 |
2142 // Tail call the full function. We do not have to patch the receiver | 2357 // Tail call the full function. We do not have to patch the receiver |
2143 // because the function makes no use of it. | 2358 // because the function makes no use of it. |
2144 __ bind(&slow); | 2359 __ bind(&slow); |
2145 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2360 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2146 NullCallWrapper(), CALL_AS_METHOD); | 2361 NullCallWrapper(), CALL_AS_METHOD); |
2147 | 2362 |
2148 __ bind(&miss); | 2363 __ bind(&miss); |
2149 // ecx: function name. | 2364 // ecx: function name. |
2150 MaybeObject* maybe_result = GenerateMissBranch(); | 2365 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2151 if (maybe_result->IsFailure()) return maybe_result; | 2366 if (maybe_result->IsFailure()) return maybe_result; |
2152 | 2367 |
2153 // Return the generated code. | 2368 // Return the generated code. |
2154 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2369 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
2155 } | 2370 } |
2156 | 2371 |
2157 | 2372 |
2158 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2373 MaybeObject* CallStubCompiler::CompileFastApiCall( |
2159 const CallOptimization& optimization, | 2374 const CallOptimization& optimization, |
2160 Object* object, | 2375 Object* object, |
2161 JSObject* holder, | 2376 JSObject* holder, |
2162 JSGlobalPropertyCell* cell, | 2377 JSGlobalPropertyCell* cell, |
2163 JSFunction* function, | 2378 JSFunction* function, |
2164 String* name) { | 2379 String* name) { |
2165 ASSERT(optimization.is_simple_api_call()); | 2380 ASSERT(optimization.is_simple_api_call()); |
2166 // Bail out if object is a global object as we don't want to | 2381 // Bail out if object is a global object as we don't want to |
2167 // repatch it to global receiver. | 2382 // repatch it to global receiver. |
2168 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2383 if (object->IsGlobalObject()) return heap()->undefined_value(); |
2169 if (cell != NULL) return heap()->undefined_value(); | 2384 if (cell != NULL) return heap()->undefined_value(); |
2170 if (!object->IsJSObject()) return heap()->undefined_value(); | 2385 if (!object->IsJSObject()) return heap()->undefined_value(); |
2171 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2386 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2172 JSObject::cast(object), holder); | 2387 JSObject::cast(object), holder); |
2173 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2388 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
2174 | 2389 |
2175 Label miss, miss_before_stack_reserved; | 2390 Label miss, miss_before_stack_reserved; |
2176 | 2391 |
2177 GenerateNameCheck(name, &miss_before_stack_reserved); | 2392 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
2178 | 2393 |
2179 // Get the receiver from the stack. | 2394 // Get the receiver from the stack. |
2180 const int argc = arguments().immediate(); | 2395 const int argc = arguments().immediate(); |
2181 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2396 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2182 | 2397 |
2183 // Check that the receiver isn't a smi. | 2398 // Check that the receiver isn't a smi. |
2184 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2399 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
2185 | 2400 |
2186 Counters* counters = isolate()->counters(); | 2401 Counters* counters = isolate()->counters(); |
2187 __ IncrementCounter(counters->call_const(), 1); | 2402 __ IncrementCounter(counters->call_const(), 1); |
(...skipping 13 matching lines...) Expand all Loading... |
2201 | 2416 |
2202 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2417 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2203 // duplicate of return address and will be overwritten. | 2418 // duplicate of return address and will be overwritten. |
2204 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2419 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
2205 if (result->IsFailure()) return result; | 2420 if (result->IsFailure()) return result; |
2206 | 2421 |
2207 __ bind(&miss); | 2422 __ bind(&miss); |
2208 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2423 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2209 | 2424 |
2210 __ bind(&miss_before_stack_reserved); | 2425 __ bind(&miss_before_stack_reserved); |
2211 MaybeObject* maybe_result = GenerateMissBranch(); | 2426 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2212 if (maybe_result->IsFailure()) return maybe_result; | 2427 if (maybe_result->IsFailure()) return maybe_result; |
2213 | 2428 |
2214 // Return the generated code. | 2429 // Return the generated code. |
2215 return GetCode(function); | 2430 return TryGetCode(function); |
2216 } | 2431 } |
2217 | 2432 |
2218 | 2433 |
2219 MaybeObject* CallStubCompiler::CompileCallConstant( | 2434 MaybeObject* CallStubCompiler::CompileCallConstant( |
2220 Object* object, | 2435 Object* object, |
2221 JSObject* holder, | 2436 JSObject* holder, |
2222 JSFunction* function, | 2437 JSFunction* function, |
2223 String* name, | 2438 String* name, |
2224 CheckType check) { | 2439 CheckType check) { |
2225 // ----------- S t a t e ------------- | 2440 // ----------- S t a t e ------------- |
2226 // -- ecx : name | 2441 // -- ecx : name |
2227 // -- esp[0] : return address | 2442 // -- esp[0] : return address |
2228 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2443 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2229 // -- ... | 2444 // -- ... |
2230 // -- esp[(argc + 1) * 4] : receiver | 2445 // -- esp[(argc + 1) * 4] : receiver |
2231 // ----------------------------------- | 2446 // ----------------------------------- |
2232 | 2447 |
2233 if (HasCustomCallGenerator(function)) { | 2448 if (HasCustomCallGenerator(function)) { |
2234 MaybeObject* maybe_result = CompileCustomCall( | 2449 MaybeObject* maybe_result = CompileCustomCall( |
2235 object, holder, NULL, function, name); | 2450 object, holder, NULL, function, name); |
2236 Object* result; | 2451 Object* result; |
2237 if (!maybe_result->ToObject(&result)) return maybe_result; | 2452 if (!maybe_result->ToObject(&result)) return maybe_result; |
2238 // undefined means bail out to regular compiler. | 2453 // undefined means bail out to regular compiler. |
2239 if (!result->IsUndefined()) return result; | 2454 if (!result->IsUndefined()) return result; |
2240 } | 2455 } |
2241 | 2456 |
2242 Label miss; | 2457 Label miss; |
2243 | 2458 |
2244 GenerateNameCheck(name, &miss); | 2459 GenerateNameCheck(Handle<String>(name), &miss); |
2245 | 2460 |
2246 // Get the receiver from the stack. | 2461 // Get the receiver from the stack. |
2247 const int argc = arguments().immediate(); | 2462 const int argc = arguments().immediate(); |
2248 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2463 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2249 | 2464 |
2250 // Check that the receiver isn't a smi. | 2465 // Check that the receiver isn't a smi. |
2251 if (check != NUMBER_CHECK) { | 2466 if (check != NUMBER_CHECK) { |
2252 __ JumpIfSmi(edx, &miss); | 2467 __ JumpIfSmi(edx, &miss); |
2253 } | 2468 } |
2254 | 2469 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2338 } | 2553 } |
2339 | 2554 |
2340 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2555 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2341 ? CALL_AS_FUNCTION | 2556 ? CALL_AS_FUNCTION |
2342 : CALL_AS_METHOD; | 2557 : CALL_AS_METHOD; |
2343 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2558 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2344 NullCallWrapper(), call_kind); | 2559 NullCallWrapper(), call_kind); |
2345 | 2560 |
2346 // Handle call cache miss. | 2561 // Handle call cache miss. |
2347 __ bind(&miss); | 2562 __ bind(&miss); |
2348 MaybeObject* maybe_result = GenerateMissBranch(); | 2563 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2349 if (maybe_result->IsFailure()) return maybe_result; | 2564 if (maybe_result->IsFailure()) return maybe_result; |
2350 | 2565 |
2351 // Return the generated code. | 2566 // Return the generated code. |
2352 return GetCode(function); | 2567 return TryGetCode(function); |
2353 } | 2568 } |
2354 | 2569 |
2355 | 2570 |
2356 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2571 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
2357 JSObject* holder, | 2572 JSObject* holder, |
2358 String* name) { | 2573 String* name) { |
2359 // ----------- S t a t e ------------- | 2574 // ----------- S t a t e ------------- |
2360 // -- ecx : name | 2575 // -- ecx : name |
2361 // -- esp[0] : return address | 2576 // -- esp[0] : return address |
2362 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2577 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2363 // -- ... | 2578 // -- ... |
2364 // -- esp[(argc + 1) * 4] : receiver | 2579 // -- esp[(argc + 1) * 4] : receiver |
2365 // ----------------------------------- | 2580 // ----------------------------------- |
2366 Label miss; | 2581 Label miss; |
2367 | 2582 |
2368 GenerateNameCheck(name, &miss); | 2583 GenerateNameCheck(Handle<String>(name), &miss); |
2369 | 2584 |
2370 // Get the number of arguments. | 2585 // Get the number of arguments. |
2371 const int argc = arguments().immediate(); | 2586 const int argc = arguments().immediate(); |
2372 | 2587 |
2373 LookupResult lookup(isolate()); | 2588 LookupResult lookup(isolate()); |
2374 LookupPostInterceptor(holder, name, &lookup); | 2589 LookupPostInterceptor(holder, name, &lookup); |
2375 | 2590 |
2376 // Get the receiver from the stack. | 2591 // Get the receiver from the stack. |
2377 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2592 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2378 | 2593 |
(...skipping 28 matching lines...) Expand all Loading... |
2407 // Invoke the function. | 2622 // Invoke the function. |
2408 __ mov(edi, eax); | 2623 __ mov(edi, eax); |
2409 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2624 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2410 ? CALL_AS_FUNCTION | 2625 ? CALL_AS_FUNCTION |
2411 : CALL_AS_METHOD; | 2626 : CALL_AS_METHOD; |
2412 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2627 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
2413 NullCallWrapper(), call_kind); | 2628 NullCallWrapper(), call_kind); |
2414 | 2629 |
2415 // Handle load cache miss. | 2630 // Handle load cache miss. |
2416 __ bind(&miss); | 2631 __ bind(&miss); |
2417 MaybeObject* maybe_result = GenerateMissBranch(); | 2632 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2418 if (maybe_result->IsFailure()) return maybe_result; | 2633 if (maybe_result->IsFailure()) return maybe_result; |
2419 | 2634 |
2420 // Return the generated code. | 2635 // Return the generated code. |
2421 return GetCode(INTERCEPTOR, name); | 2636 return TryGetCode(INTERCEPTOR, name); |
2422 } | 2637 } |
2423 | 2638 |
2424 | 2639 |
2425 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2640 MaybeObject* CallStubCompiler::CompileCallGlobal( |
2426 JSObject* object, | 2641 JSObject* object, |
2427 GlobalObject* holder, | 2642 GlobalObject* holder, |
2428 JSGlobalPropertyCell* cell, | 2643 JSGlobalPropertyCell* cell, |
2429 JSFunction* function, | 2644 JSFunction* function, |
2430 String* name) { | 2645 String* name) { |
2431 // ----------- S t a t e ------------- | 2646 // ----------- S t a t e ------------- |
2432 // -- ecx : name | 2647 // -- ecx : name |
2433 // -- esp[0] : return address | 2648 // -- esp[0] : return address |
2434 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2649 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2435 // -- ... | 2650 // -- ... |
2436 // -- esp[(argc + 1) * 4] : receiver | 2651 // -- esp[(argc + 1) * 4] : receiver |
2437 // ----------------------------------- | 2652 // ----------------------------------- |
2438 | 2653 |
2439 if (HasCustomCallGenerator(function)) { | 2654 if (HasCustomCallGenerator(function)) { |
2440 MaybeObject* maybe_result = CompileCustomCall( | 2655 MaybeObject* maybe_result = CompileCustomCall( |
2441 object, holder, cell, function, name); | 2656 object, holder, cell, function, name); |
2442 Object* result; | 2657 Object* result; |
2443 if (!maybe_result->ToObject(&result)) return maybe_result; | 2658 if (!maybe_result->ToObject(&result)) return maybe_result; |
2444 // undefined means bail out to regular compiler. | 2659 // undefined means bail out to regular compiler. |
2445 if (!result->IsUndefined()) return result; | 2660 if (!result->IsUndefined()) return result; |
2446 } | 2661 } |
2447 | 2662 |
2448 Label miss; | 2663 Label miss; |
2449 | 2664 |
2450 GenerateNameCheck(name, &miss); | 2665 GenerateNameCheck(Handle<String>(name), &miss); |
2451 | 2666 |
2452 // Get the number of arguments. | 2667 // Get the number of arguments. |
2453 const int argc = arguments().immediate(); | 2668 const int argc = arguments().immediate(); |
2454 | 2669 |
2455 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2670 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2456 | 2671 |
2457 GenerateLoadFunctionFromCell(cell, function, &miss); | 2672 GenerateLoadFunctionFromCell(cell, function, &miss); |
2458 | 2673 |
2459 // Patch the receiver on the stack with the global proxy. | 2674 // Patch the receiver on the stack with the global proxy. |
2460 if (object->IsGlobalObject()) { | 2675 if (object->IsGlobalObject()) { |
(...skipping 14 matching lines...) Expand all Loading... |
2475 // We call indirectly through the code field in the function to | 2690 // We call indirectly through the code field in the function to |
2476 // allow recompilation to take effect without changing any of the | 2691 // allow recompilation to take effect without changing any of the |
2477 // call sites. | 2692 // call sites. |
2478 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2693 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2479 expected, arguments(), JUMP_FUNCTION, | 2694 expected, arguments(), JUMP_FUNCTION, |
2480 NullCallWrapper(), call_kind); | 2695 NullCallWrapper(), call_kind); |
2481 | 2696 |
2482 // Handle call cache miss. | 2697 // Handle call cache miss. |
2483 __ bind(&miss); | 2698 __ bind(&miss); |
2484 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2699 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
2485 MaybeObject* maybe_result = GenerateMissBranch(); | 2700 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2486 if (maybe_result->IsFailure()) return maybe_result; | 2701 if (maybe_result->IsFailure()) return maybe_result; |
2487 | 2702 |
2488 // Return the generated code. | 2703 // Return the generated code. |
2489 return GetCode(NORMAL, name); | 2704 return TryGetCode(NORMAL, name); |
2490 } | 2705 } |
2491 | 2706 |
2492 | 2707 |
2493 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2708 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, |
2494 int index, | 2709 int index, |
2495 Map* transition, | 2710 Map* transition, |
2496 String* name) { | 2711 String* name) { |
2497 // ----------- S t a t e ------------- | 2712 // ----------- S t a t e ------------- |
2498 // -- eax : value | 2713 // -- eax : value |
2499 // -- ecx : name | 2714 // -- ecx : name |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2797 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 3012 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2798 | 3013 |
2799 // Check the maps of the full prototype chain. Also check that | 3014 // Check the maps of the full prototype chain. Also check that |
2800 // global property cells up to (but not including) the last object | 3015 // global property cells up to (but not including) the last object |
2801 // in the prototype chain are empty. | 3016 // in the prototype chain are empty. |
2802 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 3017 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2803 | 3018 |
2804 // If the last object in the prototype chain is a global object, | 3019 // If the last object in the prototype chain is a global object, |
2805 // check that the global property cell is empty. | 3020 // check that the global property cell is empty. |
2806 if (last->IsGlobalObject()) { | 3021 if (last->IsGlobalObject()) { |
2807 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 3022 MaybeObject* cell = TryGenerateCheckPropertyCell(masm(), |
2808 GlobalObject::cast(last), | 3023 GlobalObject::cast(last), |
2809 name, | 3024 name, |
2810 edx, | 3025 edx, |
2811 &miss); | 3026 &miss); |
2812 if (cell->IsFailure()) { | 3027 if (cell->IsFailure()) { |
2813 miss.Unuse(); | 3028 miss.Unuse(); |
2814 return cell; | 3029 return cell; |
2815 } | 3030 } |
2816 } | 3031 } |
2817 | 3032 |
2818 // Return undefined if maps of the full prototype chain are still the | 3033 // Return undefined if maps of the full prototype chain are still the |
2819 // same and no global property with this name contains a value. | 3034 // same and no global property with this name contains a value. |
2820 __ mov(eax, isolate()->factory()->undefined_value()); | 3035 __ mov(eax, isolate()->factory()->undefined_value()); |
2821 __ ret(0); | 3036 __ ret(0); |
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4016 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4231 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
4017 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4232 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
4018 } | 4233 } |
4019 | 4234 |
4020 | 4235 |
4021 #undef __ | 4236 #undef __ |
4022 | 4237 |
4023 } } // namespace v8::internal | 4238 } } // namespace v8::internal |
4024 | 4239 |
4025 #endif // V8_TARGET_ARCH_IA32 | 4240 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |