Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: src/compiler/typer.cc

Issue 1410953006: [turbofan] Properly type field access to stable heap object maps. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Final workarounds. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/typer.h ('k') | test/cctest/compiler/function-tester.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/typer.h ('k') | test/cctest/compiler/function-tester.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698