Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/types.h b/src/types.h
index 4b7d8ba..9ce650d 100644
--- a/src/types.h
+++ b/src/types.h
@@ -6,8 +6,8 @@
#define V8_TYPES_H_
#include "src/conversions.h"
-#include "src/factory.h"
#include "src/handles.h"
+#include "src/objects.h"
#include "src/ostreams.h"
namespace v8 {
@@ -95,10 +95,13 @@
// RANGE TYPES
//
// A range type represents a continuous integer interval by its minimum and
-// maximum value. Either value might be an infinity.
+// maximum value. Either value may be an infinity, in which case that infinity
+// itself is also included in the range. A range never contains NaN or -0.
//
-// Constant(v) is considered a subtype of Range(x..y) if v happens to be an
-// integer between x and y.
+// If a value v happens to be an integer n, then Constant(v) is considered a
+// subtype of Range(n, n) (and therefore also a subtype of any larger range).
+// In order to avoid large unions, however, it is usually a good idea to use
+// Range rather than Constant.
//
//
// PREDICATES
@@ -153,39 +156,32 @@
// -----------------------------------------------------------------------------
// Values for bitset types
+// clang-format off
+
#define MASK_BITSET_TYPE_LIST(V) \
- V(Representation, 0xfff00000u) \
- V(Semantic, 0x000ffffeu)
+ V(Representation, 0xff800000u) \
+ V(Semantic, 0x007ffffeu)
#define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
#define SEMANTIC(k) ((k) & BitsetType::kSemantic)
#define REPRESENTATION_BITSET_TYPE_LIST(V) \
V(None, 0) \
- V(UntaggedBit, 1u << 20 | kSemantic) \
- V(UntaggedSigned8, 1u << 21 | kSemantic) \
- V(UntaggedSigned16, 1u << 22 | kSemantic) \
- V(UntaggedSigned32, 1u << 23 | kSemantic) \
- V(UntaggedUnsigned8, 1u << 24 | kSemantic) \
- V(UntaggedUnsigned16, 1u << 25 | kSemantic) \
- V(UntaggedUnsigned32, 1u << 26 | kSemantic) \
+ V(UntaggedBit, 1u << 23 | kSemantic) \
+ V(UntaggedIntegral8, 1u << 24 | kSemantic) \
+ V(UntaggedIntegral16, 1u << 25 | kSemantic) \
+ V(UntaggedIntegral32, 1u << 26 | kSemantic) \
V(UntaggedFloat32, 1u << 27 | kSemantic) \
V(UntaggedFloat64, 1u << 28 | kSemantic) \
V(UntaggedPointer, 1u << 29 | kSemantic) \
V(TaggedSigned, 1u << 30 | kSemantic) \
V(TaggedPointer, 1u << 31 | kSemantic) \
\
- V(UntaggedSigned, kUntaggedSigned8 | kUntaggedSigned16 | \
- kUntaggedSigned32) \
- V(UntaggedUnsigned, kUntaggedUnsigned8 | kUntaggedUnsigned16 | \
- kUntaggedUnsigned32) \
- V(UntaggedIntegral8, kUntaggedSigned8 | kUntaggedUnsigned8) \
- V(UntaggedIntegral16, kUntaggedSigned16 | kUntaggedUnsigned16) \
- V(UntaggedIntegral32, kUntaggedSigned32 | kUntaggedUnsigned32) \
- V(UntaggedIntegral, kUntaggedBit | kUntaggedSigned | kUntaggedUnsigned) \
- V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
- V(UntaggedNumber, kUntaggedIntegral | kUntaggedFloat) \
- V(Untagged, kUntaggedNumber | kUntaggedPointer) \
+ V(UntaggedIntegral, kUntaggedBit | kUntaggedIntegral8 | \
+ kUntaggedIntegral16 | kUntaggedIntegral32) \
+ V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
+ V(UntaggedNumber, kUntaggedIntegral | kUntaggedFloat) \
+ V(Untagged, kUntaggedNumber | kUntaggedPointer) \
V(Tagged, kTaggedSigned | kTaggedPointer)
#define INTERNAL_BITSET_TYPE_LIST(V) \
@@ -195,71 +191,70 @@
V(OtherNumber, 1u << 4 | REPRESENTATION(kTagged | kUntaggedNumber))
#define SEMANTIC_BITSET_TYPE_LIST(V) \
- V(NegativeSignedSmall, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
+ V(Negative31, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Null, 1u << 6 | REPRESENTATION(kTaggedPointer)) \
V(Undefined, 1u << 7 | REPRESENTATION(kTaggedPointer)) \
V(Boolean, 1u << 8 | REPRESENTATION(kTaggedPointer)) \
- V(UnsignedSmall, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
+ V(Unsigned30, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(MinusZero, 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(NaN, 1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \
V(Symbol, 1u << 12 | REPRESENTATION(kTaggedPointer)) \
V(InternalizedString, 1u << 13 | REPRESENTATION(kTaggedPointer)) \
V(OtherString, 1u << 14 | REPRESENTATION(kTaggedPointer)) \
- V(Undetectable, 1u << 15 | REPRESENTATION(kTaggedPointer)) \
- V(Array, 1u << 16 | REPRESENTATION(kTaggedPointer)) \
+ V(Simd, 1u << 15 | REPRESENTATION(kTaggedPointer)) \
+ V(Undetectable, 1u << 16 | REPRESENTATION(kTaggedPointer)) \
V(OtherObject, 1u << 17 | REPRESENTATION(kTaggedPointer)) \
V(Proxy, 1u << 18 | REPRESENTATION(kTaggedPointer)) \
- V(Internal, 1u << 19 | REPRESENTATION(kTagged | kUntagged)) \
+ V(Function, 1u << 19 | REPRESENTATION(kTaggedPointer)) \
+ V(Internal, 1u << 20 | REPRESENTATION(kTagged | kUntagged)) \
\
- V(SignedSmall, kUnsignedSmall | kNegativeSignedSmall) \
- V(Signed32, kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \
- V(NegativeSigned32, kNegativeSignedSmall | kOtherSigned32) \
- V(NonNegativeSigned32, kUnsignedSmall | kOtherUnsigned31) \
- V(Unsigned32, kUnsignedSmall | kOtherUnsigned31 | kOtherUnsigned32) \
- V(Integral32, kSigned32 | kUnsigned32) \
- V(PlainNumber, kIntegral32 | kOtherNumber) \
- V(OrderedNumber, kPlainNumber | kMinusZero) \
- V(Number, kOrderedNumber | kNaN) \
- V(String, kInternalizedString | kOtherString) \
- V(UniqueName, kSymbol | kInternalizedString) \
- V(Name, kSymbol | kString) \
- V(NumberOrString, kNumber | kString) \
- V(PlainPrimitive, kNumberOrString | kBoolean | kNull | kUndefined) \
- V(Primitive, kSymbol | kPlainPrimitive) \
- V(DetectableObject, kArray | kOtherObject) \
- V(DetectableReceiver, kDetectableObject | kProxy) \
- V(Detectable, kDetectableReceiver | kNumber | kName) \
- V(Object, kDetectableObject | kUndetectable) \
- V(Receiver, kObject | kProxy) \
- V(StringOrReceiver, kString | kReceiver) \
- V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
- kReceiver) \
- V(NonNumber, kUnique | kString | kInternal) \
- V(Any, 0xfffffffeu)
+ V(Signed31, kUnsigned30 | kNegative31) \
+ V(Signed32, kSigned31 | kOtherUnsigned31 | kOtherSigned32) \
+ V(Negative32, kNegative31 | kOtherSigned32) \
+ V(Unsigned31, kUnsigned30 | kOtherUnsigned31) \
+ V(Unsigned32, kUnsigned30 | kOtherUnsigned31 | \
+ kOtherUnsigned32) \
+ V(Integral32, kSigned32 | kUnsigned32) \
+ V(PlainNumber, kIntegral32 | kOtherNumber) \
+ V(OrderedNumber, kPlainNumber | kMinusZero) \
+ V(MinusZeroOrNaN, kMinusZero | kNaN) \
+ V(Number, kOrderedNumber | kNaN) \
+ V(String, kInternalizedString | kOtherString) \
+ V(UniqueName, kSymbol | kInternalizedString) \
+ V(Name, kSymbol | kString) \
+ V(BooleanOrNumber, kBoolean | kNumber) \
+ V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
+ V(NullOrUndefined, kNull | kUndefined) \
+ V(NumberOrString, kNumber | kString) \
+ V(NumberOrUndefined, kNumber | kUndefined) \
+ V(PlainPrimitive, kNumberOrString | kBoolean | kNullOrUndefined) \
+ V(Primitive, kSymbol | kSimd | kPlainPrimitive) \
+ V(DetectableReceiver, kFunction | kOtherObject | kProxy) \
+ V(Detectable, kDetectableReceiver | kNumber | kName) \
+ V(Object, kFunction | kOtherObject | kUndetectable) \
+ V(Receiver, kObject | kProxy) \
+ V(StringOrReceiver, kString | kReceiver) \
+ V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
+ kReceiver) \
+ V(NonNumber, kUnique | kString | kInternal) \
+ V(Any, 0xfffffffeu)
+// clang-format on
/*
* 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
+ * ON OS32 N31 U30 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.
*
- * NOTE: OtherSigned32 (OS32) and OU31 (OtherUnsigned31) are empty if Smis are
- * 32-bit wide. They should thus never be used directly, only indirectly
- * via e.g. Number.
+ * Some of the atomic numerical bitsets are internal only (see
+ * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in
+ * union with certain other bitsets. For instance, OtherNumber should only
+ * occur as part of PlainNumber.
*/
#define PROPER_BITSET_TYPE_LIST(V) \
@@ -280,21 +275,30 @@
// typedef TypeImpl<Config> Type;
// typedef Base;
// typedef Struct;
+// typedef Range;
// typedef Region;
// template<class> struct Handle { typedef type; } // No template typedefs...
+//
// template<class T> static Handle<T>::type null_handle();
// template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t)
// template<class T> static Handle<T>::type cast(Handle<Type>::type);
+//
// static bool is_bitset(Type*);
// static bool is_class(Type*);
// static bool is_struct(Type*, int tag);
+// static bool is_range(Type*);
+//
// static bitset as_bitset(Type*);
// static i::Handle<i::Map> as_class(Type*);
// static Handle<Struct>::type as_struct(Type*);
+// static Handle<Range>::type as_range(Type*);
+//
// static Type* from_bitset(bitset);
// static Handle<Type>::type from_bitset(bitset, Region*);
// static Handle<Type>::type from_class(i::Handle<Map>, Region*);
// static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
+// static Handle<Type>::type from_range(Handle<Range>::type);
+//
// static Handle<Struct>::type struct_create(int tag, int length, Region*);
// static void struct_shrink(Handle<Struct>::type, int length);
// static int struct_tag(Handle<Struct>::type);
@@ -305,6 +309,12 @@
// static i::Handle<V> struct_get_value(Handle<Struct>::type, int);
// template<class V>
// static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>);
+//
+// static Handle<Range>::type range_create(Region*);
+// static int range_get_bitset(Handle<Range>::type);
+// static void range_set_bitset(Handle<Range>::type, int);
+// static double range_get_double(Handle<Range>::type, int);
+// static void range_set_double(Handle<Range>::type, int, double, Region*);
// }
template<class Config>
class TypeImpl : public Config::Base {
@@ -345,15 +355,31 @@
PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
+ static TypeImpl* SignedSmall() {
+ return BitsetType::New(BitsetType::SignedSmall());
+ }
+ static TypeHandle SignedSmall(Region* region) {
+ return BitsetType::New(BitsetType::SignedSmall(), region);
+ }
+ static TypeImpl* UnsignedSmall() {
+ return BitsetType::New(BitsetType::UnsignedSmall());
+ }
+ static TypeHandle UnsignedSmall(Region* region) {
+ return BitsetType::New(BitsetType::UnsignedSmall(), region);
+ }
+
static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
return ClassType::New(map, region);
}
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
return ConstantType::New(value, region);
}
- static TypeHandle Range(
- i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
- return RangeType::New(min, max, region);
+ static TypeHandle Range(double min, double max, Region* region) {
+ return RangeType::New(
+ min, max, BitsetType::New(REPRESENTATION(BitsetType::kTagged |
+ BitsetType::kUntaggedNumber),
+ region),
+ region);
}
static TypeHandle Context(TypeHandle outer, Region* region) {
return ContextType::New(outer, region);
@@ -390,28 +416,40 @@
function->InitParameter(2, param2);
return function;
}
+ static TypeHandle Function(TypeHandle result, int arity, TypeHandle* params,
+ Region* region) {
+ FunctionHandle function = Function(result, Any(region), arity, region);
+ for (int i = 0; i < arity; ++i) {
+ function->InitParameter(i, params[i]);
+ }
+ return function;
+ }
+
+#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
+ static TypeHandle Name(Isolate* isolate, Region* region);
+ SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
+#undef CONSTRUCT_SIMD_TYPE
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
- static TypeImpl* Union(TypeImpl* type1, TypeImpl* type2) {
- return BitsetType::New(type1->AsBitset() | type2->AsBitset());
- }
- static TypeImpl* Intersect(TypeImpl* type1, TypeImpl* type2) {
- return BitsetType::New(type1->AsBitset() & type2->AsBitset());
- }
static TypeHandle Of(double value, Region* region) {
- return Config::from_bitset(BitsetType::Lub(value), region);
+ return Config::from_bitset(BitsetType::ExpandInternals(
+ BitsetType::Lub(value)), region);
}
static TypeHandle Of(i::Object* value, Region* region) {
- return Config::from_bitset(BitsetType::Lub(value), region);
+ return Config::from_bitset(BitsetType::ExpandInternals(
+ BitsetType::Lub(value)), region);
}
static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
return Of(*value, region);
}
- // Predicates.
+ // Extraction of components.
+ static TypeHandle Representation(TypeHandle t, Region* region);
+ static TypeHandle Semantic(TypeHandle t, Region* region);
+ // Predicates.
bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
@@ -446,6 +484,7 @@
// Inspection.
+ bool IsRange() { return Config::is_range(this); }
bool IsClass() {
return Config::is_class(this)
|| Config::is_struct(this, StructuralType::kClassTag);
@@ -453,9 +492,6 @@
bool IsConstant() {
return Config::is_struct(this, StructuralType::kConstantTag);
}
- bool IsRange() {
- return Config::is_struct(this, StructuralType::kRangeTag);
- }
bool IsContext() {
return Config::is_struct(this, StructuralType::kContextTag);
}
@@ -480,11 +516,17 @@
double Min();
double Max();
- // Extracts a range from the type. If the type is a range, it just
- // returns it; if it is a union, it returns the range component.
- // Note that it does not contain range for constants.
+ // Extracts a range from the type: if the type is a range or a union
+ // containing a range, that range is returned; otherwise, NULL is returned.
RangeType* GetRange();
+ static bool IsInteger(double x) {
+ return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
+ }
+ static bool IsInteger(i::Object* x) {
+ return x->IsNumber() && IsInteger(x->Number());
+ }
+
int NumClasses();
int NumConstants();
@@ -516,6 +558,8 @@
void Print();
#endif
+ bool IsUnionForTesting() { return IsUnion(); }
+
protected:
// Friends.
@@ -543,48 +587,52 @@
}
UnionType* AsUnion() { return UnionType::cast(this); }
+ bitset Representation();
+
// Auxiliary functions.
+ bool SemanticMaybe(TypeImpl* that);
bitset BitsetGlb() { return BitsetType::Glb(this); }
bitset BitsetLub() { return BitsetType::Lub(this); }
bool SlowIs(TypeImpl* that);
-
- static bool IsInteger(double x) {
- return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
- }
- static bool IsInteger(i::Object* x) {
- return x->IsNumber() && IsInteger(x->Number());
- }
+ bool SemanticIs(TypeImpl* that);
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()) {}
+ double min;
+ double max;
+ Limits(double min, double max) : min(min), max(max) {}
+ explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
+ bool IsEmpty();
+ static Limits Empty() { return Limits(1, 0); }
+ static Limits Intersect(Limits lhs, Limits rhs);
+ static Limits Union(Limits lhs, Limits rhs);
};
- 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, ConstantType* constant);
static bool Contains(RangeType* range, i::Object* val);
static int UpdateRange(
RangeHandle type, UnionHandle result, int size, Region* region);
+ static Limits IntersectRangeAndBitset(TypeHandle range, TypeHandle bits,
+ Region* region);
+ static Limits ToLimits(bitset bits, 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);
+ static int IntersectAux(TypeHandle type, TypeHandle other, UnionHandle result,
+ int size, Limits* limits, Region* region);
+ static TypeHandle NormalizeUnion(UnionHandle unioned, int size,
+ Region* region);
+ static TypeHandle NormalizeRangeAndBitset(RangeHandle range, bitset* bits,
+ Region* region);
};
@@ -596,42 +644,31 @@
protected:
friend class TypeImpl<Config>;
- enum {
+ enum : uint32_t {
#define DECLARE_TYPE(type, value) k##type = (value),
BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
kUnusedEOL = 0
};
+ static bitset SignedSmall();
+ static bitset UnsignedSmall();
+
bitset Bitset() { return Config::as_bitset(this); }
static TypeImpl* New(bitset bits) {
- DCHECK(bits == kNone || IsInhabited(bits));
-
- if (FLAG_enable_slow_asserts) {
- // Check that the bitset does not contain any holes in number ranges.
- bitset mask = kSemantic;
- if (!i::SmiValuesAre31Bits()) {
- mask &= ~(kOtherUnsigned31 | kOtherSigned32);
- }
- bitset number_bits = bits & kPlainNumber & mask;
- if (number_bits != 0) {
- bitset lub = Lub(Min(number_bits), Max(number_bits)) & mask;
- CHECK(lub == number_bits);
- }
- }
-
return Config::from_bitset(bits);
}
static TypeHandle New(bitset bits, Region* region) {
- DCHECK(bits == kNone || IsInhabited(bits));
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) {
- return bits & kSemantic;
+ return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone;
+ }
+
+ static bool SemanticIsInhabited(bitset bits) {
+ return SEMANTIC(bits) != kNone;
}
static bool Is(bitset bits1, bitset bits2) {
@@ -642,11 +679,13 @@
static double Max(bitset);
static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset
+ static bitset Glb(double min, double max);
static bitset Lub(TypeImpl* type); // least upper bound that's a bitset
static bitset Lub(i::Map* map);
static bitset Lub(i::Object* value);
static bitset Lub(double value);
static bitset Lub(double min, double max);
+ static bitset ExpandInternals(bitset bits);
static const char* Name(bitset);
static void Print(std::ostream& os, bitset); // NOLINT
@@ -654,21 +693,17 @@
static void Print(bitset);
#endif
+ static bitset NumberBits(bitset bits);
+
private:
- struct BitsetMin{
- bitset bits;
+ struct Boundary {
+ bitset internal;
+ bitset external;
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.
- }
+ static const Boundary BoundariesArray[];
+ static inline const Boundary* Boundaries();
+ static inline size_t BoundariesSize();
};
@@ -686,7 +721,6 @@
enum Tag {
kClassTag,
kConstantTag,
- kRangeTag,
kContextTag,
kArrayTag,
kFunctionTag,
@@ -754,11 +788,6 @@
template<class Config>
class TypeImpl<Config>::ClassType : public StructuralType {
public:
- TypeHandle Bound(Region* region) {
- return Config::is_class(this) ?
- BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) :
- this->Get(0);
- }
i::Handle<i::Map> Map() {
return Config::is_class(this) ? Config::as_class(this) :
this->template GetValue<i::Map>(1);
@@ -780,6 +809,14 @@
DCHECK(type->IsClass());
return static_cast<ClassType*>(type);
}
+
+ private:
+ template<class> friend class TypeImpl;
+ bitset Lub() {
+ return Config::is_class(this) ?
+ BitsetType::Lub(*Config::as_class(this)) :
+ this->Get(0)->AsBitset();
+ }
};
@@ -789,7 +826,6 @@
template<class Config>
class TypeImpl<Config>::ConstantType : public StructuralType {
public:
- TypeHandle Bound() { return this->Get(0); }
i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
@@ -804,6 +840,10 @@
DCHECK(type->IsConstant());
return static_cast<ConstantType*>(type);
}
+
+ private:
+ template<class> friend class TypeImpl;
+ bitset Lub() { return this->Get(0)->AsBitset(); }
};
// TODO(neis): Also cache value if numerical.
// TODO(neis): Allow restricting the representation.
@@ -812,37 +852,45 @@
// -----------------------------------------------------------------------------
// Range types.
-template<class Config>
-class TypeImpl<Config>::RangeType : public StructuralType {
+template <class Config>
+class TypeImpl<Config>::RangeType : public TypeImpl<Config> {
public:
- int BitsetLub() { return this->Get(0)->AsBitset(); }
- i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); }
- i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); }
+ double Min() { return Config::range_get_double(Config::as_range(this), 0); }
+ double Max() { return Config::range_get_double(Config::as_range(this), 1); }
- static RangeHandle New(
- i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
- DCHECK(IsInteger(min->Number()) && IsInteger(max->Number()));
- DCHECK(min->Number() <= max->Number());
- RangeHandle type = Config::template cast<RangeType>(
- StructuralType::New(StructuralType::kRangeTag, 3, region));
- type->Set(0, BitsetType::New(
- BitsetType::Lub(min->Number(), max->Number()), region));
- type->SetValue(1, min);
- type->SetValue(2, max);
- return type;
+ static RangeHandle New(double min, double max, TypeHandle representation,
+ Region* region) {
+ DCHECK(IsInteger(min) && IsInteger(max));
+ DCHECK(min <= max);
+ bitset representation_bits = representation->AsBitset();
+ DCHECK(REPRESENTATION(representation_bits) == representation_bits);
+
+ typename Config::template Handle<typename Config::Range>::type range =
+ Config::range_create(region);
+
+ bitset bits = SEMANTIC(BitsetType::Lub(min, max)) | representation_bits;
+ Config::range_set_bitset(range, bits);
+ Config::range_set_double(range, 0, min, region);
+ Config::range_set_double(range, 1, max, region);
+ return Config::template cast<RangeType>(Config::from_range(range));
}
- static RangeHandle New(Limits lim, Region* region) {
- return New(lim.min, lim.max, region);
+ static RangeHandle New(Limits lim, bitset representation, Region* region) {
+ return New(lim.min, lim.max, BitsetType::New(representation, region),
+ region);
}
static RangeType* cast(TypeImpl* type) {
DCHECK(type->IsRange());
return static_cast<RangeType*>(type);
}
+
+ private:
+ template<class> friend class TypeImpl;
+ bitset Lub() {
+ return Config::range_get_bitset(Config::as_range(this));
+ }
};
-// TODO(neis): Also cache min and max values.
-// TODO(neis): Allow restricting the representation.
// -----------------------------------------------------------------------------
@@ -952,25 +1000,38 @@
typedef TypeImpl<ZoneTypeConfig> Type;
class Base {};
typedef void* Struct;
+ // Hack: the Struct and Range types can be aliased in memory, the first
+ // pointer word of each both must be the tag (kRangeStructTag for Range,
+ // anything else for Struct) so that we can differentiate them.
+ struct Range {
+ void* tag;
+ int bitset;
+ double limits[2];
+ };
typedef i::Zone Region;
template<class T> struct Handle { typedef T* type; };
- template<class T> static inline T* null_handle();
+ static const int kRangeStructTag = 0x1000;
+
+ template<class T> static inline T* null_handle() { return nullptr; }
template<class T> static inline T* handle(T* type);
template<class T> static inline T* cast(Type* type);
static inline bool is_bitset(Type* type);
static inline bool is_class(Type* type);
static inline bool is_struct(Type* type, int tag);
+ static inline bool is_range(Type* type);
static inline Type::bitset as_bitset(Type* type);
static inline i::Handle<i::Map> as_class(Type* type);
static inline Struct* as_struct(Type* type);
+ static inline Range* as_range(Type* type);
static inline Type* from_bitset(Type::bitset);
static inline Type* from_bitset(Type::bitset, Zone* zone);
static inline Type* from_class(i::Handle<i::Map> map, Zone* zone);
static inline Type* from_struct(Struct* structured);
+ static inline Type* from_range(Range* range);
static inline Struct* struct_create(int tag, int length, Zone* zone);
static inline void struct_shrink(Struct* structure, int length);
@@ -982,6 +1043,12 @@
static inline i::Handle<V> struct_get_value(Struct* structure, int i);
template<class V> static inline void struct_set_value(
Struct* structure, int i, i::Handle<V> x);
+
+ static inline Range* range_create(Zone* zone);
+ static inline int range_get_bitset(Range* range);
+ static inline void range_set_bitset(Range* range, int);
+ static inline double range_get_double(Range*, int index);
+ static inline void range_set_double(Range*, int index, double value, Zone*);
};
typedef TypeImpl<ZoneTypeConfig> Type;
@@ -995,26 +1062,34 @@
typedef TypeImpl<HeapTypeConfig> Type;
typedef i::Object Base;
typedef i::FixedArray Struct;
+ typedef i::FixedArray Range;
typedef i::Isolate Region;
template<class T> struct Handle { typedef i::Handle<T> type; };
- template<class T> static inline i::Handle<T> null_handle();
+ static const int kRangeStructTag = 0xffff;
+
+ template<class T> static inline i::Handle<T> null_handle() {
+ return i::Handle<T>();
+ }
template<class T> static inline i::Handle<T> handle(T* type);
template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
static inline bool is_bitset(Type* type);
static inline bool is_class(Type* type);
static inline bool is_struct(Type* type, int tag);
+ static inline bool is_range(Type* type);
static inline Type::bitset as_bitset(Type* type);
static inline i::Handle<i::Map> as_class(Type* type);
static inline i::Handle<Struct> as_struct(Type* type);
+ static inline i::Handle<Range> as_range(Type* type);
static inline Type* from_bitset(Type::bitset);
static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate);
static inline i::Handle<Type> from_class(
i::Handle<i::Map> map, Isolate* isolate);
static inline i::Handle<Type> from_struct(i::Handle<Struct> structure);
+ static inline i::Handle<Type> from_range(i::Handle<Range> range);
static inline i::Handle<Struct> struct_create(
int tag, int length, Isolate* isolate);
@@ -1030,6 +1105,13 @@
template<class V>
static inline void struct_set_value(
i::Handle<Struct> structure, int i, i::Handle<V> x);
+
+ static inline i::Handle<Range> range_create(Isolate* isolate);
+ static inline int range_get_bitset(i::Handle<Range> range);
+ static inline void range_set_bitset(i::Handle<Range> range, int value);
+ static inline double range_get_double(i::Handle<Range> range, int index);
+ static inline void range_set_double(i::Handle<Range> range, int index,
+ double value, Isolate* isolate);
};
typedef TypeImpl<HeapTypeConfig> HeapType;
@@ -1056,8 +1138,8 @@
}
// Unrestricted bounds.
- static BoundsImpl Unbounded(Region* region) {
- return BoundsImpl(Type::None(region), Type::Any(region));
+ static BoundsImpl Unbounded() {
+ return BoundsImpl(Type::None(), Type::Any());
}
// Meet: both b1 and b2 are known to hold.
@@ -1097,6 +1179,7 @@
typedef BoundsImpl<ZoneTypeConfig> Bounds;
-} } // namespace v8::internal
+} // namespace internal
+} // namespace v8
#endif // V8_TYPES_H_