OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/node-properties.h" | 5 #include "src/compiler/node-properties.h" |
6 #include "src/compiler/common-operator.h" | 6 #include "src/compiler/common-operator.h" |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/js-operator.h" | 8 #include "src/compiler/js-operator.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 } | 326 } |
327 if (b->opcode() == IrOpcode::kCheckHeapObject) { | 327 if (b->opcode() == IrOpcode::kCheckHeapObject) { |
328 b = GetValueInput(b, 0); | 328 b = GetValueInput(b, 0); |
329 continue; | 329 continue; |
330 } | 330 } |
331 return a == b; | 331 return a == b; |
332 } | 332 } |
333 } | 333 } |
334 | 334 |
335 // static | 335 // static |
336 bool NodeProperties::InferReceiverMaps(Node* receiver, Node* effect, | 336 NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( |
337 ZoneHandleSet<Map>* maps_return) { | 337 Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return) { |
338 HeapObjectMatcher m(receiver); | 338 HeapObjectMatcher m(receiver); |
339 if (m.HasValue()) { | 339 if (m.HasValue()) { |
340 Handle<Map> receiver_map(m.Value()->map()); | 340 Handle<Map> receiver_map(m.Value()->map()); |
341 if (receiver_map->is_stable()) { | 341 if (receiver_map->is_stable()) { |
| 342 // The {receiver_map} is only reliable when we install a stability |
| 343 // code dependency. |
342 *maps_return = ZoneHandleSet<Map>(receiver_map); | 344 *maps_return = ZoneHandleSet<Map>(receiver_map); |
343 return true; | 345 return kUnreliableReceiverMaps; |
344 } | 346 } |
345 } | 347 } |
| 348 InferReceiverMapsResult result = kReliableReceiverMaps; |
346 while (true) { | 349 while (true) { |
347 switch (effect->opcode()) { | 350 switch (effect->opcode()) { |
348 case IrOpcode::kCheckMaps: { | 351 case IrOpcode::kCheckMaps: { |
349 Node* const object = GetValueInput(effect, 0); | 352 Node* const object = GetValueInput(effect, 0); |
350 if (IsSame(receiver, object)) { | 353 if (IsSame(receiver, object)) { |
351 *maps_return = CheckMapsParametersOf(effect->op()).maps(); | 354 *maps_return = CheckMapsParametersOf(effect->op()).maps(); |
352 return true; | 355 return result; |
353 } | 356 } |
354 break; | 357 break; |
355 } | 358 } |
356 case IrOpcode::kJSCreate: { | 359 case IrOpcode::kJSCreate: { |
357 if (IsSame(receiver, effect)) { | 360 if (IsSame(receiver, effect)) { |
358 HeapObjectMatcher mtarget(GetValueInput(effect, 0)); | 361 HeapObjectMatcher mtarget(GetValueInput(effect, 0)); |
359 HeapObjectMatcher mnewtarget(GetValueInput(effect, 1)); | 362 HeapObjectMatcher mnewtarget(GetValueInput(effect, 1)); |
360 if (mtarget.HasValue() && mnewtarget.HasValue()) { | 363 if (mtarget.HasValue() && mnewtarget.HasValue()) { |
361 Handle<JSFunction> original_constructor = | 364 Handle<JSFunction> original_constructor = |
362 Handle<JSFunction>::cast(mnewtarget.Value()); | 365 Handle<JSFunction>::cast(mnewtarget.Value()); |
363 if (original_constructor->has_initial_map()) { | 366 if (original_constructor->has_initial_map()) { |
364 Handle<Map> initial_map(original_constructor->initial_map()); | 367 Handle<Map> initial_map(original_constructor->initial_map()); |
365 if (initial_map->constructor_or_backpointer() == | 368 if (initial_map->constructor_or_backpointer() == |
366 *mtarget.Value()) { | 369 *mtarget.Value()) { |
367 *maps_return = ZoneHandleSet<Map>(initial_map); | 370 *maps_return = ZoneHandleSet<Map>(initial_map); |
368 return true; | 371 return result; |
369 } | 372 } |
370 } | 373 } |
371 } | 374 } |
372 // We reached the allocation of the {receiver}. | 375 // We reached the allocation of the {receiver}. |
373 return false; | 376 return kNoReceiverMaps; |
374 } | 377 } |
375 break; | 378 break; |
376 } | 379 } |
377 case IrOpcode::kStoreField: { | 380 case IrOpcode::kStoreField: { |
378 // We only care about StoreField of maps. | 381 // We only care about StoreField of maps. |
379 Node* const object = GetValueInput(effect, 0); | 382 Node* const object = GetValueInput(effect, 0); |
380 FieldAccess const& access = FieldAccessOf(effect->op()); | 383 FieldAccess const& access = FieldAccessOf(effect->op()); |
381 if (access.base_is_tagged == kTaggedBase && | 384 if (access.base_is_tagged == kTaggedBase && |
382 access.offset == HeapObject::kMapOffset) { | 385 access.offset == HeapObject::kMapOffset) { |
383 if (IsSame(receiver, object)) { | 386 if (IsSame(receiver, object)) { |
384 Node* const value = GetValueInput(effect, 1); | 387 Node* const value = GetValueInput(effect, 1); |
385 HeapObjectMatcher m(value); | 388 HeapObjectMatcher m(value); |
386 if (m.HasValue()) { | 389 if (m.HasValue()) { |
387 *maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value())); | 390 *maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value())); |
388 return true; | 391 return result; |
389 } | 392 } |
390 } | 393 } |
391 // Without alias analysis we cannot tell whether this | 394 // Without alias analysis we cannot tell whether this |
392 // StoreField[map] affects {receiver} or not. | 395 // StoreField[map] affects {receiver} or not. |
393 return false; | 396 result = kUnreliableReceiverMaps; |
394 } | 397 } |
395 break; | 398 break; |
396 } | 399 } |
397 case IrOpcode::kJSStoreMessage: | 400 case IrOpcode::kJSStoreMessage: |
398 case IrOpcode::kJSStoreModule: | 401 case IrOpcode::kJSStoreModule: |
399 case IrOpcode::kStoreElement: | 402 case IrOpcode::kStoreElement: |
400 case IrOpcode::kStoreTypedElement: { | 403 case IrOpcode::kStoreTypedElement: { |
401 // These never change the map of objects. | 404 // These never change the map of objects. |
402 break; | 405 break; |
403 } | 406 } |
404 default: { | 407 default: { |
405 DCHECK_EQ(1, effect->op()->EffectOutputCount()); | 408 DCHECK_EQ(1, effect->op()->EffectOutputCount()); |
406 if (effect->op()->EffectInputCount() != 1 || | 409 if (effect->op()->EffectInputCount() != 1) { |
407 !effect->op()->HasProperty(Operator::kNoWrite)) { | |
408 // Didn't find any appropriate CheckMaps node. | 410 // Didn't find any appropriate CheckMaps node. |
409 return false; | 411 return kNoReceiverMaps; |
| 412 } |
| 413 if (!effect->op()->HasProperty(Operator::kNoWrite)) { |
| 414 // Without alias/escape analysis we cannot tell whether this |
| 415 // {effect} affects {receiver} or not. |
| 416 result = kUnreliableReceiverMaps; |
410 } | 417 } |
411 break; | 418 break; |
412 } | 419 } |
413 } | 420 } |
414 DCHECK_EQ(1, effect->op()->EffectInputCount()); | 421 DCHECK_EQ(1, effect->op()->EffectInputCount()); |
415 effect = NodeProperties::GetEffectInput(effect); | 422 effect = NodeProperties::GetEffectInput(effect); |
416 } | 423 } |
417 } | 424 } |
418 | 425 |
419 // static | 426 // static |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // static | 478 // static |
472 bool NodeProperties::IsInputRange(Edge edge, int first, int num) { | 479 bool NodeProperties::IsInputRange(Edge edge, int first, int num) { |
473 if (num == 0) return false; | 480 if (num == 0) return false; |
474 int const index = edge.index(); | 481 int const index = edge.index(); |
475 return first <= index && index < first + num; | 482 return first <= index && index < first + num; |
476 } | 483 } |
477 | 484 |
478 } // namespace compiler | 485 } // namespace compiler |
479 } // namespace internal | 486 } // namespace internal |
480 } // namespace v8 | 487 } // namespace v8 |
OLD | NEW |