summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/type-narrowing-reducer.cc
blob: 79687fe2a7f0384fa54b59d03ee81b5d27c91489 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/type-narrowing-reducer.h"

#include "src/compiler/js-graph.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {
namespace compiler {

TypeNarrowingReducer::TypeNarrowingReducer(Editor* editor, JSGraph* jsgraph,
                                           JSHeapBroker* broker)
    : AdvancedReducer(editor), jsgraph_(jsgraph), op_typer_(broker, zone()) {}

TypeNarrowingReducer::~TypeNarrowingReducer() = default;

Reduction TypeNarrowingReducer::Reduce(Node* node) {
  DisallowHeapAccess no_heap_access;

  Type new_type = Type::Any();

  switch (node->opcode()) {
    case IrOpcode::kNumberLessThan: {
      // TODO(turbofan) Reuse the logic from typer.cc (by integrating relational
      // comparisons with the operation typer).
      Type left_type = NodeProperties::GetType(node->InputAt(0));
      Type right_type = NodeProperties::GetType(node->InputAt(1));
      if (left_type.Is(Type::PlainNumber()) &&
          right_type.Is(Type::PlainNumber())) {
        if (left_type.Max() < right_type.Min()) {
          new_type = op_typer_.singleton_true();
        } else if (left_type.Min() >= right_type.Max()) {
          new_type = op_typer_.singleton_false();
        }
      }
      break;
    }

    case IrOpcode::kTypeGuard: {
      new_type = op_typer_.TypeTypeGuard(
          node->op(), NodeProperties::GetType(node->InputAt(0)));
      break;
    }

#define DECLARE_CASE(Name)                                                \
  case IrOpcode::k##Name: {                                               \
    new_type = op_typer_.Name(NodeProperties::GetType(node->InputAt(0)),  \
                              NodeProperties::GetType(node->InputAt(1))); \
    break;                                                                \
  }
      SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
      DECLARE_CASE(SameValue)
#undef DECLARE_CASE

#define DECLARE_CASE(Name)                                                \
  case IrOpcode::k##Name: {                                               \
    new_type = op_typer_.Name(NodeProperties::GetType(node->InputAt(0))); \
    break;                                                                \
  }
      SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
      DECLARE_CASE(ToBoolean)
#undef DECLARE_CASE

    default:
      return NoChange();
  }

  Type original_type = NodeProperties::GetType(node);
  Type restricted = Type::Intersect(new_type, original_type, zone());
  if (!original_type.Is(restricted)) {
    NodeProperties::SetType(node, restricted);
    return Changed(node);
  }
  return NoChange();
}

Graph* TypeNarrowingReducer::graph() const { return jsgraph()->graph(); }

Zone* TypeNarrowingReducer::zone() const { return graph()->zone(); }

}  // namespace compiler
}  // namespace internal
}  // namespace v8