Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 710487134edeff341d94e6b06b0f783962fe229c..fc5305bb3d5d25a01aaeba4f47ba644dfd901d0f 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -16,6 +16,16 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
+#define NATIVE_TYPES(V) \ |
+ V(Int8) \ |
+ V(Uint8) \ |
+ V(Int16) \ |
+ V(Uint16) \ |
+ V(Int32) \ |
+ V(Uint32) \ |
+ V(Float32) \ |
+ V(Float64) |
+ |
enum LazyCachedType { |
kNumberFunc0, |
kNumberFunc1, |
@@ -23,25 +33,18 @@ enum LazyCachedType { |
kImulFunc, |
kClz32Func, |
kArrayBufferFunc, |
- kInt8ArrayFunc, |
- kInt16ArrayFunc, |
- kInt32ArrayFunc, |
- kUint8ArrayFunc, |
- kUint16ArrayFunc, |
- kUint32ArrayFunc, |
- kFloat32ArrayFunc, |
- kFloat64ArrayFunc, |
+#define NATIVE_TYPE_CASE(Type) k##Type, k##Type##Array, k##Type##ArrayFunc, |
+ NATIVE_TYPES(NATIVE_TYPE_CASE) |
+#undef NATIVE_TYPE_CASE |
kNumLazyCachedTypes |
}; |
// Constructs and caches types lazily. |
// TODO(turbofan): these types could be globally cached or cached per isolate. |
-struct LazyTypeCache : public ZoneObject { |
- Zone* zone; |
- Type* cache_[kNumLazyCachedTypes]; |
- |
- explicit LazyTypeCache(Zone* z) : zone(z) { |
+class LazyTypeCache FINAL : public ZoneObject { |
+ public: |
+ explicit LazyTypeCache(Zone* zone) : zone_(zone) { |
memset(cache_, 0, sizeof(cache_)); |
} |
@@ -52,82 +55,88 @@ struct LazyTypeCache : public ZoneObject { |
return cache_[index]; |
} |
+ private: |
Type* Create(LazyCachedType type) { |
- Factory* f = zone->isolate()->factory(); |
- Handle<Smi> zero(Smi::FromInt(0), zone->isolate()); |
- |
-#define NATIVE_TYPE(sem, rep) Type::Intersect(Type::sem(), Type::rep(), zone) |
switch (type) { |
- case kNumberFunc0: { |
- return Type::Function(Type::Number(), zone); |
- } |
- case kNumberFunc1: { |
- return Type::Function(Type::Number(), Type::Number(), zone); |
- } |
- case kNumberFunc2: { |
+ case kInt8: |
+ return CreateNative(CreateRange<int8_t>(), Type::UntaggedInt8()); |
+ case kUint8: |
+ return CreateNative(CreateRange<uint8_t>(), Type::UntaggedInt8()); |
+ case kInt16: |
+ return CreateNative(CreateRange<int16_t>(), Type::UntaggedInt16()); |
+ case kUint16: |
+ return CreateNative(CreateRange<uint16_t>(), Type::UntaggedInt16()); |
+ case kInt32: |
+ return CreateNative(Type::Signed32(), Type::UntaggedInt32()); |
+ case kUint32: |
+ return CreateNative(Type::Unsigned32(), Type::UntaggedInt32()); |
+ case kFloat32: |
+ return CreateNative(Type::Number(), Type::UntaggedFloat32()); |
+ case kFloat64: |
+ return CreateNative(Type::Number(), Type::UntaggedFloat64()); |
+ case kNumberFunc0: |
+ return Type::Function(Type::Number(), zone()); |
+ case kNumberFunc1: |
+ return Type::Function(Type::Number(), Type::Number(), zone()); |
+ case kNumberFunc2: |
return Type::Function(Type::Number(), Type::Number(), Type::Number(), |
- zone); |
- } |
- case kImulFunc: { |
+ zone()); |
+ case kImulFunc: |
return Type::Function(Type::Signed32(), Type::Integral32(), |
- Type::Integral32(), zone); |
- } |
- case kClz32Func: { |
- return Type::Function(Type::Range(zero, f->NewNumber(32), zone), |
- Type::Number(), zone); |
- } |
- case kArrayBufferFunc: { |
- return Type::Function(Type::Buffer(zone), Type::Unsigned32(), zone); |
- } |
- case kInt8ArrayFunc: { |
- return GetArrayFunc(Type::Intersect( |
- Type::Range(f->NewNumber(kMinInt8), f->NewNumber(kMaxInt8), zone), |
- Type::UntaggedInt8(), zone)); |
- } |
- case kInt16ArrayFunc: { |
- return GetArrayFunc(Type::Intersect( |
- Type::Range(f->NewNumber(kMinInt16), f->NewNumber(kMaxInt16), zone), |
- Type::UntaggedInt16(), zone)); |
- } |
- case kInt32ArrayFunc: { |
- return GetArrayFunc(NATIVE_TYPE(Signed32, UntaggedInt32)); |
- } |
- case kUint8ArrayFunc: { |
- return GetArrayFunc( |
- Type::Intersect(Type::Range(zero, f->NewNumber(kMaxUInt8), zone), |
- Type::UntaggedInt8(), zone)); |
- } |
- case kUint16ArrayFunc: { |
- return GetArrayFunc( |
- Type::Intersect(Type::Range(zero, f->NewNumber(kMaxUInt16), zone), |
- Type::UntaggedInt16(), zone)); |
- } |
- case kUint32ArrayFunc: { |
- return GetArrayFunc(NATIVE_TYPE(Unsigned32, UntaggedInt32)); |
- } |
- case kFloat32ArrayFunc: { |
- return GetArrayFunc(NATIVE_TYPE(Number, UntaggedFloat32)); |
- } |
- case kFloat64ArrayFunc: { |
- return GetArrayFunc(NATIVE_TYPE(Number, UntaggedFloat64)); |
- } |
- default: |
+ Type::Integral32(), zone()); |
+ case kClz32Func: |
+ return Type::Function(CreateRange(0, 32), Type::Number(), zone()); |
+ case kArrayBufferFunc: |
+ return Type::Function(Type::Buffer(zone()), Type::Unsigned32(), zone()); |
+#define NATIVE_TYPE_CASE(Type) \ |
+ case k##Type##Array: \ |
+ return CreateArray(Get(k##Type)); \ |
+ case k##Type##ArrayFunc: \ |
+ return CreateArrayFunction(Get(k##Type##Array)); |
+ NATIVE_TYPES(NATIVE_TYPE_CASE) |
+#undef NATIVE_TYPE_CASE |
+ case kNumLazyCachedTypes: |
break; |
} |
-#undef NATIVE_TYPE |
- |
UNREACHABLE(); |
return NULL; |
} |
- Type* GetArrayFunc(Type* element) { |
- Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone); |
- Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone); |
+ Type* CreateArray(Type* element) const { |
+ return Type::Array(element, zone()); |
+ } |
+ |
+ Type* CreateArrayFunction(Type* array) const { |
+ Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone()); |
+ Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone()); |
Type* arg3 = arg2; |
- return Type::Function(Type::Array(element, zone), arg1, arg2, arg3, zone); |
+ return Type::Function(array, arg1, arg2, arg3, zone()); |
+ } |
+ |
+ Type* CreateNative(Type* semantic, Type* representation) const { |
+ return Type::Intersect(semantic, representation, zone()); |
+ } |
+ |
+ template <typename T> |
+ Type* CreateRange() const { |
+ return CreateRange(std::numeric_limits<T>::min(), |
+ std::numeric_limits<T>::max()); |
} |
+ |
+ Type* CreateRange(double min, double max) const { |
+ return Type::Range(factory()->NewNumber(min), factory()->NewNumber(max), |
+ zone()); |
+ } |
+ |
+ Factory* factory() const { return isolate()->factory(); } |
+ Isolate* isolate() const { return zone()->isolate(); } |
+ Zone* zone() const { return zone_; } |
+ |
+ Type* cache_[kNumLazyCachedTypes]; |
+ Zone* zone_; |
}; |
+ |
class Typer::Decorator : public GraphDecorator { |
public: |
explicit Decorator(Typer* typer) : typer_(typer) {} |
@@ -182,12 +191,6 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context) |
integer = Type::Range(minusinfinity, infinity, zone); |
weakint = Type::Union(integer, nan_or_minuszero, zone); |
- signed8_ = Type::Range(f->NewNumber(kMinInt8), f->NewNumber(kMaxInt8), zone); |
- unsigned8_ = Type::Range(zero, f->NewNumber(kMaxUInt8), zone); |
- signed16_ = |
- Type::Range(f->NewNumber(kMinInt16), f->NewNumber(kMaxInt16), zone); |
- unsigned16_ = Type::Range(zero, f->NewNumber(kMaxUInt16), zone); |
- |
number_fun0_ = Type::Function(number, zone); |
number_fun1_ = Type::Function(number, number, zone); |
number_fun2_ = Type::Function(number, number, number, zone); |
@@ -1606,22 +1609,14 @@ Bounds Typer::Visitor::TypeLoadField(Node* node) { |
Bounds Typer::Visitor::TypeLoadBuffer(Node* node) { |
+ // TODO(bmeurer): This typing is not yet correct. Since we can still access |
+ // out of bounds, the type in the general case has to include Undefined. |
switch (BufferAccessOf(node->op()).external_array_type()) { |
- case kExternalInt8Array: |
- return Bounds(typer_->signed8_); |
- case kExternalUint8Array: |
- return Bounds(typer_->unsigned8_); |
- case kExternalInt16Array: |
- return Bounds(typer_->signed16_); |
- case kExternalUint16Array: |
- return Bounds(typer_->unsigned16_); |
- case kExternalInt32Array: |
- return Bounds(Type::Signed32()); |
- case kExternalUint32Array: |
- return Bounds(Type::Unsigned32()); |
- case kExternalFloat32Array: |
- case kExternalFloat64Array: |
- return Bounds(Type::Number()); |
+#define NATIVE_TYPE_CASE(Type) \ |
+ case kExternal##Type##Array: \ |
+ return Bounds(typer_->cache_->Get(k##Type)); |
+ NATIVE_TYPES(NATIVE_TYPE_CASE) |
+#undef NATIVE_TYPE_CASE |
case kExternalUint8ClampedArray: |
break; |
} |
@@ -2088,6 +2083,17 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) { |
return typer_->cache_->Get(kFloat64ArrayFunc); |
} |
} |
+ } else if (value->IsJSTypedArray()) { |
+ switch (JSTypedArray::cast(*value)->type()) { |
+#define NATIVE_TYPE_CASE(Type) \ |
+ case kExternal##Type##Array: \ |
+ return typer_->cache_->Get(k##Type##Array); |
+ NATIVE_TYPES(NATIVE_TYPE_CASE) |
+#undef NATIVE_TYPE_CASE |
+ case kExternalUint8ClampedArray: |
+ // TODO(rossberg): Do we want some ClampedArray type to express this? |
+ break; |
+ } |
} |
return Type::Constant(value, zone()); |
} |