OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
960 } | 960 } |
961 | 961 |
962 JSNativeContextSpecialization::ValueEffectControl | 962 JSNativeContextSpecialization::ValueEffectControl |
963 JSNativeContextSpecialization::BuildPropertyAccess( | 963 JSNativeContextSpecialization::BuildPropertyAccess( |
964 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, | 964 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, |
965 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, | 965 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, |
966 AccessMode access_mode, LanguageMode language_mode, | 966 AccessMode access_mode, LanguageMode language_mode, |
967 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) { | 967 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) { |
968 // Determine actual holder and perform prototype chain checks. | 968 // Determine actual holder and perform prototype chain checks. |
969 Handle<JSObject> holder; | 969 Handle<JSObject> holder; |
970 if (access_info.holder().ToHandle(&holder)) { | 970 if (access_info.holder().ToHandle(&holder) && |
Benedikt Meurer
2017/01/10 08:25:55
There should never be a holder for kStoreInLiteral
Franzi
2017/01/10 10:54:02
OK. Done.
| |
971 access_mode != AccessMode::kStoreInLiteral) { | |
971 AssumePrototypesStable(access_info.receiver_maps(), holder); | 972 AssumePrototypesStable(access_info.receiver_maps(), holder); |
972 } | 973 } |
973 | 974 |
974 // Generate the actual property access. | 975 // Generate the actual property access. |
975 if (access_info.IsNotFound()) { | 976 if (access_info.IsNotFound()) { |
976 DCHECK_EQ(AccessMode::kLoad, access_mode); | 977 DCHECK_EQ(AccessMode::kLoad, access_mode); |
977 value = jsgraph()->UndefinedConstant(); | 978 value = jsgraph()->UndefinedConstant(); |
978 } else if (access_info.IsDataConstant()) { | 979 } else if (access_info.IsDataConstant()) { |
979 Node* constant_value = jsgraph()->Constant(access_info.constant()); | 980 Node* constant_value = jsgraph()->Constant(access_info.constant()); |
980 if (access_mode == AccessMode::kStore) { | 981 if (access_mode == AccessMode::kStore) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1021 } else { | 1022 } else { |
1022 value = effect = graph()->NewNode( | 1023 value = effect = graph()->NewNode( |
1023 javascript()->CallFunction( | 1024 javascript()->CallFunction( |
1024 2, 0.0f, VectorSlotPair(), | 1025 2, 0.0f, VectorSlotPair(), |
1025 ConvertReceiverMode::kNotNullOrUndefined), | 1026 ConvertReceiverMode::kNotNullOrUndefined), |
1026 target, receiver, context, frame_state0, effect, control); | 1027 target, receiver, context, frame_state0, effect, control); |
1027 control = graph()->NewNode(common()->IfSuccess(), value); | 1028 control = graph()->NewNode(common()->IfSuccess(), value); |
1028 } | 1029 } |
1029 break; | 1030 break; |
1030 } | 1031 } |
1032 case AccessMode::kStoreInLiteral: | |
1031 case AccessMode::kStore: { | 1033 case AccessMode::kStore: { |
1032 // We need a FrameState for the setter stub to restore the correct | 1034 // We need a FrameState for the setter stub to restore the correct |
1033 // context and return the appropriate value to fullcodegen. | 1035 // context and return the appropriate value to fullcodegen. |
1034 FrameStateFunctionInfo const* frame_info0 = | 1036 FrameStateFunctionInfo const* frame_info0 = |
1035 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub, | 1037 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub, |
1036 2, 0, shared_info); | 1038 2, 0, shared_info); |
1037 Node* frame_state0 = graph()->NewNode( | 1039 Node* frame_state0 = graph()->NewNode( |
1038 common()->FrameState(BailoutId::None(), | 1040 common()->FrameState(BailoutId::None(), |
1039 OutputFrameStateCombine::Ignore(), | 1041 OutputFrameStateCombine::Ignore(), |
1040 frame_info0), | 1042 frame_info0), |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1251 value = effect = control = | 1253 value = effect = control = |
1252 graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); | 1254 graph()->NewNode(common()->Call(desc), arraysize(inputs), inputs); |
1253 control = graph()->NewNode(common()->IfSuccess(), control); | 1255 control = graph()->NewNode(common()->IfSuccess(), control); |
1254 } | 1256 } |
1255 | 1257 |
1256 return ValueEffectControl(value, effect, control); | 1258 return ValueEffectControl(value, effect, control); |
1257 } | 1259 } |
1258 | 1260 |
1259 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( | 1261 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( |
1260 Node* node) { | 1262 Node* node) { |
1261 // TODO(franzih): Use feedback | 1263 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); |
1262 return NoChange(); | 1264 |
1265 // If deoptimization is disabled, we cannot optimize. | |
1266 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
1267 | |
1268 DataPropertyParameters const& p = DataPropertyParametersOf(node->op()); | |
1269 | |
1270 if (!p.feedback().IsValid()) return NoChange(); | |
1271 | |
1272 StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(), | |
1273 p.feedback().slot()); | |
1274 if (nexus.IsUninitialized()) { | |
1275 return NoChange(); | |
1276 } | |
1277 | |
1278 if (nexus.ic_state() == MEGAMORPHIC) { | |
1279 return NoChange(); | |
1280 } | |
1281 | |
1282 DCHECK_EQ(MONOMORPHIC, nexus.ic_state()); | |
1283 | |
1284 Handle<Map> receiver_map(nexus.FindFirstMap(), isolate()); | |
1285 Handle<Name> cached_name = | |
1286 handle(Name::cast(nexus.GetFeedbackExtra()), isolate()); | |
1287 | |
1288 PropertyAccessInfo access_info; | |
1289 AccessInfoFactory access_info_factory(dependencies(), native_context(), | |
1290 graph()->zone()); | |
1291 if (!access_info_factory.ComputePropertyAccessInfo( | |
1292 receiver_map, cached_name, AccessMode::kStoreInLiteral, | |
1293 &access_info)) { | |
1294 return NoChange(); | |
1295 } | |
1296 | |
1297 DCHECK_EQ(1, access_info.receiver_maps().size()); | |
Benedikt Meurer
2017/01/10 08:25:55
This check doesn't need to be here.
Franzi
2017/01/10 10:54:01
Oops, left-over debugging stuff. Deleted.
| |
1298 | |
1299 if (access_info.IsGeneric()) { | |
1300 return NoChange(); | |
1301 } | |
1302 | |
1303 Node* receiver = NodeProperties::GetValueInput(node, 0); | |
1304 Node* effect = NodeProperties::GetEffectInput(node); | |
1305 Node* control = NodeProperties::GetControlInput(node); | |
1306 | |
1307 // Monomorphic property access. | |
1308 receiver = BuildCheckHeapObject(receiver, &effect, control); | |
1309 | |
1310 effect = BuildCheckMaps(receiver, effect, control, MapList{receiver_map}); | |
Benedikt Meurer
2017/01/10 08:25:54
You can use access_info.receiver_maps() here inste
Franzi
2017/01/10 10:54:01
Done. Changed the other uses of MapList{} as well.
| |
1311 | |
1312 // Ensure that {name} matches the cached name. | |
1313 Node* name = NodeProperties::GetValueInput(node, 1); | |
1314 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name, | |
1315 jsgraph()->HeapConstant(cached_name)); | |
1316 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | |
1317 | |
1318 Node* value = NodeProperties::GetValueInput(node, 2); | |
1319 Node* context = NodeProperties::GetContextInput(node); | |
1320 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); | |
1321 | |
1322 // Generate the actual property access. | |
1323 ValueEffectControl continuation = BuildPropertyAccess( | |
1324 receiver, value, context, frame_state_lazy, effect, control, cached_name, | |
1325 access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY, | |
1326 p.feedback().vector(), p.feedback().slot()); | |
1327 value = continuation.value(); | |
1328 effect = continuation.effect(); | |
1329 control = continuation.control(); | |
1330 | |
1331 ReplaceWithValue(node, value, effect, control); | |
1332 return Replace(value); | |
1263 } | 1333 } |
1264 | 1334 |
1265 namespace { | 1335 namespace { |
1266 | 1336 |
1267 ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) { | 1337 ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) { |
1268 switch (kind) { | 1338 switch (kind) { |
1269 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1339 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1270 case TYPE##_ELEMENTS: \ | 1340 case TYPE##_ELEMENTS: \ |
1271 return kExternal##Type##Array; | 1341 return kExternal##Type##Array; |
1272 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1342 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1374 // Access the actual element. | 1444 // Access the actual element. |
1375 ExternalArrayType external_array_type = | 1445 ExternalArrayType external_array_type = |
1376 GetArrayTypeFromElementsKind(elements_kind); | 1446 GetArrayTypeFromElementsKind(elements_kind); |
1377 switch (access_mode) { | 1447 switch (access_mode) { |
1378 case AccessMode::kLoad: { | 1448 case AccessMode::kLoad: { |
1379 value = effect = graph()->NewNode( | 1449 value = effect = graph()->NewNode( |
1380 simplified()->LoadTypedElement(external_array_type), buffer, | 1450 simplified()->LoadTypedElement(external_array_type), buffer, |
1381 base_pointer, external_pointer, index, effect, control); | 1451 base_pointer, external_pointer, index, effect, control); |
1382 break; | 1452 break; |
1383 } | 1453 } |
1454 case AccessMode::kStoreInLiteral: | |
1384 case AccessMode::kStore: { | 1455 case AccessMode::kStore: { |
1385 // Ensure that the {value} is actually a Number. | 1456 // Ensure that the {value} is actually a Number. |
1386 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, | 1457 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |
1387 effect, control); | 1458 effect, control); |
1388 | 1459 |
1389 // Introduce the appropriate truncation for {value}. Currently we | 1460 // Introduce the appropriate truncation for {value}. Currently we |
1390 // only need to do this for ClamedUint8Array {receiver}s, as the | 1461 // only need to do this for ClamedUint8Array {receiver}s, as the |
1391 // other truncations are implicit in the StoreTypedElement, but we | 1462 // other truncations are implicit in the StoreTypedElement, but we |
1392 // might want to change that at some point. | 1463 // might want to change that at some point. |
1393 if (external_array_type == kExternalUint8ClampedArray) { | 1464 if (external_array_type == kExternalUint8ClampedArray) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1429 break; | 1500 break; |
1430 } | 1501 } |
1431 } | 1502 } |
1432 } else { | 1503 } else { |
1433 // Load the elements for the {receiver}. | 1504 // Load the elements for the {receiver}. |
1434 Node* elements = effect = graph()->NewNode( | 1505 Node* elements = effect = graph()->NewNode( |
1435 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, | 1506 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, |
1436 effect, control); | 1507 effect, control); |
1437 | 1508 |
1438 // Don't try to store to a copy-on-write backing store. | 1509 // Don't try to store to a copy-on-write backing store. |
1439 if (access_mode == AccessMode::kStore && | 1510 if ((access_mode == AccessMode::kStore || |
1511 access_mode == AccessMode::kStoreInLiteral) && | |
Benedikt Meurer
2017/01/10 08:25:54
This doesn't make sense. We never do a store in li
Franzi
2017/01/10 10:54:01
OK, also added a DCHECK to beginning of the functi
| |
1440 IsFastSmiOrObjectElementsKind(elements_kind) && | 1512 IsFastSmiOrObjectElementsKind(elements_kind) && |
1441 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1513 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1442 effect = graph()->NewNode(simplified()->CheckMaps(ZoneHandleSet<Map>( | 1514 effect = graph()->NewNode(simplified()->CheckMaps(ZoneHandleSet<Map>( |
1443 factory()->fixed_array_map())), | 1515 factory()->fixed_array_map())), |
1444 elements, effect, control); | 1516 elements, effect, control); |
1445 } | 1517 } |
1446 | 1518 |
1447 // Check if the {receiver} is a JSArray. | 1519 // Check if the {receiver} is a JSArray. |
1448 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); | 1520 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); |
1449 | 1521 |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1839 return jsgraph()->javascript(); | 1911 return jsgraph()->javascript(); |
1840 } | 1912 } |
1841 | 1913 |
1842 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1914 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1843 return jsgraph()->simplified(); | 1915 return jsgraph()->simplified(); |
1844 } | 1916 } |
1845 | 1917 |
1846 } // namespace compiler | 1918 } // namespace compiler |
1847 } // namespace internal | 1919 } // namespace internal |
1848 } // namespace v8 | 1920 } // namespace v8 |
OLD | NEW |