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 1230290453 : int NodeProperties::PastValueIndex(Node* node) {
23 1230417760 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 501 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 1222927156 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 2420081783 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 1209962906 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 795662998 : int NodeProperties::PastEffectIndex(Node* node) {
43 1410764424 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 64951546 : int NodeProperties::PastControlIndex(Node* node) {
49 129903156 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 169785773 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 169785773 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 6894993 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 6894993 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 5199519 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 5199518 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 255755027 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 511462700 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 333805900 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 667538826 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 10039389 : bool NodeProperties::IsValueEdge(Edge edge) {
90 10039389 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 20078778 : node->op()->ValueInputCount());
93 : }
94 :
95 :
96 : // static
97 0 : bool NodeProperties::IsContextEdge(Edge edge) {
98 0 : Node* const node = edge.from();
99 : return IsInputRange(edge, FirstContextIndex(node),
100 0 : OperatorProperties::GetContextInputCount(node->op()));
101 : }
102 :
103 :
104 : // static
105 535001 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 535001 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 535001 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 226979445 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 226979445 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 453954568 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 202842310 : bool NodeProperties::IsControlEdge(Edge edge) {
122 202842310 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 405680217 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 13585938 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 13585938 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 154607643 : for (Edge const edge : node->use_edges()) {
132 64124579 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 44507054 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 826897 : if (out_exception != nullptr) *out_exception = edge.from();
135 813367 : return true;
136 : }
137 : }
138 12772575 : return false;
139 : }
140 :
141 : // static
142 1624 : Node* NodeProperties::FindSuccessfulControlProjection(Node* node) {
143 : DCHECK_GT(node->op()->ControlOutputCount(), 0);
144 1624 : if (node->op()->HasProperty(Operator::kNoThrow)) return node;
145 58686 : for (Edge const edge : node->use_edges()) {
146 27831 : if (!NodeProperties::IsControlEdge(edge)) continue;
147 16818 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
148 224 : return edge.from();
149 : }
150 : }
151 1400 : return node;
152 : }
153 :
154 : // static
155 1433415 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
156 : DCHECK(index < node->op()->ValueInputCount());
157 1433415 : node->ReplaceInput(FirstValueIndex(node) + index, value);
158 1433415 : }
159 :
160 :
161 : // static
162 600 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
163 600 : int value_input_count = node->op()->ValueInputCount();
164 : DCHECK_LE(1, value_input_count);
165 600 : node->ReplaceInput(0, value);
166 2194 : while (--value_input_count > 0) {
167 994 : node->RemoveInput(value_input_count);
168 : }
169 600 : }
170 :
171 :
172 : // static
173 263734 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
174 263734 : node->ReplaceInput(FirstContextIndex(node), context);
175 263734 : }
176 :
177 :
178 : // static
179 13543202 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
180 : DCHECK(index < node->op()->ControlInputCount());
181 13543195 : node->ReplaceInput(FirstControlIndex(node) + index, control);
182 13543190 : }
183 :
184 :
185 : // static
186 4679762 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
187 : DCHECK(index < node->op()->EffectInputCount());
188 4679766 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
189 : }
190 :
191 :
192 : // static
193 7189874 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
194 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
195 7189877 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
196 7189874 : }
197 :
198 :
199 : // static
200 104301 : void NodeProperties::RemoveNonValueInputs(Node* node) {
201 208602 : node->TrimInputCount(node->op()->ValueInputCount());
202 104301 : }
203 :
204 :
205 : // static
206 0 : void NodeProperties::RemoveValueInputs(Node* node) {
207 0 : 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 1847513 : void NodeProperties::MergeControlToEnd(Graph* graph,
215 : CommonOperatorBuilder* common,
216 : Node* node) {
217 615838 : graph->end()->AppendInput(graph->zone(), node);
218 615839 : graph->end()->set_op(common->End(graph->end()->InputCount()));
219 615836 : }
220 :
221 :
222 : // static
223 2128987 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
224 : Node* success, Node* exception) {
225 : // Requires distinguishing between value, effect and control edges.
226 18632935 : for (Edge edge : node->use_edges()) {
227 7187472 : if (IsControlEdge(edge)) {
228 6419028 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
229 : DCHECK_NOT_NULL(success);
230 28405 : edge.UpdateTo(success);
231 4222542 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
232 : DCHECK_NOT_NULL(exception);
233 8316 : edge.UpdateTo(exception);
234 : } else {
235 : DCHECK_NOT_NULL(success);
236 2102955 : edge.UpdateTo(success);
237 : }
238 5047837 : } else if (IsEffectEdge(edge)) {
239 : DCHECK_NOT_NULL(effect);
240 1889889 : edge.UpdateTo(effect);
241 : } else {
242 : DCHECK_NOT_NULL(value);
243 3157955 : edge.UpdateTo(value);
244 : }
245 : }
246 2129004 : }
247 :
248 :
249 : // static
250 37320717 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
251 : node->set_op(new_op);
252 : Verifier::VerifyNode(node);
253 37320717 : }
254 :
255 :
256 : // static
257 88489 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
258 353084 : Node* effect = NodeProperties::GetEffectInput(node);
259 353084 : while (effect->opcode() != IrOpcode::kCheckpoint) {
260 176106 : if (effect->opcode() == IrOpcode::kDead) return effect;
261 : DCHECK_EQ(1, effect->op()->EffectInputCount());
262 176106 : effect = NodeProperties::GetEffectInput(effect);
263 : }
264 88489 : Node* frame_state = GetFrameStateInput(effect);
265 88489 : return frame_state;
266 : }
267 :
268 : // static
269 181876 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
270 545959 : for (auto use : node->uses()) {
271 363752 : if (use->opcode() == IrOpcode::kProjection &&
272 181867 : 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 0 : 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 10858258 : 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 73110607 : for (Edge const edge : node->use_edges()) {
306 25697059 : if (!IsControlEdge(edge)) continue;
307 22327021 : Node* use = edge.from();
308 : size_t index;
309 22327021 : 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 9996256 : 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 798140 : break;
326 : case IrOpcode::kIfValue:
327 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
328 674477 : index = if_value_index++;
329 674477 : break;
330 : case IrOpcode::kIfDefault:
331 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
332 63848 : index = projection_count - 1;
333 63848 : 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 22327017 : 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 10858231 : }
348 :
349 : // static
350 9770998 : bool NodeProperties::IsSame(Node* a, Node* b) {
351 : for (;;) {
352 4913409 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
353 : a = GetValueInput(a, 0);
354 1737 : continue;
355 : }
356 4911672 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
357 : b = GetValueInput(b, 0);
358 52346 : continue;
359 : }
360 4859326 : return a == b;
361 : }
362 : }
363 :
364 : // static
365 190819 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
366 4890061 : JSHeapBroker* broker, Node* receiver, Node* effect,
367 : ZoneHandleSet<Map>* maps_return) {
368 : HeapObjectMatcher m(receiver);
369 190819 : if (m.HasValue()) {
370 63817 : HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
371 : // We don't use ICs for the Array.prototype and the Object.prototype
372 : // because the runtime has to be able to intercept them properly, so
373 : // we better make sure that TurboFan doesn't outsmart the system here
374 : // by storing to elements of either prototype directly.
375 : //
376 : // TODO(bmeurer): This can be removed once the Array.prototype and
377 : // Object.prototype have NO_ELEMENTS elements kind.
378 191451 : if (!receiver.IsJSObject() ||
379 184011 : !broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
380 63572 : if (receiver.map().is_stable()) {
381 : // The {receiver_map} is only reliable when we install a stability
382 : // code dependency.
383 55994 : *maps_return = ZoneHandleSet<Map>(receiver.map().object());
384 55994 : return kUnreliableReceiverMaps;
385 : }
386 : }
387 : }
388 : InferReceiverMapsResult result = kReliableReceiverMaps;
389 : while (true) {
390 4890061 : switch (effect->opcode()) {
391 : case IrOpcode::kMapGuard: {
392 : Node* const object = GetValueInput(effect, 0);
393 171 : if (IsSame(receiver, object)) {
394 129 : *maps_return = MapGuardMapsOf(effect->op()).maps();
395 129 : return result;
396 : }
397 : break;
398 : }
399 : case IrOpcode::kCheckMaps: {
400 : Node* const object = GetValueInput(effect, 0);
401 67837 : if (IsSame(receiver, object)) {
402 40249 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
403 40249 : return result;
404 : }
405 : break;
406 : }
407 : case IrOpcode::kJSCreate: {
408 3934 : if (IsSame(receiver, effect)) {
409 : HeapObjectMatcher mtarget(GetValueInput(effect, 0));
410 : HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
411 9414 : if (mtarget.HasValue() && mnewtarget.HasValue() &&
412 8952 : mnewtarget.Ref(broker).IsJSFunction()) {
413 : JSFunctionRef original_constructor =
414 2900 : mnewtarget.Ref(broker).AsJSFunction();
415 2900 : if (original_constructor.has_initial_map()) {
416 2900 : original_constructor.Serialize();
417 2900 : MapRef initial_map = original_constructor.initial_map();
418 2900 : if (initial_map.GetConstructor().equals(mtarget.Ref(broker))) {
419 2900 : *maps_return = ZoneHandleSet<Map>(initial_map.object());
420 2900 : return result;
421 : }
422 : }
423 : }
424 : // We reached the allocation of the {receiver}.
425 : return kNoReceiverMaps;
426 : }
427 : break;
428 : }
429 : case IrOpcode::kJSCreatePromise: {
430 85 : if (IsSame(receiver, effect)) {
431 : *maps_return = ZoneHandleSet<Map>(broker->native_context()
432 44 : .promise_function()
433 44 : .initial_map()
434 22 : .object());
435 22 : return result;
436 : }
437 : break;
438 : }
439 : case IrOpcode::kStoreField: {
440 : // We only care about StoreField of maps.
441 : Node* const object = GetValueInput(effect, 0);
442 22242 : FieldAccess const& access = FieldAccessOf(effect->op());
443 22242 : if (access.base_is_tagged == kTaggedBase &&
444 : access.offset == HeapObject::kMapOffset) {
445 3833 : if (IsSame(receiver, object)) {
446 : Node* const value = GetValueInput(effect, 1);
447 : HeapObjectMatcher m(value);
448 2858 : if (m.HasValue()) {
449 2858 : *maps_return = ZoneHandleSet<Map>(m.Ref(broker).AsMap().object());
450 : return result;
451 : }
452 : }
453 : // Without alias analysis we cannot tell whether this
454 : // StoreField[map] affects {receiver} or not.
455 : result = kUnreliableReceiverMaps;
456 : }
457 : break;
458 : }
459 : case IrOpcode::kJSStoreMessage:
460 : case IrOpcode::kJSStoreModule:
461 : case IrOpcode::kStoreElement:
462 : case IrOpcode::kStoreTypedElement: {
463 : // These never change the map of objects.
464 : break;
465 : }
466 : case IrOpcode::kFinishRegion: {
467 : // FinishRegion renames the output of allocations, so we need
468 : // to update the {receiver} that we are looking for, if the
469 : // {receiver} matches the current {effect}.
470 3833 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
471 : break;
472 : }
473 : case IrOpcode::kEffectPhi: {
474 28604 : Node* control = GetControlInput(effect);
475 28604 : if (control->opcode() != IrOpcode::kLoop) {
476 : DCHECK(control->opcode() == IrOpcode::kDead ||
477 : control->opcode() == IrOpcode::kMerge);
478 : return kNoReceiverMaps;
479 : }
480 :
481 : // Continue search for receiver map outside the loop. Since operations
482 : // inside the loop may change the map, the result is unreliable.
483 12445 : effect = GetEffectInput(effect, 0);
484 : result = kUnreliableReceiverMaps;
485 12445 : continue;
486 : }
487 : default: {
488 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
489 4759800 : if (effect->op()->EffectInputCount() != 1) {
490 : // Didn't find any appropriate CheckMaps node.
491 : return kNoReceiverMaps;
492 : }
493 4724372 : if (!effect->op()->HasProperty(Operator::kNoWrite)) {
494 : // Without alias/escape analysis we cannot tell whether this
495 : // {effect} affects {receiver} or not.
496 : result = kUnreliableReceiverMaps;
497 : }
498 : break;
499 : }
500 : }
501 :
502 : // Stop walking the effect chain once we hit the definition of
503 : // the {receiver} along the {effect}s.
504 4779633 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
505 :
506 : // Continue with the next {effect}.
507 : DCHECK_EQ(1, effect->op()->EffectInputCount());
508 4742791 : effect = NodeProperties::GetEffectInput(effect);
509 : }
510 : }
511 :
512 : // static
513 1272 : bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
514 : Node* receiver, Node* effect,
515 : InstanceType instance_type) {
516 : ZoneHandleSet<Map> receiver_maps;
517 : NodeProperties::InferReceiverMapsResult result =
518 : NodeProperties::InferReceiverMaps(broker, receiver, effect,
519 1272 : &receiver_maps);
520 1272 : switch (result) {
521 : case NodeProperties::kUnreliableReceiverMaps:
522 : case NodeProperties::kReliableReceiverMaps:
523 : DCHECK_NE(0, receiver_maps.size());
524 4330 : for (size_t i = 0; i < receiver_maps.size(); ++i) {
525 : MapRef map(broker, receiver_maps[i]);
526 1530 : if (map.instance_type() != instance_type) return false;
527 : }
528 : return true;
529 :
530 : case NodeProperties::kNoReceiverMaps:
531 : return false;
532 : }
533 0 : UNREACHABLE();
534 : }
535 :
536 : // static
537 1385 : bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
538 : Node* dominator) {
539 1488 : while (effect != dominator) {
540 2010 : if (effect->op()->EffectInputCount() == 1 &&
541 : effect->op()->properties() & Operator::kNoWrite) {
542 738 : effect = NodeProperties::GetEffectInput(effect);
543 : } else {
544 : return false;
545 : }
546 : }
547 : return true;
548 : }
549 :
550 : // static
551 58645 : bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
552 : Node* effect) {
553 58645 : switch (receiver->opcode()) {
554 : #define CASE(Opcode) case IrOpcode::k##Opcode:
555 : JS_CONSTRUCT_OP_LIST(CASE)
556 : JS_CREATE_OP_LIST(CASE)
557 : #undef CASE
558 : case IrOpcode::kCheckReceiver:
559 : case IrOpcode::kConvertReceiver:
560 : case IrOpcode::kJSGetSuperConstructor:
561 : case IrOpcode::kJSToObject:
562 : return false;
563 : case IrOpcode::kHeapConstant: {
564 : HeapObjectRef value =
565 55845 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
566 55845 : return value.map().IsPrimitiveMap();
567 : }
568 : default: {
569 : // We don't really care about the exact maps here,
570 : // just the instance types, which don't change
571 : // across potential side-effecting operations.
572 : ZoneHandleSet<Map> maps;
573 2281 : if (InferReceiverMaps(broker, receiver, effect, &maps) !=
574 : kNoReceiverMaps) {
575 : // Check if one of the {maps} is not a JSReceiver map.
576 6029 : for (size_t i = 0; i < maps.size(); ++i) {
577 : MapRef map(broker, maps[i]);
578 2036 : if (!map.IsJSReceiverMap()) return true;
579 : }
580 : return false;
581 : }
582 : return true;
583 : }
584 : }
585 : }
586 :
587 : // static
588 599 : bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
589 : Node* effect) {
590 503 : if (CanBePrimitive(broker, receiver, effect)) {
591 96 : switch (receiver->opcode()) {
592 : case IrOpcode::kCheckInternalizedString:
593 : case IrOpcode::kCheckNumber:
594 : case IrOpcode::kCheckSmi:
595 : case IrOpcode::kCheckString:
596 : case IrOpcode::kCheckSymbol:
597 : case IrOpcode::kJSToLength:
598 : case IrOpcode::kJSToName:
599 : case IrOpcode::kJSToNumber:
600 : case IrOpcode::kJSToNumberConvertBigInt:
601 : case IrOpcode::kJSToNumeric:
602 : case IrOpcode::kJSToString:
603 : case IrOpcode::kToBoolean:
604 : return false;
605 : case IrOpcode::kHeapConstant: {
606 : HeapObjectRef value =
607 53 : HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
608 53 : OddballType type = value.map().oddball_type();
609 53 : return type == OddballType::kNull || type == OddballType::kUndefined;
610 : }
611 : default:
612 43 : return true;
613 : }
614 : }
615 : return false;
616 : }
617 :
618 : // static
619 833348 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
620 872662 : Node* context = NodeProperties::GetContextInput(node);
621 1720937 : while (*depth > 0 &&
622 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
623 14927 : context = NodeProperties::GetContextInput(context);
624 14927 : (*depth)--;
625 : }
626 833348 : return context;
627 : }
628 :
629 : // static
630 818922676 : Type NodeProperties::GetTypeOrAny(Node* node) {
631 818922676 : return IsTyped(node) ? node->type() : Type::Any();
632 : }
633 :
634 :
635 : // static
636 4838689 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
637 4838689 : int input_count = node->op()->ValueInputCount();
638 8559875 : for (int index = 0; index < input_count; ++index) {
639 3777892 : if (!IsTyped(GetValueInput(node, index))) return false;
640 : }
641 : return true;
642 : }
643 :
644 :
645 : // static
646 : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
647 440387420 : if (num == 0) return false;
648 : int const index = edge.index();
649 300894762 : return first <= index && index < first + num;
650 : }
651 :
652 : // static
653 236390394 : size_t NodeProperties::HashCode(Node* node) {
654 118195197 : size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount());
655 837780430 : for (Node* input : node->inputs()) {
656 : h = base::hash_combine(h, input->id());
657 : }
658 118192951 : return h;
659 : }
660 :
661 : // static
662 149089018 : bool NodeProperties::Equals(Node* a, Node* b) {
663 : DCHECK_NOT_NULL(a);
664 : DCHECK_NOT_NULL(b);
665 : DCHECK_NOT_NULL(a->op());
666 : DCHECK_NOT_NULL(b->op());
667 149089018 : if (!a->op()->Equals(b->op())) return false;
668 4412468 : if (a->InputCount() != b->InputCount()) return false;
669 : Node::Inputs aInputs = a->inputs();
670 : Node::Inputs bInputs = b->inputs();
671 :
672 : auto aIt = aInputs.begin();
673 : auto bIt = bInputs.begin();
674 : auto aEnd = aInputs.end();
675 :
676 15322179 : for (; aIt != aEnd; ++aIt, ++bIt) {
677 : DCHECK_NOT_NULL(*aIt);
678 : DCHECK_NOT_NULL(*bIt);
679 23799678 : if ((*aIt)->id() != (*bIt)->id()) return false;
680 : }
681 : return true;
682 : }
683 :
684 : } // namespace compiler
685 : } // namespace internal
686 178779 : } // namespace v8
|