Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 2198833002: [turbofan] Remove unnecessary prototype checks for element access. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 563 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 graph()->NewNode(common()->EffectPhi(this_control_count), 574 graph()->NewNode(common()->EffectPhi(this_control_count),
575 this_control_count + 1, &this_effects.front()); 575 this_control_count + 1, &this_effects.front());
576 576
577 // TODO(turbofan): The effect/control linearization will not find a 577 // TODO(turbofan): The effect/control linearization will not find a
578 // FrameState after the EffectPhi that is generated above. 578 // FrameState after the EffectPhi that is generated above.
579 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state, 579 this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
580 this_effect, this_control); 580 this_effect, this_control);
581 } 581 }
582 } 582 }
583 583
584 // Certain stores need a prototype chain check because shape changes
585 // could allow callbacks on elements in the prototype chain that are
586 // not compatible with (monomorphic) keyed stores.
587 Handle<JSObject> holder;
588 if (access_info.holder().ToHandle(&holder)) {
589 AssumePrototypesStable(receiver_maps, native_context, holder);
590 }
591
592 // Access the actual element. 584 // Access the actual element.
593 ValueEffectControl continuation = BuildElementAccess( 585 ValueEffectControl continuation = BuildElementAccess(
594 this_receiver, this_index, this_value, this_effect, this_control, 586 this_receiver, this_index, this_value, this_effect, this_control,
595 native_context, access_info, access_mode, store_mode); 587 native_context, access_info, access_mode, store_mode);
596 values.push_back(continuation.value()); 588 values.push_back(continuation.value());
597 effects.push_back(continuation.effect()); 589 effects.push_back(continuation.effect());
598 controls.push_back(continuation.control()); 590 controls.push_back(continuation.control());
599 } 591 }
600 592
601 DCHECK_NULL(fallthrough_control); 593 DCHECK_NULL(fallthrough_control);
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 return kExternalInt8Array; 941 return kExternalInt8Array;
950 } 942 }
951 943
952 } // namespace 944 } // namespace
953 945
954 JSNativeContextSpecialization::ValueEffectControl 946 JSNativeContextSpecialization::ValueEffectControl
955 JSNativeContextSpecialization::BuildElementAccess( 947 JSNativeContextSpecialization::BuildElementAccess(
956 Node* receiver, Node* index, Node* value, Node* effect, Node* control, 948 Node* receiver, Node* index, Node* value, Node* effect, Node* control,
957 Handle<Context> native_context, ElementAccessInfo const& access_info, 949 Handle<Context> native_context, ElementAccessInfo const& access_info,
958 AccessMode access_mode, KeyedAccessStoreMode store_mode) { 950 AccessMode access_mode, KeyedAccessStoreMode store_mode) {
959 // Determine actual holder and perform prototype chain checks.
960 Handle<JSObject> holder;
961 if (access_info.holder().ToHandle(&holder)) {
962 AssumePrototypesStable(access_info.receiver_maps(), native_context, holder);
963 }
964
965 // TODO(bmeurer): We currently specialize based on elements kind. We should 951 // TODO(bmeurer): We currently specialize based on elements kind. We should
966 // also be able to properly support strings and other JSObjects here. 952 // also be able to properly support strings and other JSObjects here.
967 ElementsKind elements_kind = access_info.elements_kind(); 953 ElementsKind elements_kind = access_info.elements_kind();
968 MapList const& receiver_maps = access_info.receiver_maps(); 954 MapList const& receiver_maps = access_info.receiver_maps();
969 955
970 // Load the elements for the {receiver}. 956 // Load the elements for the {receiver}.
971 Node* elements = effect = graph()->NewNode( 957 Node* elements = effect = graph()->NewNode(
972 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, 958 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
973 effect, control); 959 effect, control);
974 960
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 value = effect = 1112 value = effect =
1127 graph()->NewNode(simplified()->LoadElement(element_access), elements, 1113 graph()->NewNode(simplified()->LoadElement(element_access), elements,
1128 index, effect, control); 1114 index, effect, control);
1129 // Handle loading from holey backing stores correctly, by either mapping 1115 // Handle loading from holey backing stores correctly, by either mapping
1130 // the hole to undefined if possible, or deoptimizing otherwise. 1116 // the hole to undefined if possible, or deoptimizing otherwise.
1131 if (elements_kind == FAST_HOLEY_ELEMENTS || 1117 if (elements_kind == FAST_HOLEY_ELEMENTS ||
1132 elements_kind == FAST_HOLEY_SMI_ELEMENTS) { 1118 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
1133 // Perform the hole check on the result. 1119 // Perform the hole check on the result.
1134 CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole; 1120 CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole;
1135 // Check if we are allowed to turn the hole into undefined. 1121 // Check if we are allowed to turn the hole into undefined.
1136 // TODO(bmeurer): We might check the JSArray map from a different 1122 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) {
1137 // context here; may need reinvestigation.
1138 if (receiver_maps.size() == 1 &&
1139 receiver_maps[0].is_identical_to(
1140 handle(isolate()->get_initial_js_array_map(elements_kind))) &&
1141 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
1142 // Add a code dependency on the array protector cell.
1143 dependencies()->AssumePrototypeMapsStable(
1144 receiver_maps[0], isolate()->initial_object_prototype());
1145 dependencies()->AssumePropertyCell(factory()->array_protector());
1146 // Turn the hole into undefined. 1123 // Turn the hole into undefined.
1147 mode = CheckTaggedHoleMode::kConvertHoleToUndefined; 1124 mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
1148 } 1125 }
1149 value = effect = graph()->NewNode(simplified()->CheckTaggedHole(mode), 1126 value = effect = graph()->NewNode(simplified()->CheckTaggedHole(mode),
1150 value, effect, control); 1127 value, effect, control);
1151 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { 1128 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
1152 // Perform the hole check on the result. 1129 // Perform the hole check on the result.
1153 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole; 1130 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
1154 // Check if we are allowed to return the hole directly. 1131 // Check if we are allowed to return the hole directly.
1155 // TODO(bmeurer): We might check the JSArray map from a different 1132 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) {
1156 // context here; may need reinvestigation.
1157 if (receiver_maps.size() == 1 &&
1158 receiver_maps[0].is_identical_to(
1159 handle(isolate()->get_initial_js_array_map(elements_kind))) &&
1160 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
1161 // Add a code dependency on the array protector cell.
1162 dependencies()->AssumePrototypeMapsStable(
1163 receiver_maps[0], isolate()->initial_object_prototype());
1164 dependencies()->AssumePropertyCell(factory()->array_protector());
1165 // Return the signaling NaN hole directly if all uses are truncating. 1133 // Return the signaling NaN hole directly if all uses are truncating.
1166 mode = CheckFloat64HoleMode::kAllowReturnHole; 1134 mode = CheckFloat64HoleMode::kAllowReturnHole;
1167 } 1135 }
1168 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode), 1136 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode),
1169 value, effect, control); 1137 value, effect, control);
1170 } 1138 }
1171 } else { 1139 } else {
1172 DCHECK_EQ(AccessMode::kStore, access_mode); 1140 DCHECK_EQ(AccessMode::kStore, access_mode);
1173 if (IsFastSmiElementsKind(elements_kind)) { 1141 if (IsFastSmiElementsKind(elements_kind)) {
1174 value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(), 1142 value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 // Implemented according to ES6 section 7.3.2 GetV (V, P). 1219 // Implemented according to ES6 section 7.3.2 GetV (V, P).
1252 Handle<JSFunction> constructor; 1220 Handle<JSFunction> constructor;
1253 if (Map::GetConstructorFunction(map, native_context) 1221 if (Map::GetConstructorFunction(map, native_context)
1254 .ToHandle(&constructor)) { 1222 .ToHandle(&constructor)) {
1255 map = handle(constructor->initial_map(), isolate()); 1223 map = handle(constructor->initial_map(), isolate());
1256 } 1224 }
1257 dependencies()->AssumePrototypeMapsStable(map, holder); 1225 dependencies()->AssumePrototypeMapsStable(map, holder);
1258 } 1226 }
1259 } 1227 }
1260 1228
1229 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
1230 std::vector<Handle<Map>> const& receiver_maps,
1231 Handle<Context> native_context) {
1232 // Check if the array prototype chain is intact.
1233 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false;
1234
1235 // Make sure both the initial Array and Object prototypes are stable.
1236 Handle<JSObject> initial_array_prototype(
1237 native_context->initial_array_prototype(), isolate());
1238 Handle<JSObject> initial_object_prototype(
1239 native_context->initial_object_prototype(), isolate());
1240 if (!initial_array_prototype->map()->is_stable() ||
1241 !initial_object_prototype->map()->is_stable()) {
1242 return false;
1243 }
1244
1245 // Check if all {receiver_maps} either have the initial Array.prototype
1246 // or the initial Object.prototype as their prototype, as those are
1247 // guarded by the array protector cell.
1248 for (Handle<Map> map : receiver_maps) {
1249 if (map->prototype() != *initial_array_prototype &&
1250 map->prototype() != *initial_object_prototype) {
1251 return false;
1252 }
1253 }
1254
1255 // Install code dependencies on the prototype maps.
1256 for (Handle<Map> map : receiver_maps) {
1257 dependencies()->AssumePrototypeMapsStable(map, initial_object_prototype);
adamk 2016/08/08 22:02:00 Are you missing a call for initial_array_prototype
1258 }
1259
1260 // Install code dependency on the array protector cell.
1261 dependencies()->AssumePropertyCell(factory()->array_protector());
1262 return true;
1263 }
1264
1261 bool JSNativeContextSpecialization::ExtractReceiverMaps( 1265 bool JSNativeContextSpecialization::ExtractReceiverMaps(
1262 Node* receiver, Node* effect, FeedbackNexus const& nexus, 1266 Node* receiver, Node* effect, FeedbackNexus const& nexus,
1263 MapHandleList* receiver_maps) { 1267 MapHandleList* receiver_maps) {
1264 DCHECK_EQ(0, receiver_maps->length()); 1268 DCHECK_EQ(0, receiver_maps->length());
1265 // See if we can infer a concrete type for the {receiver}. 1269 // See if we can infer a concrete type for the {receiver}.
1266 Handle<Map> receiver_map; 1270 Handle<Map> receiver_map;
1267 if (InferReceiverMap(receiver, effect).ToHandle(&receiver_map)) { 1271 if (InferReceiverMap(receiver, effect).ToHandle(&receiver_map)) {
1268 // We can assume that the {receiver} still has the infered {receiver_map}. 1272 // We can assume that the {receiver} still has the infered {receiver_map}.
1269 receiver_maps->Add(receiver_map); 1273 receiver_maps->Add(receiver_map);
1270 return true; 1274 return true;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 } 1383 }
1380 1384
1381 1385
1382 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1386 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1383 return jsgraph()->simplified(); 1387 return jsgraph()->simplified();
1384 } 1388 }
1385 1389
1386 } // namespace compiler 1390 } // namespace compiler
1387 } // namespace internal 1391 } // namespace internal
1388 } // namespace v8 1392 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | test/mjsunit/regress/regress-crbug-616709-1.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698