Chromium Code Reviews| 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 |