Redesign of the internal type system.
Besides addressing a fundamental flaw, this significantly simplifies several aspects of the system. The downside is a loss of precision and a loss of algebraic properties. Range types are now fully implemented. R=rossberg@chromium.org BUG= Review URL: https://codereview.chromium.org/558193003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24163 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
43538e57a4
commit
6fd04d829e
950
src/types.cc
950
src/types.cc
File diff suppressed because it is too large
Load Diff
290
src/types.h
290
src/types.h
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_TYPES_H_
|
#ifndef V8_TYPES_H_
|
||||||
#define V8_TYPES_H_
|
#define V8_TYPES_H_
|
||||||
|
|
||||||
|
#include "src/conversions.h"
|
||||||
#include "src/factory.h"
|
#include "src/factory.h"
|
||||||
#include "src/handles.h"
|
#include "src/handles.h"
|
||||||
#include "src/ostreams.h"
|
#include "src/ostreams.h"
|
||||||
@ -23,6 +24,7 @@ namespace internal {
|
|||||||
// Types consist of two dimensions: semantic (value range) and representation.
|
// Types consist of two dimensions: semantic (value range) and representation.
|
||||||
// Both are related through subtyping.
|
// Both are related through subtyping.
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// SEMANTIC DIMENSION
|
// SEMANTIC DIMENSION
|
||||||
//
|
//
|
||||||
// The following equations and inequations hold for the semantic axis:
|
// The following equations and inequations hold for the semantic axis:
|
||||||
@ -61,6 +63,7 @@ namespace internal {
|
|||||||
// However, we also define a 'temporal' variant of the subtyping relation that
|
// However, we also define a 'temporal' variant of the subtyping relation that
|
||||||
// considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)).
|
// considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)).
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// REPRESENTATIONAL DIMENSION
|
// REPRESENTATIONAL DIMENSION
|
||||||
//
|
//
|
||||||
// For the representation axis, the following holds:
|
// For the representation axis, the following holds:
|
||||||
@ -88,6 +91,16 @@ namespace internal {
|
|||||||
// SignedSmall /\ TaggedInt (a 'smi')
|
// SignedSmall /\ TaggedInt (a 'smi')
|
||||||
// Number /\ TaggedPtr (a heap number)
|
// Number /\ TaggedPtr (a heap number)
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
// RANGE TYPES
|
||||||
|
//
|
||||||
|
// A range type represents a continuous integer interval by its minimum and
|
||||||
|
// maximum value. Either value might be an infinity.
|
||||||
|
//
|
||||||
|
// Constant(v) is considered a subtype of Range(x..y) if v happens to be an
|
||||||
|
// integer between x and y.
|
||||||
|
//
|
||||||
|
//
|
||||||
// PREDICATES
|
// PREDICATES
|
||||||
//
|
//
|
||||||
// There are two main functions for testing types:
|
// There are two main functions for testing types:
|
||||||
@ -109,16 +122,18 @@ namespace internal {
|
|||||||
// Any compilation decision based on such temporary properties requires runtime
|
// Any compilation decision based on such temporary properties requires runtime
|
||||||
// guarding!
|
// guarding!
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// PROPERTIES
|
// PROPERTIES
|
||||||
//
|
//
|
||||||
// Various formal properties hold for constructors, operators, and predicates
|
// Various formal properties hold for constructors, operators, and predicates
|
||||||
// over types. For example, constructors are injective, subtyping is a complete
|
// over types. For example, constructors are injective and subtyping is a
|
||||||
// partial order, union and intersection satisfy the usual algebraic properties.
|
// complete partial order.
|
||||||
//
|
//
|
||||||
// See test/cctest/test-types.cc for a comprehensive executable specification,
|
// See test/cctest/test-types.cc for a comprehensive executable specification,
|
||||||
// especially with respect to the properties of the more exotic 'temporal'
|
// especially with respect to the properties of the more exotic 'temporal'
|
||||||
// constructors and predicates (those prefixed 'Now').
|
// constructors and predicates (those prefixed 'Now').
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// IMPLEMENTATION
|
// IMPLEMENTATION
|
||||||
//
|
//
|
||||||
// Internally, all 'primitive' types, and their unions, are represented as
|
// Internally, all 'primitive' types, and their unions, are represented as
|
||||||
@ -208,11 +223,35 @@ namespace internal {
|
|||||||
kUndefined | kInternal) \
|
kUndefined | kInternal) \
|
||||||
V(Any, 0xfffffffeu)
|
V(Any, 0xfffffffeu)
|
||||||
|
|
||||||
#define BITSET_TYPE_LIST(V) \
|
/*
|
||||||
MASK_BITSET_TYPE_LIST(V) \
|
* The following diagrams show how integers (in the mathematical sense) are
|
||||||
|
* divided among the different atomic numerical types.
|
||||||
|
*
|
||||||
|
* If SmiValuesAre31Bits():
|
||||||
|
*
|
||||||
|
* ON OS32 OSS US OU31 OU32 ON
|
||||||
|
* ______[_______[_______[_______[_______[_______[_______
|
||||||
|
* -2^31 -2^30 0 2^30 2^31 2^32
|
||||||
|
*
|
||||||
|
* Otherwise:
|
||||||
|
*
|
||||||
|
* ON OSS US OU32 ON
|
||||||
|
* ______[_______________[_______________[_______[_______
|
||||||
|
* -2^31 0 2^31 2^32
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PROPER_BITSET_TYPE_LIST(V) \
|
||||||
REPRESENTATION_BITSET_TYPE_LIST(V) \
|
REPRESENTATION_BITSET_TYPE_LIST(V) \
|
||||||
SEMANTIC_BITSET_TYPE_LIST(V)
|
SEMANTIC_BITSET_TYPE_LIST(V)
|
||||||
|
|
||||||
|
#define BITSET_TYPE_LIST(V) \
|
||||||
|
MASK_BITSET_TYPE_LIST(V) \
|
||||||
|
PROPER_BITSET_TYPE_LIST(V)
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// The abstract Type class, parameterized over the low-level representation.
|
// The abstract Type class, parameterized over the low-level representation.
|
||||||
@ -282,17 +321,17 @@ class TypeImpl : public Config::Base {
|
|||||||
static TypeHandle type(Region* region) { \
|
static TypeHandle type(Region* region) { \
|
||||||
return BitsetType::New(BitsetType::k##type, region); \
|
return BitsetType::New(BitsetType::k##type, region); \
|
||||||
}
|
}
|
||||||
BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
|
PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
|
||||||
#undef DEFINE_TYPE_CONSTRUCTOR
|
#undef DEFINE_TYPE_CONSTRUCTOR
|
||||||
|
|
||||||
static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
|
static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
|
||||||
return ClassType::New(map, region);
|
return ClassType::New(map, region);
|
||||||
}
|
}
|
||||||
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
|
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
|
||||||
// TODO(neis): Return RangeType for numerical values.
|
|
||||||
return ConstantType::New(value, region);
|
return ConstantType::New(value, region);
|
||||||
}
|
}
|
||||||
static TypeHandle Range(double min, double max, Region* region) {
|
static TypeHandle Range(
|
||||||
|
i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
|
||||||
return RangeType::New(min, max, region);
|
return RangeType::New(min, max, region);
|
||||||
}
|
}
|
||||||
static TypeHandle Context(TypeHandle outer, Region* region) {
|
static TypeHandle Context(TypeHandle outer, Region* region) {
|
||||||
@ -360,7 +399,7 @@ class TypeImpl : public Config::Base {
|
|||||||
template<class TypeHandle>
|
template<class TypeHandle>
|
||||||
bool Equals(TypeHandle that) { return this->Equals(*that); }
|
bool Equals(TypeHandle that) { return this->Equals(*that); }
|
||||||
|
|
||||||
// Equivalent to Constant(value)->Is(this), but avoiding allocation.
|
// Equivalent to Constant(val)->Is(this), but avoiding allocation.
|
||||||
bool Contains(i::Object* val);
|
bool Contains(i::Object* val);
|
||||||
bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
|
bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
|
||||||
|
|
||||||
@ -407,6 +446,13 @@ class TypeImpl : public Config::Base {
|
|||||||
ArrayType* AsArray() { return ArrayType::cast(this); }
|
ArrayType* AsArray() { return ArrayType::cast(this); }
|
||||||
FunctionType* AsFunction() { return FunctionType::cast(this); }
|
FunctionType* AsFunction() { return FunctionType::cast(this); }
|
||||||
|
|
||||||
|
// Minimum and maximum of a numeric type.
|
||||||
|
// These functions do not distinguish between -0 and +0. If the type equals
|
||||||
|
// kNaN, they return NaN; otherwise kNaN is ignored. Only call these
|
||||||
|
// functions on subtypes of Number.
|
||||||
|
double Min();
|
||||||
|
double Max();
|
||||||
|
|
||||||
int NumClasses();
|
int NumClasses();
|
||||||
int NumConstants();
|
int NumConstants();
|
||||||
|
|
||||||
@ -469,16 +515,45 @@ class TypeImpl : public Config::Base {
|
|||||||
|
|
||||||
bitset BitsetGlb() { return BitsetType::Glb(this); }
|
bitset BitsetGlb() { return BitsetType::Glb(this); }
|
||||||
bitset BitsetLub() { return BitsetType::Lub(this); }
|
bitset BitsetLub() { return BitsetType::Lub(this); }
|
||||||
bitset InherentBitsetLub() { return BitsetType::InherentLub(this); }
|
|
||||||
|
|
||||||
bool SlowIs(TypeImpl* that);
|
bool SlowIs(TypeImpl* that);
|
||||||
|
|
||||||
TypeHandle Rebound(bitset bound, Region* region);
|
static bool IsInteger(double x) {
|
||||||
bitset BoundBy(TypeImpl* that);
|
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
|
||||||
int IndexInUnion(bitset bound, UnionHandle unioned, int current_size);
|
}
|
||||||
static int ExtendUnion(
|
static bool IsInteger(i::Object* x) {
|
||||||
UnionHandle unioned, int current_size, TypeHandle t,
|
return x->IsNumber() && IsInteger(x->Number());
|
||||||
TypeHandle other, bool is_intersect, Region* region);
|
}
|
||||||
|
|
||||||
|
struct Limits {
|
||||||
|
i::Handle<i::Object> min;
|
||||||
|
i::Handle<i::Object> max;
|
||||||
|
Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) :
|
||||||
|
min(min), max(max) {}
|
||||||
|
explicit Limits(RangeType* range) :
|
||||||
|
min(range->Min()), max(range->Max()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Limits Intersect(Limits lhs, Limits rhs);
|
||||||
|
static Limits Union(Limits lhs, Limits rhs);
|
||||||
|
static bool Overlap(RangeType* lhs, RangeType* rhs);
|
||||||
|
static bool Contains(RangeType* lhs, RangeType* rhs);
|
||||||
|
static bool Contains(RangeType* range, i::Object* val);
|
||||||
|
|
||||||
|
RangeType* GetRange();
|
||||||
|
static int UpdateRange(
|
||||||
|
RangeHandle type, UnionHandle result, int size, Region* region);
|
||||||
|
|
||||||
|
bool SimplyEquals(TypeImpl* that);
|
||||||
|
template<class TypeHandle>
|
||||||
|
bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); }
|
||||||
|
|
||||||
|
static int AddToUnion(
|
||||||
|
TypeHandle type, UnionHandle result, int size, Region* region);
|
||||||
|
static int IntersectAux(
|
||||||
|
TypeHandle type, TypeHandle other,
|
||||||
|
UnionHandle result, int size, Region* region);
|
||||||
|
static TypeHandle NormalizeUnion(UnionHandle unioned, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -499,19 +574,28 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
|
|||||||
|
|
||||||
bitset Bitset() { return Config::as_bitset(this); }
|
bitset Bitset() { return Config::as_bitset(this); }
|
||||||
|
|
||||||
static TypeImpl* New(bitset bits) { return Config::from_bitset(bits); }
|
static TypeImpl* New(bitset bits) {
|
||||||
|
DCHECK(bits == kNone || IsInhabited(bits));
|
||||||
|
return Config::from_bitset(bits);
|
||||||
|
}
|
||||||
static TypeHandle New(bitset bits, Region* region) {
|
static TypeHandle New(bitset bits, Region* region) {
|
||||||
|
DCHECK(bits == kNone || IsInhabited(bits));
|
||||||
return Config::from_bitset(bits, region);
|
return Config::from_bitset(bits, region);
|
||||||
}
|
}
|
||||||
|
// TODO(neis): Eventually allow again for types with empty semantics
|
||||||
|
// part and modify intersection and possibly subtyping accordingly.
|
||||||
|
|
||||||
static bool IsInhabited(bitset bits) {
|
static bool IsInhabited(bitset bits) {
|
||||||
return (bits & kRepresentation) && (bits & kSemantic);
|
return bits & kSemantic;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Is(bitset bits1, bitset bits2) {
|
static bool Is(bitset bits1, bitset bits2) {
|
||||||
return (bits1 | bits2) == bits2;
|
return (bits1 | bits2) == bits2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double Min(bitset);
|
||||||
|
static double Max(bitset);
|
||||||
|
|
||||||
static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset
|
static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset
|
||||||
static bitset Lub(TypeImpl* type); // least upper bound that's a bitset
|
static bitset Lub(TypeImpl* type); // least upper bound that's a bitset
|
||||||
static bitset Lub(i::Object* value);
|
static bitset Lub(i::Object* value);
|
||||||
@ -519,12 +603,29 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
|
|||||||
static bitset Lub(int32_t value);
|
static bitset Lub(int32_t value);
|
||||||
static bitset Lub(uint32_t value);
|
static bitset Lub(uint32_t value);
|
||||||
static bitset Lub(i::Map* map);
|
static bitset Lub(i::Map* map);
|
||||||
static bitset Lub(double min, double max);
|
static bitset Lub(Limits lim);
|
||||||
static bitset InherentLub(TypeImpl* type);
|
|
||||||
|
|
||||||
static const char* Name(bitset);
|
static const char* Name(bitset);
|
||||||
static void Print(OStream& os, bitset); // NOLINT
|
static void Print(OStream& os, bitset); // NOLINT
|
||||||
using TypeImpl::PrintTo;
|
#ifdef DEBUG
|
||||||
|
static void Print(bitset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct BitsetMin{
|
||||||
|
bitset bits;
|
||||||
|
double min;
|
||||||
|
};
|
||||||
|
static const BitsetMin BitsetMins31[];
|
||||||
|
static const BitsetMin BitsetMins32[];
|
||||||
|
static const BitsetMin* BitsetMins() {
|
||||||
|
return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32;
|
||||||
|
}
|
||||||
|
static size_t BitsetMinsSize() {
|
||||||
|
return i::SmiValuesAre31Bits() ? 7 : 5;
|
||||||
|
/* arraysize(BitsetMins31) : arraysize(BitsetMins32); */
|
||||||
|
// Using arraysize here doesn't compile on Windows.
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -611,35 +712,25 @@ template<class Config>
|
|||||||
class TypeImpl<Config>::ClassType : public StructuralType {
|
class TypeImpl<Config>::ClassType : public StructuralType {
|
||||||
public:
|
public:
|
||||||
TypeHandle Bound(Region* region) {
|
TypeHandle Bound(Region* region) {
|
||||||
return Config::is_class(this)
|
return Config::is_class(this) ?
|
||||||
? BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region)
|
BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) :
|
||||||
: this->Get(0);
|
this->Get(0);
|
||||||
}
|
}
|
||||||
i::Handle<i::Map> Map() {
|
i::Handle<i::Map> Map() {
|
||||||
return Config::is_class(this)
|
return Config::is_class(this) ? Config::as_class(this) :
|
||||||
? Config::as_class(this)
|
this->template GetValue<i::Map>(1);
|
||||||
: this->template GetValue<i::Map>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClassHandle New(
|
|
||||||
i::Handle<i::Map> map, TypeHandle bound, Region* region) {
|
|
||||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*map)));
|
|
||||||
ClassHandle type = Config::template cast<ClassType>(
|
|
||||||
StructuralType::New(StructuralType::kClassTag, 2, region));
|
|
||||||
type->Set(0, bound);
|
|
||||||
type->SetValue(1, map);
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClassHandle New(i::Handle<i::Map> map, Region* region) {
|
static ClassHandle New(i::Handle<i::Map> map, Region* region) {
|
||||||
ClassHandle type =
|
ClassHandle type =
|
||||||
Config::template cast<ClassType>(Config::from_class(map, region));
|
Config::template cast<ClassType>(Config::from_class(map, region));
|
||||||
if (type->IsClass()) {
|
if (!type->IsClass()) {
|
||||||
return type;
|
type = Config::template cast<ClassType>(
|
||||||
} else {
|
StructuralType::New(StructuralType::kClassTag, 2, region));
|
||||||
TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region);
|
type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
|
||||||
return New(map, bound, region);
|
type->SetValue(1, map);
|
||||||
}
|
}
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClassType* cast(TypeImpl* type) {
|
static ClassType* cast(TypeImpl* type) {
|
||||||
@ -658,26 +749,21 @@ class TypeImpl<Config>::ConstantType : public StructuralType {
|
|||||||
TypeHandle Bound() { return this->Get(0); }
|
TypeHandle Bound() { return this->Get(0); }
|
||||||
i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
|
i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
|
||||||
|
|
||||||
static ConstantHandle New(
|
static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
|
||||||
i::Handle<i::Object> value, TypeHandle bound, Region* region) {
|
|
||||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*value)));
|
|
||||||
ConstantHandle type = Config::template cast<ConstantType>(
|
ConstantHandle type = Config::template cast<ConstantType>(
|
||||||
StructuralType::New(StructuralType::kConstantTag, 2, region));
|
StructuralType::New(StructuralType::kConstantTag, 2, region));
|
||||||
type->Set(0, bound);
|
type->Set(0, BitsetType::New(BitsetType::Lub(*value), region));
|
||||||
type->SetValue(1, value);
|
type->SetValue(1, value);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
|
|
||||||
TypeHandle bound = BitsetType::New(BitsetType::Lub(*value), region);
|
|
||||||
return New(value, bound, region);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConstantType* cast(TypeImpl* type) {
|
static ConstantType* cast(TypeImpl* type) {
|
||||||
DCHECK(type->IsConstant());
|
DCHECK(type->IsConstant());
|
||||||
return static_cast<ConstantType*>(type);
|
return static_cast<ConstantType*>(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// TODO(neis): Also cache value if numerical.
|
||||||
|
// TODO(neis): Allow restricting the representation.
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -686,27 +772,23 @@ class TypeImpl<Config>::ConstantType : public StructuralType {
|
|||||||
template<class Config>
|
template<class Config>
|
||||||
class TypeImpl<Config>::RangeType : public StructuralType {
|
class TypeImpl<Config>::RangeType : public StructuralType {
|
||||||
public:
|
public:
|
||||||
TypeHandle Bound() { return this->Get(0); }
|
int BitsetLub() { return this->Get(0)->AsBitset(); }
|
||||||
double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); }
|
i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); }
|
||||||
double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); }
|
i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); }
|
||||||
|
|
||||||
static RangeHandle New(
|
static RangeHandle New(
|
||||||
double min, double max, TypeHandle bound, Region* region) {
|
i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
|
||||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max)));
|
DCHECK(min->Number() <= max->Number());
|
||||||
RangeHandle type = Config::template cast<RangeType>(
|
RangeHandle type = Config::template cast<RangeType>(
|
||||||
StructuralType::New(StructuralType::kRangeTag, 3, region));
|
StructuralType::New(StructuralType::kRangeTag, 3, region));
|
||||||
type->Set(0, bound);
|
type->Set(0, BitsetType::New(BitsetType::Lub(Limits(min, max)), region));
|
||||||
Factory* factory = Config::isolate(region)->factory();
|
type->SetValue(1, min);
|
||||||
Handle<HeapNumber> minV = factory->NewHeapNumber(min);
|
type->SetValue(2, max);
|
||||||
Handle<HeapNumber> maxV = factory->NewHeapNumber(max);
|
|
||||||
type->SetValue(1, minV);
|
|
||||||
type->SetValue(2, maxV);
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RangeHandle New(double min, double max, Region* region) {
|
static RangeHandle New(Limits lim, Region* region) {
|
||||||
TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region);
|
return New(lim.min, lim.max, region);
|
||||||
return New(min, max, bound, region);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RangeType* cast(TypeImpl* type) {
|
static RangeType* cast(TypeImpl* type) {
|
||||||
@ -714,6 +796,8 @@ class TypeImpl<Config>::RangeType : public StructuralType {
|
|||||||
return static_cast<RangeType*>(type);
|
return static_cast<RangeType*>(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// TODO(neis): Also cache min and max values.
|
||||||
|
// TODO(neis): Allow restricting the representation.
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -722,23 +806,13 @@ class TypeImpl<Config>::RangeType : public StructuralType {
|
|||||||
template<class Config>
|
template<class Config>
|
||||||
class TypeImpl<Config>::ContextType : public StructuralType {
|
class TypeImpl<Config>::ContextType : public StructuralType {
|
||||||
public:
|
public:
|
||||||
TypeHandle Bound() { return this->Get(0); }
|
TypeHandle Outer() { return this->Get(0); }
|
||||||
TypeHandle Outer() { return this->Get(1); }
|
|
||||||
|
|
||||||
static ContextHandle New(TypeHandle outer, TypeHandle bound, Region* region) {
|
|
||||||
DCHECK(BitsetType::Is(
|
|
||||||
bound->AsBitset(), BitsetType::kInternal & BitsetType::kTaggedPtr));
|
|
||||||
ContextHandle type = Config::template cast<ContextType>(
|
|
||||||
StructuralType::New(StructuralType::kContextTag, 2, region));
|
|
||||||
type->Set(0, bound);
|
|
||||||
type->Set(1, outer);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ContextHandle New(TypeHandle outer, Region* region) {
|
static ContextHandle New(TypeHandle outer, Region* region) {
|
||||||
TypeHandle bound = BitsetType::New(
|
ContextHandle type = Config::template cast<ContextType>(
|
||||||
BitsetType::kInternal & BitsetType::kTaggedPtr, region);
|
StructuralType::New(StructuralType::kContextTag, 1, region));
|
||||||
return New(outer, bound, region);
|
type->Set(0, outer);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ContextType* cast(TypeImpl* type) {
|
static ContextType* cast(TypeImpl* type) {
|
||||||
@ -754,21 +828,13 @@ class TypeImpl<Config>::ContextType : public StructuralType {
|
|||||||
template<class Config>
|
template<class Config>
|
||||||
class TypeImpl<Config>::ArrayType : public StructuralType {
|
class TypeImpl<Config>::ArrayType : public StructuralType {
|
||||||
public:
|
public:
|
||||||
TypeHandle Bound() { return this->Get(0); }
|
TypeHandle Element() { return this->Get(0); }
|
||||||
TypeHandle Element() { return this->Get(1); }
|
|
||||||
|
|
||||||
static ArrayHandle New(TypeHandle element, TypeHandle bound, Region* region) {
|
|
||||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kArray));
|
|
||||||
ArrayHandle type = Config::template cast<ArrayType>(
|
|
||||||
StructuralType::New(StructuralType::kArrayTag, 2, region));
|
|
||||||
type->Set(0, bound);
|
|
||||||
type->Set(1, element);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ArrayHandle New(TypeHandle element, Region* region) {
|
static ArrayHandle New(TypeHandle element, Region* region) {
|
||||||
TypeHandle bound = BitsetType::New(BitsetType::kArray, region);
|
ArrayHandle type = Config::template cast<ArrayType>(
|
||||||
return New(element, bound, region);
|
StructuralType::New(StructuralType::kArrayTag, 1, region));
|
||||||
|
type->Set(0, element);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArrayType* cast(TypeImpl* type) {
|
static ArrayType* cast(TypeImpl* type) {
|
||||||
@ -784,30 +850,20 @@ class TypeImpl<Config>::ArrayType : public StructuralType {
|
|||||||
template<class Config>
|
template<class Config>
|
||||||
class TypeImpl<Config>::FunctionType : public StructuralType {
|
class TypeImpl<Config>::FunctionType : public StructuralType {
|
||||||
public:
|
public:
|
||||||
int Arity() { return this->Length() - 3; }
|
int Arity() { return this->Length() - 2; }
|
||||||
TypeHandle Bound() { return this->Get(0); }
|
TypeHandle Result() { return this->Get(0); }
|
||||||
TypeHandle Result() { return this->Get(1); }
|
TypeHandle Receiver() { return this->Get(1); }
|
||||||
TypeHandle Receiver() { return this->Get(2); }
|
TypeHandle Parameter(int i) { return this->Get(2 + i); }
|
||||||
TypeHandle Parameter(int i) { return this->Get(3 + i); }
|
|
||||||
|
|
||||||
void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); }
|
void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
|
||||||
|
|
||||||
static FunctionHandle New(
|
|
||||||
TypeHandle result, TypeHandle receiver, TypeHandle bound,
|
|
||||||
int arity, Region* region) {
|
|
||||||
DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kFunction));
|
|
||||||
FunctionHandle type = Config::template cast<FunctionType>(
|
|
||||||
StructuralType::New(StructuralType::kFunctionTag, 3 + arity, region));
|
|
||||||
type->Set(0, bound);
|
|
||||||
type->Set(1, result);
|
|
||||||
type->Set(2, receiver);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FunctionHandle New(
|
static FunctionHandle New(
|
||||||
TypeHandle result, TypeHandle receiver, int arity, Region* region) {
|
TypeHandle result, TypeHandle receiver, int arity, Region* region) {
|
||||||
TypeHandle bound = BitsetType::New(BitsetType::kFunction, region);
|
FunctionHandle type = Config::template cast<FunctionType>(
|
||||||
return New(result, receiver, bound, arity, region);
|
StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
|
||||||
|
type->Set(0, result);
|
||||||
|
type->Set(1, receiver);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FunctionType* cast(TypeImpl* type) {
|
static FunctionType* cast(TypeImpl* type) {
|
||||||
@ -854,11 +910,6 @@ struct ZoneTypeConfig {
|
|||||||
typedef i::Zone Region;
|
typedef i::Zone Region;
|
||||||
template<class T> struct Handle { typedef T* type; };
|
template<class T> struct Handle { typedef T* type; };
|
||||||
|
|
||||||
// TODO(neis): This will be removed again once we have struct_get_double().
|
|
||||||
static inline i::Isolate* isolate(Region* region) {
|
|
||||||
return region->isolate();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> static inline T* handle(T* type);
|
template<class T> static inline T* handle(T* type);
|
||||||
template<class T> static inline T* cast(Type* type);
|
template<class T> static inline T* cast(Type* type);
|
||||||
|
|
||||||
@ -901,11 +952,6 @@ struct HeapTypeConfig {
|
|||||||
typedef i::Isolate Region;
|
typedef i::Isolate Region;
|
||||||
template<class T> struct Handle { typedef i::Handle<T> type; };
|
template<class T> struct Handle { typedef i::Handle<T> type; };
|
||||||
|
|
||||||
// TODO(neis): This will be removed again once we have struct_get_double().
|
|
||||||
static inline i::Isolate* isolate(Region* region) {
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> static inline i::Handle<T> handle(T* type);
|
template<class T> static inline i::Handle<T> handle(T* type);
|
||||||
template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
|
template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user