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

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

Issue 794113002: [turbofan] Fix typing of typed array loads/stores. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years 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') | no next file » | 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/bootstrapper.h" 5 #include "src/bootstrapper.h"
6 #include "src/compiler/graph-inl.h" 6 #include "src/compiler/graph-inl.h"
7 #include "src/compiler/graph-reducer.h" 7 #include "src/compiler/graph-reducer.h"
8 #include "src/compiler/js-operator.h" 8 #include "src/compiler/js-operator.h"
9 #include "src/compiler/node.h" 9 #include "src/compiler/node.h"
10 #include "src/compiler/node-properties-inl.h" 10 #include "src/compiler/node-properties-inl.h"
11 #include "src/compiler/node-properties.h" 11 #include "src/compiler/node-properties.h"
12 #include "src/compiler/simplified-operator.h" 12 #include "src/compiler/simplified-operator.h"
13 #include "src/compiler/typer.h" 13 #include "src/compiler/typer.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace compiler { 17 namespace compiler {
18 18
19 #define NATIVE_TYPES(V) \
20 V(Int8) \
21 V(Uint8) \
22 V(Int16) \
23 V(Uint16) \
24 V(Int32) \
25 V(Uint32) \
26 V(Float32) \
27 V(Float64)
28
19 enum LazyCachedType { 29 enum LazyCachedType {
20 kNumberFunc0, 30 kNumberFunc0,
21 kNumberFunc1, 31 kNumberFunc1,
22 kNumberFunc2, 32 kNumberFunc2,
23 kImulFunc, 33 kImulFunc,
24 kClz32Func, 34 kClz32Func,
25 kArrayBufferFunc, 35 kArrayBufferFunc,
26 kInt8ArrayFunc, 36 #define NATIVE_TYPE_CASE(Type) k##Type, k##Type##Array, k##Type##ArrayFunc,
27 kInt16ArrayFunc, 37 NATIVE_TYPES(NATIVE_TYPE_CASE)
28 kInt32ArrayFunc, 38 #undef NATIVE_TYPE_CASE
29 kUint8ArrayFunc,
30 kUint16ArrayFunc,
31 kUint32ArrayFunc,
32 kFloat32ArrayFunc,
33 kFloat64ArrayFunc,
34 kNumLazyCachedTypes 39 kNumLazyCachedTypes
35 }; 40 };
36 41
37 42
38 // Constructs and caches types lazily. 43 // Constructs and caches types lazily.
39 // TODO(turbofan): these types could be globally cached or cached per isolate. 44 // TODO(turbofan): these types could be globally cached or cached per isolate.
40 struct LazyTypeCache : public ZoneObject { 45 class LazyTypeCache FINAL : public ZoneObject {
41 Zone* zone; 46 public:
42 Type* cache_[kNumLazyCachedTypes]; 47 explicit LazyTypeCache(Zone* zone) : zone_(zone) {
43
44 explicit LazyTypeCache(Zone* z) : zone(z) {
45 memset(cache_, 0, sizeof(cache_)); 48 memset(cache_, 0, sizeof(cache_));
46 } 49 }
47 50
48 inline Type* Get(LazyCachedType type) { 51 inline Type* Get(LazyCachedType type) {
49 int index = static_cast<int>(type); 52 int index = static_cast<int>(type);
50 DCHECK(index < kNumLazyCachedTypes); 53 DCHECK(index < kNumLazyCachedTypes);
51 if (cache_[index] == NULL) cache_[index] = Create(type); 54 if (cache_[index] == NULL) cache_[index] = Create(type);
52 return cache_[index]; 55 return cache_[index];
53 } 56 }
54 57
58 private:
55 Type* Create(LazyCachedType type) { 59 Type* Create(LazyCachedType type) {
56 Factory* f = zone->isolate()->factory();
57 Handle<Smi> zero(Smi::FromInt(0), zone->isolate());
58
59 #define NATIVE_TYPE(sem, rep) Type::Intersect(Type::sem(), Type::rep(), zone)
60 switch (type) { 60 switch (type) {
61 case kNumberFunc0: { 61 case kInt8:
62 return Type::Function(Type::Number(), zone); 62 return CreateNative(CreateRange<int8_t>(), Type::UntaggedInt8());
63 } 63 case kUint8:
64 case kNumberFunc1: { 64 return CreateNative(CreateRange<uint8_t>(), Type::UntaggedInt8());
65 return Type::Function(Type::Number(), Type::Number(), zone); 65 case kInt16:
66 } 66 return CreateNative(CreateRange<int16_t>(), Type::UntaggedInt16());
67 case kNumberFunc2: { 67 case kUint16:
68 return CreateNative(CreateRange<uint16_t>(), Type::UntaggedInt16());
69 case kInt32:
70 return CreateNative(Type::Signed32(), Type::UntaggedInt32());
71 case kUint32:
72 return CreateNative(Type::Unsigned32(), Type::UntaggedInt32());
73 case kFloat32:
74 return CreateNative(Type::Number(), Type::UntaggedFloat32());
75 case kFloat64:
76 return CreateNative(Type::Number(), Type::UntaggedFloat64());
77 case kNumberFunc0:
78 return Type::Function(Type::Number(), zone());
79 case kNumberFunc1:
80 return Type::Function(Type::Number(), Type::Number(), zone());
81 case kNumberFunc2:
68 return Type::Function(Type::Number(), Type::Number(), Type::Number(), 82 return Type::Function(Type::Number(), Type::Number(), Type::Number(),
69 zone); 83 zone());
70 } 84 case kImulFunc:
71 case kImulFunc: {
72 return Type::Function(Type::Signed32(), Type::Integral32(), 85 return Type::Function(Type::Signed32(), Type::Integral32(),
73 Type::Integral32(), zone); 86 Type::Integral32(), zone());
74 } 87 case kClz32Func:
75 case kClz32Func: { 88 return Type::Function(CreateRange(0, 32), Type::Number(), zone());
76 return Type::Function(Type::Range(zero, f->NewNumber(32), zone), 89 case kArrayBufferFunc:
77 Type::Number(), zone); 90 return Type::Function(Type::Buffer(zone()), Type::Unsigned32(), zone());
78 } 91 #define NATIVE_TYPE_CASE(Type) \
79 case kArrayBufferFunc: { 92 case k##Type##Array: \
80 return Type::Function(Type::Buffer(zone), Type::Unsigned32(), zone); 93 return CreateArray(Get(k##Type)); \
81 } 94 case k##Type##ArrayFunc: \
82 case kInt8ArrayFunc: { 95 return CreateArrayFunction(Get(k##Type##Array));
83 return GetArrayFunc(Type::Intersect( 96 NATIVE_TYPES(NATIVE_TYPE_CASE)
84 Type::Range(f->NewNumber(kMinInt8), f->NewNumber(kMaxInt8), zone), 97 #undef NATIVE_TYPE_CASE
85 Type::UntaggedInt8(), zone)); 98 case kNumLazyCachedTypes:
86 }
87 case kInt16ArrayFunc: {
88 return GetArrayFunc(Type::Intersect(
89 Type::Range(f->NewNumber(kMinInt16), f->NewNumber(kMaxInt16), zone),
90 Type::UntaggedInt16(), zone));
91 }
92 case kInt32ArrayFunc: {
93 return GetArrayFunc(NATIVE_TYPE(Signed32, UntaggedInt32));
94 }
95 case kUint8ArrayFunc: {
96 return GetArrayFunc(
97 Type::Intersect(Type::Range(zero, f->NewNumber(kMaxUInt8), zone),
98 Type::UntaggedInt8(), zone));
99 }
100 case kUint16ArrayFunc: {
101 return GetArrayFunc(
102 Type::Intersect(Type::Range(zero, f->NewNumber(kMaxUInt16), zone),
103 Type::UntaggedInt16(), zone));
104 }
105 case kUint32ArrayFunc: {
106 return GetArrayFunc(NATIVE_TYPE(Unsigned32, UntaggedInt32));
107 }
108 case kFloat32ArrayFunc: {
109 return GetArrayFunc(NATIVE_TYPE(Number, UntaggedFloat32));
110 }
111 case kFloat64ArrayFunc: {
112 return GetArrayFunc(NATIVE_TYPE(Number, UntaggedFloat64));
113 }
114 default:
115 break; 99 break;
116 } 100 }
117 #undef NATIVE_TYPE
118
119 UNREACHABLE(); 101 UNREACHABLE();
120 return NULL; 102 return NULL;
121 } 103 }
122 104
123 Type* GetArrayFunc(Type* element) { 105 Type* CreateArray(Type* element) const {
124 Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone); 106 return Type::Array(element, zone());
125 Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone); 107 }
108
109 Type* CreateArrayFunction(Type* array) const {
110 Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone());
111 Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone());
126 Type* arg3 = arg2; 112 Type* arg3 = arg2;
127 return Type::Function(Type::Array(element, zone), arg1, arg2, arg3, zone); 113 return Type::Function(array, arg1, arg2, arg3, zone());
128 } 114 }
115
116 Type* CreateNative(Type* semantic, Type* representation) const {
117 return Type::Intersect(semantic, representation, zone());
118 }
119
120 template <typename T>
121 Type* CreateRange() const {
122 return CreateRange(std::numeric_limits<T>::min(),
123 std::numeric_limits<T>::max());
124 }
125
126 Type* CreateRange(double min, double max) const {
127 return Type::Range(factory()->NewNumber(min), factory()->NewNumber(max),
128 zone());
129 }
130
131 Factory* factory() const { return isolate()->factory(); }
132 Isolate* isolate() const { return zone()->isolate(); }
133 Zone* zone() const { return zone_; }
134
135 Type* cache_[kNumLazyCachedTypes];
136 Zone* zone_;
129 }; 137 };
130 138
139
131 class Typer::Decorator : public GraphDecorator { 140 class Typer::Decorator : public GraphDecorator {
132 public: 141 public:
133 explicit Decorator(Typer* typer) : typer_(typer) {} 142 explicit Decorator(Typer* typer) : typer_(typer) {}
134 virtual void Decorate(Node* node); 143 virtual void Decorate(Node* node);
135 144
136 private: 145 private:
137 Typer* typer_; 146 Typer* typer_;
138 }; 147 };
139 148
140 149
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 singleton_one = Type::Range(one, one, zone); 184 singleton_one = Type::Range(one, one, zone);
176 zero_or_one = Type::Union(singleton_zero, singleton_one, zone); 185 zero_or_one = Type::Union(singleton_zero, singleton_one, zone);
177 zeroish = Type::Union(singleton_zero, nan_or_minuszero, zone); 186 zeroish = Type::Union(singleton_zero, nan_or_minuszero, zone);
178 signed32ish = Type::Union(signed32, truncating_to_zero, zone); 187 signed32ish = Type::Union(signed32, truncating_to_zero, zone);
179 unsigned32ish = Type::Union(unsigned32, truncating_to_zero, zone); 188 unsigned32ish = Type::Union(unsigned32, truncating_to_zero, zone);
180 falsish = Type::Union(Type::Undetectable(), 189 falsish = Type::Union(Type::Undetectable(),
181 Type::Union(zeroish, undefined_or_null, zone), zone); 190 Type::Union(zeroish, undefined_or_null, zone), zone);
182 integer = Type::Range(minusinfinity, infinity, zone); 191 integer = Type::Range(minusinfinity, infinity, zone);
183 weakint = Type::Union(integer, nan_or_minuszero, zone); 192 weakint = Type::Union(integer, nan_or_minuszero, zone);
184 193
185 signed8_ = Type::Range(f->NewNumber(kMinInt8), f->NewNumber(kMaxInt8), zone);
186 unsigned8_ = Type::Range(zero, f->NewNumber(kMaxUInt8), zone);
187 signed16_ =
188 Type::Range(f->NewNumber(kMinInt16), f->NewNumber(kMaxInt16), zone);
189 unsigned16_ = Type::Range(zero, f->NewNumber(kMaxUInt16), zone);
190
191 number_fun0_ = Type::Function(number, zone); 194 number_fun0_ = Type::Function(number, zone);
192 number_fun1_ = Type::Function(number, number, zone); 195 number_fun1_ = Type::Function(number, number, zone);
193 number_fun2_ = Type::Function(number, number, number, zone); 196 number_fun2_ = Type::Function(number, number, number, zone);
194 197
195 weakint_fun1_ = Type::Function(weakint, number, zone); 198 weakint_fun1_ = Type::Function(weakint, number, zone);
196 random_fun_ = Type::Function(Type::Union( 199 random_fun_ = Type::Function(Type::Union(
197 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); 200 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone);
198 201
199 const int limits_count = 20; 202 const int limits_count = 20;
200 203
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 ChangeRepresentation(arg.upper, Type::TaggedPtr(), zone())); 1602 ChangeRepresentation(arg.upper, Type::TaggedPtr(), zone()));
1600 } 1603 }
1601 1604
1602 1605
1603 Bounds Typer::Visitor::TypeLoadField(Node* node) { 1606 Bounds Typer::Visitor::TypeLoadField(Node* node) {
1604 return Bounds(FieldAccessOf(node->op()).type); 1607 return Bounds(FieldAccessOf(node->op()).type);
1605 } 1608 }
1606 1609
1607 1610
1608 Bounds Typer::Visitor::TypeLoadBuffer(Node* node) { 1611 Bounds Typer::Visitor::TypeLoadBuffer(Node* node) {
1612 // TODO(bmeurer): This typing is not yet correct. Since we can still access
1613 // out of bounds, the type in the general case has to include Undefined.
1609 switch (BufferAccessOf(node->op()).external_array_type()) { 1614 switch (BufferAccessOf(node->op()).external_array_type()) {
1610 case kExternalInt8Array: 1615 #define NATIVE_TYPE_CASE(Type) \
1611 return Bounds(typer_->signed8_); 1616 case kExternal##Type##Array: \
1612 case kExternalUint8Array: 1617 return Bounds(typer_->cache_->Get(k##Type));
1613 return Bounds(typer_->unsigned8_); 1618 NATIVE_TYPES(NATIVE_TYPE_CASE)
1614 case kExternalInt16Array: 1619 #undef NATIVE_TYPE_CASE
1615 return Bounds(typer_->signed16_);
1616 case kExternalUint16Array:
1617 return Bounds(typer_->unsigned16_);
1618 case kExternalInt32Array:
1619 return Bounds(Type::Signed32());
1620 case kExternalUint32Array:
1621 return Bounds(Type::Unsigned32());
1622 case kExternalFloat32Array:
1623 case kExternalFloat64Array:
1624 return Bounds(Type::Number());
1625 case kExternalUint8ClampedArray: 1620 case kExternalUint8ClampedArray:
1626 break; 1621 break;
1627 } 1622 }
1628 UNREACHABLE(); 1623 UNREACHABLE();
1629 return Bounds(); 1624 return Bounds();
1630 } 1625 }
1631 1626
1632 1627
1633 Bounds Typer::Visitor::TypeLoadElement(Node* node) { 1628 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
1634 return Bounds(ElementAccessOf(node->op()).type); 1629 return Bounds(ElementAccessOf(node->op()).type);
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 } else if (*value == native->uint16_array_fun()) { 2076 } else if (*value == native->uint16_array_fun()) {
2082 return typer_->cache_->Get(kUint16ArrayFunc); 2077 return typer_->cache_->Get(kUint16ArrayFunc);
2083 } else if (*value == native->uint32_array_fun()) { 2078 } else if (*value == native->uint32_array_fun()) {
2084 return typer_->cache_->Get(kUint32ArrayFunc); 2079 return typer_->cache_->Get(kUint32ArrayFunc);
2085 } else if (*value == native->float32_array_fun()) { 2080 } else if (*value == native->float32_array_fun()) {
2086 return typer_->cache_->Get(kFloat32ArrayFunc); 2081 return typer_->cache_->Get(kFloat32ArrayFunc);
2087 } else if (*value == native->float64_array_fun()) { 2082 } else if (*value == native->float64_array_fun()) {
2088 return typer_->cache_->Get(kFloat64ArrayFunc); 2083 return typer_->cache_->Get(kFloat64ArrayFunc);
2089 } 2084 }
2090 } 2085 }
2086 } else if (value->IsJSTypedArray()) {
2087 switch (JSTypedArray::cast(*value)->type()) {
2088 #define NATIVE_TYPE_CASE(Type) \
2089 case kExternal##Type##Array: \
2090 return typer_->cache_->Get(k##Type##Array);
2091 NATIVE_TYPES(NATIVE_TYPE_CASE)
2092 #undef NATIVE_TYPE_CASE
2093 case kExternalUint8ClampedArray:
2094 // TODO(rossberg): Do we want some ClampedArray type to express this?
2095 break;
2096 }
2091 } 2097 }
2092 return Type::Constant(value, zone()); 2098 return Type::Constant(value, zone());
2093 } 2099 }
2094 2100
2095 } // namespace compiler 2101 } // namespace compiler
2096 } // namespace internal 2102 } // namespace internal
2097 } // namespace v8 2103 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/typer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698