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 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 :
21 : // static
22 75343 : int NodeProperties::PastValueIndex(Node* node) {
23 75343 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 544 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 1202546641 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1190704164 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 1190566625 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 92456948 : int NodeProperties::PastEffectIndex(Node* node) {
43 701548279 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 66988573 : int NodeProperties::PastControlIndex(Node* node) {
49 66989946 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 165765648 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 165765648 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 5925012 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 5925012 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 4707584 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 4707577 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 246197520 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 492310978 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 325661333 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 651200042 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 9719268 : bool NodeProperties::IsValueEdge(Edge edge) {
90 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 9719268 : node->op()->ValueInputCount());
93 : }
94 :
95 :
96 : // static
97 0 : bool NodeProperties::IsContextEdge(Edge edge) {
98 : Node* const node = edge.from();
99 : return IsInputRange(edge, FirstContextIndex(node),
100 0 : OperatorProperties::GetContextInputCount(node->op()));
101 : }
102 :
103 :
104 : // static
105 518434 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 518434 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 221554037 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 221545209 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 203331575 : bool NodeProperties::IsControlEdge(Edge edge) {
122 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 203325785 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 12637033 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 12637033 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 137627061 : for (Edge const edge : node->use_edges()) {
132 62918857 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 21015580 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 858021 : if (out_exception != nullptr) *out_exception = edge.from();
135 847707 : return true;
136 : }
137 : }
138 11789347 : return false;
139 : }
140 :
141 : // static
142 1851 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
143 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
144 1851 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
145 46875 : for (Edge const edge : node->use_edges()) {
146 22609 : if (!NodeProperties::IsControlEdge(edge)) continue;
147 8886 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
148 194 : return edge.from();
149 : }
150 : }
151 1657 : return node;
152 : }
153 :
154 : // static
155 1344065 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
156 : DCHECK(index < node->op()->ValueInputCount());
157 1344065 : node->ReplaceInput(FirstValueIndex(node) + index, value);
158 1344065 : }
159 :
160 :
161 : // static
162 700 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
163 : int value_input_count = node->op()->ValueInputCount();
164 : DCHECK_LE(1, value_input_count);
165 700 : node->ReplaceInput(0, value);
166 2900 : while (--value_input_count > 0) {
167 1100 : node->RemoveInput(value_input_count);
168 : }
169 700 : }
170 :
171 :
172 : // static
173 270291 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
174 270291 : node->ReplaceInput(FirstContextIndex(node), context);
175 270291 : }
176 :
177 :
178 : // static
179 13176139 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
180 : DCHECK(index < node->op()->ControlInputCount());
181 13176126 : node->ReplaceInput(FirstControlIndex(node) + index, control);
182 13176119 : }
183 :
184 :
185 : // static
186 4474625 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
187 : DCHECK(index < node->op()->EffectInputCount());
188 4474602 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
189 : }
190 :
191 :
192 : // static
193 6696727 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
194 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
195 6696727 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
196 6696721 : }
197 :
198 :
199 : // static
200 90515 : void NodeProperties::RemoveNonValueInputs(Node* node) {
201 90515 : node->TrimInputCount(node->op()->ValueInputCount());
202 90515 : }
203 :
204 :
205 : // static
206 0 : void NodeProperties::RemoveValueInputs(Node* node) {
207 : int value_input_count = node->op()->ValueInputCount();
208 0 : while (--value_input_count >= 0) {
209 0 : node->RemoveInput(value_input_count);
210 : }
211 0 : }
212 :
213 :
214 693156 : void NodeProperties::MergeControlToEnd(Graph* graph,
215 : CommonOperatorBuilder* common,
216 : Node* node) {
217 693156 : graph->end()->AppendInput(graph->zone(), node);
218 693184 : graph->end()->set_op(common->End(graph->end()->InputCount()));
219 693193 : }
220 :
221 :
222 : // static
223 2390457 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
224 : Node* success, Node* exception) {
225 : // Requires distinguishing between value, effect and control edges.
226 20535794 : for (Edge edge : node->use_edges()) {
227 9072637 : if (IsControlEdge(edge)) {
228 3611482 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
229 : DCHECK_NOT_NULL(success);
230 25755 : edge.UpdateTo(success);
231 3585727 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
232 : DCHECK_NOT_NULL(exception);
233 7554 : edge.UpdateTo(exception);
234 : } else {
235 : DCHECK_NOT_NULL(success);
236 3578173 : edge.UpdateTo(success);
237 : }
238 5461495 : } else if (IsEffectEdge(edge)) {
239 : DCHECK_NOT_NULL(effect);
240 2132900 : edge.UpdateTo(effect);
241 : } else {
242 : DCHECK_NOT_NULL(value);
243 3328580 : edge.UpdateTo(value);
244 : }
245 : }
246 2390520 : }
247 :
248 :
249 : // static
250 38013974 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
251 : node->set_op(new_op);
252 : Verifier::VerifyNode(node);
253 38013974 : }
254 :
255 :
256 : // static
257 87459 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
258 87459 : Node* effect = NodeProperties::GetEffectInput(node);
259 436889 : while (effect->opcode() != IrOpcode::kCheckpoint) {
260 174715 : if (effect->opcode() == IrOpcode::kDead) return effect;
261 : DCHECK_EQ(1, effect->op()->EffectInputCount());
262 174715 : effect = NodeProperties::GetEffectInput(effect);
263 : }
264 87459 : Node* frame_state = GetFrameStateInput(effect);
265 87459 : return frame_state;
266 : }
267 :
268 : // static
269 182166 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
270 182382 : for (auto use : node->uses()) {
271 364357 : if (use->opcode() == IrOpcode::kProjection &&
272 182177 : ProjectionIndexOf(use->op()) == projection_index) {
273 : return use;
274 : }
275 : }
276 : return nullptr;
277 : }
278 :
279 :
280 : // static
281 0 : void NodeProperties::CollectValueProjections(Node* node, Node** projections,
282 : size_t projection_count) {
283 : #ifdef DEBUG
284 : for (size_t index = 0; index < projection_count; ++index) {
285 : DCHECK_NULL(projections[index]);
286 : }
287 : #endif
288 0 : for (Edge const edge : node->use_edges()) {
289 0 : if (!IsValueEdge(edge)) continue;
290 : Node* use = edge.from();
291 : DCHECK_EQ(IrOpcode::kProjection, use->opcode());
292 0 : projections[ProjectionIndexOf(use->op())] = use;
293 : }
294 0 : }
295 :
296 :
297 : // static
298 11155983 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
299 : size_t projection_count) {
300 : #ifdef DEBUG
301 : DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
302 : std::memset(projections, 0, sizeof(*projections) * projection_count);
303 : #endif
304 : size_t if_value_index = 0;
305 64074359 : for (Edge const edge : node->use_edges()) {
306 26459207 : if (!IsControlEdge(edge)) continue;
307 : Node* use = edge.from();
308 : size_t index;
309 22907626 : switch (use->opcode()) {
310 : case IrOpcode::kIfTrue:
311 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
312 : index = 0;
313 : break;
314 : case IrOpcode::kIfFalse:
315 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
316 : index = 1;
317 10259144 : break;
318 : case IrOpcode::kIfSuccess:
319 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
320 : index = 0;
321 : break;
322 : case IrOpcode::kIfException:
323 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
324 : index = 1;
325 835748 : break;
326 : case IrOpcode::kIfValue:
327 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
328 657111 : index = if_value_index++;
329 657111 : break;
330 : case IrOpcode::kIfDefault:
331 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
332 61047 : index = projection_count - 1;
333 61047 : break;
334 : default:
335 : continue;
336 : }
337 : DCHECK_LT(if_value_index, projection_count);
338 : DCHECK_LT(index, projection_count);
339 : DCHECK_NULL(projections[index]);
340 22907678 : projections[index] = use;
341 : }
342 : #ifdef DEBUG
343 : for (size_t index = 0; index < projection_count; ++index) {
344 : DCHECK_NOT_NULL(projections[index]);
345 : }
346 : #endif
347 11155945 : }
348 :
349 : // static
350 4850214 : bool NodeProperties::IsSame(Node* a, Node* b) {
351 : for (;;) {
352 4901791 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
353 : a = GetValueInput(a, 0);
354 2148 : continue;
355 : }
356 4899643 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
357 : b = GetValueInput(b, 0);
358 49429 : continue;
359 : }
360 4850214 : return a == b;
361 : }
362 : }
363 :
364 : // static
365 16704 : base::Optional<MapRef> NodeProperties::GetJSCreateMap(JSHeapBroker* broker,
366 : Node* receiver) {
367 : DCHECK(receiver->opcode() == IrOpcode::kJSCreate ||
368 : receiver->opcode() == IrOpcode::kJSCreateArray);
369 : HeapObjectMatcher mtarget(GetValueInput(receiver, 0));
370 : HeapObjectMatcher mnewtarget(GetValueInput(receiver, 1));
371 50112 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
372 32994 : mnewtarget.Ref(broker).IsJSFunction()) {
373 8124 : ObjectRef target = mtarget.Ref(broker);
374 8124 : JSFunctionRef newtarget = mnewtarget.Ref(broker).AsJSFunction();
375 8124 : if (newtarget.map().has_prototype_slot() && newtarget.has_initial_map()) {
376 8089 : if (broker->mode() == JSHeapBroker::kSerializing) newtarget.Serialize();
377 8089 : MapRef initial_map = newtarget.initial_map();
378 8089 : if (initial_map.GetConstructor().equals(target)) {
379 : DCHECK(target.AsJSFunction().map().is_constructor());
380 : DCHECK(newtarget.map().is_constructor());
381 8089 : return initial_map;
382 : }
383 : }
384 : }
385 : return base::nullopt;
386 : }
387 :
388 : // static
389 189448 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
390 : JSHeapBroker* broker, Node* receiver, Node* effect,
391 : ZoneHandleSet<Map>* maps_return) {
392 : HeapObjectMatcher m(receiver);
393 189448 : if (m.HasValue()) {
394 66829 : HeapObjectRef receiver = m.Ref(broker);
395 : // We don't use ICs for the Array.prototype and the Object.prototype
396 : // because the runtime has to be able to intercept them properly, so
397 : // we better make sure that TurboFan doesn't outsmart the system here
398 : // by storing to elements of either prototype directly.
399 : //
400 : // TODO(bmeurer): This can be removed once the Array.prototype and
401 : // Object.prototype have NO_ELEMENTS elements kind.
402 200487 : if (!receiver.IsJSObject() ||
403 192135 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
404 66577 : if (receiver.map().is_stable()) {
405 : // The {receiver_map} is only reliable when we install a stability
406 : // code dependency.
407 58907 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
408 58907 : return kUnreliableReceiverMaps;
409 : }
410 : }
411 : }
412 : InferReceiverMapsResult result = kReliableReceiverMaps;
413 : while (true) {
414 4882861 : switch (effect->opcode()) {
415 : case IrOpcode::kMapGuard: {
416 : Node* const object = GetValueInput(effect, 0);
417 181 : if (IsSame(receiver, object)) {
418 139 : *maps_return = MapGuardMapsOf(effect->op());
419 139 : return result;
420 : }
421 : break;
422 : }
423 : case IrOpcode::kCheckMaps: {
424 : Node* const object = GetValueInput(effect, 0);
425 60609 : if (IsSame(receiver, object)) {
426 35957 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
427 35957 : return result;
428 : }
429 : break;
430 : }
431 : case IrOpcode::kJSCreate: {
432 4020 : if (IsSame(receiver, effect)) {
433 3185 : base::Optional<MapRef> initial_map = GetJSCreateMap(broker, receiver);
434 3185 : if (initial_map.has_value()) {
435 2937 : *maps_return = ZoneHandleSet<Map>(initial_map->object());
436 2937 : return result;
437 : }
438 : // We reached the allocation of the {receiver}.
439 : return kNoReceiverMaps;
440 : }
441 : break;
442 : }
443 : case IrOpcode::kJSCreatePromise: {
444 86 : if (IsSame(receiver, effect)) {
445 44 : *maps_return = ZoneHandleSet<Map>(broker->native_context()
446 44 : .promise_function()
447 44 : .initial_map()
448 22 : .object());
449 22 : return result;
450 : }
451 : break;
452 : }
453 : case IrOpcode::kStoreField: {
454 : // We only care about StoreField of maps.
455 : Node* const object = GetValueInput(effect, 0);
456 22349 : FieldAccess const& access = FieldAccessOf(effect->op());
457 22349 : if (access.base_is_tagged == kTaggedBase &&
458 : access.offset == HeapObject::kMapOffset) {
459 3885 : if (IsSame(receiver, object)) {
460 : Node* const value = GetValueInput(effect, 1);
461 : HeapObjectMatcher m(value);
462 2855 : if (m.HasValue()) {
463 2855 : *maps_return = ZoneHandleSet<Map>(m.Ref(broker).AsMap().object());
464 : return result;
465 : }
466 : }
467 : // Without alias analysis we cannot tell whether this
468 : // StoreField[map] affects {receiver} or not.
469 : result = kUnreliableReceiverMaps;
470 : }
471 : break;
472 : }
473 : case IrOpcode::kJSStoreMessage:
474 : case IrOpcode::kJSStoreModule:
475 : case IrOpcode::kStoreElement:
476 : case IrOpcode::kStoreTypedElement: {
477 : // These never change the map of objects.
478 : break;
479 : }
480 : case IrOpcode::kFinishRegion: {
481 : // FinishRegion renames the output of allocations, so we need
482 : // to update the {receiver} that we are looking for, if the
483 : // {receiver} matches the current {effect}.
484 3885 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
485 : break;
486 : }
487 : case IrOpcode::kEffectPhi: {
488 26754 : Node* control = GetControlInput(effect);
489 26754 : if (control->opcode() != IrOpcode::kLoop) {
490 : DCHECK(control->opcode() == IrOpcode::kDead ||
491 : control->opcode() == IrOpcode::kMerge);
492 : return kNoReceiverMaps;
493 : }
494 :
495 : // Continue search for receiver map outside the loop. Since operations
496 : // inside the loop may change the map, the result is unreliable.
497 10825 : effect = GetEffectInput(effect, 0);
498 : result = kUnreliableReceiverMaps;
499 10825 : continue;
500 : }
501 : default: {
502 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
503 4761702 : if (effect->op()->EffectInputCount() != 1) {
504 : // Didn't find any appropriate CheckMaps node.
505 : return kNoReceiverMaps;
506 : }
507 4725301 : if (!effect->op()->HasProperty(Operator::kNoWrite)) {
508 : // Without alias/escape analysis we cannot tell whether this
509 : // {effect} affects {receiver} or not.
510 : result = kUnreliableReceiverMaps;
511 : }
512 : break;
513 : }
514 : }
515 :
516 : // Stop walking the effect chain once we hit the definition of
517 : // the {receiver} along the {effect}s.
518 4777548 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
519 :
520 : // Continue with the next {effect}.
521 : DCHECK_EQ(1, effect->op()->EffectInputCount());
522 4741495 : effect = NodeProperties::GetEffectInput(effect);
523 : }
524 : }
525 :
526 : // static
527 1840 : bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
528 : Node* receiver, Node* effect,
529 : InstanceType instance_type) {
530 : ZoneHandleSet<Map> receiver_maps;
531 : NodeProperties::InferReceiverMapsResult result =
532 : NodeProperties::InferReceiverMaps(broker, receiver, effect,
533 1840 : &receiver_maps);
534 1840 : switch (result) {
535 : case NodeProperties::kUnreliableReceiverMaps:
536 : case NodeProperties::kReliableReceiverMaps:
537 : DCHECK_NE(0, receiver_maps.size());
538 6046 : for (size_t i = 0; i < receiver_maps.size(); ++i) {
539 : MapRef map(broker, receiver_maps[i]);
540 2104 : if (map.instance_type() != instance_type) return false;
541 : }
542 : return true;
543 :
544 : case NodeProperties::kNoReceiverMaps:
545 : return false;
546 : }
547 0 : UNREACHABLE();
548 : }
549 :
550 : // static
551 384 : bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
552 : Node* dominator) {
553 1878 : while (effect != dominator) {
554 2032 : if (effect->op()->EffectInputCount() == 1 &&
555 : effect->op()->properties() & Operator::kNoWrite) {
556 747 : effect = NodeProperties::GetEffectInput(effect);
557 : } else {
558 : return false;
559 : }
560 : }
561 : return true;
562 : }
563 :
564 : // static
565 59506 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
566 : Node* effect) {
567 59506 : switch (receiver->opcode()) {
568 : #define CASE(Opcode) case IrOpcode::k##Opcode:
569 : JS_CONSTRUCT_OP_LIST(CASE)
570 : JS_CREATE_OP_LIST(CASE)
571 : #undef CASE
572 : case IrOpcode::kCheckReceiver:
573 : case IrOpcode::kConvertReceiver:
574 : case IrOpcode::kJSGetSuperConstructor:
575 : case IrOpcode::kJSToObject:
576 : return false;
577 : case IrOpcode::kHeapConstant: {
578 56659 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
579 56659 : return value.map().IsPrimitiveMap();
580 : }
581 : default: {
582 : // We don't really care about the exact maps here,
583 : // just the instance types, which don't change
584 : // across potential side-effecting operations.
585 : ZoneHandleSet<Map> maps;
586 2323 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
587 : kNoReceiverMaps) {
588 : // Check if one of the {maps} is not a JSReceiver map.
589 6117 : for (size_t i = 0; i < maps.size(); ++i) {
590 : MapRef map(broker, maps[i]);
591 2067 : if (!map.IsJSReceiverMap()) return true;
592 : }
593 : return false;
594 : }
595 : return true;
596 : }
597 : }
598 : }
599 :
600 : // static
601 529 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
602 : Node* effect) {
603 529 : if (CanBePrimitive(broker, receiver, effect)) {
604 112 : switch (receiver->opcode()) {
605 : case IrOpcode::kCheckInternalizedString:
606 : case IrOpcode::kCheckNumber:
607 : case IrOpcode::kCheckSmi:
608 : case IrOpcode::kCheckString:
609 : case IrOpcode::kCheckSymbol:
610 : case IrOpcode::kJSToLength:
611 : case IrOpcode::kJSToName:
612 : case IrOpcode::kJSToNumber:
613 : case IrOpcode::kJSToNumberConvertBigInt:
614 : case IrOpcode::kJSToNumeric:
615 : case IrOpcode::kJSToString:
616 : case IrOpcode::kToBoolean:
617 : return false;
618 : case IrOpcode::kHeapConstant: {
619 62 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
620 62 : OddballType type = value.map().oddball_type();
621 62 : return type == OddballType::kNull || type == OddballType::kUndefined;
622 : }
623 : default:
624 50 : return true;
625 : }
626 : }
627 : return false;
628 : }
629 :
630 : // static
631 879088 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
632 : Node* context = NodeProperties::GetContextInput(node);
633 955303 : while (*depth > 0 &&
634 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
635 : context = NodeProperties::GetContextInput(context);
636 16351 : (*depth)--;
637 : }
638 879088 : return context;
639 : }
640 :
641 : // static
642 777074265 : Type NodeProperties::GetTypeOrAny(Node* node) {
643 777074265 : return IsTyped(node) ? node->type() : Type::Any();
644 : }
645 :
646 :
647 : // static
648 4909025 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
649 : int input_count = node->op()->ValueInputCount();
650 12443009 : for (int index = 0; index < input_count; ++index) {
651 3823703 : if (!IsTyped(GetValueInput(node, index))) return false;
652 : }
653 : return true;
654 : }
655 :
656 :
657 : // static
658 : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
659 435108696 : if (num == 0) return false;
660 : int const index = edge.index();
661 298140639 : return first <= index && index < first + num;
662 : }
663 :
664 : // static
665 143620956 : size_t NodeProperties::HashCode(Node* node) {
666 143620956 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
667 469188560 : for (Node* input : node->inputs()) {
668 : h = base::hash_combine(h, input->id());
669 : }
670 143612162 : return h;
671 : }
672 :
673 : // static
674 88144608 : bool NodeProperties::Equals(Node* a, Node* b) {
675 : DCHECK_NOT_NULL(a);
676 : DCHECK_NOT_NULL(b);
677 : DCHECK_NOT_NULL(a->op());
678 : DCHECK_NOT_NULL(b->op());
679 88144608 : if (!a->op()->Equals(b->op())) return false;
680 4566093 : if (a->InputCount() != b->InputCount()) return false;
681 : Node::Inputs aInputs = a->inputs();
682 : Node::Inputs bInputs = b->inputs();
683 :
684 : auto aIt = aInputs.begin();
685 : auto bIt = bInputs.begin();
686 : auto aEnd = aInputs.end();
687 :
688 10861952 : for (; aIt != aEnd; ++aIt, ++bIt) {
689 : DCHECK_NOT_NULL(*aIt);
690 : DCHECK_NOT_NULL(*bIt);
691 8036954 : if ((*aIt)->id() != (*bIt)->id()) return false;
692 : }
693 : return true;
694 : }
695 :
696 : } // namespace compiler
697 : } // namespace internal
698 122004 : } // namespace v8
|