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 814240994 : int NodeProperties::PastValueIndex(Node* node) {
23 814257378 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 21 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 811154284 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1602297412 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 801091076 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 658113392 : int NodeProperties::PastEffectIndex(Node* node) {
43 1164212134 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 50728216 : int NodeProperties::PastControlIndex(Node* node) {
49 101455406 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 42587821 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 42587821 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 1704019 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 1704019 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 3440945 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 3440949 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 99358501 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 198716868 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 261497051 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 522995136 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 1148241 : bool NodeProperties::IsValueEdge(Edge edge) {
90 1148241 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 2296482 : 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 519797 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 519797 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 519797 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 103577177 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 103577177 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 207153264 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 185791501 : bool NodeProperties::IsControlEdge(Edge edge) {
122 185791501 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 371576459 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 13123235 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 13123235 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 101157954 : for (Edge const edge : node->use_edges()) {
132 44669237 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 32200990 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 1183644 : if (out_exception != nullptr) *out_exception = edge.from();
135 1179796 : return true;
136 : }
137 : }
138 11819480 : return false;
139 : }
140 :
141 :
142 : // static
143 191015 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
144 : DCHECK(index < node->op()->ValueInputCount());
145 191015 : node->ReplaceInput(FirstValueIndex(node) + index, value);
146 191015 : }
147 :
148 :
149 : // static
150 583 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
151 583 : int value_input_count = node->op()->ValueInputCount();
152 : DCHECK_LE(1, value_input_count);
153 583 : node->ReplaceInput(0, value);
154 2295 : while (--value_input_count > 0) {
155 1129 : node->RemoveInput(value_input_count);
156 : }
157 583 : }
158 :
159 :
160 : // static
161 505327 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
162 505327 : node->ReplaceInput(FirstContextIndex(node), context);
163 505326 : }
164 :
165 :
166 : // static
167 8089615 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
168 : DCHECK(index < node->op()->ControlInputCount());
169 8089609 : node->ReplaceInput(FirstControlIndex(node) + index, control);
170 8089589 : }
171 :
172 :
173 : // static
174 3936178 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
175 : DCHECK(index < node->op()->EffectInputCount());
176 3936169 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
177 : }
178 :
179 :
180 : // static
181 6086861 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
182 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
183 6086863 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
184 6086864 : }
185 :
186 :
187 : // static
188 348815 : void NodeProperties::RemoveNonValueInputs(Node* node) {
189 697630 : node->TrimInputCount(node->op()->ValueInputCount());
190 348815 : }
191 :
192 :
193 : // static
194 8 : void NodeProperties::RemoveValueInputs(Node* node) {
195 8 : int value_input_count = node->op()->ValueInputCount();
196 32 : while (--value_input_count >= 0) {
197 16 : node->RemoveInput(value_input_count);
198 : }
199 8 : }
200 :
201 :
202 613284 : void NodeProperties::MergeControlToEnd(Graph* graph,
203 : CommonOperatorBuilder* common,
204 : Node* node) {
205 204428 : graph->end()->AppendInput(graph->zone(), node);
206 204428 : graph->end()->set_op(common->End(graph->end()->InputCount()));
207 204428 : }
208 :
209 :
210 : // static
211 1640758 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
212 : Node* success, Node* exception) {
213 : // Requires distinguishing between value, effect and control edges.
214 10138473 : for (Edge edge : node->use_edges()) {
215 4248853 : if (IsControlEdge(edge)) {
216 4687050 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
217 : DCHECK_NOT_NULL(success);
218 25471 : edge.UpdateTo(success);
219 3073758 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
220 : DCHECK_NOT_NULL(exception);
221 10899 : edge.UpdateTo(exception);
222 : } else {
223 : DCHECK_NOT_NULL(success);
224 1525980 : edge.UpdateTo(success);
225 : }
226 2686514 : } else if (IsEffectEdge(edge)) {
227 : DCHECK_NOT_NULL(effect);
228 1483435 : edge.UpdateTo(effect);
229 : } else {
230 : DCHECK_NOT_NULL(value);
231 1203088 : edge.UpdateTo(value);
232 : }
233 : }
234 1640767 : }
235 :
236 :
237 : // static
238 22699112 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
239 : node->set_op(new_op);
240 : Verifier::VerifyNode(node);
241 22699112 : }
242 :
243 :
244 : // static
245 50910 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
246 280607 : Node* effect = NodeProperties::GetEffectInput(node);
247 280607 : while (effect->opcode() != IrOpcode::kCheckpoint) {
248 178787 : if (effect->opcode() == IrOpcode::kDead) return effect;
249 : DCHECK_EQ(1, effect->op()->EffectInputCount());
250 178787 : effect = NodeProperties::GetEffectInput(effect);
251 : }
252 50910 : Node* frame_state = GetFrameStateInput(effect);
253 50910 : return frame_state;
254 : }
255 :
256 : // static
257 196807 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
258 393915 : for (auto use : node->uses()) {
259 393598 : if (use->opcode() == IrOpcode::kProjection &&
260 196787 : ProjectionIndexOf(use->op()) == projection_index) {
261 : return use;
262 : }
263 : }
264 : return nullptr;
265 : }
266 :
267 :
268 : // static
269 8054470 : void NodeProperties::CollectControlProjections(Node* node, Node** projections,
270 : size_t projection_count) {
271 : #ifdef DEBUG
272 : DCHECK_LE(static_cast<int>(projection_count), node->UseCount());
273 : std::memset(projections, 0, sizeof(*projections) * projection_count);
274 : #endif
275 : size_t if_value_index = 0;
276 49083962 : for (Edge const edge : node->use_edges()) {
277 20514781 : if (!IsControlEdge(edge)) continue;
278 16237072 : Node* use = edge.from();
279 : size_t index;
280 16237072 : switch (use->opcode()) {
281 : case IrOpcode::kIfTrue:
282 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
283 : index = 0;
284 : break;
285 : case IrOpcode::kIfFalse:
286 : DCHECK_EQ(IrOpcode::kBranch, node->opcode());
287 : index = 1;
288 7091812 : break;
289 : case IrOpcode::kIfSuccess:
290 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
291 : index = 0;
292 : break;
293 : case IrOpcode::kIfException:
294 : DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
295 : index = 1;
296 926118 : break;
297 : case IrOpcode::kIfValue:
298 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
299 165030 : index = if_value_index++;
300 165030 : break;
301 : case IrOpcode::kIfDefault:
302 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
303 36475 : index = projection_count - 1;
304 36475 : break;
305 : default:
306 : continue;
307 : }
308 : DCHECK_LT(if_value_index, projection_count);
309 : DCHECK_LT(index, projection_count);
310 : DCHECK_NULL(projections[index]);
311 16237001 : projections[index] = use;
312 : }
313 : #ifdef DEBUG
314 : for (size_t index = 0; index < projection_count; ++index) {
315 : DCHECK_NOT_NULL(projections[index]);
316 : }
317 : #endif
318 8054400 : }
319 :
320 : // static
321 3123644 : bool NodeProperties::IsSame(Node* a, Node* b) {
322 : for (;;) {
323 1581121 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
324 : a = GetValueInput(a, 0);
325 84 : continue;
326 : }
327 1581037 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
328 : b = GetValueInput(b, 0);
329 38430 : continue;
330 : }
331 1542607 : return a == b;
332 : }
333 : }
334 :
335 : // static
336 193496 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
337 1563016 : Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return) {
338 : HeapObjectMatcher m(receiver);
339 193496 : if (m.HasValue()) {
340 : Handle<Map> receiver_map(m.Value()->map());
341 95010 : if (receiver_map->is_stable()) {
342 : // The {receiver_map} is only reliable when we install a stability
343 : // code dependency.
344 90851 : *maps_return = ZoneHandleSet<Map>(receiver_map);
345 : return kUnreliableReceiverMaps;
346 : }
347 : }
348 : InferReceiverMapsResult result = kReliableReceiverMaps;
349 : while (true) {
350 1563016 : switch (effect->opcode()) {
351 : case IrOpcode::kCheckMaps: {
352 : Node* const object = GetValueInput(effect, 0);
353 51837 : if (IsSame(receiver, object)) {
354 26050 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
355 26050 : return result;
356 : }
357 : break;
358 : }
359 : case IrOpcode::kJSCreate: {
360 698 : if (IsSame(receiver, effect)) {
361 : HeapObjectMatcher mtarget(GetValueInput(effect, 0));
362 : HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
363 520 : if (mtarget.HasValue() && mnewtarget.HasValue()) {
364 : Handle<JSFunction> original_constructor =
365 : Handle<JSFunction>::cast(mnewtarget.Value());
366 520 : if (original_constructor->has_initial_map()) {
367 : Handle<Map> initial_map(original_constructor->initial_map());
368 520 : if (initial_map->constructor_or_backpointer() ==
369 : *mtarget.Value()) {
370 520 : *maps_return = ZoneHandleSet<Map>(initial_map);
371 : return result;
372 : }
373 : }
374 : }
375 : // We reached the allocation of the {receiver}.
376 : return kNoReceiverMaps;
377 : }
378 : break;
379 : }
380 : case IrOpcode::kStoreField: {
381 : // We only care about StoreField of maps.
382 : Node* const object = GetValueInput(effect, 0);
383 9922 : FieldAccess const& access = FieldAccessOf(effect->op());
384 9922 : if (access.base_is_tagged == kTaggedBase &&
385 : access.offset == HeapObject::kMapOffset) {
386 3351 : if (IsSame(receiver, object)) {
387 : Node* const value = GetValueInput(effect, 1);
388 : HeapObjectMatcher m(value);
389 2790 : if (m.HasValue()) {
390 2790 : *maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value()));
391 : return result;
392 : }
393 : }
394 : // Without alias analysis we cannot tell whether this
395 : // StoreField[map] affects {receiver} or not.
396 : result = kUnreliableReceiverMaps;
397 : }
398 : break;
399 : }
400 : case IrOpcode::kJSStoreMessage:
401 : case IrOpcode::kJSStoreModule:
402 : case IrOpcode::kStoreElement:
403 : case IrOpcode::kStoreTypedElement: {
404 : // These never change the map of objects.
405 : break;
406 : }
407 : case IrOpcode::kFinishRegion: {
408 : // FinishRegion renames the output of allocations, so we need
409 : // to update the {receiver} that we are looking for, if the
410 : // {receiver} matches the current {effect}.
411 3351 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
412 : break;
413 : }
414 : default: {
415 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
416 1488586 : if (effect->op()->EffectInputCount() != 1) {
417 : // Didn't find any appropriate CheckMaps node.
418 : return kNoReceiverMaps;
419 : }
420 1438000 : if (!effect->op()->HasProperty(Operator::kNoWrite)) {
421 : // Without alias/escape analysis we cannot tell whether this
422 : // {effect} affects {receiver} or not.
423 : result = kUnreliableReceiverMaps;
424 : }
425 : break;
426 : }
427 : }
428 :
429 : // Stop walking the effect chain once we hit the definition of
430 : // the {receiver} along the {effect}s.
431 1483070 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
432 :
433 : // Continue with the next {effect}.
434 : DCHECK_EQ(1, effect->op()->EffectInputCount());
435 1460371 : effect = NodeProperties::GetEffectInput(effect);
436 1460371 : }
437 : }
438 :
439 : // static
440 773126 : MaybeHandle<Context> NodeProperties::GetSpecializationContext(
441 773126 : Node* node, MaybeHandle<Context> context) {
442 773126 : switch (node->opcode()) {
443 : case IrOpcode::kHeapConstant:
444 : return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
445 : case IrOpcode::kParameter: {
446 262949 : Node* const start = NodeProperties::GetValueInput(node, 0);
447 : DCHECK_EQ(IrOpcode::kStart, start->opcode());
448 262949 : int const index = ParameterIndexOf(node->op());
449 : // The context is always the last parameter to a JavaScript function, and
450 : // {Parameter} indices start at -1, so value outputs of {Start} look like
451 : // this: closure, receiver, param0, ..., paramN, context.
452 525898 : if (index == start->op()->ValueOutputCount() - 2) {
453 262893 : return context;
454 : }
455 : break;
456 : }
457 : default:
458 : break;
459 : }
460 : return MaybeHandle<Context>();
461 : }
462 :
463 :
464 : // static
465 773125 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
466 13410 : Node* context = NodeProperties::GetContextInput(node);
467 1563417 : while (*depth > 0 &&
468 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
469 : context = NodeProperties::GetContextInput(context);
470 3757 : (*depth)--;
471 : }
472 773125 : return context;
473 : }
474 :
475 : // static
476 0 : Type* NodeProperties::GetTypeOrAny(Node* node) {
477 0 : return IsTyped(node) ? node->type() : Type::Any();
478 : }
479 :
480 :
481 : // static
482 2538552 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
483 2538552 : int input_count = node->op()->ValueInputCount();
484 3539881 : for (int index = 0; index < input_count; ++index) {
485 1068319 : if (!IsTyped(GetValueInput(node, index))) return false;
486 : }
487 : return true;
488 : }
489 :
490 :
491 : // static
492 : bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
493 291029083 : if (num == 0) return false;
494 : int const index = edge.index();
495 221579592 : return first <= index && index < first + num;
496 : }
497 :
498 : } // namespace compiler
499 : } // namespace internal
500 : } // namespace v8
|