1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/TypeDescrSet.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,204 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_TypeRepresentationSet_h 1.11 +#define jit_TypeRepresentationSet_h 1.12 + 1.13 +#include "builtin/TypedObject.h" 1.14 +#include "jit/IonAllocPolicy.h" 1.15 +#include "js/HashTable.h" 1.16 + 1.17 +// TypeRepresentationSet stores a set of TypeRepresentation* objects, 1.18 +// representing the possible types of the binary data associated with 1.19 +// a typed object value. Often TypeRepresentationSets will be 1.20 +// singleton sets, but it is also possible to have cases where many 1.21 +// type representations flow into a single point. In such cases, the 1.22 +// various type representations may differ in their details but often 1.23 +// have a common prefix. We try to optimize this case as well. 1.24 +// 1.25 +// So, for example, consider some code like: 1.26 +// 1.27 +// var Point2Type = new StructType({x: uint8, y: uint8}); 1.28 +// var Point3Type = new StructType({x: uint8, y: uint8, z: uint8}); 1.29 +// 1.30 +// function distance2d(pnt) { 1.31 +// return Math.sqrt(pnt.x * pnt.x + pnt.y * pnt.y); 1.32 +// } 1.33 +// 1.34 +// Even if the function `distance2d()` were used with instances of 1.35 +// both Point2Type and Point3Type, we can still generate optimal code, 1.36 +// because both of those types contain fields named `x` and `y` with 1.37 +// the same types at the same offset. 1.38 + 1.39 +namespace js { 1.40 +namespace jit { 1.41 + 1.42 +class IonBuilder; 1.43 +class TypeDescrSet; 1.44 + 1.45 +class TypeDescrSetBuilder { 1.46 + private: 1.47 + Vector<TypeDescr *, 4, SystemAllocPolicy> entries_; 1.48 + bool invalid_; 1.49 + 1.50 + public: 1.51 + TypeDescrSetBuilder(); 1.52 + 1.53 + bool insert(TypeDescr *typeRepr); 1.54 + bool build(IonBuilder &builder, TypeDescrSet *out); 1.55 +}; 1.56 + 1.57 +class TypeDescrSet { 1.58 + private: 1.59 + friend struct TypeDescrSetHasher; 1.60 + friend class TypeDescrSetBuilder; 1.61 + 1.62 + size_t length_; 1.63 + TypeDescr **entries_; // Allocated using temp policy 1.64 + 1.65 + TypeDescrSet(size_t length, TypeDescr **entries); 1.66 + 1.67 + size_t length() const { 1.68 + return length_; 1.69 + } 1.70 + 1.71 + TypeDescr *get(uint32_t i) const { 1.72 + return entries_[i]; 1.73 + } 1.74 + 1.75 + template<typename T> 1.76 + bool genericType(typename T::Type *out); 1.77 + 1.78 + public: 1.79 + ////////////////////////////////////////////////////////////////////// 1.80 + // Constructors 1.81 + // 1.82 + // For more flexible constructors, see 1.83 + // TypeDescrSetBuilder above. 1.84 + 1.85 + TypeDescrSet(const TypeDescrSet &c); 1.86 + TypeDescrSet(); // empty set 1.87 + 1.88 + ////////////////////////////////////////////////////////////////////// 1.89 + // Query the set 1.90 + 1.91 + bool empty() const; 1.92 + bool allOfKind(TypeDescr::Kind kind); 1.93 + 1.94 + // Returns true only when non-empty and `kind()` is 1.95 + // `TypeDescr::Array` 1.96 + bool allOfArrayKind(); 1.97 + 1.98 + // Returns true only if (1) non-empty, (2) for all types t in this 1.99 + // set, t is sized, and (3) there is some size S such that for all 1.100 + // types t in this set, `t.size() == S`. When the above holds, 1.101 + // then also sets `*out` to S; otherwise leaves `*out` unchanged 1.102 + // and returns false. 1.103 + // 1.104 + // At the moment condition (2) trivially holds. When Bug 922115 1.105 + // lands, some array types will be unsized. 1.106 + bool allHaveSameSize(int32_t *out); 1.107 + 1.108 + types::TemporaryTypeSet *suitableTypeSet(IonBuilder &builder, 1.109 + const Class *knownClass); 1.110 + 1.111 + ////////////////////////////////////////////////////////////////////// 1.112 + // The following operations are only valid on a non-empty set: 1.113 + 1.114 + TypeDescr::Kind kind(); 1.115 + 1.116 + // Returns the prototype that a typed object whose type is within 1.117 + // this TypeDescrSet would have. Returns `null` if this cannot be 1.118 + // predicted or instances of the type are not objects (e.g., uint8). 1.119 + JSObject *knownPrototype() const; 1.120 + 1.121 + ////////////////////////////////////////////////////////////////////// 1.122 + // Scalar operations 1.123 + // 1.124 + // Only valid when `kind() == TypeDescr::Scalar` 1.125 + 1.126 + // If all type descrs in this set have a single type, returns true 1.127 + // and sets *out. Else returns false. 1.128 + bool scalarType(ScalarTypeDescr::Type *out); 1.129 + 1.130 + ////////////////////////////////////////////////////////////////////// 1.131 + // Reference operations 1.132 + // 1.133 + // Only valid when `kind() == TypeDescr::Reference` 1.134 + 1.135 + // If all type descrs in this set have a single type, returns true 1.136 + // and sets *out. Else returns false. 1.137 + bool referenceType(ReferenceTypeDescr::Type *out); 1.138 + 1.139 + ////////////////////////////////////////////////////////////////////// 1.140 + // Reference operations 1.141 + // 1.142 + // Only valid when `kind() == TypeDescr::X4` 1.143 + 1.144 + // If all type descrs in this set have a single type, returns true 1.145 + // and sets *out. Else returns false. 1.146 + bool x4Type(X4TypeDescr::Type *out); 1.147 + 1.148 + ////////////////////////////////////////////////////////////////////// 1.149 + // SizedArray operations 1.150 + // 1.151 + // Only valid when `kind() == TypeDescr::SizedArray` 1.152 + 1.153 + // Determines whether all arrays in this set have the same, 1.154 + // statically known, array length and return that length 1.155 + // (via `*length`) if so. Otherwise returns false. 1.156 + bool hasKnownArrayLength(int32_t *length); 1.157 + 1.158 + // Returns a `TypeDescrSet` representing the element 1.159 + // types of the various array types in this set. The returned set 1.160 + // may be the empty set. 1.161 + bool arrayElementType(IonBuilder &builder, TypeDescrSet *out); 1.162 + 1.163 + ////////////////////////////////////////////////////////////////////// 1.164 + // Struct operations 1.165 + // 1.166 + // Only valid when `kind() == TypeDescr::Struct` 1.167 + 1.168 + // Searches the type in the set for a field named `id`. All 1.169 + // possible types must agree on the offset of the field within the 1.170 + // structure and the possible types of the field must be 1.171 + // compatible. If any pair of types disagree on the offset or have 1.172 + // incompatible types for the field, then `*out` will be set to 1.173 + // the empty set. 1.174 + // 1.175 + // Upon success, `out` will be set to the set of possible types of 1.176 + // the field and `offset` will be set to the field's offset within 1.177 + // the struct (measured in bytes). 1.178 + // 1.179 + // The parameter `*index` is special. If all types agree on the 1.180 + // index of the field, then `*index` is set to the field index. 1.181 + // Otherwise, it is set to SIZE_MAX. Note that two types may agree 1.182 + // on the type and offset of a field but disagree about its index, 1.183 + // e.g. the field `c` in `new StructType({a: uint8, b: uint8, c: 1.184 + // uint16})` and `new StructType({a: uint16, c: uint16})`. 1.185 + bool fieldNamed(IonBuilder &builder, 1.186 + jsid id, 1.187 + int32_t *offset, 1.188 + TypeDescrSet *out, 1.189 + size_t *index); 1.190 +}; 1.191 + 1.192 +struct TypeDescrSetHasher 1.193 +{ 1.194 + typedef TypeDescrSet Lookup; 1.195 + static HashNumber hash(TypeDescrSet key); 1.196 + static bool match(TypeDescrSet key1, 1.197 + TypeDescrSet key2); 1.198 +}; 1.199 + 1.200 +typedef js::HashSet<TypeDescrSet, 1.201 + TypeDescrSetHasher, 1.202 + IonAllocPolicy> TypeDescrSetHash; 1.203 + 1.204 +} // namespace jit 1.205 +} // namespace js 1.206 + 1.207 +#endif