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

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

Issue 2002253003: [turbofan] Properly connect DeoptimizeIf/Unless to effect chain. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix JSCallReducer Created 4 years, 7 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-global-object-specialization.cc ('k') | src/compiler/memory-optimizer.cc » ('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"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 // The final states for every polymorphic branch. We join them with 105 // The final states for every polymorphic branch. We join them with
106 // Merge++Phi+EffectPhi at the bottom. 106 // Merge++Phi+EffectPhi at the bottom.
107 ZoneVector<Node*> values(zone()); 107 ZoneVector<Node*> values(zone());
108 ZoneVector<Node*> effects(zone()); 108 ZoneVector<Node*> effects(zone());
109 ZoneVector<Node*> controls(zone()); 109 ZoneVector<Node*> controls(zone());
110 110
111 // Ensure that {index} matches the specified {name} (if {index} is given). 111 // Ensure that {index} matches the specified {name} (if {index} is given).
112 if (index != nullptr) { 112 if (index != nullptr) {
113 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()), 113 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()),
114 index, jsgraph()->HeapConstant(name)); 114 index, jsgraph()->HeapConstant(name));
115 control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 115 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
116 effect, control); 116 frame_state, effect, control);
117 } 117 }
118 118
119 // Check if {receiver} may be a number. 119 // Check if {receiver} may be a number.
120 bool receiverissmi_possible = false; 120 bool receiverissmi_possible = false;
121 for (PropertyAccessInfo const& access_info : access_infos) { 121 for (PropertyAccessInfo const& access_info : access_infos) {
122 if (access_info.receiver_type()->Is(Type::Number())) { 122 if (access_info.receiver_type()->Is(Type::Number())) {
123 receiverissmi_possible = true; 123 receiverissmi_possible = true;
124 break; 124 break;
125 } 125 }
126 } 126 }
127 127
128 // Ensure that {receiver} is a heap object. 128 // Ensure that {receiver} is a heap object.
129 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); 129 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
130 Node* receiverissmi_control = nullptr; 130 Node* receiverissmi_control = nullptr;
131 Node* receiverissmi_effect = effect; 131 Node* receiverissmi_effect = effect;
132 if (receiverissmi_possible) { 132 if (receiverissmi_possible) {
133 Node* branch = graph()->NewNode(common()->Branch(), check, control); 133 Node* branch = graph()->NewNode(common()->Branch(), check, control);
134 control = graph()->NewNode(common()->IfFalse(), branch); 134 control = graph()->NewNode(common()->IfFalse(), branch);
135 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); 135 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
136 receiverissmi_effect = effect; 136 receiverissmi_effect = effect;
137 } else { 137 } else {
138 control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, 138 control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
139 effect, control); 139 frame_state, effect, control);
140 } 140 }
141 141
142 // Load the {receiver} map. The resulting effect is the dominating effect for 142 // Load the {receiver} map. The resulting effect is the dominating effect for
143 // all (polymorphic) branches. 143 // all (polymorphic) branches.
144 Node* receiver_map = effect = 144 Node* receiver_map = effect =
145 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 145 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
146 receiver, effect, control); 146 receiver, effect, control);
147 147
148 // Generate code for the various different property access patterns. 148 // Generate code for the various different property access patterns.
149 Node* fallthrough_control = control; 149 Node* fallthrough_control = control;
150 for (size_t j = 0; j < access_infos.size(); ++j) { 150 for (size_t j = 0; j < access_infos.size(); ++j) {
151 PropertyAccessInfo const& access_info = access_infos[j]; 151 PropertyAccessInfo const& access_info = access_infos[j];
152 Node* this_value = value; 152 Node* this_value = value;
153 Node* this_receiver = receiver; 153 Node* this_receiver = receiver;
154 Node* this_effect = effect; 154 Node* this_effect = effect;
155 Node* this_control; 155 Node* this_control;
156 156
157 // Perform map check on {receiver}. 157 // Perform map check on {receiver}.
158 Type* receiver_type = access_info.receiver_type(); 158 Type* receiver_type = access_info.receiver_type();
159 if (receiver_type->Is(Type::String())) { 159 if (receiver_type->Is(Type::String())) {
160 Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver); 160 Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver);
161 if (j == access_infos.size() - 1) { 161 if (j == access_infos.size() - 1) {
162 this_control = 162 this_control = this_effect =
163 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 163 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
164 this_effect, fallthrough_control); 164 this_effect, fallthrough_control);
165 fallthrough_control = nullptr; 165 fallthrough_control = nullptr;
166 } else { 166 } else {
167 Node* branch = 167 Node* branch =
168 graph()->NewNode(common()->Branch(), check, fallthrough_control); 168 graph()->NewNode(common()->Branch(), check, fallthrough_control);
169 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 169 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
170 this_control = graph()->NewNode(common()->IfTrue(), branch); 170 this_control = graph()->NewNode(common()->IfTrue(), branch);
171 } 171 }
172 } else { 172 } else {
173 // Emit a (sequence of) map checks for other {receiver}s. 173 // Emit a (sequence of) map checks for other {receiver}s.
174 ZoneVector<Node*> this_controls(zone()); 174 ZoneVector<Node*> this_controls(zone());
175 ZoneVector<Node*> this_effects(zone()); 175 ZoneVector<Node*> this_effects(zone());
176 int num_classes = access_info.receiver_type()->NumClasses(); 176 int num_classes = access_info.receiver_type()->NumClasses();
177 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); 177 for (auto i = access_info.receiver_type()->Classes(); !i.Done();
178 i.Advance()) { 178 i.Advance()) {
179 DCHECK_LT(0, num_classes); 179 DCHECK_LT(0, num_classes);
180 Handle<Map> map = i.Current(); 180 Handle<Map> map = i.Current();
181 Node* check = 181 Node* check =
182 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), 182 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
183 receiver_map, jsgraph()->Constant(map)); 183 receiver_map, jsgraph()->Constant(map));
184 if (--num_classes == 0 && j == access_infos.size() - 1) { 184 if (--num_classes == 0 && j == access_infos.size() - 1) {
185 this_controls.push_back( 185 Node* deoptimize =
186 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 186 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
187 this_effect, fallthrough_control)); 187 this_effect, fallthrough_control);
188 this_effects.push_back(this_effect); 188 this_controls.push_back(deoptimize);
189 this_effects.push_back(deoptimize);
189 fallthrough_control = nullptr; 190 fallthrough_control = nullptr;
190 } else { 191 } else {
191 Node* branch = 192 Node* branch =
192 graph()->NewNode(common()->Branch(), check, fallthrough_control); 193 graph()->NewNode(common()->Branch(), check, fallthrough_control);
193 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 194 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
194 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); 195 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
195 this_effects.push_back(this_effect); 196 this_effects.push_back(this_effect);
196 } 197 }
197 } 198 }
198 199
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 231
231 // Generate the actual property access. 232 // Generate the actual property access.
232 if (access_info.IsNotFound()) { 233 if (access_info.IsNotFound()) {
233 DCHECK_EQ(AccessMode::kLoad, access_mode); 234 DCHECK_EQ(AccessMode::kLoad, access_mode);
234 this_value = jsgraph()->UndefinedConstant(); 235 this_value = jsgraph()->UndefinedConstant();
235 } else if (access_info.IsDataConstant()) { 236 } else if (access_info.IsDataConstant()) {
236 this_value = jsgraph()->Constant(access_info.constant()); 237 this_value = jsgraph()->Constant(access_info.constant());
237 if (access_mode == AccessMode::kStore) { 238 if (access_mode == AccessMode::kStore) {
238 Node* check = graph()->NewNode( 239 Node* check = graph()->NewNode(
239 simplified()->ReferenceEqual(Type::Tagged()), value, this_value); 240 simplified()->ReferenceEqual(Type::Tagged()), value, this_value);
240 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 241 this_control = this_effect =
241 frame_state, this_effect, this_control); 242 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
243 this_effect, this_control);
242 } 244 }
243 } else { 245 } else {
244 DCHECK(access_info.IsDataField()); 246 DCHECK(access_info.IsDataField());
245 FieldIndex const field_index = access_info.field_index(); 247 FieldIndex const field_index = access_info.field_index();
246 FieldCheck const field_check = access_info.field_check(); 248 FieldCheck const field_check = access_info.field_check();
247 Type* const field_type = access_info.field_type(); 249 Type* const field_type = access_info.field_type();
248 switch (field_check) { 250 switch (field_check) {
249 case FieldCheck::kNone: 251 case FieldCheck::kNone:
250 break; 252 break;
251 case FieldCheck::kJSArrayBufferViewBufferNotNeutered: { 253 case FieldCheck::kJSArrayBufferViewBufferNotNeutered: {
252 Node* this_buffer = this_effect = 254 Node* this_buffer = this_effect =
253 graph()->NewNode(simplified()->LoadField( 255 graph()->NewNode(simplified()->LoadField(
254 AccessBuilder::ForJSArrayBufferViewBuffer()), 256 AccessBuilder::ForJSArrayBufferViewBuffer()),
255 this_receiver, this_effect, this_control); 257 this_receiver, this_effect, this_control);
256 Node* this_buffer_bit_field = this_effect = 258 Node* this_buffer_bit_field = this_effect =
257 graph()->NewNode(simplified()->LoadField( 259 graph()->NewNode(simplified()->LoadField(
258 AccessBuilder::ForJSArrayBufferBitField()), 260 AccessBuilder::ForJSArrayBufferBitField()),
259 this_buffer, this_effect, this_control); 261 this_buffer, this_effect, this_control);
260 Node* check = graph()->NewNode( 262 Node* check = graph()->NewNode(
261 machine()->Word32Equal(), 263 machine()->Word32Equal(),
262 graph()->NewNode(machine()->Word32And(), this_buffer_bit_field, 264 graph()->NewNode(machine()->Word32And(), this_buffer_bit_field,
263 jsgraph()->Int32Constant( 265 jsgraph()->Int32Constant(
264 1 << JSArrayBuffer::WasNeutered::kShift)), 266 1 << JSArrayBuffer::WasNeutered::kShift)),
265 jsgraph()->Int32Constant(0)); 267 jsgraph()->Int32Constant(0));
266 this_control = 268 this_control = this_effect =
267 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 269 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
268 this_effect, this_control); 270 this_effect, this_control);
269 break; 271 break;
270 } 272 }
271 } 273 }
272 if (access_mode == AccessMode::kLoad && 274 if (access_mode == AccessMode::kLoad &&
273 access_info.holder().ToHandle(&holder)) { 275 access_info.holder().ToHandle(&holder)) {
274 this_receiver = jsgraph()->Constant(holder); 276 this_receiver = jsgraph()->Constant(holder);
275 } 277 }
276 Node* this_storage = this_receiver; 278 Node* this_storage = this_receiver;
(...skipping 18 matching lines...) Expand all
295 field_access.machine_type = MachineType::Float64(); 297 field_access.machine_type = MachineType::Float64();
296 } 298 }
297 this_value = this_effect = 299 this_value = this_effect =
298 graph()->NewNode(simplified()->LoadField(field_access), 300 graph()->NewNode(simplified()->LoadField(field_access),
299 this_storage, this_effect, this_control); 301 this_storage, this_effect, this_control);
300 } else { 302 } else {
301 DCHECK_EQ(AccessMode::kStore, access_mode); 303 DCHECK_EQ(AccessMode::kStore, access_mode);
302 if (field_type->Is(Type::UntaggedFloat64())) { 304 if (field_type->Is(Type::UntaggedFloat64())) {
303 Node* check = 305 Node* check =
304 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); 306 graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
305 this_control = 307 this_control = this_effect =
306 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 308 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
307 this_effect, this_control); 309 this_effect, this_control);
308 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), 310 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
309 this_value, this_control); 311 this_value, this_control);
310 312
311 if (!field_index.is_inobject() || field_index.is_hidden_field() || 313 if (!field_index.is_inobject() || field_index.is_hidden_field() ||
312 !FLAG_unbox_double_fields) { 314 !FLAG_unbox_double_fields) {
313 if (access_info.HasTransitionMap()) { 315 if (access_info.HasTransitionMap()) {
314 // Allocate a MutableHeapNumber for the new property. 316 // Allocate a MutableHeapNumber for the new property.
315 this_effect = 317 this_effect =
(...skipping 22 matching lines...) Expand all
338 field_access.name = MaybeHandle<Name>(); 340 field_access.name = MaybeHandle<Name>();
339 field_access.machine_type = MachineType::Float64(); 341 field_access.machine_type = MachineType::Float64();
340 } 342 }
341 } else { 343 } else {
342 // Unboxed double field, we store directly to the field. 344 // Unboxed double field, we store directly to the field.
343 field_access.machine_type = MachineType::Float64(); 345 field_access.machine_type = MachineType::Float64();
344 } 346 }
345 } else if (field_type->Is(Type::TaggedSigned())) { 347 } else if (field_type->Is(Type::TaggedSigned())) {
346 Node* check = 348 Node* check =
347 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); 349 graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
348 this_control = 350 this_control = this_effect =
349 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 351 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
350 this_effect, this_control); 352 this_effect, this_control);
351 this_value = 353 this_value =
352 graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), 354 graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
353 this_value, this_control); 355 this_value, this_control);
354 } else if (field_type->Is(Type::TaggedPointer())) { 356 } else if (field_type->Is(Type::TaggedPointer())) {
355 Node* check = 357 Node* check =
356 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); 358 graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
357 this_control = 359 this_control = this_effect =
358 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, 360 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
359 this_effect, this_control); 361 this_effect, this_control);
360 if (field_type->NumClasses() == 1) { 362 if (field_type->NumClasses() == 1) {
361 // Emit a map check for the value. 363 // Emit a map check for the value.
362 Node* this_value_map = this_effect = graph()->NewNode( 364 Node* this_value_map = this_effect = graph()->NewNode(
363 simplified()->LoadField(AccessBuilder::ForMap()), this_value, 365 simplified()->LoadField(AccessBuilder::ForMap()), this_value,
364 this_effect, this_control); 366 this_effect, this_control);
365 Node* check = graph()->NewNode( 367 Node* check = graph()->NewNode(
366 simplified()->ReferenceEqual(Type::Internal()), this_value_map, 368 simplified()->ReferenceEqual(Type::Internal()), this_value_map,
367 jsgraph()->Constant(field_type->Classes().Current())); 369 jsgraph()->Constant(field_type->Classes().Current()));
368 this_control = 370 this_control = this_effect =
369 graph()->NewNode(common()->DeoptimizeUnless(), check, 371 graph()->NewNode(common()->DeoptimizeUnless(), check,
370 frame_state, this_effect, this_control); 372 frame_state, this_effect, this_control);
371 } else { 373 } else {
372 DCHECK_EQ(0, field_type->NumClasses()); 374 DCHECK_EQ(0, field_type->NumClasses());
373 } 375 }
374 } else { 376 } else {
375 DCHECK(field_type->Is(Type::Tagged())); 377 DCHECK(field_type->Is(Type::Tagged()));
376 } 378 }
377 Handle<Map> transition_map; 379 Handle<Map> transition_map;
378 if (access_info.transition_map().ToHandle(&transition_map)) { 380 if (access_info.transition_map().ToHandle(&transition_map)) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 if (access_infos.empty()) return NoChange(); 551 if (access_infos.empty()) return NoChange();
550 552
551 // The final states for every polymorphic branch. We join them with 553 // The final states for every polymorphic branch. We join them with
552 // Merge+Phi+EffectPhi at the bottom. 554 // Merge+Phi+EffectPhi at the bottom.
553 ZoneVector<Node*> values(zone()); 555 ZoneVector<Node*> values(zone());
554 ZoneVector<Node*> effects(zone()); 556 ZoneVector<Node*> effects(zone());
555 ZoneVector<Node*> controls(zone()); 557 ZoneVector<Node*> controls(zone());
556 558
557 // Ensure that {receiver} is a heap object. 559 // Ensure that {receiver} is a heap object.
558 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); 560 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
559 control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, 561 control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
560 effect, control); 562 frame_state, effect, control);
561 563
562 // Load the {receiver} map. The resulting effect is the dominating effect for 564 // Load the {receiver} map. The resulting effect is the dominating effect for
563 // all (polymorphic) branches. 565 // all (polymorphic) branches.
564 Node* receiver_map = effect = 566 Node* receiver_map = effect =
565 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 567 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
566 receiver, effect, control); 568 receiver, effect, control);
567 569
568 // Generate code for the various different element access patterns. 570 // Generate code for the various different element access patterns.
569 Node* fallthrough_control = control; 571 Node* fallthrough_control = control;
570 for (size_t j = 0; j < access_infos.size(); ++j) { 572 for (size_t j = 0; j < access_infos.size(); ++j) {
(...skipping 19 matching lines...) Expand all
590 Node* check = 592 Node* check =
591 graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), 593 graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
592 receiver_map, jsgraph()->Constant(map)); 594 receiver_map, jsgraph()->Constant(map));
593 if (--num_classes == 0 && num_transitions == 0 && 595 if (--num_classes == 0 && num_transitions == 0 &&
594 j == access_infos.size() - 1) { 596 j == access_infos.size() - 1) {
595 // Last map check on the fallthrough control path, do a conditional 597 // Last map check on the fallthrough control path, do a conditional
596 // eager deoptimization exit here. 598 // eager deoptimization exit here.
597 // TODO(turbofan): This is ugly as hell! We should probably introduce 599 // TODO(turbofan): This is ugly as hell! We should probably introduce
598 // macro-ish operators for property access that encapsulate this whole 600 // macro-ish operators for property access that encapsulate this whole
599 // mess. 601 // mess.
600 this_controls.push_back(graph()->NewNode(common()->DeoptimizeUnless(), 602 Node* deoptimize =
601 check, frame_state, effect, 603 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
602 fallthrough_control)); 604 effect, fallthrough_control);
605 this_controls.push_back(deoptimize);
606 this_effects.push_back(deoptimize);
603 fallthrough_control = nullptr; 607 fallthrough_control = nullptr;
604 } else { 608 } else {
605 Node* branch = 609 Node* branch =
606 graph()->NewNode(common()->Branch(), check, fallthrough_control); 610 graph()->NewNode(common()->Branch(), check, fallthrough_control);
607 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); 611 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
612 this_effects.push_back(effect);
608 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 613 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
609 } 614 }
610 this_effects.push_back(effect);
611 if (!map->IsJSArrayMap()) receiver_is_jsarray = false; 615 if (!map->IsJSArrayMap()) receiver_is_jsarray = false;
612 } 616 }
613 617
614 // Generate possible elements kind transitions. 618 // Generate possible elements kind transitions.
615 for (auto transition : access_info.transitions()) { 619 for (auto transition : access_info.transitions()) {
616 DCHECK_LT(0u, num_transitions); 620 DCHECK_LT(0u, num_transitions);
617 Handle<Map> transition_source = transition.first; 621 Handle<Map> transition_source = transition.first;
618 Handle<Map> transition_target = transition.second; 622 Handle<Map> transition_target = transition.second;
619 Node* transition_control; 623 Node* transition_control;
620 Node* transition_effect = effect; 624 Node* transition_effect = effect;
621 625
622 // Check if {receiver} has the specified {transition_source} map. 626 // Check if {receiver} has the specified {transition_source} map.
623 Node* check = graph()->NewNode( 627 Node* check = graph()->NewNode(
624 simplified()->ReferenceEqual(Type::Any()), receiver_map, 628 simplified()->ReferenceEqual(Type::Any()), receiver_map,
625 jsgraph()->HeapConstant(transition_source)); 629 jsgraph()->HeapConstant(transition_source));
626 if (--num_transitions == 0 && j == access_infos.size() - 1) { 630 if (--num_transitions == 0 && j == access_infos.size() - 1) {
627 transition_control = 631 transition_control = transition_effect =
628 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, 632 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
629 transition_effect, fallthrough_control); 633 transition_effect, fallthrough_control);
630 fallthrough_control = nullptr; 634 fallthrough_control = nullptr;
631 } else { 635 } else {
632 Node* branch = 636 Node* branch =
633 graph()->NewNode(common()->Branch(), check, fallthrough_control); 637 graph()->NewNode(common()->Branch(), check, fallthrough_control);
634 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); 638 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
635 transition_control = graph()->NewNode(common()->IfTrue(), branch); 639 transition_control = graph()->NewNode(common()->IfTrue(), branch);
636 } 640 }
637 641
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 // not compatible with (monomorphic) keyed stores. 686 // not compatible with (monomorphic) keyed stores.
683 Handle<JSObject> holder; 687 Handle<JSObject> holder;
684 if (access_info.holder().ToHandle(&holder)) { 688 if (access_info.holder().ToHandle(&holder)) {
685 AssumePrototypesStable(receiver_type, native_context, holder); 689 AssumePrototypesStable(receiver_type, native_context, holder);
686 } 690 }
687 691
688 // Check that the {index} is actually a Number. 692 // Check that the {index} is actually a Number.
689 if (!NumberMatcher(this_index).HasValue()) { 693 if (!NumberMatcher(this_index).HasValue()) {
690 Node* check = 694 Node* check =
691 graph()->NewNode(simplified()->ObjectIsNumber(), this_index); 695 graph()->NewNode(simplified()->ObjectIsNumber(), this_index);
692 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 696 this_control = this_effect =
693 frame_state, this_effect, this_control); 697 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
698 this_effect, this_control);
694 this_index = graph()->NewNode(simplified()->TypeGuard(Type::Number()), 699 this_index = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
695 this_index, this_control); 700 this_index, this_control);
696 } 701 }
697 702
698 // Convert the {index} to an unsigned32 value and check if the result is 703 // Convert the {index} to an unsigned32 value and check if the result is
699 // equal to the original {index}. 704 // equal to the original {index}.
700 if (!NumberMatcher(this_index).IsInRange(0.0, kMaxUInt32)) { 705 if (!NumberMatcher(this_index).IsInRange(0.0, kMaxUInt32)) {
701 Node* this_index32 = 706 Node* this_index32 =
702 graph()->NewNode(simplified()->NumberToUint32(), this_index); 707 graph()->NewNode(simplified()->NumberToUint32(), this_index);
703 Node* check = graph()->NewNode(simplified()->NumberEqual(), this_index32, 708 Node* check = graph()->NewNode(simplified()->NumberEqual(), this_index32,
704 this_index); 709 this_index);
705 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 710 this_control = this_effect =
706 frame_state, this_effect, this_control); 711 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
712 this_effect, this_control);
707 this_index = this_index32; 713 this_index = this_index32;
708 } 714 }
709 715
710 // TODO(bmeurer): We currently specialize based on elements kind. We should 716 // TODO(bmeurer): We currently specialize based on elements kind. We should
711 // also be able to properly support strings and other JSObjects here. 717 // also be able to properly support strings and other JSObjects here.
712 ElementsKind elements_kind = access_info.elements_kind(); 718 ElementsKind elements_kind = access_info.elements_kind();
713 719
714 // Load the elements for the {receiver}. 720 // Load the elements for the {receiver}.
715 Node* this_elements = this_effect = graph()->NewNode( 721 Node* this_elements = this_effect = graph()->NewNode(
716 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), 722 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
717 this_receiver, this_effect, this_control); 723 this_receiver, this_effect, this_control);
718 724
719 // Don't try to store to a copy-on-write backing store. 725 // Don't try to store to a copy-on-write backing store.
720 if (access_mode == AccessMode::kStore && 726 if (access_mode == AccessMode::kStore &&
721 IsFastSmiOrObjectElementsKind(elements_kind)) { 727 IsFastSmiOrObjectElementsKind(elements_kind)) {
722 Node* this_elements_map = this_effect = 728 Node* this_elements_map = this_effect =
723 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 729 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
724 this_elements, this_effect, this_control); 730 this_elements, this_effect, this_control);
725 Node* check = graph()->NewNode( 731 Node* check = graph()->NewNode(
726 simplified()->ReferenceEqual(Type::Any()), this_elements_map, 732 simplified()->ReferenceEqual(Type::Any()), this_elements_map,
727 jsgraph()->HeapConstant(factory()->fixed_array_map())); 733 jsgraph()->HeapConstant(factory()->fixed_array_map()));
728 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 734 this_control = this_effect =
729 frame_state, this_effect, this_control); 735 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
736 this_effect, this_control);
730 } 737 }
731 738
732 // Load the length of the {receiver}. 739 // Load the length of the {receiver}.
733 Node* this_length = this_effect = 740 Node* this_length = this_effect =
734 receiver_is_jsarray 741 receiver_is_jsarray
735 ? graph()->NewNode( 742 ? graph()->NewNode(
736 simplified()->LoadField( 743 simplified()->LoadField(
737 AccessBuilder::ForJSArrayLength(elements_kind)), 744 AccessBuilder::ForJSArrayLength(elements_kind)),
738 this_receiver, this_effect, this_control) 745 this_receiver, this_effect, this_control)
739 : graph()->NewNode( 746 : graph()->NewNode(
740 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), 747 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
741 this_elements, this_effect, this_control); 748 this_elements, this_effect, this_control);
742 749
743 // Check that the {index} is in the valid range for the {receiver}. 750 // Check that the {index} is in the valid range for the {receiver}.
744 Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index, 751 Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index,
745 this_length); 752 this_length);
746 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 753 this_control = this_effect =
747 frame_state, this_effect, this_control); 754 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
755 this_effect, this_control);
748 756
749 // Compute the element access. 757 // Compute the element access.
750 Type* element_type = Type::Any(); 758 Type* element_type = Type::Any();
751 MachineType element_machine_type = MachineType::AnyTagged(); 759 MachineType element_machine_type = MachineType::AnyTagged();
752 if (IsFastDoubleElementsKind(elements_kind)) { 760 if (IsFastDoubleElementsKind(elements_kind)) {
753 element_type = Type::Number(); 761 element_type = Type::Number();
754 element_machine_type = MachineType::Float64(); 762 element_machine_type = MachineType::Float64();
755 } else if (IsFastSmiElementsKind(elements_kind)) { 763 } else if (IsFastSmiElementsKind(elements_kind)) {
756 element_type = type_cache_.kSmi; 764 element_type = type_cache_.kSmi;
757 } 765 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 // Turn the hole into undefined. 809 // Turn the hole into undefined.
802 this_control = 810 this_control =
803 graph()->NewNode(common()->Merge(2), if_true, if_false); 811 graph()->NewNode(common()->Merge(2), if_true, if_false);
804 this_value = graph()->NewNode( 812 this_value = graph()->NewNode(
805 common()->Phi(MachineRepresentation::kTagged, 2), 813 common()->Phi(MachineRepresentation::kTagged, 2),
806 jsgraph()->UndefinedConstant(), this_value, this_control); 814 jsgraph()->UndefinedConstant(), this_value, this_control);
807 element_type = 815 element_type =
808 Type::Union(element_type, Type::Undefined(), graph()->zone()); 816 Type::Union(element_type, Type::Undefined(), graph()->zone());
809 } else { 817 } else {
810 // Deoptimize in case of the hole. 818 // Deoptimize in case of the hole.
811 this_control = 819 this_control = this_effect =
812 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, 820 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
813 this_effect, this_control); 821 this_effect, this_control);
814 } 822 }
815 // Rename the result to represent the actual type (not polluted by the 823 // Rename the result to represent the actual type (not polluted by the
816 // hole). 824 // hole).
817 this_value = graph()->NewNode(simplified()->TypeGuard(element_type), 825 this_value = graph()->NewNode(simplified()->TypeGuard(element_type),
818 this_value, this_control); 826 this_value, this_control);
819 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { 827 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
820 // Perform the hole check on the result. 828 // Perform the hole check on the result.
821 Node* check = 829 Node* check =
822 graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value); 830 graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value);
823 // Check if we are allowed to return the hole directly. 831 // Check if we are allowed to return the hole directly.
824 Type* initial_holey_array_type = Type::Class( 832 Type* initial_holey_array_type = Type::Class(
825 handle(isolate()->get_initial_js_array_map(elements_kind)), 833 handle(isolate()->get_initial_js_array_map(elements_kind)),
826 graph()->zone()); 834 graph()->zone());
827 if (receiver_type->NowIs(initial_holey_array_type) && 835 if (receiver_type->NowIs(initial_holey_array_type) &&
828 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 836 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
829 // Add a code dependency on the array protector cell. 837 // Add a code dependency on the array protector cell.
830 AssumePrototypesStable(receiver_type, native_context, 838 AssumePrototypesStable(receiver_type, native_context,
831 isolate()->initial_object_prototype()); 839 isolate()->initial_object_prototype());
832 dependencies()->AssumePropertyCell(factory()->array_protector()); 840 dependencies()->AssumePropertyCell(factory()->array_protector());
833 // Turn the hole into undefined. 841 // Turn the hole into undefined.
834 this_value = graph()->NewNode( 842 this_value = graph()->NewNode(
835 common()->Select(MachineRepresentation::kTagged, 843 common()->Select(MachineRepresentation::kTagged,
836 BranchHint::kFalse), 844 BranchHint::kFalse),
837 check, jsgraph()->UndefinedConstant(), this_value); 845 check, jsgraph()->UndefinedConstant(), this_value);
838 } else { 846 } else {
839 // Deoptimize in case of the hole. 847 // Deoptimize in case of the hole.
840 this_control = 848 this_control = this_effect =
841 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, 849 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
842 this_effect, this_control); 850 this_effect, this_control);
843 } 851 }
844 } 852 }
845 } else { 853 } else {
846 DCHECK_EQ(AccessMode::kStore, access_mode); 854 DCHECK_EQ(AccessMode::kStore, access_mode);
847 if (IsFastSmiElementsKind(elements_kind)) { 855 if (IsFastSmiElementsKind(elements_kind)) {
848 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value); 856 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
849 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 857 this_control = this_effect =
850 frame_state, this_effect, this_control); 858 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
859 this_effect, this_control);
851 this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), 860 this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
852 this_value, this_control); 861 this_value, this_control);
853 } else if (IsFastDoubleElementsKind(elements_kind)) { 862 } else if (IsFastDoubleElementsKind(elements_kind)) {
854 Node* check = 863 Node* check =
855 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); 864 graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
856 this_control = graph()->NewNode(common()->DeoptimizeUnless(), check, 865 this_control = this_effect =
857 frame_state, this_effect, this_control); 866 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
867 this_effect, this_control);
858 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), 868 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
859 this_value, this_control); 869 this_value, this_control);
860 } 870 }
861 this_effect = graph()->NewNode(simplified()->StoreElement(element_access), 871 this_effect = graph()->NewNode(simplified()->StoreElement(element_access),
862 this_elements, this_index, this_value, 872 this_elements, this_index, this_value,
863 this_effect, this_control); 873 this_effect, this_control);
864 } 874 }
865 875
866 // Remember the final state for this element access. 876 // Remember the final state for this element access.
867 values.push_back(this_value); 877 values.push_back(this_value);
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 } 1154 }
1145 1155
1146 1156
1147 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1157 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1148 return jsgraph()->simplified(); 1158 return jsgraph()->simplified();
1149 } 1159 }
1150 1160
1151 } // namespace compiler 1161 } // namespace compiler
1152 } // namespace internal 1162 } // namespace internal
1153 } // namespace v8 1163 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-global-object-specialization.cc ('k') | src/compiler/memory-optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698