Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/node-properties.h"
6 : #include "src/compiler/common-operator.h"
7 : #include "src/compiler/graph.h"
8 : #include "src/compiler/js-operator.h"
9 : #include "src/compiler/linkage.h"
10 : #include "src/compiler/node-matchers.h"
11 : #include "src/compiler/operator-properties.h"
12 : #include "src/compiler/simplified-operator.h"
13 : #include "src/compiler/verifier.h"
14 : #include "src/handles-inl.h"
15 : #include "src/objects-inl.h"
16 : #include "src/zone/zone-handle-set.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace compiler {
21 :
22 : // static
23 1086960339 : int NodeProperties::PastValueIndex(Node* node) {
24 1087113055 : return FirstValueIndex(node) + node->op()->ValueInputCount();
25 : }
26 :
27 :
28 : // static
29 501 : int NodeProperties::PastContextIndex(Node* node) {
30 : return FirstContextIndex(node) +
31 1080260046 : OperatorProperties::GetContextInputCount(node->op());
32 : }
33 :
34 :
35 : // static
36 2136580776 : int NodeProperties::PastFrameStateIndex(Node* node) {
37 : return FirstFrameStateIndex(node) +
38 1068193455 : OperatorProperties::GetFrameStateInputCount(node->op());
39 : }
40 :
41 :
42 : // static
43 712692555 : int NodeProperties::PastEffectIndex(Node* node) {
44 1261302716 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
45 : }
46 :
47 :
48 : // static
49 59695063 : int NodeProperties::PastControlIndex(Node* node) {
50 119390358 : return FirstControlIndex(node) + node->op()->ControlInputCount();
51 : }
52 :
53 :
54 : // static
55 153992285 : Node* NodeProperties::GetValueInput(Node* node, int index) {
56 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
57 153992285 : return node->InputAt(FirstValueIndex(node) + index);
58 : }
59 :
60 :
61 : // static
62 5224454 : Node* NodeProperties::GetContextInput(Node* node) {
63 : DCHECK(OperatorProperties::HasContextInput(node->op()));
64 5224454 : return node->InputAt(FirstContextIndex(node));
65 : }
66 :
67 :
68 : // static
69 4339555 : Node* NodeProperties::GetFrameStateInput(Node* node) {
70 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
71 4339565 : return node->InputAt(FirstFrameStateIndex(node));
72 : }
73 :
74 :
75 : // static
76 223446998 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
77 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
78 446883340 : return node->InputAt(FirstEffectIndex(node) + index);
79 : }
80 :
81 :
82 : // static
83 300712066 : Node* NodeProperties::GetControlInput(Node* node, int index) {
84 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
85 300674043 : return node->InputAt(FirstControlIndex(node) + index);
86 : }
87 :
88 :
89 : // static
90 8263794 : bool NodeProperties::IsValueEdge(Edge edge) {
91 8263794 : Node* const node = edge.from();
92 : return IsInputRange(edge, FirstValueIndex(node),
93 16527588 : node->op()->ValueInputCount());
94 : }
95 :
96 :
97 : // static
98 0 : bool NodeProperties::IsContextEdge(Edge edge) {
99 0 : Node* const node = edge.from();
100 : return IsInputRange(edge, FirstContextIndex(node),
101 0 : OperatorProperties::GetContextInputCount(node->op()));
102 : }
103 :
104 :
105 : // static
106 543022 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
107 543022 : Node* const node = edge.from();
108 : return IsInputRange(edge, FirstFrameStateIndex(node),
109 543022 : OperatorProperties::GetFrameStateInputCount(node->op()));
110 : }
111 :
112 :
113 : // static
114 195683825 : bool NodeProperties::IsEffectEdge(Edge edge) {
115 195683825 : Node* const node = edge.from();
116 : return IsInputRange(edge, FirstEffectIndex(node),
117 391363738 : node->op()->EffectInputCount());
118 : }
119 :
120 :
121 : // static
122 176774009 : bool NodeProperties::IsControlEdge(Edge edge) {
123 176774009 : Node* const node = edge.from();
124 : return IsInputRange(edge, FirstControlIndex(node),
125 353543813 : node->op()->ControlInputCount());
126 : }
127 :
128 :
129 : // static
130 11284618 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
131 11284618 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
132 124808395 : for (Edge const edge : node->use_edges()) {
133 51468890 : if (!NodeProperties::IsControlEdge(edge)) continue;
134 36935228 : if (edge.from()->opcode() == IrOpcode::kIfException) {
135 711513 : if (out_exception != nullptr) *out_exception = edge.from();
136 698644 : return true;
137 : }
138 : }
139 10586023 : return false;
140 : }
141 :
142 : // static
143 1600 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
144 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
145 1600 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
146 53432 : for (Edge const edge : node->use_edges()) {
147 25224 : if (!NodeProperties::IsControlEdge(edge)) continue;
148 17096 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
149 216 : return edge.from();
150 : }
151 : }
152 1384 : return node;
153 : }
154 :
155 : // static
156 892206 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
157 : DCHECK(index < node->op()->ValueInputCount());
158 892206 : node->ReplaceInput(FirstValueIndex(node) + index, value);
159 892206 : }
160 :
161 :
162 : // static
163 829 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
164 829 : int value_input_count = node->op()->ValueInputCount();
165 : DCHECK_LE(1, value_input_count);
166 829 : node->ReplaceInput(0, value);
167 3065 : while (--value_input_count > 0) {
168 1407 : node->RemoveInput(value_input_count);
169 : }
170 829 : }
171 :
172 :
173 : // static
174 391389 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
175 391389 : node->ReplaceInput(FirstContextIndex(node), context);
176 391389 : }
177 :
178 :
179 : // static
180 11471532 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
181 : DCHECK(index < node->op()->ControlInputCount());
182 11471540 : node->ReplaceInput(FirstControlIndex(node) + index, control);
183 11471536 : }
184 :
185 :
186 : // static
187 4294908 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
188 : DCHECK(index < node->op()->EffectInputCount());
189 4294909 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
190 : }
191 :
192 :
193 : // static
194 7128926 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
195 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
196 7128930 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
197 7128937 : }
198 :
199 :
200 : // static
201 110546 : void NodeProperties::RemoveNonValueInputs(Node* node) {
202 221092 : node->TrimInputCount(node->op()->ValueInputCount());
203 110546 : }
204 :
205 :
206 : // static
207 0 : void NodeProperties::RemoveValueInputs(Node* node) {
208 0 : int value_input_count = node->op()->ValueInputCount();
209 0 : while (--value_input_count >= 0) {
210 0 : node->RemoveInput(value_input_count);
211 : }
212 0 : }
213 :
214 :
215 1988480 : void NodeProperties::MergeControlToEnd(Graph* graph,
216 : CommonOperatorBuilder* common,
217 : Node* node) {
218 662824 : graph->end()->AppendInput(graph->zone(), node);
219 662829 : graph->end()->set_op(common->End(graph->end()->InputCount()));
220 662827 : }
221 :
222 :
223 : // static
224 2007367 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
225 : Node* success, Node* exception) {
226 : // Requires distinguishing between value, effect and control edges.
227 16752302 : for (Edge edge : node->use_edges()) {
228 6368769 : if (IsControlEdge(edge)) {
229 6531825 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
230 : DCHECK_NOT_NULL(success);
231 27176 : edge.UpdateTo(success);
232 4300198 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
233 : DCHECK_NOT_NULL(exception);
234 8270 : edge.UpdateTo(exception);
235 : } else {
236 : DCHECK_NOT_NULL(success);
237 2141829 : edge.UpdateTo(success);
238 : }
239 4191560 : } else if (IsEffectEdge(edge)) {
240 : DCHECK_NOT_NULL(effect);
241 1825979 : edge.UpdateTo(effect);
242 : } else {
243 : DCHECK_NOT_NULL(value);
244 2365578 : edge.UpdateTo(value);
245 : }
246 : }
247 2007397 : }
248 :
249 :
250 : // static
251 39362668 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
252 : node->set_op(new_op);
253 : Verifier::VerifyNode(node);
254 39362668 : }
255 :
256 :
257 : // static
258 89214 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
259 353631 : Node* effect = NodeProperties::GetEffectInput(node);
260 353631 : while (effect->opcode() != IrOpcode::kCheckpoint) {
261 175203 : if (effect->opcode() == IrOpcode::kDead) return effect;
262 : DCHECK_EQ(1, effect->op()->EffectInputCount());
263 175203 : effect = NodeProperties::GetEffectInput(effect);
264 : }
265 89214 : Node* frame_state = GetFrameStateInput(effect);
266 89214 : return frame_state;
267 : }
268 :
269 : // static
270 206191 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
271 618915 : for (auto use : node->uses()) {
272 412391 : if (use->opcode() == IrOpcode::kProjection &&
273 206185 : ProjectionIndexOf(use->op()) == projection_index) {
274 : return use;
275 : }
276 : }
277 : return nullptr;
278 : }
279 :
280 :
281 : // static
282 0 : void NodeProperties::CollectValueProjections(Node* node, Node** projections,
283 : size_t projection_count) {
284 : #ifdef DEBUG
285 : for (size_t index = 0; index < projection_count; ++index) {
286 : DCHECK_NULL(projections[index]);
287 : }
288 : #endif
289 0 : for (Edge const edge : node->use_edges()) {
290 0 : if (!IsValueEdge(edge)) continue;
291 0 : Node* use = edge.from();
292 : DCHECK_EQ(IrOpcode::kProjection, use->opcode());
293 0 : projections[ProjectionIndexOf(use->op())] = use;
294 : }
295 0 : }
296 :
297 :
298 : // static
299 10609647 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
300 : size_t projection_count) {
301 : #ifdef DEBUG
302 : DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
303 : std::memset(projections, 0, sizeof(*projections) * projection_count);
304 : #endif
305 : size_t if_value_index = 0;
306 70777251 : for (Edge const edge : node->use_edges()) {
307 24778970 : if (!IsControlEdge(edge)) continue;
308 21896016 : Node* use = edge.from();
309 : size_t index;
310 21896016 : switch (use->opcode()) {
311 : case IrOpcode::kIfTrue:
312 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
313 : index = 0;
314 : break;
315 : case IrOpcode::kIfFalse:
316 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
317 : index = 1;
318 9853496 : break;
319 : case IrOpcode::kIfSuccess:
320 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
321 : index = 0;
322 : break;
323 : case IrOpcode::kIfException:
324 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
325 : index = 1;
326 683995 : break;
327 : case IrOpcode::kIfValue:
328 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
329 748881 : index = if_value_index++;
330 748881 : break;
331 : case IrOpcode::kIfDefault:
332 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
333 72176 : index = projection_count - 1;
334 72176 : break;
335 : default:
336 : continue;
337 : }
338 : DCHECK_LT(if_value_index, projection_count);
339 : DCHECK_LT(index, projection_count);
340 : DCHECK_NULL(projections[index]);
341 21895975 : projections[index] = use;
342 : }
343 : #ifdef DEBUG
344 : for (size_t index = 0; index < projection_count; ++index) {
345 : DCHECK_NOT_NULL(projections[index]);
346 : }
347 : #endif
348 10609664 : }
349 :
350 : // static
351 20284551 : bool NodeProperties::IsSame(Node* a, Node* b) {
352 : for (;;) {
353 10169586 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
354 : a = GetValueInput(a, 0);
355 1591 : continue;
356 : }
357 10167995 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
358 : b = GetValueInput(b, 0);
359 51439 : continue;
360 : }
361 10116556 : return a == b;
362 : }
363 : }
364 :
365 : // static
366 206386 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
367 10150008 : JSHeapBroker* broker, Node* receiver, Node* effect,
368 : ZoneHandleSet<Map>* maps_return) {
369 : HeapObjectMatcher m(receiver);
370 206386 : if (m.HasValue()) {
371 75791 : HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
372 : // We don't use ICs for the Array.prototype and the Object.prototype
373 : // because the runtime has to be able to intercept them properly, so
374 : // we better make sure that TurboFan doesn't outsmart the system here
375 : // by storing to elements of either prototype directly.
376 : //
377 : // TODO(bmeurer): This can be removed once the Array.prototype and
378 : // Object.prototype have NO_ELEMENTS elements kind.
379 227373 : if (!receiver.IsJSObject() ||
380 214409 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
381 75542 : if (receiver.map().is_stable()) {
382 : // The {receiver_map} is only reliable when we install a stability
383 : // code dependency.
384 67626 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
385 67626 : return kUnreliableReceiverMaps;
386 : }
387 : }
388 : }
389 : InferReceiverMapsResult result = kReliableReceiverMaps;
390 : while (true) {
391 10150008 : switch (effect->opcode()) {
392 : case IrOpcode::kMapGuard: {
393 : Node* const object = GetValueInput(effect, 0);
394 176 : if (IsSame(receiver, object)) {
395 134 : *maps_return = MapGuardMapsOf(effect->op()).maps();
396 134 : return result;
397 : }
398 : break;
399 : }
400 : case IrOpcode::kCheckMaps: {
401 : Node* const object = GetValueInput(effect, 0);
402 68559 : if (IsSame(receiver, object)) {
403 41893 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
404 41891 : return result;
405 : }
406 : break;
407 : }
408 : case IrOpcode::kJSCreate: {
409 4029 : if (IsSame(receiver, effect)) {
410 : HeapObjectMatcher mtarget(GetValueInput(effect, 0));
411 : HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
412 9660 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
413 9198 : mnewtarget.Ref(broker).IsJSFunction()) {
414 : JSFunctionRef original_constructor =
415 2982 : mnewtarget.Ref(broker).AsJSFunction();
416 2982 : if (original_constructor.has_initial_map()) {
417 2982 : original_constructor.Serialize();
418 2982 : MapRef initial_map = original_constructor.initial_map();
419 2982 : if (initial_map.GetConstructor().equals(mtarget.Ref(broker))) {
420 2982 : *maps_return = ZoneHandleSet<Map>(initial_map.object());
421 2982 : return result;
422 : }
423 : }
424 : }
425 : // We reached the allocation of the {receiver}.
426 : return kNoReceiverMaps;
427 : }
428 : break;
429 : }
430 : case IrOpcode::kJSCreatePromise: {
431 85 : if (IsSame(receiver, effect)) {
432 : *maps_return = ZoneHandleSet<Map>(broker->native_context()
433 44 : .promise_function()
434 44 : .initial_map()
435 22 : .object());
436 22 : return result;
437 : }
438 : break;
439 : }
440 : case IrOpcode::kStoreField: {
441 : // We only care about StoreField of maps.
442 : Node* const object = GetValueInput(effect, 0);
443 22757 : FieldAccess const& access = FieldAccessOf(effect->op());
444 22757 : if (access.base_is_tagged == kTaggedBase &&
445 : access.offset == HeapObject::kMapOffset) {
446 3821 : if (IsSame(receiver, object)) {
447 : Node* const value = GetValueInput(effect, 1);
448 : HeapObjectMatcher m(value);
449 2823 : if (m.HasValue()) {
450 2823 : *maps_return = ZoneHandleSet<Map>(m.Ref(broker).AsMap().object());
451 : return result;
452 : }
453 : }
454 : // Without alias analysis we cannot tell whether this
455 : // StoreField[map] affects {receiver} or not.
456 : result = kUnreliableReceiverMaps;
457 : }
458 : break;
459 : }
460 : case IrOpcode::kJSStoreMessage:
461 : case IrOpcode::kJSStoreModule:
462 : case IrOpcode::kStoreElement:
463 : case IrOpcode::kStoreTypedElement: {
464 : // These never change the map of objects.
465 : break;
466 : }
467 : case IrOpcode::kFinishRegion: {
468 : // FinishRegion renames the output of allocations, so we need
469 : // to update the {receiver} that we are looking for, if the
470 : // {receiver} matches the current {effect}.
471 3821 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
472 : break;
473 : }
474 : case IrOpcode::kEffectPhi: {
475 28243 : Node* control = GetControlInput(effect);
476 28243 : if (control->opcode() != IrOpcode::kLoop) {
477 : DCHECK(control->opcode() == IrOpcode::kDead ||
478 : control->opcode() == IrOpcode::kMerge);
479 : return kNoReceiverMaps;
480 : }
481 :
482 : // Continue search for receiver map outside the loop. Since operations
483 : // inside the loop may change the map, the result is unreliable.
484 12121 : effect = GetEffectInput(effect, 0);
485 : result = kUnreliableReceiverMaps;
486 12121 : continue;
487 : }
488 : default: {
489 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
490 10018808 : if (effect->op()->EffectInputCount() != 1) {
491 : // Didn't find any appropriate CheckMaps node.
492 : return kNoReceiverMaps;
493 : }
494 9981213 : if (!effect->op()->HasProperty(Operator::kNoWrite)) {
495 : // Without alias/escape analysis we cannot tell whether this
496 : // {effect} affects {receiver} or not.
497 : result = kUnreliableReceiverMaps;
498 : }
499 : break;
500 : }
501 : }
502 :
503 : // Stop walking the effect chain once we hit the definition of
504 : // the {receiver} along the {effect}s.
505 10036077 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
506 :
507 : // Continue with the next {effect}.
508 : DCHECK_EQ(1, effect->op()->EffectInputCount());
509 9999126 : effect = NodeProperties::GetEffectInput(effect);
510 : }
511 : }
512 :
513 : // static
514 1023 : MaybeHandle<Map> NodeProperties::GetMapWitness(JSHeapBroker* broker,
515 : Node* node) {
516 : ZoneHandleSet<Map> maps;
517 : Node* receiver = NodeProperties::GetValueInput(node, 1);
518 1023 : Node* effect = NodeProperties::GetEffectInput(node);
519 : NodeProperties::InferReceiverMapsResult result =
520 1023 : NodeProperties::InferReceiverMaps(broker, receiver, effect, &maps);
521 2046 : if (result == NodeProperties::kReliableReceiverMaps && maps.size() == 1) {
522 1007 : return maps[0];
523 : }
524 16 : return MaybeHandle<Map>();
525 : }
526 :
527 : // static
528 1358 : bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
529 : Node* receiver, Node* effect,
530 : InstanceType instance_type) {
531 : ZoneHandleSet<Map> receiver_maps;
532 : NodeProperties::InferReceiverMapsResult result =
533 : NodeProperties::InferReceiverMaps(broker, receiver, effect,
534 1358 : &receiver_maps);
535 1358 : switch (result) {
536 : case NodeProperties::kUnreliableReceiverMaps:
537 : case NodeProperties::kReliableReceiverMaps:
538 : DCHECK_NE(0, receiver_maps.size());
539 4584 : for (size_t i = 0; i < receiver_maps.size(); ++i) {
540 : MapRef map(broker, receiver_maps[i]);
541 1614 : if (map.instance_type() != instance_type) return false;
542 : }
543 : return true;
544 :
545 : case NodeProperties::kNoReceiverMaps:
546 : return false;
547 : }
548 0 : UNREACHABLE();
549 : }
550 :
551 : // static
552 2439 : bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
553 : Node* dominator) {
554 2611 : while (effect != dominator) {
555 3647 : if (effect->op()->EffectInputCount() == 1 &&
556 : effect->op()->properties() & Operator::kNoWrite) {
557 1393 : effect = NodeProperties::GetEffectInput(effect);
558 : } else {
559 : return false;
560 : }
561 : }
562 : return true;
563 : }
564 :
565 : // static
566 59728 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
567 : Node* effect) {
568 59728 : switch (receiver->opcode()) {
569 : #define CASE(Opcode) case IrOpcode::k##Opcode:
570 : JS_CONSTRUCT_OP_LIST(CASE)
571 : JS_CREATE_OP_LIST(CASE)
572 : #undef CASE
573 : case IrOpcode::kCheckReceiver:
574 : case IrOpcode::kConvertReceiver:
575 : case IrOpcode::kJSGetSuperConstructor:
576 : case IrOpcode::kJSToObject:
577 : return false;
578 : case IrOpcode::kHeapConstant: {
579 : HeapObjectRef value =
580 56681 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
581 56681 : return value.map().IsPrimitiveMap();
582 : }
583 : default: {
584 : // We don't really care about the exact maps here,
585 : // just the instance types, which don't change
586 : // across potential side-effecting operations.
587 : ZoneHandleSet<Map> maps;
588 2499 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
589 : kNoReceiverMaps) {
590 : // Check if one of the {maps} is not a JSReceiver map.
591 6101 : for (size_t i = 0; i < maps.size(); ++i) {
592 : MapRef map(broker, maps[i]);
593 2061 : if (!map.IsJSReceiverMap()) return true;
594 : }
595 : return false;
596 : }
597 : return true;
598 : }
599 : }
600 : }
601 :
602 : // static
603 879 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
604 : Node* effect) {
605 649 : if (CanBePrimitive(broker, receiver, effect)) {
606 230 : switch (receiver->opcode()) {
607 : case IrOpcode::kCheckInternalizedString:
608 : case IrOpcode::kCheckNumber:
609 : case IrOpcode::kCheckSmi:
610 : case IrOpcode::kCheckString:
611 : case IrOpcode::kCheckSymbol:
612 : case IrOpcode::kJSToLength:
613 : case IrOpcode::kJSToName:
614 : case IrOpcode::kJSToNumber:
615 : case IrOpcode::kJSToNumberConvertBigInt:
616 : case IrOpcode::kJSToNumeric:
617 : case IrOpcode::kJSToString:
618 : case IrOpcode::kToBoolean:
619 : return false;
620 : case IrOpcode::kHeapConstant: {
621 : HeapObjectRef value =
622 92 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
623 92 : OddballType type = value.map().oddball_type();
624 92 : return type == OddballType::kNull || type == OddballType::kUndefined;
625 : }
626 : default:
627 138 : return true;
628 : }
629 : }
630 : return false;
631 : }
632 :
633 : // static
634 831324 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
635 28720 : Node* context = NodeProperties::GetContextInput(node);
636 1707072 : while (*depth > 0 &&
637 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
638 : context = NodeProperties::GetContextInput(context);
639 15704 : (*depth)--;
640 : }
641 831324 : return context;
642 : }
643 :
644 : // static
645 709386705 : Type NodeProperties::GetTypeOrAny(Node* node) {
646 709386705 : return IsTyped(node) ? node->type() : Type::Any();
647 : }
648 :
649 :
650 : // static
651 5131546 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
652 5131546 : int input_count = node->op()->ValueInputCount();
653 9021096 : for (int index = 0; index < input_count; ++index) {
654 3946253 : if (!IsTyped(GetValueInput(node, index))) return false;
655 : }
656 : return true;
657 : }
658 :
659 :
660 : // static
661 : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
662 381256533 : if (num == 0) return false;
663 : int const index = edge.index();
664 258439459 : return first <= index && index < first + num;
665 : }
666 :
667 : // static
668 223583206 : size_t NodeProperties::HashCode(Node* node) {
669 111791603 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
670 752479997 : for (Node* input : node->inputs()) {
671 : h = base::hash_combine(h, input->id());
672 : }
673 111788825 : return h;
674 : }
675 :
676 : // static
677 125610076 : bool NodeProperties::Equals(Node* a, Node* b) {
678 : DCHECK_NOT_NULL(a);
679 : DCHECK_NOT_NULL(b);
680 : DCHECK_NOT_NULL(a->op());
681 : DCHECK_NOT_NULL(b->op());
682 125610076 : if (!a->op()->Equals(b->op())) return false;
683 3727964 : if (a->InputCount() != b->InputCount()) return false;
684 : Node::Inputs aInputs = a->inputs();
685 : Node::Inputs bInputs = b->inputs();
686 :
687 : auto aIt = aInputs.begin();
688 : auto bIt = bInputs.begin();
689 : auto aEnd = aInputs.end();
690 :
691 13598070 : for (; aIt != aEnd; ++aIt, ++bIt) {
692 : DCHECK_NOT_NULL(*aIt);
693 : DCHECK_NOT_NULL(*bIt);
694 22538298 : if ((*aIt)->id() != (*bIt)->id()) return false;
695 : }
696 : return true;
697 : }
698 :
699 : } // namespace compiler
700 : } // namespace internal
701 183867 : } // namespace v8
|