Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 35664edb9b2d854c61ac15ac93353ccfa8ac17dc..67b73ebad00f1896104c65864d415ac24694906b 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -15,6 +15,118 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
+enum LazyCachedType { |
+ kNumberFunc0, |
+ kNumberFunc1, |
+ kNumberFunc2, |
+ kImulFunc, |
+ kClz32Func, |
+ kArrayBufferFunc, |
+ kInt8ArrayFunc, |
+ kInt16ArrayFunc, |
+ kInt32ArrayFunc, |
+ kUint8ArrayFunc, |
+ kUint16ArrayFunc, |
+ kUint32ArrayFunc, |
+ kFloat32ArrayFunc, |
+ kFloat64ArrayFunc, |
+ 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) { |
+ memset(cache_, 0, sizeof(cache_)); |
+ } |
+ |
+ inline Type* Get(LazyCachedType type) { |
+ int index = static_cast<int>(type); |
+ DCHECK(index < kNumLazyCachedTypes); |
+ if (cache_[index] == NULL) cache_[index] = Create(type); |
+ return cache_[index]; |
+ } |
+ |
+ 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: { |
+ return Type::Function(Type::Number(), Type::Number(), Type::Number(), |
+ 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: |
+ 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* arg3 = arg2; |
+ return Type::Function(Type::Array(element, zone), arg1, arg2, arg3, zone); |
+ } |
+}; |
+ |
class Typer::Decorator : public GraphDecorator { |
public: |
explicit Decorator(Typer* typer) : typer_(typer) {} |
@@ -29,6 +141,7 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context) |
: graph_(graph), |
context_(context), |
decorator_(NULL), |
+ cache_(new (graph->zone()) LazyTypeCache(graph->zone())), |
weaken_min_limits_(graph->zone()), |
weaken_max_limits_(graph->zone()) { |
Zone* zone = this->zone(); |
@@ -42,9 +155,6 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context) |
Type* number = Type::Number(); |
Type* signed32 = Type::Signed32(); |
Type* unsigned32 = Type::Unsigned32(); |
- Type* integral32 = Type::Integral32(); |
- Type* object = Type::Object(); |
- Type* undefined = Type::Undefined(); |
Type* nan_or_minuszero = Type::Union(Type::NaN(), Type::MinusZero(), zone); |
Type* truncating_to_zero = |
Type::Union(Type::Union(Type::Constant(infinity, zone), |
@@ -78,46 +188,11 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context) |
number_fun0_ = Type::Function(number, zone); |
number_fun1_ = Type::Function(number, number, zone); |
number_fun2_ = Type::Function(number, number, number, zone); |
+ |
weakint_fun1_ = Type::Function(weakint, number, zone); |
- imul_fun_ = Type::Function(signed32, integral32, integral32, zone); |
- clz32_fun_ = Type::Function( |
- Type::Range(zero, f->NewNumber(32), zone), number, zone); |
random_fun_ = Type::Function(Type::Union( |
Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); |
-#define NATIVE_TYPE(sem, rep) Type::Intersect(sem, rep, zone) |
- Type* int8 = NATIVE_TYPE(signed8_, Type::UntaggedInt8()); |
- Type* uint8 = NATIVE_TYPE(unsigned8_, Type::UntaggedInt8()); |
- Type* int16 = NATIVE_TYPE(signed16_, Type::UntaggedInt16()); |
- Type* uint16 = NATIVE_TYPE(unsigned16_, Type::UntaggedInt16()); |
- Type* int32 = NATIVE_TYPE(Type::Signed32(), Type::UntaggedInt32()); |
- Type* uint32 = NATIVE_TYPE(Type::Unsigned32(), Type::UntaggedInt32()); |
- Type* float32 = NATIVE_TYPE(Type::Number(), Type::UntaggedFloat32()); |
- Type* float64 = NATIVE_TYPE(Type::Number(), Type::UntaggedFloat64()); |
-#undef NATIVE_TYPE |
- |
- Type* buffer = Type::Buffer(zone); |
- Type* int8_array = Type::Array(int8, zone); |
- Type* int16_array = Type::Array(int16, zone); |
- Type* int32_array = Type::Array(int32, zone); |
- Type* uint8_array = Type::Array(uint8, zone); |
- Type* uint16_array = Type::Array(uint16, zone); |
- Type* uint32_array = Type::Array(uint32, zone); |
- Type* float32_array = Type::Array(float32, zone); |
- Type* float64_array = Type::Array(float64, zone); |
- Type* arg1 = Type::Union(unsigned32, object, zone); |
- Type* arg2 = Type::Union(unsigned32, undefined, zone); |
- Type* arg3 = arg2; |
- array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); |
- int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); |
- int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); |
- int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); |
- uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); |
- uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); |
- uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); |
- float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); |
- float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); |
- |
const int limits_count = 20; |
weaken_min_limits_.reserve(limits_count + 1); |
@@ -1950,41 +2025,29 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) { |
return typer_->weakint_fun1_; |
case kMathCeil: |
return typer_->weakint_fun1_; |
- case kMathAbs: |
- // TODO(rossberg): can't express overloading |
- return typer_->number_fun1_; |
+ // Unary math functions. |
+ case kMathAbs: // TODO(rossberg): can't express overloading |
case kMathLog: |
- return typer_->number_fun1_; |
case kMathExp: |
- return typer_->number_fun1_; |
case kMathSqrt: |
- return typer_->number_fun1_; |
- case kMathPow: |
- return typer_->number_fun2_; |
- case kMathMax: |
- return typer_->number_fun2_; |
- case kMathMin: |
- return typer_->number_fun2_; |
case kMathCos: |
- return typer_->number_fun1_; |
case kMathSin: |
- return typer_->number_fun1_; |
case kMathTan: |
- return typer_->number_fun1_; |
case kMathAcos: |
- return typer_->number_fun1_; |
case kMathAsin: |
- return typer_->number_fun1_; |
case kMathAtan: |
- return typer_->number_fun1_; |
+ case kMathFround: |
+ return typer_->cache_->Get(kNumberFunc1); |
+ // Binary math functions. |
case kMathAtan2: |
- return typer_->number_fun2_; |
+ case kMathPow: |
+ case kMathMax: |
+ case kMathMin: |
+ return typer_->cache_->Get(kNumberFunc2); |
case kMathImul: |
- return typer_->imul_fun_; |
+ return typer_->cache_->Get(kImulFunc); |
case kMathClz32: |
- return typer_->clz32_fun_; |
- case kMathFround: |
- return typer_->number_fun1_; |
+ return typer_->cache_->Get(kClz32Func); |
default: |
break; |
} |
@@ -1992,23 +2055,23 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) { |
Handle<Context> native = |
handle(context().ToHandleChecked()->native_context(), isolate()); |
if (*value == native->array_buffer_fun()) { |
- return typer_->array_buffer_fun_; |
+ return typer_->cache_->Get(kArrayBufferFunc); |
} else if (*value == native->int8_array_fun()) { |
- return typer_->int8_array_fun_; |
+ return typer_->cache_->Get(kInt8ArrayFunc); |
} else if (*value == native->int16_array_fun()) { |
- return typer_->int16_array_fun_; |
+ return typer_->cache_->Get(kInt16ArrayFunc); |
} else if (*value == native->int32_array_fun()) { |
- return typer_->int32_array_fun_; |
+ return typer_->cache_->Get(kInt32ArrayFunc); |
} else if (*value == native->uint8_array_fun()) { |
- return typer_->uint8_array_fun_; |
+ return typer_->cache_->Get(kUint8ArrayFunc); |
} else if (*value == native->uint16_array_fun()) { |
- return typer_->uint16_array_fun_; |
+ return typer_->cache_->Get(kUint16ArrayFunc); |
} else if (*value == native->uint32_array_fun()) { |
- return typer_->uint32_array_fun_; |
+ return typer_->cache_->Get(kUint32ArrayFunc); |
} else if (*value == native->float32_array_fun()) { |
- return typer_->float32_array_fun_; |
+ return typer_->cache_->Get(kFloat32ArrayFunc); |
} else if (*value == native->float64_array_fun()) { |
- return typer_->float64_array_fun_; |
+ return typer_->cache_->Get(kFloat64ArrayFunc); |
} |
} |
} |