Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jit_TypedObjectPrediction_h
8 : #define jit_TypedObjectPrediction_h
9 :
10 : #include "builtin/TypedObject.h"
11 : #include "jit/JitAllocPolicy.h"
12 :
13 : namespace js {
14 : namespace jit {
15 :
16 : // A TypedObjectPrediction summarizes what we know about the type of a
17 : // typed object at a given point (if anything). The prediction will
18 : // begin as precise as possible and degrade to less precise as more
19 : // typed object types are merged using |addDescr()|.
20 : //
21 : // To create a TypedObjectPrediction from TI, one initially creates an
22 : // empty prediction using the |TypedObjectPrediction()| constructor,
23 : // and then invokes |addDescr()| with the prototype of each typed
24 : // object. The prediction will automatically downgrade to less and
25 : // less specific settings as needed. Note that creating a prediction
26 : // in this way can never yield precise array dimensions, since TI only
27 : // tracks the prototype.
28 : //
29 : // TypedObjectPredictions can also result from other predictions using
30 : // the query methods (e.g., |arrayElementType()|). In those cases, the
31 : // precise array dimensions may be known.
32 : //
33 : // To query a prediction, you must first check whether it is "useless"
34 : // using |isUseless()|. If this is true, there is no usable
35 : // information to be extracted. Otherwise, you can inquire after the
36 : // |kind()| of the data (struct, array, etc) and from there make more
37 : // specific queries.
38 : class TypedObjectPrediction {
39 : public:
40 : enum PredictionKind {
41 : // No data.
42 : Empty,
43 :
44 : // Inconsistent data.
45 : Inconsistent,
46 :
47 : // Multiple different struct types flow into the same location,
48 : // but they share fields in common. Prefix indicates that the first
49 : // N fields of some struct type are known to be valid. This occurs
50 : // in a subtyping scenario.
51 : Prefix,
52 :
53 : // The TypeDescr of the value is known. This is the most specific
54 : // possible value and includes precise array bounds.
55 : Descr
56 : };
57 :
58 : struct PrefixData {
59 : const StructTypeDescr* descr;
60 : size_t fields;
61 : };
62 :
63 : union Data {
64 : const TypeDescr* descr;
65 : PrefixData prefix;
66 : };
67 :
68 : private:
69 : PredictionKind kind_;
70 : Data data_;
71 :
72 104 : PredictionKind predictionKind() const {
73 104 : return kind_;
74 : }
75 :
76 0 : void markInconsistent() {
77 0 : kind_ = Inconsistent;
78 0 : }
79 :
80 0 : const TypeDescr& descr() const {
81 0 : MOZ_ASSERT(predictionKind() == Descr);
82 0 : return *data_.descr;
83 : }
84 :
85 0 : const PrefixData& prefix() const {
86 0 : MOZ_ASSERT(predictionKind() == Prefix);
87 0 : return data_.prefix;
88 : }
89 :
90 0 : void setDescr(const TypeDescr& descr) {
91 0 : kind_ = Descr;
92 0 : data_.descr = &descr;
93 0 : }
94 :
95 0 : void setPrefix(const StructTypeDescr& descr, size_t fields) {
96 0 : kind_ = Prefix;
97 0 : data_.prefix.descr = &descr;
98 0 : data_.prefix.fields = fields;
99 0 : }
100 :
101 : void markAsCommonPrefix(const StructTypeDescr& descrA,
102 : const StructTypeDescr& descrB,
103 : size_t max);
104 :
105 : template<typename T>
106 : typename T::Type extractType() const;
107 :
108 : bool hasFieldNamedPrefix(const StructTypeDescr& descr,
109 : size_t fieldCount,
110 : jsid id,
111 : size_t* fieldOffset,
112 : TypedObjectPrediction* out,
113 : size_t* index) const;
114 :
115 : public:
116 :
117 : ///////////////////////////////////////////////////////////////////////////
118 : // Constructing a prediction. Generally, you start with an empty
119 : // prediction and invoke addDescr() repeatedly.
120 :
121 250 : TypedObjectPrediction() {
122 250 : kind_ = Empty;
123 250 : }
124 :
125 0 : explicit TypedObjectPrediction(const TypeDescr& descr) {
126 0 : setDescr(descr);
127 0 : }
128 :
129 : TypedObjectPrediction(const StructTypeDescr& descr, size_t fields) {
130 : setPrefix(descr, fields);
131 : }
132 :
133 : void addDescr(const TypeDescr& descr);
134 :
135 : ///////////////////////////////////////////////////////////////////////////
136 : // Queries that are always valid.
137 :
138 104 : bool isUseless() const {
139 104 : return predictionKind() == Empty || predictionKind() == Inconsistent;
140 : }
141 :
142 : // Determines whether we can predict the prototype for the typed
143 : // object instance. Returns null if we cannot or if the typed
144 : // object is of scalar/reference kind, in which case instances are
145 : // not objects and hence do not have a (publicly available)
146 : // prototype.
147 : const TypedProto* getKnownPrototype() const;
148 :
149 : ///////////////////////////////////////////////////////////////////////////
150 : // Queries that are valid if not useless.
151 :
152 : type::Kind kind() const;
153 :
154 : bool ofArrayKind() const;
155 :
156 : // Returns true if the size of this typed object is statically
157 : // known and sets |*out| to that size. Otherwise returns false.
158 : //
159 : // The size may not be statically known if (1) the object is
160 : // an array whose dimensions are unknown or (2) only a prefix
161 : // of its type is known.
162 : bool hasKnownSize(uint32_t* out) const;
163 :
164 : //////////////////////////////////////////////////////////////////////
165 : // Simple operations
166 : //
167 : // Only valid when |kind()| is Scalar, Reference, or Simd (as appropriate).
168 :
169 : ScalarTypeDescr::Type scalarType() const;
170 : ReferenceTypeDescr::Type referenceType() const;
171 : SimdType simdType() const;
172 :
173 : ///////////////////////////////////////////////////////////////////////////
174 : // Queries valid only for arrays.
175 :
176 : // Returns true if the length of the array is statically known,
177 : // and sets |*length| appropriately. Otherwise returns false.
178 : bool hasKnownArrayLength(int32_t* length) const;
179 :
180 : // Returns a prediction for the array element type, if any.
181 : TypedObjectPrediction arrayElementType() const;
182 :
183 : //////////////////////////////////////////////////////////////////////
184 : // Struct operations
185 : //
186 : // Only valid when |kind() == TypeDescr::Struct|
187 :
188 : // Returns true if the predicted type includes a field named |id|
189 : // and sets |*fieldOffset|, |*fieldType|, and |*fieldIndex| with
190 : // the offset (in bytes), type, and index of the field
191 : // respectively. Otherwise returns false.
192 : bool hasFieldNamed(jsid id,
193 : size_t* fieldOffset,
194 : TypedObjectPrediction* fieldType,
195 : size_t* fieldIndex) const;
196 : };
197 :
198 : } // namespace jit
199 : } // namespace js
200 :
201 : #endif
|