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/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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |