| 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 |