OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/typer.h" | 5 #include "src/compiler/typer.h" |
6 | 6 |
7 #include "src/base/flags.h" | 7 #include "src/base/flags.h" |
8 #include "src/base/lazy-instance.h" | 8 #include "src/base/lazy-instance.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/common-operator.h" | 11 #include "src/compiler/common-operator.h" |
11 #include "src/compiler/graph-reducer.h" | 12 #include "src/compiler/graph-reducer.h" |
12 #include "src/compiler/js-operator.h" | 13 #include "src/compiler/js-operator.h" |
13 #include "src/compiler/node.h" | 14 #include "src/compiler/node.h" |
14 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/node-properties.h" |
15 #include "src/compiler/simplified-operator.h" | 16 #include "src/compiler/simplified-operator.h" |
16 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
17 #include "src/zone-type-cache.h" | 18 #include "src/zone-type-cache.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
(...skipping 10 matching lines...) Expand all Loading... |
30 class Typer::Decorator final : public GraphDecorator { | 31 class Typer::Decorator final : public GraphDecorator { |
31 public: | 32 public: |
32 explicit Decorator(Typer* typer) : typer_(typer) {} | 33 explicit Decorator(Typer* typer) : typer_(typer) {} |
33 void Decorate(Node* node) final; | 34 void Decorate(Node* node) final; |
34 | 35 |
35 private: | 36 private: |
36 Typer* const typer_; | 37 Typer* const typer_; |
37 }; | 38 }; |
38 | 39 |
39 | 40 |
40 Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type) | 41 Typer::Typer(Isolate* isolate, Graph* graph, Flags flags, |
| 42 CompilationDependencies* dependencies, |
| 43 Type::FunctionType* function_type) |
41 : isolate_(isolate), | 44 : isolate_(isolate), |
42 graph_(graph), | 45 graph_(graph), |
| 46 flags_(flags), |
| 47 dependencies_(dependencies), |
43 function_type_(function_type), | 48 function_type_(function_type), |
44 decorator_(nullptr), | 49 decorator_(nullptr), |
45 cache_(kCache.Get()) { | 50 cache_(kCache.Get()) { |
46 Zone* zone = this->zone(); | 51 Zone* zone = this->zone(); |
47 Factory* const factory = isolate->factory(); | 52 Factory* const factory = isolate->factory(); |
48 | 53 |
49 Type* infinity = Type::Constant(factory->infinity_value(), zone); | 54 Type* infinity = Type::Constant(factory->infinity_value(), zone); |
50 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); | 55 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); |
51 // TODO(neis): Unfortunately, the infinities created in other places might | 56 // TODO(neis): Unfortunately, the infinities created in other places might |
52 // be different ones (eg the result of NewNumber in TypeNumberConstant). | 57 // be different ones (eg the result of NewNumber in TypeNumberConstant). |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 Node* operand_node = NodeProperties::GetValueInput(node, i); | 202 Node* operand_node = NodeProperties::GetValueInput(node, i); |
198 return TypeOrNone(operand_node); | 203 return TypeOrNone(operand_node); |
199 } | 204 } |
200 | 205 |
201 Type* WrapContextTypeForInput(Node* node); | 206 Type* WrapContextTypeForInput(Node* node); |
202 Type* Weaken(Node* node, Type* current_type, Type* previous_type); | 207 Type* Weaken(Node* node, Type* current_type, Type* previous_type); |
203 | 208 |
204 Zone* zone() { return typer_->zone(); } | 209 Zone* zone() { return typer_->zone(); } |
205 Isolate* isolate() { return typer_->isolate(); } | 210 Isolate* isolate() { return typer_->isolate(); } |
206 Graph* graph() { return typer_->graph(); } | 211 Graph* graph() { return typer_->graph(); } |
| 212 Typer::Flags flags() const { return typer_->flags(); } |
| 213 CompilationDependencies* dependencies() const { |
| 214 return typer_->dependencies(); |
| 215 } |
207 | 216 |
208 void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); } | 217 void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); } |
209 bool IsWeakened(NodeId node_id) { | 218 bool IsWeakened(NodeId node_id) { |
210 return weakened_nodes_.find(node_id) != weakened_nodes_.end(); | 219 return weakened_nodes_.find(node_id) != weakened_nodes_.end(); |
211 } | 220 } |
212 | 221 |
213 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); | 222 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); |
214 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); | 223 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); |
215 | 224 |
216 Type* TypeUnaryOp(Node* node, UnaryTyperFun); | 225 Type* TypeUnaryOp(Node* node, UnaryTyperFun); |
(...skipping 28 matching lines...) Expand all Loading... |
245 | 254 |
246 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); | 255 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); |
247 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) | 256 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) |
248 #undef DECLARE_METHOD | 257 #undef DECLARE_METHOD |
249 | 258 |
250 static Type* JSUnaryNotTyper(Type*, Typer*); | 259 static Type* JSUnaryNotTyper(Type*, Typer*); |
251 static Type* JSTypeOfTyper(Type*, Typer*); | 260 static Type* JSTypeOfTyper(Type*, Typer*); |
252 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); | 261 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); |
253 static Type* JSCallFunctionTyper(Type*, Typer*); | 262 static Type* JSCallFunctionTyper(Type*, Typer*); |
254 | 263 |
| 264 static Type* ReferenceEqualTyper(Type*, Type*, Typer*); |
| 265 |
255 Reduction UpdateType(Node* node, Type* current) { | 266 Reduction UpdateType(Node* node, Type* current) { |
256 if (NodeProperties::IsTyped(node)) { | 267 if (NodeProperties::IsTyped(node)) { |
257 // Widen the type of a previously typed node. | 268 // Widen the type of a previously typed node. |
258 Type* previous = NodeProperties::GetType(node); | 269 Type* previous = NodeProperties::GetType(node); |
259 if (node->opcode() == IrOpcode::kPhi) { | 270 if (node->opcode() == IrOpcode::kPhi) { |
260 // Speed up termination in the presence of range types: | 271 // Speed up termination in the presence of range types: |
261 current = Weaken(node, current, previous); | 272 current = Weaken(node, current, previous); |
262 } | 273 } |
263 | 274 |
264 DCHECK(previous->Is(current)); | 275 DCHECK(previous->Is(current)); |
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 Type* Typer::Visitor::TypeNumberToUint32(Node* node) { | 1579 Type* Typer::Visitor::TypeNumberToUint32(Node* node) { |
1569 return TypeUnaryOp(node, NumberToUint32); | 1580 return TypeUnaryOp(node, NumberToUint32); |
1570 } | 1581 } |
1571 | 1582 |
1572 | 1583 |
1573 Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) { | 1584 Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) { |
1574 return TypeUnaryOp(node, ToNumber); | 1585 return TypeUnaryOp(node, ToNumber); |
1575 } | 1586 } |
1576 | 1587 |
1577 | 1588 |
| 1589 // static |
| 1590 Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1591 if (lhs->IsConstant() && rhs->Is(lhs)) { |
| 1592 return t->singleton_true_; |
| 1593 } |
| 1594 return Type::Boolean(); |
| 1595 } |
| 1596 |
| 1597 |
1578 Type* Typer::Visitor::TypeReferenceEqual(Node* node) { | 1598 Type* Typer::Visitor::TypeReferenceEqual(Node* node) { |
1579 return Type::Boolean(zone()); | 1599 return TypeBinaryOp(node, ReferenceEqualTyper); |
1580 } | 1600 } |
1581 | 1601 |
1582 | 1602 |
1583 Type* Typer::Visitor::TypeStringEqual(Node* node) { | 1603 Type* Typer::Visitor::TypeStringEqual(Node* node) { |
1584 return Type::Boolean(zone()); | 1604 return Type::Boolean(zone()); |
1585 } | 1605 } |
1586 | 1606 |
1587 | 1607 |
1588 Type* Typer::Visitor::TypeStringLessThan(Node* node) { | 1608 Type* Typer::Visitor::TypeStringLessThan(Node* node) { |
1589 return Type::Boolean(zone()); | 1609 return Type::Boolean(zone()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1659 Type* Typer::Visitor::TypeChangeBitToBool(Node* node) { | 1679 Type* Typer::Visitor::TypeChangeBitToBool(Node* node) { |
1660 Type* arg = Operand(node, 0); | 1680 Type* arg = Operand(node, 0); |
1661 // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean())); | 1681 // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean())); |
1662 return ChangeRepresentation(arg, Type::TaggedPointer(), zone()); | 1682 return ChangeRepresentation(arg, Type::TaggedPointer(), zone()); |
1663 } | 1683 } |
1664 | 1684 |
1665 | 1685 |
1666 Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::TaggedPointer(); } | 1686 Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::TaggedPointer(); } |
1667 | 1687 |
1668 | 1688 |
| 1689 namespace { |
| 1690 |
| 1691 MaybeHandle<Map> GetStableMapFromObjectType(Type* object_type) { |
| 1692 if (object_type->IsConstant() && |
| 1693 object_type->AsConstant()->Value()->IsHeapObject()) { |
| 1694 Handle<Map> object_map( |
| 1695 Handle<HeapObject>::cast(object_type->AsConstant()->Value())->map()); |
| 1696 if (object_map->is_stable()) return object_map; |
| 1697 } else if (object_type->IsClass()) { |
| 1698 Handle<Map> object_map = object_type->AsClass()->Map(); |
| 1699 if (object_map->is_stable()) return object_map; |
| 1700 } |
| 1701 return MaybeHandle<Map>(); |
| 1702 } |
| 1703 |
| 1704 } // namespace |
| 1705 |
| 1706 |
1669 Type* Typer::Visitor::TypeLoadField(Node* node) { | 1707 Type* Typer::Visitor::TypeLoadField(Node* node) { |
1670 return FieldAccessOf(node->op()).type; | 1708 FieldAccess const& access = FieldAccessOf(node->op()); |
| 1709 if (access.base_is_tagged == kTaggedBase && |
| 1710 access.offset == HeapObject::kMapOffset) { |
| 1711 // The type of LoadField[Map](o) is Constant(map) if map is stable and |
| 1712 // either |
| 1713 // (a) o has type Constant(object) and map == object->map, or |
| 1714 // (b) o has type Class(map), |
| 1715 // and either |
| 1716 // (1) map cannot transition further, or |
| 1717 // (2) deoptimization is enabled and we can add a code dependency on the |
| 1718 // stability of map (to guard the Constant type information). |
| 1719 Type* const object = Operand(node, 0); |
| 1720 if (object->Is(Type::None())) return Type::None(); |
| 1721 Handle<Map> object_map; |
| 1722 if (GetStableMapFromObjectType(object).ToHandle(&object_map)) { |
| 1723 if (object_map->CanTransition()) { |
| 1724 if (flags() & kDeoptimizationEnabled) { |
| 1725 dependencies()->AssumeMapStable(object_map); |
| 1726 } else { |
| 1727 return access.type; |
| 1728 } |
| 1729 } |
| 1730 Type* object_map_type = Type::Constant(object_map, zone()); |
| 1731 DCHECK(object_map_type->Is(access.type)); |
| 1732 return object_map_type; |
| 1733 } |
| 1734 } |
| 1735 return access.type; |
1671 } | 1736 } |
1672 | 1737 |
1673 | 1738 |
1674 Type* Typer::Visitor::TypeLoadBuffer(Node* node) { | 1739 Type* Typer::Visitor::TypeLoadBuffer(Node* node) { |
1675 // TODO(bmeurer): This typing is not yet correct. Since we can still access | 1740 // TODO(bmeurer): This typing is not yet correct. Since we can still access |
1676 // out of bounds, the type in the general case has to include Undefined. | 1741 // out of bounds, the type in the general case has to include Undefined. |
1677 switch (BufferAccessOf(node->op()).external_array_type()) { | 1742 switch (BufferAccessOf(node->op()).external_array_type()) { |
1678 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1743 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
1679 case kExternal##Type##Array: \ | 1744 case kExternal##Type##Array: \ |
1680 return typer_->cache_.k##Type; | 1745 return typer_->cache_.k##Type; |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 } | 2171 } |
2107 if (Type::IsInteger(*value)) { | 2172 if (Type::IsInteger(*value)) { |
2108 return Type::Range(value->Number(), value->Number(), zone()); | 2173 return Type::Range(value->Number(), value->Number(), zone()); |
2109 } | 2174 } |
2110 return Type::Constant(value, zone()); | 2175 return Type::Constant(value, zone()); |
2111 } | 2176 } |
2112 | 2177 |
2113 } // namespace compiler | 2178 } // namespace compiler |
2114 } // namespace internal | 2179 } // namespace internal |
2115 } // namespace v8 | 2180 } // namespace v8 |
OLD | NEW |