OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ic/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 Node* instance_type, Node* key, | 1149 Node* instance_type, Node* key, |
1150 const LoadICParameters* p, | 1150 const LoadICParameters* p, |
1151 Label* slow) { | 1151 Label* slow) { |
1152 Comment("key is unique name"); | 1152 Comment("key is unique name"); |
1153 Label if_found_on_receiver(this), if_property_dictionary(this), | 1153 Label if_found_on_receiver(this), if_property_dictionary(this), |
1154 lookup_prototype_chain(this); | 1154 lookup_prototype_chain(this); |
1155 Variable var_details(this, MachineRepresentation::kWord32); | 1155 Variable var_details(this, MachineRepresentation::kWord32); |
1156 Variable var_value(this, MachineRepresentation::kTagged); | 1156 Variable var_value(this, MachineRepresentation::kTagged); |
1157 | 1157 |
1158 // Receivers requiring non-standard accesses (interceptors, access | 1158 // Receivers requiring non-standard accesses (interceptors, access |
1159 // checks, string wrappers, proxies) are handled in the runtime. | 1159 // checks, strings and string wrappers, proxies) are handled in the runtime. |
1160 // We special-case strings here, to support loading <Symbol.split> etc. | 1160 GotoIf(Int32LessThanOrEqual(instance_type, |
1161 Variable var_receiver(this, MachineRepresentation::kTagged); | 1161 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
1162 Variable var_receiver_map(this, MachineRepresentation::kTagged); | |
1163 Variable var_instance_type(this, MachineRepresentation::kWord32); | |
1164 var_receiver.Bind(receiver); | |
1165 var_receiver_map.Bind(receiver_map); | |
1166 var_instance_type.Bind(instance_type); | |
1167 Label normal_receiver(this); | |
1168 GotoIf(Int32GreaterThan(instance_type, | |
1169 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | |
1170 &normal_receiver); | |
1171 GotoIf(Int32GreaterThanOrEqual(instance_type, | |
1172 Int32Constant(FIRST_NONSTRING_TYPE)), | |
1173 slow); | 1162 slow); |
1174 CSA_ASSERT(this, WordEqual(LoadMapConstructorFunctionIndex(receiver_map), | |
1175 IntPtrConstant(Context::STRING_FUNCTION_INDEX))); | |
1176 Node* native_context = LoadNativeContext(p->context); | |
1177 Node* constructor_function = | |
1178 LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX); | |
1179 Node* initial_map = LoadObjectField(constructor_function, | |
1180 JSFunction::kPrototypeOrInitialMapOffset); | |
1181 var_receiver.Bind(LoadMapPrototype(initial_map)); | |
1182 var_receiver_map.Bind(LoadMap(var_receiver.value())); | |
1183 var_instance_type.Bind(LoadMapInstanceType(var_receiver_map.value())); | |
1184 Goto(&normal_receiver); | |
1185 | 1163 |
1186 Bind(&normal_receiver); | |
1187 receiver = var_receiver.value(); | |
1188 receiver_map = var_receiver_map.value(); | |
1189 instance_type = var_instance_type.value(); | |
1190 // Check if the receiver has fast or slow properties. | 1164 // Check if the receiver has fast or slow properties. |
1191 Node* properties = LoadProperties(receiver); | 1165 Node* properties = LoadProperties(receiver); |
1192 Node* properties_map = LoadMap(properties); | 1166 Node* properties_map = LoadMap(properties); |
1193 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), | 1167 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), |
1194 &if_property_dictionary); | 1168 &if_property_dictionary); |
1195 | 1169 |
1196 // Try looking up the property on the receiver; if unsuccessful, look | 1170 // Try looking up the property on the receiver; if unsuccessful, look |
1197 // for a handler in the stub cache. | 1171 // for a handler in the stub cache. |
1198 Comment("DescriptorArray lookup"); | 1172 Comment("DescriptorArray lookup"); |
1199 | 1173 |
1200 // Skip linear search if there are too many descriptors. | 1174 // Skip linear search if there are too many descriptors. |
1201 // TODO(jkummerow): Consider implementing binary search. | 1175 // TODO(jkummerow): Consider implementing binary search. |
1202 // See also TryLookupProperty() which has the same limitation. | 1176 // See also TryLookupProperty() which has the same limitation. |
1203 const int32_t kMaxLinear = 210; | 1177 const int32_t kMaxLinear = 210; |
1204 Label stub_cache(this); | 1178 Label stub_cache(this); |
1205 Node* bitfield3 = LoadMapBitField3(var_receiver_map.value()); | 1179 Node* bitfield3 = LoadMapBitField3(receiver_map); |
1206 Node* nof = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); | 1180 Node* nof = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); |
1207 GotoIf(UintPtrLessThan(IntPtrConstant(kMaxLinear), nof), &stub_cache); | 1181 GotoIf(UintPtrLessThan(IntPtrConstant(kMaxLinear), nof), &stub_cache); |
1208 Node* descriptors = LoadMapDescriptors(var_receiver_map.value()); | 1182 Node* descriptors = LoadMapDescriptors(receiver_map); |
1209 Variable var_name_index(this, MachineType::PointerRepresentation()); | 1183 Variable var_name_index(this, MachineType::PointerRepresentation()); |
1210 Label if_descriptor_found(this); | 1184 Label if_descriptor_found(this); |
1211 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, | 1185 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, |
1212 &var_name_index, &stub_cache); | 1186 &var_name_index, &stub_cache); |
1213 | 1187 |
1214 Bind(&if_descriptor_found); | 1188 Bind(&if_descriptor_found); |
1215 { | 1189 { |
1216 LoadPropertyFromFastObject(receiver, var_receiver_map.value(), descriptors, | 1190 LoadPropertyFromFastObject(receiver, receiver_map, descriptors, |
1217 var_name_index.value(), &var_details, | 1191 var_name_index.value(), &var_details, |
1218 &var_value); | 1192 &var_value); |
1219 Goto(&if_found_on_receiver); | 1193 Goto(&if_found_on_receiver); |
1220 } | 1194 } |
1221 | 1195 |
1222 Bind(&stub_cache); | 1196 Bind(&stub_cache); |
1223 { | 1197 { |
1224 Comment("stub cache probe for fast property load"); | 1198 Comment("stub cache probe for fast property load"); |
1225 Variable var_handler(this, MachineRepresentation::kTagged); | 1199 Variable var_handler(this, MachineRepresentation::kTagged); |
1226 Label found_handler(this, &var_handler), stub_cache_miss(this); | 1200 Label found_handler(this, &var_handler), stub_cache_miss(this); |
(...skipping 27 matching lines...) Expand all Loading... |
1254 { | 1228 { |
1255 LoadPropertyFromNameDictionary(properties, var_name_index.value(), | 1229 LoadPropertyFromNameDictionary(properties, var_name_index.value(), |
1256 &var_details, &var_value); | 1230 &var_details, &var_value); |
1257 Goto(&if_found_on_receiver); | 1231 Goto(&if_found_on_receiver); |
1258 } | 1232 } |
1259 } | 1233 } |
1260 | 1234 |
1261 Bind(&if_found_on_receiver); | 1235 Bind(&if_found_on_receiver); |
1262 { | 1236 { |
1263 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(), | 1237 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(), |
1264 p->context, var_receiver.value(), slow); | 1238 p->context, receiver, slow); |
1265 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); | 1239 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); |
1266 Return(value); | 1240 Return(value); |
1267 } | 1241 } |
1268 | 1242 |
1269 Bind(&lookup_prototype_chain); | 1243 Bind(&lookup_prototype_chain); |
1270 { | 1244 { |
1271 Variable var_holder_map(this, MachineRepresentation::kTagged); | 1245 Variable var_holder_map(this, MachineRepresentation::kTagged); |
1272 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); | 1246 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); |
1273 Label return_undefined(this); | 1247 Label return_undefined(this); |
1274 Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; | 1248 Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; |
1275 Label loop(this, arraysize(merged_variables), merged_variables); | 1249 Label loop(this, arraysize(merged_variables), merged_variables); |
1276 | 1250 |
1277 var_holder_map.Bind(var_receiver_map.value()); | 1251 var_holder_map.Bind(receiver_map); |
1278 var_holder_instance_type.Bind(var_instance_type.value()); | 1252 var_holder_instance_type.Bind(instance_type); |
1279 // Private symbols must not be looked up on the prototype chain. | 1253 // Private symbols must not be looked up on the prototype chain. |
1280 GotoIf(IsPrivateSymbol(key), &return_undefined); | 1254 GotoIf(IsPrivateSymbol(key), &return_undefined); |
1281 Goto(&loop); | 1255 Goto(&loop); |
1282 Bind(&loop); | 1256 Bind(&loop); |
1283 { | 1257 { |
1284 // Bailout if it can be an integer indexed exotic case. | 1258 // Bailout if it can be an integer indexed exotic case. |
1285 GotoIf(Word32Equal(var_holder_instance_type.value(), | 1259 GotoIf(Word32Equal(var_holder_instance_type.value(), |
1286 Int32Constant(JS_TYPED_ARRAY_TYPE)), | 1260 Int32Constant(JS_TYPED_ARRAY_TYPE)), |
1287 slow); | 1261 slow); |
1288 Node* proto = LoadMapPrototype(var_holder_map.value()); | 1262 Node* proto = LoadMapPrototype(var_holder_map.value()); |
1289 GotoIf(WordEqual(proto, NullConstant()), &return_undefined); | 1263 GotoIf(WordEqual(proto, NullConstant()), &return_undefined); |
1290 Node* proto_map = LoadMap(proto); | 1264 Node* proto_map = LoadMap(proto); |
1291 Node* proto_instance_type = LoadMapInstanceType(proto_map); | 1265 Node* proto_instance_type = LoadMapInstanceType(proto_map); |
1292 var_holder_map.Bind(proto_map); | 1266 var_holder_map.Bind(proto_map); |
1293 var_holder_instance_type.Bind(proto_instance_type); | 1267 var_holder_instance_type.Bind(proto_instance_type); |
1294 Label next_proto(this), return_value(this, &var_value), goto_slow(this); | 1268 Label next_proto(this), return_value(this, &var_value), goto_slow(this); |
1295 TryGetOwnProperty(p->context, var_receiver.value(), proto, proto_map, | 1269 TryGetOwnProperty(p->context, receiver, proto, proto_map, |
1296 proto_instance_type, key, &return_value, &var_value, | 1270 proto_instance_type, key, &return_value, &var_value, |
1297 &next_proto, &goto_slow); | 1271 &next_proto, &goto_slow); |
1298 | 1272 |
1299 // This trampoline and the next are required to appease Turbofan's | 1273 // This trampoline and the next are required to appease Turbofan's |
1300 // variable merging. | 1274 // variable merging. |
1301 Bind(&next_proto); | 1275 Bind(&next_proto); |
1302 Goto(&loop); | 1276 Goto(&loop); |
1303 | 1277 |
1304 Bind(&goto_slow); | 1278 Bind(&goto_slow); |
1305 Goto(slow); | 1279 Goto(slow); |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1974 Node* slot = Parameter(Descriptor::kSlot); | 1948 Node* slot = Parameter(Descriptor::kSlot); |
1975 Node* context = Parameter(Descriptor::kContext); | 1949 Node* context = Parameter(Descriptor::kContext); |
1976 Node* vector = LoadTypeFeedbackVectorForStub(); | 1950 Node* vector = LoadTypeFeedbackVectorForStub(); |
1977 | 1951 |
1978 StoreICParameters p(context, receiver, name, value, slot, vector); | 1952 StoreICParameters p(context, receiver, name, value, slot, vector); |
1979 KeyedStoreIC(&p, language_mode); | 1953 KeyedStoreIC(&p, language_mode); |
1980 } | 1954 } |
1981 | 1955 |
1982 } // namespace internal | 1956 } // namespace internal |
1983 } // namespace v8 | 1957 } // namespace v8 |
OLD | NEW |