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 75687 : int NodeProperties::PastValueIndex(Node* node) {
23 75687 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 544 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 1198373851 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1186587606 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 1186400643 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 92350532 : int NodeProperties::PastEffectIndex(Node* node) {
43 700436953 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 66902135 : int NodeProperties::PastControlIndex(Node* node) {
49 66903608 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 165200376 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 165200376 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 5920471 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 5920471 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 4703150 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 4703152 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 243446607 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 486835380 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 324929860 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 649740228 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 9680492 : bool NodeProperties::IsValueEdge(Edge edge) {
90 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 9680492 : 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 513703 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 513703 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 221229301 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 221220675 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 203163009 : bool NodeProperties::IsControlEdge(Edge edge) {
122 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 203166603 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 12629658 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 12629658 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 137598529 : for (Edge const edge : node->use_edges()) {
132 62904724 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 21001773 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 849811 : if (out_exception != nullptr) *out_exception = edge.from();
135 840597 : return true;
136 : }
137 : }
138 11789081 : return false;
139 : }
140 :
141 : // static
142 1876 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
143 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
144 1876 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
145 53050 : for (Edge const edge : node->use_edges()) {
146 25684 : if (!NodeProperties::IsControlEdge(edge)) continue;
147 8911 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
148 194 : return edge.from();
149 : }
150 : }
151 1682 : return node;
152 : }
153 :
154 : // static
155 639913 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
156 : DCHECK(index < node->op()->ValueInputCount());
157 639913 : node->ReplaceInput(FirstValueIndex(node) + index, value);
158 639913 : }
159 :
160 :
161 : // static
162 621 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
163 : int value_input_count = node->op()->ValueInputCount();
164 : DCHECK_LE(1, value_input_count);
165 621 : node->ReplaceInput(0, value);
166 2657 : while (--value_input_count > 0) {
167 1018 : node->RemoveInput(value_input_count);
168 : }
169 621 : }
170 :
171 :
172 : // static
173 270042 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
174 270042 : node->ReplaceInput(FirstContextIndex(node), context);
175 270042 : }
176 :
177 :
178 : // static
179 13146198 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
180 : DCHECK(index < node->op()->ControlInputCount());
181 13146193 : node->ReplaceInput(FirstControlIndex(node) + index, control);
182 13146188 : }
183 :
184 :
185 : // static
186 4471888 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
187 : DCHECK(index < node->op()->EffectInputCount());
188 4471884 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
189 : }
190 :
191 :
192 : // static
193 6687663 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
194 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
195 6687667 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
196 6687664 : }
197 :
198 :
199 : // static
200 90376 : void NodeProperties::RemoveNonValueInputs(Node* node) {
201 90376 : node->TrimInputCount(node->op()->ValueInputCount());
202 90376 : }
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 691567 : void NodeProperties::MergeControlToEnd(Graph* graph,
215 : CommonOperatorBuilder* common,
216 : Node* node) {
217 691567 : graph->end()->AppendInput(graph->zone(), node);
218 691599 : graph->end()->set_op(common->End(graph->end()->InputCount()));
219 691602 : }
220 :
221 :
222 : // static
223 2379873 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
224 : Node* success, Node* exception) {
225 : // Requires distinguishing between value, effect and control edges.
226 20480001 : for (Edge edge : node->use_edges()) {
227 9050059 : if (IsControlEdge(edge)) {
228 3605916 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
229 : DCHECK_NOT_NULL(success);
230 24369 : edge.UpdateTo(success);
231 3581547 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
232 : DCHECK_NOT_NULL(exception);
233 7410 : edge.UpdateTo(exception);
234 : } else {
235 : DCHECK_NOT_NULL(success);
236 3574137 : edge.UpdateTo(success);
237 : }
238 5444349 : } else if (IsEffectEdge(edge)) {
239 : DCHECK_NOT_NULL(effect);
240 2125389 : edge.UpdateTo(effect);
241 : } else {
242 : DCHECK_NOT_NULL(value);
243 3318933 : edge.UpdateTo(value);
244 : }
245 : }
246 2379883 : }
247 :
248 :
249 : // static
250 37991020 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
251 : node->set_op(new_op);
252 : Verifier::VerifyNode(node);
253 37991020 : }
254 :
255 :
256 : // static
257 87192 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
258 87192 : Node* effect = NodeProperties::GetEffectInput(node);
259 435816 : while (effect->opcode() != IrOpcode::kCheckpoint) {
260 174312 : if (effect->opcode() == IrOpcode::kDead) return effect;
261 : DCHECK_EQ(1, effect->op()->EffectInputCount());
262 174312 : effect = NodeProperties::GetEffectInput(effect);
263 : }
264 87192 : Node* frame_state = GetFrameStateInput(effect);
265 87192 : return frame_state;
266 : }
267 :
268 : // static
269 182270 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
270 182486 : for (auto use : node->uses()) {
271 364568 : if (use->opcode() == IrOpcode::kProjection &&
272 182279 : 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 11132770 : 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 63914388 : for (Edge const edge : node->use_edges()) {
306 26390889 : if (!IsControlEdge(edge)) continue;
307 : Node* use = edge.from();
308 : size_t index;
309 22861130 : 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 10241401 : 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 829768 : break;
326 : case IrOpcode::kIfValue:
327 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
328 657624 : index = if_value_index++;
329 657624 : break;
330 : case IrOpcode::kIfDefault:
331 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
332 61415 : index = projection_count - 1;
333 61415 : 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 22861163 : 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 11132610 : }
348 :
349 : // static
350 4830638 : bool NodeProperties::IsSame(Node* a, Node* b) {
351 : for (;;) {
352 4877710 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
353 : a = GetValueInput(a, 0);
354 1938 : continue;
355 : }
356 4875772 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
357 : b = GetValueInput(b, 0);
358 45134 : continue;
359 : }
360 4830638 : return a == b;
361 : }
362 : }
363 :
364 : // static
365 16675 : 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 50025 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
372 32907 : mnewtarget.Ref(broker).IsJSFunction()) {
373 8095 : ObjectRef target = mtarget.Ref(broker);
374 8095 : JSFunctionRef newtarget = mnewtarget.Ref(broker).AsJSFunction();
375 8095 : if (newtarget.map().has_prototype_slot() && newtarget.has_initial_map()) {
376 8060 : if (broker->mode() == JSHeapBroker::kSerializing) newtarget.Serialize();
377 8060 : MapRef initial_map = newtarget.initial_map();
378 8060 : if (initial_map.GetConstructor().equals(target)) {
379 : DCHECK(target.AsJSFunction().map().is_constructor());
380 : DCHECK(newtarget.map().is_constructor());
381 8060 : return initial_map;
382 : }
383 : }
384 : }
385 : return base::nullopt;
386 : }
387 :
388 : // static
389 187156 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
390 : JSHeapBroker* broker, Node* receiver, Node* effect,
391 : ZoneHandleSet<Map>* maps_return) {
392 : HeapObjectMatcher m(receiver);
393 187156 : if (m.HasValue()) {
394 66727 : 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 200181 : if (!receiver.IsJSObject() ||
403 191867 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
404 66475 : if (receiver.map().is_stable()) {
405 : // The {receiver_map} is only reliable when we install a stability
406 : // code dependency.
407 58867 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
408 58867 : return kUnreliableReceiverMaps;
409 : }
410 : }
411 : }
412 : InferReceiverMapsResult result = kReliableReceiverMaps;
413 : while (true) {
414 4865090 : switch (effect->opcode()) {
415 : case IrOpcode::kMapGuard: {
416 : Node* const object = GetValueInput(effect, 0);
417 178 : if (IsSame(receiver, object)) {
418 136 : *maps_return = MapGuardMapsOf(effect->op());
419 136 : return result;
420 : }
421 : break;
422 : }
423 : case IrOpcode::kCheckMaps: {
424 : Node* const object = GetValueInput(effect, 0);
425 57239 : if (IsSame(receiver, object)) {
426 34913 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
427 34913 : return result;
428 : }
429 : break;
430 : }
431 : case IrOpcode::kJSCreate: {
432 3999 : if (IsSame(receiver, effect)) {
433 3173 : base::Optional<MapRef> initial_map = GetJSCreateMap(broker, receiver);
434 3173 : if (initial_map.has_value()) {
435 2925 : *maps_return = ZoneHandleSet<Map>(initial_map->object());
436 2925 : 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 22086 : FieldAccess const& access = FieldAccessOf(effect->op());
457 22086 : if (access.base_is_tagged == kTaggedBase &&
458 : access.offset == HeapObject::kMapOffset) {
459 3772 : if (IsSame(receiver, object)) {
460 : Node* const value = GetValueInput(effect, 1);
461 : HeapObjectMatcher m(value);
462 2760 : if (m.HasValue()) {
463 2760 : *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 3772 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
485 : break;
486 : }
487 : case IrOpcode::kEffectPhi: {
488 26085 : Node* control = GetControlInput(effect);
489 26085 : 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 10749 : effect = GetEffectInput(effect, 0);
498 : result = kUnreliableReceiverMaps;
499 10749 : continue;
500 : }
501 : default: {
502 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
503 4748538 : if (effect->op()->EffectInputCount() != 1) {
504 : // Didn't find any appropriate CheckMaps node.
505 : return kNoReceiverMaps;
506 : }
507 4712129 : 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 4761592 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
519 :
520 : // Continue with the next {effect}.
521 : DCHECK_EQ(1, effect->op()->EffectInputCount());
522 4726052 : effect = NodeProperties::GetEffectInput(effect);
523 : }
524 : }
525 :
526 : // static
527 1699 : 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 1699 : &receiver_maps);
534 1699 : 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 1923 : 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 59213 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
566 : Node* effect) {
567 59213 : 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 56388 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
579 56388 : 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 2302 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
587 : kNoReceiverMaps) {
588 : // Check if one of the {maps} is not a JSReceiver map.
589 6075 : for (size_t i = 0; i < maps.size(); ++i) {
590 : MapRef map(broker, maps[i]);
591 2053 : if (!map.IsJSReceiverMap()) return true;
592 : }
593 : return false;
594 : }
595 : return true;
596 : }
597 : }
598 : }
599 :
600 : // static
601 523 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
602 : Node* effect) {
603 523 : if (CanBePrimitive(broker, receiver, effect)) {
604 106 : 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 60 : HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
620 60 : OddballType type = value.map().oddball_type();
621 60 : return type == OddballType::kNull || type == OddballType::kUndefined;
622 : }
623 : default:
624 46 : return true;
625 : }
626 : }
627 : return false;
628 : }
629 :
630 : // static
631 879626 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
632 : Node* context = NodeProperties::GetContextInput(node);
633 955664 : while (*depth > 0 &&
634 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
635 : context = NodeProperties::GetContextInput(context);
636 16342 : (*depth)--;
637 : }
638 879626 : return context;
639 : }
640 :
641 : // static
642 776184460 : Type NodeProperties::GetTypeOrAny(Node* node) {
643 776184460 : return IsTyped(node) ? node->type() : Type::Any();
644 : }
645 :
646 :
647 : // static
648 4900738 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
649 : int input_count = node->op()->ValueInputCount();
650 12419672 : for (int index = 0; index < input_count; ++index) {
651 3816173 : 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 434581473 : if (num == 0) return false;
660 : int const index = edge.index();
661 297767547 : return first <= index && index < first + num;
662 : }
663 :
664 : // static
665 143577035 : size_t NodeProperties::HashCode(Node* node) {
666 143577035 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
667 468755320 : for (Node* input : node->inputs()) {
668 : h = base::hash_combine(h, input->id());
669 : }
670 143573558 : return h;
671 : }
672 :
673 : // static
674 86453944 : 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 86453944 : if (!a->op()->Equals(b->op())) return false;
680 4520330 : 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 10824114 : for (; aIt != aEnd; ++aIt, ++bIt) {
689 : DCHECK_NOT_NULL(*aIt);
690 : DCHECK_NOT_NULL(*bIt);
691 7989884 : if ((*aIt)->id() != (*bIt)->id()) return false;
692 : }
693 : return true;
694 : }
695 :
696 : } // namespace compiler
697 : } // namespace internal
698 122036 : } // namespace v8
|