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

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

Issue 2936673005: [turbofan] Refactor property access building. (Closed)
Patch Set: Address reviewer comments Created 3 years, 6 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
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/property-access-builder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "src/compiler/access-info.h" 11 #include "src/compiler/access-info.h"
12 #include "src/compiler/js-graph.h" 12 #include "src/compiler/js-graph.h"
13 #include "src/compiler/js-operator.h" 13 #include "src/compiler/js-operator.h"
14 #include "src/compiler/linkage.h" 14 #include "src/compiler/linkage.h"
15 #include "src/compiler/node-matchers.h" 15 #include "src/compiler/node-matchers.h"
16 #include "src/compiler/property-access-builder.h"
16 #include "src/compiler/type-cache.h" 17 #include "src/compiler/type-cache.h"
17 #include "src/feedback-vector.h" 18 #include "src/feedback-vector.h"
18 #include "src/field-index-inl.h" 19 #include "src/field-index-inl.h"
19 #include "src/isolate-inl.h" 20 #include "src/isolate-inl.h"
20 21
21 namespace v8 { 22 namespace v8 {
22 namespace internal { 23 namespace internal {
23 namespace compiler { 24 namespace compiler {
24 25
25 namespace { 26 namespace {
26 27
27 bool HasNumberMaps(MapHandles const& maps) { 28 bool HasNumberMaps(MapHandles const& maps) {
28 for (auto map : maps) { 29 for (auto map : maps) {
29 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; 30 if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
30 } 31 }
31 return false; 32 return false;
32 } 33 }
33 34
34 bool HasOnlyJSArrayMaps(MapHandles const& maps) { 35 bool HasOnlyJSArrayMaps(MapHandles const& maps) {
35 for (auto map : maps) { 36 for (auto map : maps) {
36 if (!map->IsJSArrayMap()) return false; 37 if (!map->IsJSArrayMap()) return false;
37 } 38 }
38 return true; 39 return true;
39 } 40 }
40 41
41 bool HasOnlyNumberMaps(MapHandles const& maps) {
42 for (auto map : maps) {
43 if (map->instance_type() != HEAP_NUMBER_TYPE) return false;
44 }
45 return true;
46 }
47
48 bool HasOnlyStringMaps(MapHandles const& maps) { 42 bool HasOnlyStringMaps(MapHandles const& maps) {
49 for (auto map : maps) { 43 for (auto map : maps) {
50 if (!map->IsStringMap()) return false; 44 if (!map->IsStringMap()) return false;
51 } 45 }
52 return true; 46 return true;
53 } 47 }
54 48
55 bool HasOnlySequentialStringMaps(MapHandles const& maps) {
56 for (auto map : maps) {
57 if (!map->IsStringMap()) return false;
58 if (!StringShape(map->instance_type()).IsSequential()) {
59 return false;
60 }
61 }
62 return true;
63 }
64
65 } // namespace 49 } // namespace
66 50
67 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { 51 struct JSNativeContextSpecialization::ScriptContextTableLookupResult {
68 Handle<Context> context; 52 Handle<Context> context;
69 bool immutable; 53 bool immutable;
70 int index; 54 int index;
71 }; 55 };
72 56
73 JSNativeContextSpecialization::JSNativeContextSpecialization( 57 JSNativeContextSpecialization::JSNativeContextSpecialization(
74 Editor* editor, JSGraph* jsgraph, Flags flags, 58 Editor* editor, JSGraph* jsgraph, Flags flags,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 // Compute property access info for @@hasInstance on {receiver}. 170 // Compute property access info for @@hasInstance on {receiver}.
187 PropertyAccessInfo access_info; 171 PropertyAccessInfo access_info;
188 AccessInfoFactory access_info_factory(dependencies(), native_context(), 172 AccessInfoFactory access_info_factory(dependencies(), native_context(),
189 graph()->zone()); 173 graph()->zone());
190 if (!access_info_factory.ComputePropertyAccessInfo( 174 if (!access_info_factory.ComputePropertyAccessInfo(
191 receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad, 175 receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad,
192 &access_info)) { 176 &access_info)) {
193 return NoChange(); 177 return NoChange();
194 } 178 }
195 179
180 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
181
196 if (access_info.IsNotFound()) { 182 if (access_info.IsNotFound()) {
197 // If there's no @@hasInstance handler, the OrdinaryHasInstance operation 183 // If there's no @@hasInstance handler, the OrdinaryHasInstance operation
198 // takes over, but that requires the {receiver} to be callable. 184 // takes over, but that requires the {receiver} to be callable.
199 if (receiver->IsCallable()) { 185 if (receiver->IsCallable()) {
200 // Determine actual holder and perform prototype chain checks. 186 // Determine actual holder and perform prototype chain checks.
201 Handle<JSObject> holder; 187 Handle<JSObject> holder;
202 if (access_info.holder().ToHandle(&holder)) { 188 if (access_info.holder().ToHandle(&holder)) {
203 AssumePrototypesStable(access_info.receiver_maps(), holder); 189 access_builder.AssumePrototypesStable(
190 native_context(), access_info.receiver_maps(), holder);
204 } 191 }
205 192
206 // Monomorphic property access. 193 // Monomorphic property access.
207 effect = BuildCheckMaps(constructor, effect, control, 194 access_builder.BuildCheckMaps(constructor, &effect, control,
208 access_info.receiver_maps()); 195 access_info.receiver_maps());
209 196
210 // Lower to OrdinaryHasInstance(C, O). 197 // Lower to OrdinaryHasInstance(C, O).
211 NodeProperties::ReplaceValueInput(node, constructor, 0); 198 NodeProperties::ReplaceValueInput(node, constructor, 0);
212 NodeProperties::ReplaceValueInput(node, object, 1); 199 NodeProperties::ReplaceValueInput(node, object, 1);
213 NodeProperties::ReplaceEffectInput(node, effect); 200 NodeProperties::ReplaceEffectInput(node, effect);
214 NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance()); 201 NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
215 Reduction const reduction = ReduceJSOrdinaryHasInstance(node); 202 Reduction const reduction = ReduceJSOrdinaryHasInstance(node);
216 return reduction.Changed() ? reduction : Changed(node); 203 return reduction.Changed() ? reduction : Changed(node);
217 } 204 }
218 } else if (access_info.IsDataConstant() || 205 } else if (access_info.IsDataConstant() ||
219 access_info.IsDataConstantField()) { 206 access_info.IsDataConstantField()) {
220 // Determine actual holder and perform prototype chain checks. 207 // Determine actual holder and perform prototype chain checks.
221 Handle<JSObject> holder; 208 Handle<JSObject> holder;
222 if (access_info.holder().ToHandle(&holder)) { 209 if (access_info.holder().ToHandle(&holder)) {
223 AssumePrototypesStable(access_info.receiver_maps(), holder); 210 access_builder.AssumePrototypesStable(
211 native_context(), access_info.receiver_maps(), holder);
224 } else { 212 } else {
225 holder = receiver; 213 holder = receiver;
226 } 214 }
227 215
228 Handle<Object> constant; 216 Handle<Object> constant;
229 if (access_info.IsDataConstant()) { 217 if (access_info.IsDataConstant()) {
230 DCHECK(!FLAG_track_constant_fields); 218 DCHECK(!FLAG_track_constant_fields);
231 constant = access_info.constant(); 219 constant = access_info.constant();
232 } else { 220 } else {
233 DCHECK(FLAG_track_constant_fields); 221 DCHECK(FLAG_track_constant_fields);
234 DCHECK(access_info.IsDataConstantField()); 222 DCHECK(access_info.IsDataConstantField());
235 // The value must be callable therefore tagged. 223 // The value must be callable therefore tagged.
236 DCHECK(CanBeTaggedPointer(access_info.field_representation())); 224 DCHECK(CanBeTaggedPointer(access_info.field_representation()));
237 FieldIndex field_index = access_info.field_index(); 225 FieldIndex field_index = access_info.field_index();
238 constant = JSObject::FastPropertyAt(holder, Representation::Tagged(), 226 constant = JSObject::FastPropertyAt(holder, Representation::Tagged(),
239 field_index); 227 field_index);
240 } 228 }
241 DCHECK(constant->IsCallable()); 229 DCHECK(constant->IsCallable());
242 230
243 // Monomorphic property access. 231 // Monomorphic property access.
244 effect = BuildCheckMaps(constructor, effect, control, 232 access_builder.BuildCheckMaps(constructor, &effect, control,
245 access_info.receiver_maps()); 233 access_info.receiver_maps());
246 234
247 // Call the @@hasInstance handler. 235 // Call the @@hasInstance handler.
248 Node* target = jsgraph()->Constant(constant); 236 Node* target = jsgraph()->Constant(constant);
249 node->InsertInput(graph()->zone(), 0, target); 237 node->InsertInput(graph()->zone(), 0, target);
250 node->ReplaceInput(1, constructor); 238 node->ReplaceInput(1, constructor);
251 node->ReplaceInput(2, object); 239 node->ReplaceInput(2, object);
252 node->ReplaceInput(5, effect); 240 node->ReplaceInput(5, effect);
253 NodeProperties::ChangeOp( 241 NodeProperties::ChangeOp(
254 node, javascript()->Call(3, CallFrequency(), VectorSlotPair(), 242 node, javascript()->Call(3, CallFrequency(), VectorSlotPair(),
255 ConvertReceiverMode::kNotNullOrUndefined)); 243 ConvertReceiverMode::kNotNullOrUndefined));
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 622 }
635 623
636 // Collect call nodes to rewire exception edges. 624 // Collect call nodes to rewire exception edges.
637 ZoneVector<Node*> if_exception_nodes(zone()); 625 ZoneVector<Node*> if_exception_nodes(zone());
638 ZoneVector<Node*>* if_exceptions = nullptr; 626 ZoneVector<Node*>* if_exceptions = nullptr;
639 Node* if_exception = nullptr; 627 Node* if_exception = nullptr;
640 if (NodeProperties::IsExceptionalCall(node, &if_exception)) { 628 if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
641 if_exceptions = &if_exception_nodes; 629 if_exceptions = &if_exception_nodes;
642 } 630 }
643 631
632 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
633
644 // Check for the monomorphic cases. 634 // Check for the monomorphic cases.
645 if (access_infos.size() == 1) { 635 if (access_infos.size() == 1) {
646 PropertyAccessInfo access_info = access_infos.front(); 636 PropertyAccessInfo access_info = access_infos.front();
647 if (HasOnlyStringMaps(access_info.receiver_maps())) { 637 // Try to build string check or number check if possible.
648 if (HasOnlySequentialStringMaps(access_info.receiver_maps())) { 638 // Otherwise build a map check.
649 receiver = effect = graph()->NewNode(simplified()->CheckSeqString(), 639 if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
650 receiver, effect, control); 640 &receiver, &effect, control) &&
651 } else { 641 !access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
652 // Monormorphic string access (ignoring the fact that there are multiple 642 &receiver, &effect, control)) {
653 // String maps). 643 receiver =
654 receiver = effect = graph()->NewNode(simplified()->CheckString(), 644 access_builder.BuildCheckHeapObject(receiver, &effect, control);
655 receiver, effect, control); 645 access_builder.BuildCheckMaps(receiver, &effect, control,
656 } 646 access_info.receiver_maps());
657
658 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) {
659 // Monomorphic number access (we also deal with Smis here).
660 receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
661 receiver, effect, control);
662 } else {
663 // Monomorphic property access.
664 receiver = BuildCheckHeapObject(receiver, &effect, control);
665 effect = BuildCheckMaps(receiver, effect, control,
666 access_info.receiver_maps());
667 } 647 }
668 648
669 // Generate the actual property access. 649 // Generate the actual property access.
670 ValueEffectControl continuation = BuildPropertyAccess( 650 ValueEffectControl continuation = BuildPropertyAccess(
671 receiver, value, context, frame_state, effect, control, name, 651 receiver, value, context, frame_state, effect, control, name,
672 if_exceptions, access_info, access_mode, language_mode); 652 if_exceptions, access_info, access_mode, language_mode);
673 value = continuation.value(); 653 value = continuation.value();
674 effect = continuation.effect(); 654 effect = continuation.effect();
675 control = continuation.control(); 655 control = continuation.control();
676 } else { 656 } else {
(...skipping 15 matching lines...) Expand all
692 // Ensure that {receiver} is a heap object. 672 // Ensure that {receiver} is a heap object.
693 Node* receiverissmi_control = nullptr; 673 Node* receiverissmi_control = nullptr;
694 Node* receiverissmi_effect = effect; 674 Node* receiverissmi_effect = effect;
695 if (receiverissmi_possible) { 675 if (receiverissmi_possible) {
696 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); 676 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
697 Node* branch = graph()->NewNode(common()->Branch(), check, control); 677 Node* branch = graph()->NewNode(common()->Branch(), check, control);
698 control = graph()->NewNode(common()->IfFalse(), branch); 678 control = graph()->NewNode(common()->IfFalse(), branch);
699 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); 679 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
700 receiverissmi_effect = effect; 680 receiverissmi_effect = effect;
701 } else { 681 } else {
702 receiver = BuildCheckHeapObject(receiver, &effect, control); 682 receiver =
683 access_builder.BuildCheckHeapObject(receiver, &effect, control);
703 } 684 }
704 685
705 // Load the {receiver} map. The resulting effect is the dominating effect 686 // Load the {receiver} map. The resulting effect is the dominating effect
706 // for all (polymorphic) branches. 687 // for all (polymorphic) branches.
707 Node* receiver_map = effect = 688 Node* receiver_map = effect =
708 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 689 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
709 receiver, effect, control); 690 receiver, effect, control);
710 691
711 // Generate code for the various different property access patterns. 692 // Generate code for the various different property access patterns.
712 Node* fallthrough_control = control; 693 Node* fallthrough_control = control;
713 for (size_t j = 0; j < access_infos.size(); ++j) { 694 for (size_t j = 0; j < access_infos.size(); ++j) {
714 PropertyAccessInfo const& access_info = access_infos[j]; 695 PropertyAccessInfo const& access_info = access_infos[j];
715 Node* this_value = value; 696 Node* this_value = value;
716 Node* this_receiver = receiver; 697 Node* this_receiver = receiver;
717 Node* this_effect = effect; 698 Node* this_effect = effect;
718 Node* this_control = fallthrough_control; 699 Node* this_control = fallthrough_control;
719 700
720 // Perform map check on {receiver}. 701 // Perform map check on {receiver}.
721 MapHandles const& receiver_maps = access_info.receiver_maps(); 702 MapHandles const& receiver_maps = access_info.receiver_maps();
722 { 703 {
723 // Emit a (sequence of) map checks for other {receiver}s. 704 // Emit a (sequence of) map checks for other {receiver}s.
724 ZoneVector<Node*> this_controls(zone()); 705 ZoneVector<Node*> this_controls(zone());
725 ZoneVector<Node*> this_effects(zone()); 706 ZoneVector<Node*> this_effects(zone());
726 if (j == access_infos.size() - 1) { 707 if (j == access_infos.size() - 1) {
727 // Last map check on the fallthrough control path, do a 708 // Last map check on the fallthrough control path, do a
728 // conditional eager deoptimization exit here. 709 // conditional eager deoptimization exit here.
729 this_effect = BuildCheckMaps(receiver, this_effect, this_control, 710 access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
730 receiver_maps); 711 receiver_maps);
731 this_effects.push_back(this_effect); 712 this_effects.push_back(this_effect);
732 this_controls.push_back(fallthrough_control); 713 this_controls.push_back(fallthrough_control);
733 fallthrough_control = nullptr; 714 fallthrough_control = nullptr;
734 } else { 715 } else {
735 for (auto map : receiver_maps) { 716 for (auto map : receiver_maps) {
736 Node* check = 717 Node* check =
737 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, 718 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map,
738 jsgraph()->Constant(map)); 719 jsgraph()->Constant(map));
739 Node* branch = graph()->NewNode(common()->Branch(), check, 720 Node* branch = graph()->NewNode(common()->Branch(), check,
740 fallthrough_control); 721 fallthrough_control);
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 } 1004 }
1024 } 1005 }
1025 1006
1026 // Install dependencies on the relevant prototype maps. 1007 // Install dependencies on the relevant prototype maps.
1027 for (Handle<Map> prototype_map : prototype_maps) { 1008 for (Handle<Map> prototype_map : prototype_maps) {
1028 dependencies()->AssumeMapStable(prototype_map); 1009 dependencies()->AssumeMapStable(prototype_map);
1029 } 1010 }
1030 } 1011 }
1031 1012
1032 // Ensure that {receiver} is a heap object. 1013 // Ensure that {receiver} is a heap object.
1033 receiver = BuildCheckHeapObject(receiver, &effect, control); 1014 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
1015 receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
1034 1016
1035 // Check for the monomorphic case. 1017 // Check for the monomorphic case.
1036 if (access_infos.size() == 1) { 1018 if (access_infos.size() == 1) {
1037 ElementAccessInfo access_info = access_infos.front(); 1019 ElementAccessInfo access_info = access_infos.front();
1038 1020
1039 // Perform possible elements kind transitions. 1021 // Perform possible elements kind transitions.
1040 for (auto transition : access_info.transitions()) { 1022 for (auto transition : access_info.transitions()) {
1041 Handle<Map> const transition_source = transition.first; 1023 Handle<Map> const transition_source = transition.first;
1042 Handle<Map> const transition_target = transition.second; 1024 Handle<Map> const transition_target = transition.second;
1043 effect = graph()->NewNode( 1025 effect = graph()->NewNode(
1044 simplified()->TransitionElementsKind(ElementsTransition( 1026 simplified()->TransitionElementsKind(ElementsTransition(
1045 IsSimpleMapChangeTransition(transition_source->elements_kind(), 1027 IsSimpleMapChangeTransition(transition_source->elements_kind(),
1046 transition_target->elements_kind()) 1028 transition_target->elements_kind())
1047 ? ElementsTransition::kFastTransition 1029 ? ElementsTransition::kFastTransition
1048 : ElementsTransition::kSlowTransition, 1030 : ElementsTransition::kSlowTransition,
1049 transition_source, transition_target)), 1031 transition_source, transition_target)),
1050 receiver, effect, control); 1032 receiver, effect, control);
1051 } 1033 }
1052 1034
1053 // TODO(turbofan): The effect/control linearization will not find a 1035 // TODO(turbofan): The effect/control linearization will not find a
1054 // FrameState after the StoreField or Call that is generated for the 1036 // FrameState after the StoreField or Call that is generated for the
1055 // elements kind transition above. This is because those operators 1037 // elements kind transition above. This is because those operators
1056 // don't have the kNoWrite flag on it, even though they are not 1038 // don't have the kNoWrite flag on it, even though they are not
1057 // observable by JavaScript. 1039 // observable by JavaScript.
1058 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect, 1040 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect,
1059 control); 1041 control);
1060 1042
1061 // Perform map check on the {receiver}. 1043 // Perform map check on the {receiver}.
1062 effect = BuildCheckMaps(receiver, effect, control, 1044 access_builder.BuildCheckMaps(receiver, &effect, control,
1063 access_info.receiver_maps()); 1045 access_info.receiver_maps());
1064 1046
1065 // Access the actual element. 1047 // Access the actual element.
1066 ValueEffectControl continuation = 1048 ValueEffectControl continuation =
1067 BuildElementAccess(receiver, index, value, effect, control, 1049 BuildElementAccess(receiver, index, value, effect, control,
1068 access_info, access_mode, store_mode); 1050 access_info, access_mode, store_mode);
1069 value = continuation.value(); 1051 value = continuation.value();
1070 effect = continuation.effect(); 1052 effect = continuation.effect();
1071 control = continuation.control(); 1053 control = continuation.control();
1072 } else { 1054 } else {
1073 // The final states for every polymorphic branch. We join them with 1055 // The final states for every polymorphic branch. We join them with
(...skipping 30 matching lines...) Expand all
1104 // Load the {receiver} map. 1086 // Load the {receiver} map.
1105 Node* receiver_map = this_effect = 1087 Node* receiver_map = this_effect =
1106 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 1088 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1107 receiver, this_effect, this_control); 1089 receiver, this_effect, this_control);
1108 1090
1109 // Perform map check(s) on {receiver}. 1091 // Perform map check(s) on {receiver}.
1110 MapHandles const& receiver_maps = access_info.receiver_maps(); 1092 MapHandles const& receiver_maps = access_info.receiver_maps();
1111 if (j == access_infos.size() - 1) { 1093 if (j == access_infos.size() - 1) {
1112 // Last map check on the fallthrough control path, do a 1094 // Last map check on the fallthrough control path, do a
1113 // conditional eager deoptimization exit here. 1095 // conditional eager deoptimization exit here.
1114 this_effect = BuildCheckMaps(receiver, this_effect, this_control, 1096 access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
1115 receiver_maps); 1097 receiver_maps);
1116 fallthrough_control = nullptr; 1098 fallthrough_control = nullptr;
1117 } else { 1099 } else {
1118 ZoneVector<Node*> this_controls(zone()); 1100 ZoneVector<Node*> this_controls(zone());
1119 ZoneVector<Node*> this_effects(zone()); 1101 ZoneVector<Node*> this_effects(zone());
1120 for (Handle<Map> map : receiver_maps) { 1102 for (Handle<Map> map : receiver_maps) {
1121 Node* check = 1103 Node* check =
1122 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, 1104 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map,
1123 jsgraph()->Constant(map)); 1105 jsgraph()->Constant(map));
1124 Node* branch = graph()->NewNode(common()->Branch(), check, 1106 Node* branch = graph()->NewNode(common()->Branch(), check,
1125 fallthrough_control); 1107 fallthrough_control);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); 1322 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot());
1341 1323
1342 // Extract the keyed access store mode from the KEYED_STORE_IC. 1324 // Extract the keyed access store mode from the KEYED_STORE_IC.
1343 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); 1325 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
1344 1326
1345 // Try to lower the keyed access based on the {nexus}. 1327 // Try to lower the keyed access based on the {nexus}.
1346 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 1328 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
1347 p.language_mode(), store_mode); 1329 p.language_mode(), store_mode);
1348 } 1330 }
1349 1331
1332 Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
1333 Node* receiver, Node* context, Node* frame_state, Node** effect,
1334 Node** control, ZoneVector<Node*>* if_exceptions,
1335 PropertyAccessInfo const& access_info) {
1336 Node* target = jsgraph()->Constant(access_info.constant());
1337 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
1338 Handle<SharedFunctionInfo> shared_info =
1339 frame_info.shared_info().ToHandleChecked();
1340 // We need a FrameState for the getter stub to restore the correct
1341 // context before returning to fullcodegen.
1342 FrameStateFunctionInfo const* frame_info0 =
1343 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub, 1, 0,
1344 shared_info);
1345 Node* frame_state0 = graph()->NewNode(
1346 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
1347 frame_info0),
1348 graph()->NewNode(common()->StateValues(1, SparseInputMask::Dense()),
1349 receiver),
1350 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(), context,
1351 target, frame_state);
1352
1353 // Introduce the call to the getter function.
1354 Node* value;
1355 if (access_info.constant()->IsJSFunction()) {
1356 value = *effect = *control = graph()->NewNode(
1357 jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
1358 ConvertReceiverMode::kNotNullOrUndefined),
1359 target, receiver, context, frame_state0, *effect, *control);
1360 } else {
1361 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1362 Handle<FunctionTemplateInfo> function_template_info(
1363 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1364 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1365 value = InlineApiCall(receiver, context, target, frame_state0, nullptr,
1366 effect, control, shared_info, function_template_info);
1367 }
1368 // Remember to rewire the IfException edge if this is inside a try-block.
1369 if (if_exceptions != nullptr) {
1370 // Create the appropriate IfException/IfSuccess projections.
1371 Node* const if_exception =
1372 graph()->NewNode(common()->IfException(), *control, *effect);
1373 Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
1374 if_exceptions->push_back(if_exception);
1375 *control = if_success;
1376 }
1377 return value;
1378 }
1379
1380 Node* JSNativeContextSpecialization::InlinePropertySetterCall(
1381 Node* receiver, Node* value, Node* context, Node* frame_state,
1382 Node** effect, Node** control, ZoneVector<Node*>* if_exceptions,
1383 PropertyAccessInfo const& access_info) {
1384 Node* target = jsgraph()->Constant(access_info.constant());
1385 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
1386 Handle<SharedFunctionInfo> shared_info =
1387 frame_info.shared_info().ToHandleChecked();
1388 // We need a FrameState for the setter stub to restore the correct
1389 // context and return the appropriate value to fullcodegen.
1390 FrameStateFunctionInfo const* frame_info0 =
1391 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub, 2, 0,
1392 shared_info);
1393 Node* frame_state0 = graph()->NewNode(
1394 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
1395 frame_info0),
1396 graph()->NewNode(common()->StateValues(2, SparseInputMask::Dense()),
1397 receiver, value),
1398 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(), context,
1399 target, frame_state);
1400
1401 // Introduce the call to the setter function.
1402 if (access_info.constant()->IsJSFunction()) {
1403 *effect = *control = graph()->NewNode(
1404 jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
1405 ConvertReceiverMode::kNotNullOrUndefined),
1406 target, receiver, value, context, frame_state0, *effect, *control);
1407 } else {
1408 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1409 Handle<FunctionTemplateInfo> function_template_info(
1410 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1411 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1412 value = InlineApiCall(receiver, context, target, frame_state0, value,
1413 effect, control, shared_info, function_template_info);
1414 }
1415 // Remember to rewire the IfException edge if this is inside a try-block.
1416 if (if_exceptions != nullptr) {
1417 // Create the appropriate IfException/IfSuccess projections.
1418 Node* const if_exception =
1419 graph()->NewNode(common()->IfException(), *control, *effect);
1420 Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
1421 if_exceptions->push_back(if_exception);
1422 *control = if_success;
1423 }
1424 return value;
1425 }
1426
1427 Node* JSNativeContextSpecialization::InlineApiCall(
1428 Node* receiver, Node* context, Node* target, Node* frame_state, Node* value,
1429 Node** effect, Node** control, Handle<SharedFunctionInfo> shared_info,
1430 Handle<FunctionTemplateInfo> function_template_info) {
1431 Handle<CallHandlerInfo> call_handler_info = handle(
1432 CallHandlerInfo::cast(function_template_info->call_code()), isolate());
1433 Handle<Object> call_data_object(call_handler_info->data(), isolate());
1434
1435 // Only setters have a value.
1436 int const argc = value == nullptr ? 0 : 1;
1437 // The stub always expects the receiver as the first param on the stack.
1438 CallApiCallbackStub stub(
1439 isolate(), argc,
1440 true /* FunctionTemplateInfo doesn't have an associated context. */);
1441 CallInterfaceDescriptor call_interface_descriptor =
1442 stub.GetCallInterfaceDescriptor();
1443 CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
1444 isolate(), graph()->zone(), call_interface_descriptor,
1445 call_interface_descriptor.GetStackParameterCount() + argc +
1446 1 /* implicit receiver */,
1447 CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
1448 MachineType::AnyTagged(), 1);
1449
1450 Node* data = jsgraph()->Constant(call_data_object);
1451 ApiFunction function(v8::ToCData<Address>(call_handler_info->callback()));
1452 Node* function_reference =
1453 graph()->NewNode(common()->ExternalConstant(ExternalReference(
1454 &function, ExternalReference::DIRECT_API_CALL, isolate())));
1455 Node* code = jsgraph()->HeapConstant(stub.GetCode());
1456
1457 // Add CallApiCallbackStub's register argument as well.
1458 Node* inputs[11] = {
1459 code, target, data, receiver /* holder */, function_reference, receiver};
1460 int index = 6 + argc;
1461 inputs[index++] = context;
1462 inputs[index++] = frame_state;
1463 inputs[index++] = *effect;
1464 inputs[index++] = *control;
1465 // This needs to stay here because of the edge case described in
1466 // http://crbug.com/675648.
1467 if (value != nullptr) {
1468 inputs[6] = value;
1469 }
1470
1471 return *effect = *control =
1472 graph()->NewNode(common()->Call(call_descriptor), index, inputs);
1473 }
1474
1475 JSNativeContextSpecialization::ValueEffectControl
1476 JSNativeContextSpecialization::BuildPropertyLoad(
1477 Node* receiver, Node* context, Node* frame_state, Node* effect,
1478 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
1479 PropertyAccessInfo const& access_info, LanguageMode language_mode) {
1480 // Determine actual holder and perform prototype chain checks.
1481 Handle<JSObject> holder;
1482 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
1483 if (access_info.holder().ToHandle(&holder)) {
1484 access_builder.AssumePrototypesStable(native_context(),
1485 access_info.receiver_maps(), holder);
1486 }
1487
1488 // Generate the actual property access.
1489 Node* value;
1490 if (access_info.IsNotFound()) {
1491 value = jsgraph()->UndefinedConstant();
1492 } else if (access_info.IsDataConstant()) {
1493 DCHECK(!FLAG_track_constant_fields);
1494 value = jsgraph()->Constant(access_info.constant());
1495 } else if (access_info.IsAccessorConstant()) {
1496 value = InlinePropertyGetterCall(receiver, context, frame_state, &effect,
1497 &control, if_exceptions, access_info);
1498 } else {
1499 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
1500 value = access_builder.BuildLoadDataField(name, access_info, receiver,
1501 &effect, &control);
1502 }
1503
1504 return ValueEffectControl(value, effect, control);
1505 }
1506
1350 JSNativeContextSpecialization::ValueEffectControl 1507 JSNativeContextSpecialization::ValueEffectControl
1351 JSNativeContextSpecialization::BuildPropertyAccess( 1508 JSNativeContextSpecialization::BuildPropertyAccess(
1352 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, 1509 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
1353 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions, 1510 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
1354 PropertyAccessInfo const& access_info, AccessMode access_mode, 1511 PropertyAccessInfo const& access_info, AccessMode access_mode,
1355 LanguageMode language_mode) { 1512 LanguageMode language_mode) {
1513 switch (access_mode) {
1514 case AccessMode::kLoad:
1515 return BuildPropertyLoad(receiver, context, frame_state, effect, control,
1516 name, if_exceptions, access_info, language_mode);
1517 case AccessMode::kStore:
1518 case AccessMode::kStoreInLiteral:
1519 return BuildPropertyStore(receiver, value, context, frame_state, effect,
1520 control, name, if_exceptions, access_info,
1521 access_mode, language_mode);
1522 }
1523 UNREACHABLE();
1524 return ValueEffectControl();
1525 }
1526
1527 JSNativeContextSpecialization::ValueEffectControl
1528 JSNativeContextSpecialization::BuildPropertyStore(
1529 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
1530 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
1531 PropertyAccessInfo const& access_info, AccessMode access_mode,
1532 LanguageMode language_mode) {
1356 // Determine actual holder and perform prototype chain checks. 1533 // Determine actual holder and perform prototype chain checks.
1357 Handle<JSObject> holder; 1534 Handle<JSObject> holder;
1535 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
1358 if (access_info.holder().ToHandle(&holder)) { 1536 if (access_info.holder().ToHandle(&holder)) {
1359 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); 1537 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
1360 AssumePrototypesStable(access_info.receiver_maps(), holder); 1538 access_builder.AssumePrototypesStable(native_context(),
1361 } 1539 access_info.receiver_maps(), holder);
1540 }
1541
1542 DCHECK(!access_info.IsNotFound());
1362 1543
1363 // Generate the actual property access. 1544 // Generate the actual property access.
1364 if (access_info.IsNotFound()) { 1545 if (access_info.IsDataConstant()) {
1365 DCHECK_EQ(AccessMode::kLoad, access_mode);
1366 value = jsgraph()->UndefinedConstant();
1367 } else if (access_info.IsDataConstant()) {
1368 DCHECK(!FLAG_track_constant_fields); 1546 DCHECK(!FLAG_track_constant_fields);
1369 Node* constant_value = jsgraph()->Constant(access_info.constant()); 1547 Node* constant_value = jsgraph()->Constant(access_info.constant());
1370 if (access_mode == AccessMode::kStore) { 1548 Node* check =
1371 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), value, 1549 graph()->NewNode(simplified()->ReferenceEqual(), value, constant_value);
1372 constant_value); 1550 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1373 effect =
1374 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1375 }
1376 value = constant_value; 1551 value = constant_value;
1377 } else if (access_info.IsAccessorConstant()) { 1552 } else if (access_info.IsAccessorConstant()) {
1378 Node* target = jsgraph()->Constant(access_info.constant()); 1553 value =
1379 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); 1554 InlinePropertySetterCall(receiver, value, context, frame_state, &effect,
1380 Handle<SharedFunctionInfo> shared_info = 1555 &control, if_exceptions, access_info);
1381 frame_info.shared_info().ToHandleChecked();
1382 switch (access_mode) {
1383 case AccessMode::kLoad: {
1384 // We need a FrameState for the getter stub to restore the correct
1385 // context before returning to unoptimized code.
1386 FrameStateFunctionInfo const* frame_info0 =
1387 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub,
1388 1, 0, shared_info);
1389 Node* frame_state0 = graph()->NewNode(
1390 common()->FrameState(BailoutId::None(),
1391 OutputFrameStateCombine::Ignore(),
1392 frame_info0),
1393 graph()->NewNode(common()->StateValues(1, SparseInputMask::Dense()),
1394 receiver),
1395 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
1396 context, target, frame_state);
1397
1398 // Introduce the call to the getter function.
1399 if (access_info.constant()->IsJSFunction()) {
1400 value = effect = control = graph()->NewNode(
1401 javascript()->Call(2, CallFrequency(), VectorSlotPair(),
1402 ConvertReceiverMode::kNotNullOrUndefined),
1403 target, receiver, context, frame_state0, effect, control);
1404 } else {
1405 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1406 Handle<FunctionTemplateInfo> function_template_info(
1407 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1408 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1409 ValueEffectControl value_effect_control = InlineApiCall(
1410 receiver, context, target, frame_state0, nullptr, effect, control,
1411 shared_info, function_template_info);
1412 value = value_effect_control.value();
1413 effect = value_effect_control.effect();
1414 control = value_effect_control.control();
1415 }
1416 break;
1417 }
1418 case AccessMode::kStore: {
1419 // We need a FrameState for the setter stub to restore the correct
1420 // context and return the appropriate value to unoptimized code.
1421 FrameStateFunctionInfo const* frame_info0 =
1422 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub,
1423 2, 0, shared_info);
1424 Node* frame_state0 = graph()->NewNode(
1425 common()->FrameState(BailoutId::None(),
1426 OutputFrameStateCombine::Ignore(),
1427 frame_info0),
1428 graph()->NewNode(common()->StateValues(2, SparseInputMask::Dense()),
1429 receiver, value),
1430 jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
1431 context, target, frame_state);
1432
1433 // Introduce the call to the setter function.
1434 if (access_info.constant()->IsJSFunction()) {
1435 effect = control = graph()->NewNode(
1436 javascript()->Call(3, CallFrequency(), VectorSlotPair(),
1437 ConvertReceiverMode::kNotNullOrUndefined),
1438 target, receiver, value, context, frame_state0, effect, control);
1439 } else {
1440 DCHECK(access_info.constant()->IsFunctionTemplateInfo());
1441 Handle<FunctionTemplateInfo> function_template_info(
1442 Handle<FunctionTemplateInfo>::cast(access_info.constant()));
1443 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1444 ValueEffectControl value_effect_control = InlineApiCall(
1445 receiver, context, target, frame_state0, value, effect, control,
1446 shared_info, function_template_info);
1447 value = value_effect_control.value();
1448 effect = value_effect_control.effect();
1449 control = value_effect_control.control();
1450 }
1451 break;
1452 }
1453 case AccessMode::kStoreInLiteral: {
1454 UNREACHABLE();
1455 break;
1456 }
1457 }
1458 // Remember to rewire the IfException edge if this is inside a try-block.
1459 if (if_exceptions != nullptr) {
1460 // Create the appropriate IfException/IfSuccess projections.
1461 Node* const if_exception =
1462 graph()->NewNode(common()->IfException(), control, effect);
1463 Node* const if_success = graph()->NewNode(common()->IfSuccess(), control);
1464 if_exceptions->push_back(if_exception);
1465 control = if_success;
1466 }
1467 } else { 1556 } else {
1468 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField()); 1557 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
1469 FieldIndex const field_index = access_info.field_index(); 1558 FieldIndex const field_index = access_info.field_index();
1470 Type* const field_type = access_info.field_type(); 1559 Type* const field_type = access_info.field_type();
1471 MachineRepresentation const field_representation = 1560 MachineRepresentation const field_representation =
1472 access_info.field_representation(); 1561 access_info.field_representation();
1473 if (access_mode == AccessMode::kLoad) {
1474 if (access_info.holder().ToHandle(&holder)) {
1475 receiver = jsgraph()->Constant(holder);
1476 }
1477 // Optimize immutable property loads.
1478 HeapObjectMatcher m(receiver);
1479 if (m.HasValue() && m.Value()->IsJSObject()) {
1480 // TODO(ishell): Use something simpler like
1481 //
1482 // Handle<Object> value =
1483 // JSObject::FastPropertyAt(Handle<JSObject>::cast(m.Value()),
1484 // Representation::Tagged(), field_index);
1485 //
1486 // here, once we have the immutable bit in the access_info.
1487
1488 // TODO(turbofan): Given that we already have the field_index here, we
1489 // might be smarter in the future and not rely on the LookupIterator,
1490 // but for now let's just do what Crankshaft does.
1491 LookupIterator it(m.Value(), name,
1492 LookupIterator::OWN_SKIP_INTERCEPTOR);
1493 if (it.state() == LookupIterator::DATA) {
1494 bool is_reaonly_non_configurable =
1495 it.IsReadOnly() && !it.IsConfigurable();
1496 if (is_reaonly_non_configurable ||
1497 (FLAG_track_constant_fields &&
1498 access_info.IsDataConstantField())) {
1499 Node* value = jsgraph()->Constant(JSReceiver::GetDataProperty(&it));
1500 if (!is_reaonly_non_configurable) {
1501 // It's necessary to add dependency on the map that introduced
1502 // the field.
1503 DCHECK(access_info.IsDataConstantField());
1504 DCHECK(!it.is_dictionary_holder());
1505 Handle<Map> field_owner_map = it.GetFieldOwnerMap();
1506 dependencies()->AssumeFieldOwner(field_owner_map);
1507 }
1508 return ValueEffectControl(value, effect, control);
1509 }
1510 }
1511 }
1512 }
1513 Node* storage = receiver; 1562 Node* storage = receiver;
1514 if (!field_index.is_inobject()) { 1563 if (!field_index.is_inobject()) {
1515 storage = effect = graph()->NewNode( 1564 storage = effect = graph()->NewNode(
1516 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), 1565 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
1517 storage, effect, control); 1566 storage, effect, control);
1518 } 1567 }
1519 FieldAccess field_access = { 1568 FieldAccess field_access = {
1520 kTaggedBase, 1569 kTaggedBase,
1521 field_index.offset(), 1570 field_index.offset(),
1522 name, 1571 name,
1523 MaybeHandle<Map>(), 1572 MaybeHandle<Map>(),
1524 field_type, 1573 field_type,
1525 MachineType::TypeForRepresentation(field_representation), 1574 MachineType::TypeForRepresentation(field_representation),
1526 kFullWriteBarrier}; 1575 kFullWriteBarrier};
1527 if (access_mode == AccessMode::kLoad) { 1576 bool store_to_constant_field = FLAG_track_constant_fields &&
1528 if (field_representation == MachineRepresentation::kFloat64) { 1577 (access_mode == AccessMode::kStore) &&
1578 access_info.IsDataConstantField();
1579
1580 DCHECK(access_mode == AccessMode::kStore ||
1581 access_mode == AccessMode::kStoreInLiteral);
1582 switch (field_representation) {
1583 case MachineRepresentation::kFloat64: {
1584 value = effect = graph()->NewNode(simplified()->CheckNumber(), value,
1585 effect, control);
1529 if (!field_index.is_inobject() || field_index.is_hidden_field() || 1586 if (!field_index.is_inobject() || field_index.is_hidden_field() ||
1530 !FLAG_unbox_double_fields) { 1587 !FLAG_unbox_double_fields) {
1531 FieldAccess const storage_access = {kTaggedBase, 1588 if (access_info.HasTransitionMap()) {
1532 field_index.offset(), 1589 // Allocate a MutableHeapNumber for the new property.
1533 name, 1590 effect = graph()->NewNode(
1534 MaybeHandle<Map>(), 1591 common()->BeginRegion(RegionObservability::kNotObservable),
1535 Type::OtherInternal(), 1592 effect);
1536 MachineType::TaggedPointer(), 1593 Node* box = effect = graph()->NewNode(
1537 kPointerWriteBarrier}; 1594 simplified()->Allocate(Type::OtherInternal(), NOT_TENURED),
1538 storage = effect = 1595 jsgraph()->Constant(HeapNumber::kSize), effect, control);
1539 graph()->NewNode(simplified()->LoadField(storage_access), storage, 1596 effect = graph()->NewNode(
1540 effect, control); 1597 simplified()->StoreField(AccessBuilder::ForMap()), box,
1541 field_access.offset = HeapNumber::kValueOffset; 1598 jsgraph()->HeapConstant(factory()->mutable_heap_number_map()),
1542 field_access.name = MaybeHandle<Name>(); 1599 effect, control);
1543 } 1600 effect = graph()->NewNode(
1544 } else if (field_representation == 1601 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()),
1545 MachineRepresentation::kTaggedPointer) { 1602 box, value, effect, control);
1546 // Remember the map of the field value, if its map is stable. This is 1603 value = effect =
1547 // used by the LoadElimination to eliminate map checks on the result. 1604 graph()->NewNode(common()->FinishRegion(), box, effect);
1548 Handle<Map> field_map; 1605
1549 if (access_info.field_map().ToHandle(&field_map)) { 1606 field_access.type = Type::Any();
1550 if (field_map->is_stable()) { 1607 field_access.machine_type = MachineType::TaggedPointer();
1551 dependencies()->AssumeMapStable(field_map); 1608 field_access.write_barrier_kind = kPointerWriteBarrier;
1552 field_access.map = field_map; 1609 } else {
1610 // We just store directly to the MutableHeapNumber.
1611 FieldAccess const storage_access = {kTaggedBase,
1612 field_index.offset(),
1613 name,
1614 MaybeHandle<Map>(),
1615 Type::OtherInternal(),
1616 MachineType::TaggedPointer(),
1617 kPointerWriteBarrier};
1618 storage = effect =
1619 graph()->NewNode(simplified()->LoadField(storage_access),
1620 storage, effect, control);
1621 field_access.offset = HeapNumber::kValueOffset;
1622 field_access.name = MaybeHandle<Name>();
1623 field_access.machine_type = MachineType::Float64();
1553 } 1624 }
1554 } 1625 }
1626 if (store_to_constant_field) {
1627 DCHECK(!access_info.HasTransitionMap());
1628 // If the field is constant check that the value we are going
1629 // to store matches current value.
1630 Node* current_value = effect = graph()->NewNode(
1631 simplified()->LoadField(field_access), storage, effect, control);
1632
1633 Node* check = graph()->NewNode(simplified()->NumberEqual(),
1634 current_value, value);
1635 effect =
1636 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1637 return ValueEffectControl(value, effect, control);
1638 }
1639 break;
1555 } 1640 }
1556 value = effect = graph()->NewNode(simplified()->LoadField(field_access), 1641 case MachineRepresentation::kTaggedSigned:
1557 storage, effect, control); 1642 case MachineRepresentation::kTaggedPointer:
1558 } else { 1643 case MachineRepresentation::kTagged:
1559 bool store_to_constant_field = FLAG_track_constant_fields && 1644 if (store_to_constant_field) {
1560 (access_mode == AccessMode::kStore) && 1645 DCHECK(!access_info.HasTransitionMap());
1561 access_info.IsDataConstantField(); 1646 // If the field is constant check that the value we are going
1647 // to store matches current value.
1648 Node* current_value = effect = graph()->NewNode(
1649 simplified()->LoadField(field_access), storage, effect, control);
1562 1650
1563 DCHECK(access_mode == AccessMode::kStore || 1651 Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
1564 access_mode == AccessMode::kStoreInLiteral); 1652 current_value, value);
1565 switch (field_representation) { 1653 effect =
1566 case MachineRepresentation::kFloat64: { 1654 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1567 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, 1655 return ValueEffectControl(value, effect, control);
1656 }
1657
1658 if (field_representation == MachineRepresentation::kTaggedSigned) {
1659 value = effect = graph()->NewNode(simplified()->CheckSmi(), value,
1568 effect, control); 1660 effect, control);
1569 if (!field_index.is_inobject() || field_index.is_hidden_field() || 1661 field_access.write_barrier_kind = kNoWriteBarrier;
1570 !FLAG_unbox_double_fields) {
1571 if (access_info.HasTransitionMap()) {
1572 // Allocate a MutableHeapNumber for the new property.
1573 effect = graph()->NewNode(
1574 common()->BeginRegion(RegionObservability::kNotObservable),
1575 effect);
1576 Node* box = effect = graph()->NewNode(
1577 simplified()->Allocate(Type::OtherInternal(), NOT_TENURED),
1578 jsgraph()->Constant(HeapNumber::kSize), effect, control);
1579 effect = graph()->NewNode(
1580 simplified()->StoreField(AccessBuilder::ForMap()), box,
1581 jsgraph()->HeapConstant(factory()->mutable_heap_number_map()),
1582 effect, control);
1583 effect = graph()->NewNode(
1584 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()),
1585 box, value, effect, control);
1586 value = effect =
1587 graph()->NewNode(common()->FinishRegion(), box, effect);
1588 1662
1589 field_access.type = Type::Any(); 1663 } else if (field_representation ==
1590 field_access.machine_type = MachineType::TaggedPointer(); 1664 MachineRepresentation::kTaggedPointer) {
1591 field_access.write_barrier_kind = kPointerWriteBarrier; 1665 // Ensure that {value} is a HeapObject.
1592 } else { 1666 value = access_builder.BuildCheckHeapObject(value, &effect, control);
1593 // We just store directly to the MutableHeapNumber. 1667 Handle<Map> field_map;
1594 FieldAccess const storage_access = {kTaggedBase, 1668 if (access_info.field_map().ToHandle(&field_map)) {
1595 field_index.offset(), 1669 // Emit a map check for the value.
1596 name, 1670 effect = graph()->NewNode(
1597 MaybeHandle<Map>(), 1671 simplified()->CheckMaps(CheckMapsFlag::kNone,
1598 Type::OtherInternal(), 1672 ZoneHandleSet<Map>(field_map)),
1599 MachineType::TaggedPointer(), 1673 value, effect, control);
1600 kPointerWriteBarrier};
1601 storage = effect =
1602 graph()->NewNode(simplified()->LoadField(storage_access),
1603 storage, effect, control);
1604 field_access.offset = HeapNumber::kValueOffset;
1605 field_access.name = MaybeHandle<Name>();
1606 field_access.machine_type = MachineType::Float64();
1607 }
1608 } 1674 }
1609 if (store_to_constant_field) { 1675 field_access.write_barrier_kind = kPointerWriteBarrier;
1610 DCHECK(!access_info.HasTransitionMap());
1611 // If the field is constant check that the value we are going
1612 // to store matches current value.
1613 Node* current_value = effect =
1614 graph()->NewNode(simplified()->LoadField(field_access), storage,
1615 effect, control);
1616 1676
1617 Node* check = graph()->NewNode(simplified()->NumberEqual(), 1677 } else {
1618 current_value, value); 1678 DCHECK_EQ(MachineRepresentation::kTagged, field_representation);
1619 effect = graph()->NewNode(simplified()->CheckIf(), check, effect,
1620 control);
1621 return ValueEffectControl(value, effect, control);
1622 }
1623 break;
1624 } 1679 }
1625 case MachineRepresentation::kTaggedSigned: 1680 break;
1626 case MachineRepresentation::kTaggedPointer: 1681 case MachineRepresentation::kNone:
1627 case MachineRepresentation::kTagged: 1682 case MachineRepresentation::kBit:
1628 if (store_to_constant_field) { 1683 case MachineRepresentation::kWord8:
1629 DCHECK(!access_info.HasTransitionMap()); 1684 case MachineRepresentation::kWord16:
1630 // If the field is constant check that the value we are going 1685 case MachineRepresentation::kWord32:
1631 // to store matches current value. 1686 case MachineRepresentation::kWord64:
1632 Node* current_value = effect = 1687 case MachineRepresentation::kFloat32:
1633 graph()->NewNode(simplified()->LoadField(field_access), storage, 1688 case MachineRepresentation::kSimd128:
1634 effect, control); 1689 UNREACHABLE();
1690 break;
1691 }
1692 // Check if we need to perform a transitioning store.
1693 Handle<Map> transition_map;
1694 if (access_info.transition_map().ToHandle(&transition_map)) {
1695 // Check if we need to grow the properties backing store
1696 // with this transitioning store.
1697 Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
1698 isolate());
1699 if (original_map->unused_property_fields() == 0) {
1700 DCHECK(!field_index.is_inobject());
1635 1701
1636 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), 1702 // Reallocate the properties {storage}.
1637 current_value, value); 1703 storage = effect = BuildExtendPropertiesBackingStore(
1638 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, 1704 original_map, storage, effect, control);
1639 control);
1640 return ValueEffectControl(value, effect, control);
1641 }
1642 1705
1643 if (field_representation == MachineRepresentation::kTaggedSigned) { 1706 // Perform the actual store.
1644 value = effect = graph()->NewNode(simplified()->CheckSmi(), value,
1645 effect, control);
1646 field_access.write_barrier_kind = kNoWriteBarrier;
1647
1648 } else if (field_representation ==
1649 MachineRepresentation::kTaggedPointer) {
1650 // Ensure that {value} is a HeapObject.
1651 value = BuildCheckHeapObject(value, &effect, control);
1652 Handle<Map> field_map;
1653 if (access_info.field_map().ToHandle(&field_map)) {
1654 // Emit a map check for the value.
1655 effect = graph()->NewNode(
1656 simplified()->CheckMaps(CheckMapsFlag::kNone,
1657 ZoneHandleSet<Map>(field_map)),
1658 value, effect, control);
1659 }
1660 field_access.write_barrier_kind = kPointerWriteBarrier;
1661
1662 } else {
1663 DCHECK_EQ(MachineRepresentation::kTagged, field_representation);
1664 }
1665 break;
1666 case MachineRepresentation::kNone:
1667 case MachineRepresentation::kBit:
1668 case MachineRepresentation::kWord8:
1669 case MachineRepresentation::kWord16:
1670 case MachineRepresentation::kWord32:
1671 case MachineRepresentation::kWord64:
1672 case MachineRepresentation::kFloat32:
1673 case MachineRepresentation::kSimd128:
1674 UNREACHABLE();
1675 break;
1676 }
1677 // Check if we need to perform a transitioning store.
1678 Handle<Map> transition_map;
1679 if (access_info.transition_map().ToHandle(&transition_map)) {
1680 // Check if we need to grow the properties backing store
1681 // with this transitioning store.
1682 Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
1683 isolate());
1684 if (original_map->unused_property_fields() == 0) {
1685 DCHECK(!field_index.is_inobject());
1686
1687 // Reallocate the properties {storage}.
1688 storage = effect = BuildExtendPropertiesBackingStore(
1689 original_map, storage, effect, control);
1690
1691 // Perform the actual store.
1692 effect = graph()->NewNode(simplified()->StoreField(field_access),
1693 storage, value, effect, control);
1694
1695 // Atomically switch to the new properties below.
1696 field_access = AccessBuilder::ForJSObjectProperties();
1697 value = storage;
1698 storage = receiver;
1699 }
1700 effect = graph()->NewNode(
1701 common()->BeginRegion(RegionObservability::kObservable), effect);
1702 effect = graph()->NewNode(
1703 simplified()->StoreField(AccessBuilder::ForMap()), receiver,
1704 jsgraph()->Constant(transition_map), effect, control);
1705 effect = graph()->NewNode(simplified()->StoreField(field_access), 1707 effect = graph()->NewNode(simplified()->StoreField(field_access),
1706 storage, value, effect, control); 1708 storage, value, effect, control);
1707 effect = graph()->NewNode(common()->FinishRegion(), 1709
1708 jsgraph()->UndefinedConstant(), effect); 1710 // Atomically switch to the new properties below.
1709 } else { 1711 field_access = AccessBuilder::ForJSObjectProperties();
1710 // Regular non-transitioning field store. 1712 value = storage;
1711 effect = graph()->NewNode(simplified()->StoreField(field_access), 1713 storage = receiver;
1712 storage, value, effect, control);
1713 } 1714 }
1715 effect = graph()->NewNode(
1716 common()->BeginRegion(RegionObservability::kObservable), effect);
1717 effect = graph()->NewNode(
1718 simplified()->StoreField(AccessBuilder::ForMap()), receiver,
1719 jsgraph()->Constant(transition_map), effect, control);
1720 effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
1721 value, effect, control);
1722 effect = graph()->NewNode(common()->FinishRegion(),
1723 jsgraph()->UndefinedConstant(), effect);
1724 } else {
1725 // Regular non-transitioning field store.
1726 effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
1727 value, effect, control);
1714 } 1728 }
1715 } 1729 }
1716 1730
1717 return ValueEffectControl(value, effect, control); 1731 return ValueEffectControl(value, effect, control);
1718 } 1732 }
1719 1733
1720 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( 1734 Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
1721 Node* node) { 1735 Node* node) {
1722 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); 1736 DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());
1723 1737
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 receiver_map, cached_name, AccessMode::kStoreInLiteral, 1770 receiver_map, cached_name, AccessMode::kStoreInLiteral,
1757 &access_info)) { 1771 &access_info)) {
1758 return NoChange(); 1772 return NoChange();
1759 } 1773 }
1760 1774
1761 Node* receiver = NodeProperties::GetValueInput(node, 0); 1775 Node* receiver = NodeProperties::GetValueInput(node, 0);
1762 Node* effect = NodeProperties::GetEffectInput(node); 1776 Node* effect = NodeProperties::GetEffectInput(node);
1763 Node* control = NodeProperties::GetControlInput(node); 1777 Node* control = NodeProperties::GetControlInput(node);
1764 1778
1765 // Monomorphic property access. 1779 // Monomorphic property access.
1766 receiver = BuildCheckHeapObject(receiver, &effect, control); 1780 PropertyAccessBuilder access_builder(jsgraph(), dependencies());
1767 1781 receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
1768 effect = 1782 access_builder.BuildCheckMaps(receiver, &effect, control,
1769 BuildCheckMaps(receiver, effect, control, access_info.receiver_maps()); 1783 access_info.receiver_maps());
1770 1784
1771 // Ensure that {name} matches the cached name. 1785 // Ensure that {name} matches the cached name.
1772 Node* name = NodeProperties::GetValueInput(node, 1); 1786 Node* name = NodeProperties::GetValueInput(node, 1);
1773 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name, 1787 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name,
1774 jsgraph()->HeapConstant(cached_name)); 1788 jsgraph()->HeapConstant(cached_name));
1775 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); 1789 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1776 1790
1777 Node* value = NodeProperties::GetValueInput(node, 2); 1791 Node* value = NodeProperties::GetValueInput(node, 2);
1778 Node* context = NodeProperties::GetContextInput(node); 1792 Node* context = NodeProperties::GetContextInput(node);
1779 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); 1793 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
2100 2114
2101 // Perform the actual element access. 2115 // Perform the actual element access.
2102 effect = graph()->NewNode(simplified()->StoreElement(element_access), 2116 effect = graph()->NewNode(simplified()->StoreElement(element_access),
2103 elements, index, value, effect, control); 2117 elements, index, value, effect, control);
2104 } 2118 }
2105 } 2119 }
2106 2120
2107 return ValueEffectControl(value, effect, control); 2121 return ValueEffectControl(value, effect, control);
2108 } 2122 }
2109 2123
2110 JSNativeContextSpecialization::ValueEffectControl
2111 JSNativeContextSpecialization::InlineApiCall(
2112 Node* receiver, Node* context, Node* target, Node* frame_state, Node* value,
2113 Node* effect, Node* control, Handle<SharedFunctionInfo> shared_info,
2114 Handle<FunctionTemplateInfo> function_template_info) {
2115 Handle<CallHandlerInfo> call_handler_info = handle(
2116 CallHandlerInfo::cast(function_template_info->call_code()), isolate());
2117 Handle<Object> call_data_object(call_handler_info->data(), isolate());
2118
2119 // Only setters have a value.
2120 int const argc = value == nullptr ? 0 : 1;
2121 // The stub always expects the receiver as the first param on the stack.
2122 CallApiCallbackStub stub(
2123 isolate(), argc,
2124 true /* FunctionTemplateInfo doesn't have an associated context. */);
2125 CallInterfaceDescriptor call_interface_descriptor =
2126 stub.GetCallInterfaceDescriptor();
2127 CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
2128 isolate(), graph()->zone(), call_interface_descriptor,
2129 call_interface_descriptor.GetStackParameterCount() + argc +
2130 1 /* implicit receiver */,
2131 CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
2132 MachineType::AnyTagged(), 1);
2133
2134 Node* data = jsgraph()->Constant(call_data_object);
2135 ApiFunction function(v8::ToCData<Address>(call_handler_info->callback()));
2136 Node* function_reference =
2137 graph()->NewNode(common()->ExternalConstant(ExternalReference(
2138 &function, ExternalReference::DIRECT_API_CALL, isolate())));
2139 Node* code = jsgraph()->HeapConstant(stub.GetCode());
2140
2141 // Add CallApiCallbackStub's register argument as well.
2142 Node* inputs[11] = {
2143 code, target, data, receiver /* holder */, function_reference, receiver};
2144 int index = 6 + argc;
2145 inputs[index++] = context;
2146 inputs[index++] = frame_state;
2147 inputs[index++] = effect;
2148 inputs[index++] = control;
2149 // This needs to stay here because of the edge case described in
2150 // http://crbug.com/675648.
2151 if (value != nullptr) {
2152 inputs[6] = value;
2153 }
2154
2155 Node* control0;
2156 Node* effect0;
2157 Node* value0 = effect0 = control0 =
2158 graph()->NewNode(common()->Call(call_descriptor), index, inputs);
2159 return ValueEffectControl(value0, effect0, control0);
2160 }
2161
2162 Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
2163 Node** effect,
2164 Node* control) {
2165 switch (receiver->opcode()) {
2166 case IrOpcode::kHeapConstant:
2167 case IrOpcode::kJSCreate:
2168 case IrOpcode::kJSCreateArguments:
2169 case IrOpcode::kJSCreateArray:
2170 case IrOpcode::kJSCreateClosure:
2171 case IrOpcode::kJSCreateIterResultObject:
2172 case IrOpcode::kJSCreateLiteralArray:
2173 case IrOpcode::kJSCreateLiteralObject:
2174 case IrOpcode::kJSCreateLiteralRegExp:
2175 case IrOpcode::kJSConvertReceiver:
2176 case IrOpcode::kJSToName:
2177 case IrOpcode::kJSToString:
2178 case IrOpcode::kJSToObject:
2179 case IrOpcode::kJSTypeOf: {
2180 return receiver;
2181 }
2182 default: {
2183 return *effect = graph()->NewNode(simplified()->CheckHeapObject(),
2184 receiver, *effect, control);
2185 }
2186 }
2187 }
2188
2189 Node* JSNativeContextSpecialization::BuildCheckMaps(
2190 Node* receiver, Node* effect, Node* control,
2191 MapHandles const& receiver_maps) {
2192 HeapObjectMatcher m(receiver);
2193 if (m.HasValue()) {
2194 Handle<Map> receiver_map(m.Value()->map(), isolate());
2195 if (receiver_map->is_stable()) {
2196 for (Handle<Map> map : receiver_maps) {
2197 if (map.is_identical_to(receiver_map)) {
2198 dependencies()->AssumeMapStable(receiver_map);
2199 return effect;
2200 }
2201 }
2202 }
2203 }
2204 ZoneHandleSet<Map> maps;
2205 CheckMapsFlags flags = CheckMapsFlag::kNone;
2206 for (Handle<Map> map : receiver_maps) {
2207 maps.insert(map, graph()->zone());
2208 if (map->is_migration_target()) {
2209 flags |= CheckMapsFlag::kTryMigrateInstance;
2210 }
2211 }
2212 return graph()->NewNode(simplified()->CheckMaps(flags, maps), receiver,
2213 effect, control);
2214 }
2215
2216 Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( 2124 Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
2217 Handle<Map> map, Node* properties, Node* effect, Node* control) { 2125 Handle<Map> map, Node* properties, Node* effect, Node* control) {
2218 // TODO(bmeurer/jkummerow): Property deletions can undo map transitions 2126 // TODO(bmeurer/jkummerow): Property deletions can undo map transitions
2219 // while keeping the backing store around, meaning that even though the 2127 // while keeping the backing store around, meaning that even though the
2220 // map might believe that objects have no unused property fields, there 2128 // map might believe that objects have no unused property fields, there
2221 // might actually be some. It would be nice to not create a new backing 2129 // might actually be some. It would be nice to not create a new backing
2222 // store in that case (i.e. when properties->length() >= new_length). 2130 // store in that case (i.e. when properties->length() >= new_length).
2223 // However, introducing branches and Phi nodes here would make it more 2131 // However, introducing branches and Phi nodes here would make it more
2224 // difficult for escape analysis to get rid of the backing stores used 2132 // difficult for escape analysis to get rid of the backing stores used
2225 // for intermediate states of chains of property additions. That makes 2133 // for intermediate states of chains of property additions. That makes
(...skipping 28 matching lines...) Expand all
2254 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), 2162 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
2255 new_properties, jsgraph()->Constant(new_length), effect, control); 2163 new_properties, jsgraph()->Constant(new_length), effect, control);
2256 for (int i = 0; i < new_length; ++i) { 2164 for (int i = 0; i < new_length; ++i) {
2257 effect = graph()->NewNode( 2165 effect = graph()->NewNode(
2258 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), 2166 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)),
2259 new_properties, values[i], effect, control); 2167 new_properties, values[i], effect, control);
2260 } 2168 }
2261 return graph()->NewNode(common()->FinishRegion(), new_properties, effect); 2169 return graph()->NewNode(common()->FinishRegion(), new_properties, effect);
2262 } 2170 }
2263 2171
2264 void JSNativeContextSpecialization::AssumePrototypesStable(
2265 MapHandles const& receiver_maps, Handle<JSObject> holder) {
2266 // Determine actual holder and perform prototype chain checks.
2267 for (auto map : receiver_maps) {
2268 // Perform the implicit ToObject for primitives here.
2269 // Implemented according to ES6 section 7.3.2 GetV (V, P).
2270 Handle<JSFunction> constructor;
2271 if (Map::GetConstructorFunction(map, native_context())
2272 .ToHandle(&constructor)) {
2273 map = handle(constructor->initial_map(), isolate());
2274 }
2275 dependencies()->AssumePrototypeMapsStable(map, holder);
2276 }
2277 }
2278
2279 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined( 2172 bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
2280 MapHandles const& receiver_maps) { 2173 MapHandles const& receiver_maps) {
2281 // Check if the array prototype chain is intact. 2174 // Check if the array prototype chain is intact.
2282 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false; 2175 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false;
2283 2176
2284 // Make sure both the initial Array and Object prototypes are stable. 2177 // Make sure both the initial Array and Object prototypes are stable.
2285 Handle<JSObject> initial_array_prototype( 2178 Handle<JSObject> initial_array_prototype(
2286 native_context()->initial_array_prototype(), isolate()); 2179 native_context()->initial_array_prototype(), isolate());
2287 Handle<JSObject> initial_object_prototype( 2180 Handle<JSObject> initial_object_prototype(
2288 native_context()->initial_object_prototype(), isolate()); 2181 native_context()->initial_object_prototype(), isolate());
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 return jsgraph()->javascript(); 2319 return jsgraph()->javascript();
2427 } 2320 }
2428 2321
2429 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 2322 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
2430 return jsgraph()->simplified(); 2323 return jsgraph()->simplified();
2431 } 2324 }
2432 2325
2433 } // namespace compiler 2326 } // namespace compiler
2434 } // namespace internal 2327 } // namespace internal
2435 } // namespace v8 2328 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/property-access-builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698