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 814502052 : int NodeProperties::PastValueIndex(Node* node) {
23 814518583 : return FirstValueIndex(node) + node->op()->ValueInputCount();
24 : }
25 :
26 :
27 : // static
28 21 : int NodeProperties::PastContextIndex(Node* node) {
29 : return FirstContextIndex(node) +
30 811373752 : OperatorProperties::GetContextInputCount(node->op());
31 : }
32 :
33 :
34 : // static
35 1602793296 : int NodeProperties::PastFrameStateIndex(Node* node) {
36 : return FirstFrameStateIndex(node) +
37 801314917 : OperatorProperties::GetFrameStateInputCount(node->op());
38 : }
39 :
40 :
41 : // static
42 658338336 : int NodeProperties::PastEffectIndex(Node* node) {
43 1164485218 : return FirstEffectIndex(node) + node->op()->EffectInputCount();
44 : }
45 :
46 :
47 : // static
48 50781181 : int NodeProperties::PastControlIndex(Node* node) {
49 101561280 : return FirstControlIndex(node) + node->op()->ControlInputCount();
50 : }
51 :
52 :
53 : // static
54 42673998 : Node* NodeProperties::GetValueInput(Node* node, int index) {
55 : DCHECK(0 <= index && index < node->op()->ValueInputCount());
56 42673998 : return node->InputAt(FirstValueIndex(node) + index);
57 : }
58 :
59 :
60 : // static
61 1706098 : Node* NodeProperties::GetContextInput(Node* node) {
62 : DCHECK(OperatorProperties::HasContextInput(node->op()));
63 1706098 : return node->InputAt(FirstContextIndex(node));
64 : }
65 :
66 :
67 : // static
68 3436504 : Node* NodeProperties::GetFrameStateInput(Node* node) {
69 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
70 3436503 : return node->InputAt(FirstFrameStateIndex(node));
71 : }
72 :
73 :
74 : // static
75 99385183 : Node* NodeProperties::GetEffectInput(Node* node, int index) {
76 : DCHECK(0 <= index && index < node->op()->EffectInputCount());
77 198770974 : return node->InputAt(FirstEffectIndex(node) + index);
78 : }
79 :
80 :
81 : // static
82 261615527 : Node* NodeProperties::GetControlInput(Node* node, int index) {
83 : DCHECK(0 <= index && index < node->op()->ControlInputCount());
84 523233078 : return node->InputAt(FirstControlIndex(node) + index);
85 : }
86 :
87 :
88 : // static
89 1149915 : bool NodeProperties::IsValueEdge(Edge edge) {
90 1149915 : Node* const node = edge.from();
91 : return IsInputRange(edge, FirstValueIndex(node),
92 2299830 : 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 519211 : bool NodeProperties::IsFrameStateEdge(Edge edge) {
106 519211 : Node* const node = edge.from();
107 : return IsInputRange(edge, FirstFrameStateIndex(node),
108 519211 : OperatorProperties::GetFrameStateInputCount(node->op()));
109 : }
110 :
111 :
112 : // static
113 103636647 : bool NodeProperties::IsEffectEdge(Edge edge) {
114 103636647 : Node* const node = edge.from();
115 : return IsInputRange(edge, FirstEffectIndex(node),
116 207272380 : node->op()->EffectInputCount());
117 : }
118 :
119 :
120 : // static
121 185664420 : bool NodeProperties::IsControlEdge(Edge edge) {
122 185664420 : Node* const node = edge.from();
123 : return IsInputRange(edge, FirstControlIndex(node),
124 371320577 : node->op()->ControlInputCount());
125 : }
126 :
127 :
128 : // static
129 13113639 : bool NodeProperties::IsExceptionalCall(Node* node, Node** out_exception) {
130 13113639 : if (node->op()->HasProperty(Operator::kNoThrow)) return false;
131 100931870 : for (Edge const edge : node->use_edges()) {
132 44562796 : if (!NodeProperties::IsControlEdge(edge)) continue;
133 32061802 : if (edge.from()->opcode() == IrOpcode::kIfException) {
134 1184863 : if (out_exception != nullptr) *out_exception = edge.from();
135 1181005 : return true;
136 : }
137 : }
138 11806278 : return false;
139 : }
140 :
141 :
142 : // static
143 190766 : void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
144 : DCHECK(index < node->op()->ValueInputCount());
145 190766 : node->ReplaceInput(FirstValueIndex(node) + index, value);
146 190766 : }
147 :
148 :
149 : // static
150 582 : void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
151 582 : int value_input_count = node->op()->ValueInputCount();
152 : DCHECK_LE(1, value_input_count);
153 582 : node->ReplaceInput(0, value);
154 2291 : while (--value_input_count > 0) {
155 1127 : node->RemoveInput(value_input_count);
156 : }
157 582 : }
158 :
159 :
160 : // static
161 505017 : void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
162 505017 : node->ReplaceInput(FirstContextIndex(node), context);
163 505017 : }
164 :
165 :
166 : // static
167 8095228 : void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
168 : DCHECK(index < node->op()->ControlInputCount());
169 8095226 : node->ReplaceInput(FirstControlIndex(node) + index, control);
170 8095200 : }
171 :
172 :
173 : // static
174 3932995 : void NodeProperties::ReplaceEffectInput(Node* node, Node* effect, int index) {
175 : DCHECK(index < node->op()->EffectInputCount());
176 3932996 : return node->ReplaceInput(FirstEffectIndex(node) + index, effect);
177 : }
178 :
179 :
180 : // static
181 6082755 : void NodeProperties::ReplaceFrameStateInput(Node* node, Node* frame_state) {
182 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
183 6082757 : node->ReplaceInput(FirstFrameStateIndex(node), frame_state);
184 6082755 : }
185 :
186 :
187 : // static
188 352520 : void NodeProperties::RemoveNonValueInputs(Node* node) {
189 705040 : node->TrimInputCount(node->op()->ValueInputCount());
190 352520 : }
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 613509 : void NodeProperties::MergeControlToEnd(Graph* graph,
203 : CommonOperatorBuilder* common,
204 : Node* node) {
205 204503 : graph->end()->AppendInput(graph->zone(), node);
206 204503 : graph->end()->set_op(common->End(graph->end()->InputCount()));
207 204503 : }
208 :
209 :
210 : // static
211 1643345 : void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
212 : Node* success, Node* exception) {
213 : // Requires distinguishing between value, effect and control edges.
214 10138678 : for (Edge edge : node->use_edges()) {
215 4247669 : if (IsControlEdge(edge)) {
216 4687431 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
217 : DCHECK_NOT_NULL(success);
218 25633 : edge.UpdateTo(success);
219 3073688 : } else if (edge.from()->opcode() == IrOpcode::kIfException) {
220 : DCHECK_NOT_NULL(exception);
221 10971 : edge.UpdateTo(exception);
222 : } else {
223 : DCHECK_NOT_NULL(success);
224 1525873 : edge.UpdateTo(success);
225 : }
226 2685197 : } else if (IsEffectEdge(edge)) {
227 : DCHECK_NOT_NULL(effect);
228 1481893 : edge.UpdateTo(effect);
229 : } else {
230 : DCHECK_NOT_NULL(value);
231 1203310 : edge.UpdateTo(value);
232 : }
233 : }
234 1643340 : }
235 :
236 :
237 : // static
238 22730270 : void NodeProperties::ChangeOp(Node* node, const Operator* new_op) {
239 : node->set_op(new_op);
240 : Verifier::VerifyNode(node);
241 22730270 : }
242 :
243 :
244 : // static
245 51107 : Node* NodeProperties::FindFrameStateBefore(Node* node) {
246 281403 : Node* effect = NodeProperties::GetEffectInput(node);
247 281403 : while (effect->opcode() != IrOpcode::kCheckpoint) {
248 179189 : if (effect->opcode() == IrOpcode::kDead) return effect;
249 : DCHECK_EQ(1, effect->op()->EffectInputCount());
250 179189 : effect = NodeProperties::GetEffectInput(effect);
251 : }
252 51107 : Node* frame_state = GetFrameStateInput(effect);
253 51107 : return frame_state;
254 : }
255 :
256 : // static
257 196924 : Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
258 394153 : for (auto use : node->uses()) {
259 393830 : if (use->opcode() == IrOpcode::kProjection &&
260 196903 : ProjectionIndexOf(use->op()) == projection_index) {
261 : return use;
262 : }
263 : }
264 : return nullptr;
265 : }
266 :
267 :
268 : // static
269 8054866 : 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 49095506 : for (Edge const edge : node->use_edges()) {
277 20520308 : if (!IsControlEdge(edge)) continue;
278 16239637 : Node* use = edge.from();
279 : size_t index;
280 16239637 : 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 7090418 : 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 927148 : break;
297 : case IrOpcode::kIfValue:
298 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
299 167414 : index = if_value_index++;
300 167414 : break;
301 : case IrOpcode::kIfDefault:
302 : DCHECK_EQ(IrOpcode::kSwitch, node->opcode());
303 37321 : index = projection_count - 1;
304 37321 : 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 16239583 : 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 8054890 : }
319 :
320 : // static
321 3077867 : bool NodeProperties::IsSame(Node* a, Node* b) {
322 : for (;;) {
323 1558040 : if (a->opcode() == IrOpcode::kCheckHeapObject) {
324 : a = GetValueInput(a, 0);
325 84 : continue;
326 : }
327 1557956 : if (b->opcode() == IrOpcode::kCheckHeapObject) {
328 : b = GetValueInput(b, 0);
329 38045 : continue;
330 : }
331 1519911 : return a == b;
332 : }
333 : }
334 :
335 : // static
336 192535 : NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
337 1539931 : Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return) {
338 : HeapObjectMatcher m(receiver);
339 192535 : if (m.HasValue()) {
340 : Handle<Map> receiver_map(m.Value()->map());
341 94503 : if (receiver_map->is_stable()) {
342 : // The {receiver_map} is only reliable when we install a stability
343 : // code dependency.
344 90293 : *maps_return = ZoneHandleSet<Map>(receiver_map);
345 : return kUnreliableReceiverMaps;
346 : }
347 : }
348 : InferReceiverMapsResult result = kReliableReceiverMaps;
349 : while (true) {
350 1539931 : switch (effect->opcode()) {
351 : case IrOpcode::kCheckMaps: {
352 : Node* const object = GetValueInput(effect, 0);
353 51643 : if (IsSame(receiver, object)) {
354 25663 : *maps_return = CheckMapsParametersOf(effect->op()).maps();
355 25663 : return result;
356 : }
357 : break;
358 : }
359 : case IrOpcode::kJSCreate: {
360 696 : if (IsSame(receiver, effect)) {
361 : HeapObjectMatcher mtarget(GetValueInput(effect, 0));
362 : HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
363 518 : if (mtarget.HasValue() && mnewtarget.HasValue()) {
364 : Handle<JSFunction> original_constructor =
365 : Handle<JSFunction>::cast(mnewtarget.Value());
366 518 : if (original_constructor->has_initial_map()) {
367 : Handle<Map> initial_map(original_constructor->initial_map());
368 518 : if (initial_map->constructor_or_backpointer() ==
369 : *mtarget.Value()) {
370 518 : *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 10230 : FieldAccess const& access = FieldAccessOf(effect->op());
384 10230 : if (access.base_is_tagged == kTaggedBase &&
385 : access.offset == HeapObject::kMapOffset) {
386 3429 : if (IsSame(receiver, object)) {
387 : Node* const value = GetValueInput(effect, 1);
388 : HeapObjectMatcher m(value);
389 2788 : if (m.HasValue()) {
390 2788 : *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 3429 : if (IsSame(receiver, effect)) receiver = GetValueInput(effect, 0);
412 : break;
413 : }
414 : default: {
415 : DCHECK_EQ(1, effect->op()->EffectOutputCount());
416 1465196 : if (effect->op()->EffectInputCount() != 1) {
417 : // Didn't find any appropriate CheckMaps node.
418 : return kNoReceiverMaps;
419 : }
420 1414653 : 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 1460419 : if (IsSame(receiver, effect)) return kNoReceiverMaps;
432 :
433 : // Continue with the next {effect}.
434 : DCHECK_EQ(1, effect->op()->EffectInputCount());
435 1437689 : effect = NodeProperties::GetEffectInput(effect);
436 1437689 : }
437 : }
438 :
439 : // static
440 774113 : MaybeHandle<Context> NodeProperties::GetSpecializationContext(
441 774113 : Node* node, MaybeHandle<Context> context) {
442 774113 : switch (node->opcode()) {
443 : case IrOpcode::kHeapConstant:
444 : return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
445 : case IrOpcode::kParameter: {
446 262673 : Node* const start = NodeProperties::GetValueInput(node, 0);
447 : DCHECK_EQ(IrOpcode::kStart, start->opcode());
448 262673 : 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 525346 : if (index == start->op()->ValueOutputCount() - 2) {
453 262617 : return context;
454 : }
455 : break;
456 : }
457 : default:
458 : break;
459 : }
460 : return MaybeHandle<Context>();
461 : }
462 :
463 :
464 : // static
465 774113 : Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
466 13412 : Node* context = NodeProperties::GetContextInput(node);
467 1565404 : while (*depth > 0 &&
468 : IrOpcode::IsContextChainExtendingOpcode(context->opcode())) {
469 : context = NodeProperties::GetContextInput(context);
470 3766 : (*depth)--;
471 : }
472 774113 : 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 2540115 : bool NodeProperties::AllValueInputsAreTyped(Node* node) {
483 2540115 : int input_count = node->op()->ValueInputCount();
484 3544940 : for (int index = 0; index < input_count; ++index) {
485 1071815 : 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 290961016 : if (num == 0) return false;
494 : int const index = edge.index();
495 221545436 : return first <= index && index < first + num;
496 : }
497 :
498 : } // namespace compiler
499 : } // namespace internal
500 : } // namespace v8
|