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 75577 : int NodeProperties::PastValueIndex(Node* node) {
23 75577 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 498 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 1231173481 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1218281094 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 1218118997 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 92242502 : int NodeProperties::PastEffectIndex(Node* node) {
43 713317190 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 66802175 : int NodeProperties::PastControlIndex(Node* node) {
49 66802930 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 170857126 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 170857126 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 6172256 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 6172256 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 5229505 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 5229512 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 254472461 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 508871924 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 336029863 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 671970940 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 9580383 : bool NodeProperties::IsValueEdge(Edge edge) {
90 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 9580383 : 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 517112 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 517112 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 228531800 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 228526018 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 204776956 : bool NodeProperties::IsControlEdge(Edge edge) {
122 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 204772216 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 13688542 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 13688542 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 141764379 : for (Edge const edge : node->use_edges()) {
132 64446995 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 21681569 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 828471 : if (out_exception != nullptr) *out_exception = edge.from();
135 818149 : return true;
136 : }
137 : }
138 12870389 : return false;
139 : }
140 :
141 : // static
142 1414 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
143 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
144 1414 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
145 40370 : for (Edge const edge : node->use_edges()) {
146 19575 : if (!NodeProperties::IsControlEdge(edge)) continue;
147 7801 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
148 194 : return edge.from();
149 : }
150 : }
151 1220 : return node;
152 : }
153 :
154 : // static
155 1355916 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
156 : DCHECK(index < node->op()->ValueInputCount());
157 1355916 : node->ReplaceInput(FirstValueIndex(node) + index, value);
158 1355916 : }
159 :
160 :
161 : // static
162 686 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
163 : int value_input_count = node->op()->ValueInputCount();
164 : DCHECK_LE(1, value_input_count);
165 686 : node->ReplaceInput(0, value);
166 2840 : while (--value_input_count > 0) {
167 1077 : node->RemoveInput(value_input_count);
168 : }
169 686 : }
170 :
171 :
172 : // static
173 266250 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
174 266250 : node->ReplaceInput(FirstContextIndex(node), context);
175 266250 : }
176 :
177 :
178 : // static
179 13514173 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
180 : DCHECK(index < node->op()->ControlInputCount());
181 13514167 : node->ReplaceInput(FirstControlIndex(node) + index, control);
182 13514159 : }
183 :
184 :
185 : // static
186 4762500 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
187 : DCHECK(index < node->op()->EffectInputCount());
188 4762493 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
189 : }
190 :
191 :
192 : // static
193 7250850 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
194 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
195 7250857 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
196 7250855 : }
197 :
198 :
199 : // static
200 104295 : void NodeProperties::RemoveNonValueInputs(Node* node) {
201 104295 : node->TrimInputCount(node->op()->ValueInputCount());
202 104295 : }
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 609992 : void NodeProperties::MergeControlToEnd(Graph* graph,
215 : CommonOperatorBuilder* common,
216 : Node* node) {
217 609992 : graph->end()->AppendInput(graph->zone(), node);
218 609994 : graph->end()->set_op(common->End(graph->end()->InputCount()));
219 609996 : }
220 :
221 :
222 : // static
223 2136233 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
224 : Node* success, Node* exception) {
225 : // Requires distinguishing between value, effect and control edges.
226 16571617 : for (Edge edge : node->use_edges()) {
227 7217689 : if (IsControlEdge(edge)) {
228 2155499 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
229 : DCHECK_NOT_NULL(success);
230 25659 : edge.UpdateTo(success);
231 2129840 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
232 : DCHECK_NOT_NULL(exception);
233 7281 : edge.UpdateTo(exception);
234 : } else {
235 : DCHECK_NOT_NULL(success);
236 2122559 : edge.UpdateTo(success);
237 : }
238 5062292 : } else if (IsEffectEdge(edge)) {
239 : DCHECK_NOT_NULL(effect);
240 1898479 : edge.UpdateTo(effect);
241 : } else {
242 : DCHECK_NOT_NULL(value);
243 3163845 : edge.UpdateTo(value);
244 : }
245 : }
246 2136239 : }
247 :
248 :
249 : // static
250 38403363 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
251 : node->set_op(new_op);
252 : Verifier::VerifyNode(node);
253 38403363 : }
254 :
255 :
256 : // static
257 87194 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
258 87194 : Node* effect = NodeProperties::GetEffectInput(node);
259 436650 : while (effect->opcode() != IrOpcode::kCheckpoint) {
260 174728 : if (effect->opcode() == IrOpcode::kDead) return effect;
261 : DCHECK_EQ(1, effect->op()->EffectInputCount());
262 174728 : effect = NodeProperties::GetEffectInput(effect);
263 : }
264 87194 : Node* frame_state = GetFrameStateInput(effect);
265 87194 : return frame_state;
266 : }
267 :
268 : // static
269 340740 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
270 341075 : for (auto use : node->uses()) {
271 681498 : if (use->opcode() == IrOpcode::kProjection &&
272 340745 : 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 11087762 : 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 63485248 : for (Edge const edge : node->use_edges()) {
306 26198705 : if (!IsControlEdge(edge)) continue;
307 : Node* use = edge.from();
308 : size_t index;
309 22771963 : 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 10219041 : 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 806229 : break;
326 : case IrOpcode::kIfValue:
327 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
328 659054 : index = if_value_index++;
329 659054 : break;
330 : case IrOpcode::kIfDefault:
331 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
332 62492 : index = projection_count - 1;
333 62492 : 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 22772035 : 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 11087838 : }
348 :
349 : // static
350 4929577 : bool NodeProperties::IsSame(Node* a, Node* b) {
351 : for (;;) {
352 4982813 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
353 : a = GetValueInput(a, 0);
354 2159 : continue;
355 : }
356 4980654 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
357 : b = GetValueInput(b, 0);
358 51077 : continue;
359 : }
360 4929577 : return a == b;
361 : }
362 : }
363 :
364 : // static
365 16301 : 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 48903 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
372 31785 : mnewtarget.Ref(broker).IsJSFunction()) {
373 7721 : ObjectRef target = mtarget.Ref(broker);
374 7721 : JSFunctionRef newtarget = mnewtarget.Ref(broker).AsJSFunction();
375 7721 : if (newtarget.map().has_prototype_slot() && newtarget.has_initial_map()) {
376 7686 : if (broker->mode() == JSHeapBroker::kSerializing) newtarget.Serialize();
377 7686 : MapRef initial_map = newtarget.initial_map();
378 7686 : if (initial_map.GetConstructor().equals(target)) {
379 : DCHECK(target.AsJSFunction().map().is_constructor());
380 : DCHECK(newtarget.map().is_constructor());
381 7686 : return initial_map;
382 : }
383 : }
384 : }
385 : return base::nullopt;
386 : }
387 :
388 : // static
389 186690 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
390 : JSHeapBroker* broker, Node* receiver, Node* effect,
391 : ZoneHandleSet<Map>* maps_return) {
392 : HeapObjectMatcher m(receiver);
393 186690 : if (m.HasValue()) {
394 65212 : HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
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 195636 : if (!receiver.IsJSObject() ||
403 188082 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
404 64956 : if (receiver.map().is_stable()) {
405 : // The {receiver_map} is only reliable when we install a stability
406 : // code dependency.
407 57215 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
408 57215 : return kUnreliableReceiverMaps;
409 : }
410 : }
411 : }
412 : InferReceiverMapsResult result = kReliableReceiverMaps;
413 : while (true) {
414 4960899 : 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 62138 : if (IsSame(receiver, object)) {
426 37294 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
427 37294 : return result;
428 : }
429 : break;
430 : }
431 : case IrOpcode::kJSCreate: {
432 4023 : if (IsSame(receiver, effect)) {
433 3184 : base::Optional<MapRef> initial_map = GetJSCreateMap(broker, receiver);
434 3184 : if (initial_map.has_value()) {
435 2936 : *maps_return = ZoneHandleSet<Map>(initial_map->object());
436 2936 : 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 22475 : FieldAccess const& access = FieldAccessOf(effect->op());
457 22475 : if (access.base_is_tagged == kTaggedBase &&
458 : access.offset == HeapObject::kMapOffset) {
459 3957 : if (IsSame(receiver, object)) {
460 : Node* const value = GetValueInput(effect, 1);
461 : HeapObjectMatcher m(value);
462 2832 : if (m.HasValue()) {
463 2832 : *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 3957 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
485 : break;
486 : }
487 : case IrOpcode::kEffectPhi: {
488 26964 : Node* control = GetControlInput(effect);
489 26964 : 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 10896 : effect = GetEffectInput(effect, 0);
498 : result = kUnreliableReceiverMaps;
499 10896 : continue;
500 : }
501 : default: {
502 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
503 4837743 : if (effect->op()->EffectInputCount() != 1) {
504 : // Didn't find any appropriate CheckMaps node.
505 : return kNoReceiverMaps;
506 : }
507 4802514 : 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 4855238 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
519 :
520 : // Continue with the next {effect}.
521 : DCHECK_EQ(1, effect->op()->EffectInputCount());
522 4820528 : effect = NodeProperties::GetEffectInput(effect);
523 : }
524 : }
525 :
526 : // static
527 1778 : 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 1778 : &receiver_maps);
534 1778 : switch (result) {
535 : case NodeProperties::kUnreliableReceiverMaps:
536 : case NodeProperties::kReliableReceiverMaps:
537 : DCHECK_NE(0, receiver_maps.size());
538 5770 : for (size_t i = 0; i < receiver_maps.size(); ++i) {
539 : MapRef map(broker, receiver_maps[i]);
540 1997 : 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 58886 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
566 : Node* effect) {
567 58886 : 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 : HeapObjectRef value =
579 56039 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
580 56039 : return value.map().IsPrimitiveMap();
581 : }
582 : default: {
583 : // We don't really care about the exact maps here,
584 : // just the instance types, which don't change
585 : // across potential side-effecting operations.
586 : ZoneHandleSet<Map> maps;
587 2318 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
588 : kNoReceiverMaps) {
589 : // Check if one of the {maps} is not a JSReceiver map.
590 6086 : for (size_t i = 0; i < maps.size(); ++i) {
591 : MapRef map(broker, maps[i]);
592 2056 : if (!map.IsJSReceiverMap()) return true;
593 : }
594 : return false;
595 : }
596 : return true;
597 : }
598 : }
599 : }
600 :
601 : // static
602 532 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
603 : Node* effect) {
604 532 : if (CanBePrimitive(broker, receiver, effect)) {
605 115 : switch (receiver->opcode()) {
606 : case IrOpcode::kCheckInternalizedString:
607 : case IrOpcode::kCheckNumber:
608 : case IrOpcode::kCheckSmi:
609 : case IrOpcode::kCheckString:
610 : case IrOpcode::kCheckSymbol:
611 : case IrOpcode::kJSToLength:
612 : case IrOpcode::kJSToName:
613 : case IrOpcode::kJSToNumber:
614 : case IrOpcode::kJSToNumberConvertBigInt:
615 : case IrOpcode::kJSToNumeric:
616 : case IrOpcode::kJSToString:
617 : case IrOpcode::kToBoolean:
618 : return false;
619 : case IrOpcode::kHeapConstant: {
620 : HeapObjectRef value =
621 58 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
622 58 : OddballType type = value.map().oddball_type();
623 58 : return type == OddballType::kNull || type == OddballType::kUndefined;
624 : }
625 : default:
626 57 : return true;
627 : }
628 : }
629 : return false;
630 : }
631 :
632 : // static
633 866222 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
634 : Node* context = NodeProperties::GetContextInput(node);
635 940534 : while (*depth > 0 &&
636 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
637 : context = NodeProperties::GetContextInput(context);
638 16027 : (*depth)--;
639 : }
640 866222 : return context;
641 : }
642 :
643 : // static
644 824060061 : Type NodeProperties::GetTypeOrAny(Node* node) {
645 824060061 : return IsTyped(node) ? node->type() : Type::Any();
646 : }
647 :
648 :
649 : // static
650 4895031 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
651 : int input_count = node->op()->ValueInputCount();
652 12440153 : for (int index = 0; index < input_count; ++index) {
653 3829265 : if (!IsTyped(GetValueInput(node, index))) return false;
654 : }
655 : return true;
656 : }
657 :
658 :
659 : // static
660 : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
661 443395729 : if (num == 0) return false;
662 : int const index = edge.index();
663 302346871 : return first <= index && index < first + num;
664 : }
665 :
666 : // static
667 119579438 : size_t NodeProperties::HashCode(Node* node) {
668 119579438 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
669 423264451 : for (Node* input : node->inputs()) {
670 : h = base::hash_combine(h, input->id());
671 : }
672 119575732 : return h;
673 : }
674 :
675 : // static
676 75875162 : bool NodeProperties::Equals(Node* a, Node* b) {
677 : DCHECK_NOT_NULL(a);
678 : DCHECK_NOT_NULL(b);
679 : DCHECK_NOT_NULL(a->op());
680 : DCHECK_NOT_NULL(b->op());
681 75875162 : if (!a->op()->Equals(b->op())) return false;
682 4410154 : if (a->InputCount() != b->InputCount()) return false;
683 : Node::Inputs aInputs = a->inputs();
684 : Node::Inputs bInputs = b->inputs();
685 :
686 : auto aIt = aInputs.begin();
687 : auto bIt = bInputs.begin();
688 : auto aEnd = aInputs.end();
689 :
690 10804007 : for (; aIt != aEnd; ++aIt, ++bIt) {
691 : DCHECK_NOT_NULL(*aIt);
692 : DCHECK_NOT_NULL(*bIt);
693 7798051 : if ((*aIt)->id() != (*bIt)->id()) return false;
694 : }
695 : return true;
696 : }
697 :
698 : } // namespace compiler
699 : } // namespace internal
700 120216 : } // namespace v8
|