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 74584 : int NodeProperties::PastValueIndex(Node* node) {
23 74584 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 544 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 1197119859 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1185291757 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 1185168233 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 92271640 : int NodeProperties::PastEffectIndex(Node* node) {
43 699970666 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 66852796 : int NodeProperties::PastControlIndex(Node* node) {
49 66854561 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 165284373 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 165284373 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 5912090 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 5912090 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 4700661 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 4700660 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 243152934 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 486227664 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 324840485 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 649554410 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 9692688 : bool NodeProperties::IsValueEdge(Edge edge) {
90 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 9692688 : 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 516681 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 516681 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 220810266 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 220801426 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 202917726 : bool NodeProperties::IsControlEdge(Edge edge) {
122 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 202911920 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 12618464 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 12618464 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 137449320 : for (Edge const edge : node->use_edges()) {
132 62834929 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 20982340 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 848411 : if (out_exception != nullptr) *out_exception = edge.from();
135 839023 : return true;
136 : }
137 : }
138 11779462 : return false;
139 : }
140 :
141 : // static
142 1879 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
143 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
144 1879 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
145 53083 : for (Edge const edge : node->use_edges()) {
146 25699 : if (!NodeProperties::IsControlEdge(edge)) continue;
147 8919 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
148 194 : return edge.from();
149 : }
150 : }
151 1685 : return node;
152 : }
153 :
154 : // static
155 648936 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
156 : DCHECK(index < node->op()->ValueInputCount());
157 648936 : node->ReplaceInput(FirstValueIndex(node) + index, value);
158 648936 : }
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 2904 : while (--value_input_count > 0) {
167 1102 : node->RemoveInput(value_input_count);
168 : }
169 700 : }
170 :
171 :
172 : // static
173 270093 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
174 270093 : node->ReplaceInput(FirstContextIndex(node), context);
175 270093 : }
176 :
177 :
178 : // static
179 13155263 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
180 : DCHECK(index < node->op()->ControlInputCount());
181 13155244 : node->ReplaceInput(FirstControlIndex(node) + index, control);
182 13155246 : }
183 :
184 :
185 : // static
186 4468187 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
187 : DCHECK(index < node->op()->EffectInputCount());
188 4468169 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
189 : }
190 :
191 :
192 : // static
193 6684982 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
194 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
195 6684983 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
196 6684975 : }
197 :
198 :
199 : // static
200 90497 : void NodeProperties::RemoveNonValueInputs(Node* node) {
201 90497 : node->TrimInputCount(node->op()->ValueInputCount());
202 90497 : }
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 693247 : void NodeProperties::MergeControlToEnd(Graph* graph,
215 : CommonOperatorBuilder* common,
216 : Node* node) {
217 693247 : graph->end()->AppendInput(graph->zone(), node);
218 693285 : graph->end()->set_op(common->End(graph->end()->InputCount()));
219 693292 : }
220 :
221 :
222 : // static
223 2380432 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
224 : Node* success, Node* exception) {
225 : // Requires distinguishing between value, effect and control edges.
226 20480927 : for (Edge edge : node->use_edges()) {
227 9050230 : if (IsControlEdge(edge)) {
228 3606718 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
229 : DCHECK_NOT_NULL(success);
230 24602 : edge.UpdateTo(success);
231 3582116 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
232 : DCHECK_NOT_NULL(exception);
233 7415 : edge.UpdateTo(exception);
234 : } else {
235 : DCHECK_NOT_NULL(success);
236 3574701 : edge.UpdateTo(success);
237 : }
238 5443796 : } else if (IsEffectEdge(edge)) {
239 : DCHECK_NOT_NULL(effect);
240 2127228 : edge.UpdateTo(effect);
241 : } else {
242 : DCHECK_NOT_NULL(value);
243 3316558 : edge.UpdateTo(value);
244 : }
245 : }
246 2380467 : }
247 :
248 :
249 : // static
250 37967310 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
251 : node->set_op(new_op);
252 : Verifier::VerifyNode(node);
253 37967310 : }
254 :
255 :
256 : // static
257 87481 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
258 87481 : Node* effect = NodeProperties::GetEffectInput(node);
259 437297 : while (effect->opcode() != IrOpcode::kCheckpoint) {
260 174908 : if (effect->opcode() == IrOpcode::kDead) return effect;
261 : DCHECK_EQ(1, effect->op()->EffectInputCount());
262 174908 : effect = NodeProperties::GetEffectInput(effect);
263 : }
264 87481 : Node* frame_state = GetFrameStateInput(effect);
265 87481 : return frame_state;
266 : }
267 :
268 : // static
269 182053 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
270 182269 : for (auto use : node->uses()) {
271 364115 : if (use->opcode() == IrOpcode::kProjection &&
272 182058 : 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 11135306 : 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 63903581 : for (Edge const edge : node->use_edges()) {
306 26384129 : if (!IsControlEdge(edge)) continue;
307 : Node* use = edge.from();
308 : size_t index;
309 22861978 : 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 10248278 : 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 828007 : break;
326 : case IrOpcode::kIfValue:
327 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
328 650608 : index = if_value_index++;
329 650608 : break;
330 : case IrOpcode::kIfDefault:
331 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
332 59057 : index = projection_count - 1;
333 59057 : 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 22861949 : 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 11135323 : }
348 :
349 : // static
350 4834002 : bool NodeProperties::IsSame(Node* a, Node* b) {
351 : for (;;) {
352 4881789 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
353 : a = GetValueInput(a, 0);
354 2026 : continue;
355 : }
356 4879763 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
357 : b = GetValueInput(b, 0);
358 45761 : continue;
359 : }
360 4834002 : return a == b;
361 : }
362 : }
363 :
364 : // static
365 16696 : 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 50088 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
372 32970 : mnewtarget.Ref(broker).IsJSFunction()) {
373 8116 : ObjectRef target = mtarget.Ref(broker);
374 8116 : JSFunctionRef newtarget = mnewtarget.Ref(broker).AsJSFunction();
375 8116 : if (newtarget.map().has_prototype_slot() && newtarget.has_initial_map()) {
376 8081 : if (broker->mode() == JSHeapBroker::kSerializing) newtarget.Serialize();
377 8081 : MapRef initial_map = newtarget.initial_map();
378 8081 : if (initial_map.GetConstructor().equals(target)) {
379 : DCHECK(target.AsJSFunction().map().is_constructor());
380 : DCHECK(newtarget.map().is_constructor());
381 8081 : return initial_map;
382 : }
383 : }
384 : }
385 : return base::nullopt;
386 : }
387 :
388 : // static
389 187492 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
390 : JSHeapBroker* broker, Node* receiver, Node* effect,
391 : ZoneHandleSet<Map>* maps_return) {
392 : HeapObjectMatcher m(receiver);
393 187492 : if (m.HasValue()) {
394 66872 : 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 200616 : if (!receiver.IsJSObject() ||
403 192288 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
404 66611 : if (receiver.map().is_stable()) {
405 : // The {receiver_map} is only reliable when we install a stability
406 : // code dependency.
407 58918 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
408 58918 : return kUnreliableReceiverMaps;
409 : }
410 : }
411 : }
412 : InferReceiverMapsResult result = kReliableReceiverMaps;
413 : while (true) {
414 4867871 : switch (effect->opcode()) {
415 : case IrOpcode::kMapGuard: {
416 : Node* const object = GetValueInput(effect, 0);
417 180 : if (IsSame(receiver, object)) {
418 138 : *maps_return = MapGuardMapsOf(effect->op());
419 138 : return result;
420 : }
421 : break;
422 : }
423 : case IrOpcode::kCheckMaps: {
424 : Node* const object = GetValueInput(effect, 0);
425 57831 : if (IsSame(receiver, object)) {
426 35172 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
427 35172 : return result;
428 : }
429 : break;
430 : }
431 : case IrOpcode::kJSCreate: {
432 4013 : if (IsSame(receiver, effect)) {
433 3180 : base::Optional<MapRef> initial_map = GetJSCreateMap(broker, receiver);
434 3180 : if (initial_map.has_value()) {
435 2932 : *maps_return = ZoneHandleSet<Map>(initial_map->object());
436 2932 : 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 22284 : FieldAccess const& access = FieldAccessOf(effect->op());
457 22284 : if (access.base_is_tagged == kTaggedBase &&
458 : access.offset == HeapObject::kMapOffset) {
459 3864 : if (IsSame(receiver, object)) {
460 : Node* const value = GetValueInput(effect, 1);
461 : HeapObjectMatcher m(value);
462 2839 : if (m.HasValue()) {
463 2839 : *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 3864 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
485 : break;
486 : }
487 : case IrOpcode::kEffectPhi: {
488 26157 : Node* control = GetControlInput(effect);
489 26157 : 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 10746 : effect = GetEffectInput(effect, 0);
498 : result = kUnreliableReceiverMaps;
499 10746 : continue;
500 : }
501 : default: {
502 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
503 4750304 : if (effect->op()->EffectInputCount() != 1) {
504 : // Didn't find any appropriate CheckMaps node.
505 : return kNoReceiverMaps;
506 : }
507 4714105 : 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 4764164 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
519 :
520 : // Continue with the next {effect}.
521 : DCHECK_EQ(1, effect->op()->EffectInputCount());
522 4728551 : effect = NodeProperties::GetEffectInput(effect);
523 : }
524 : }
525 :
526 : // static
527 1705 : 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 1705 : &receiver_maps);
534 1705 : switch (result) {
535 : case NodeProperties::kUnreliableReceiverMaps:
536 : case NodeProperties::kReliableReceiverMaps:
537 : DCHECK_NE(0, receiver_maps.size());
538 5543 : for (size_t i = 0; i < receiver_maps.size(); ++i) {
539 : MapRef map(broker, receiver_maps[i]);
540 1920 : 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 59567 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
566 : Node* effect) {
567 59567 : 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 56712 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
579 56712 : 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 2326 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
587 : kNoReceiverMaps) {
588 : // Check if one of the {maps} is not a JSReceiver map.
589 6125 : for (size_t i = 0; i < maps.size(); ++i) {
590 : MapRef map(broker, maps[i]);
591 2071 : if (!map.IsJSReceiverMap()) return true;
592 : }
593 : return false;
594 : }
595 : return true;
596 : }
597 : }
598 : }
599 :
600 : // static
601 532 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
602 : Node* effect) {
603 532 : if (CanBePrimitive(broker, receiver, effect)) {
604 115 : 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 64 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
620 64 : OddballType type = value.map().oddball_type();
621 64 : return type == OddballType::kNull || type == OddballType::kUndefined;
622 : }
623 : default:
624 51 : return true;
625 : }
626 : }
627 : return false;
628 : }
629 :
630 : // static
631 877854 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
632 : Node* context = NodeProperties::GetContextInput(node);
633 953786 : while (*depth > 0 &&
634 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
635 : context = NodeProperties::GetContextInput(context);
636 16332 : (*depth)--;
637 : }
638 877854 : return context;
639 : }
640 :
641 : // static
642 775533076 : Type NodeProperties::GetTypeOrAny(Node* node) {
643 775533076 : return IsTyped(node) ? node->type() : Type::Any();
644 : }
645 :
646 :
647 : // static
648 4901286 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
649 : int input_count = node->op()->ValueInputCount();
650 12420516 : for (int index = 0; index < input_count; ++index) {
651 3816319 : 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 433922715 : if (num == 0) return false;
660 : int const index = edge.index();
661 297280070 : return first <= index && index < first + num;
662 : }
663 :
664 : // static
665 143378231 : size_t NodeProperties::HashCode(Node* node) {
666 143378231 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
667 468210548 : for (Node* input : node->inputs()) {
668 : h = base::hash_combine(h, input->id());
669 : }
670 143373148 : return h;
671 : }
672 :
673 : // static
674 87823715 : 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 87823715 : if (!a->op()->Equals(b->op())) return false;
680 4526640 : 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 10800810 : for (; aIt != aEnd; ++aIt, ++bIt) {
689 : DCHECK_NOT_NULL(*aIt);
690 : DCHECK_NOT_NULL(*bIt);
691 8000623 : if ((*aIt)->id() != (*bIt)->id()) return false;
692 : }
693 : return true;
694 : }
695 :
696 : } // namespace compiler
697 : } // namespace internal
698 121996 : } // namespace v8
|