-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathSym.h
336 lines (289 loc) · 13.3 KB
/
Sym.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
class Lifetime;
namespace IR
{
class Instr;
class Opnd;
}
class StackSym;
class PropertySym;
typedef JsUtil::BaseDictionary<StackSym*, StackSym*, JitArenaAllocator, PrimeSizePolicy> StackSymMap;
typedef JsUtil::BaseDictionary<StackSym*, IR::Instr*, JitArenaAllocator, PrimeSizePolicy> SymInstrMap;
enum SymKind : BYTE
{
SymKindInvalid,
SymKindStack,
SymKindProperty
};
typedef uint32 SymID;
///---------------------------------------------------------------------------
///
/// class Sym
/// StackSym
/// PropertySym
///
///---------------------------------------------------------------------------
class Sym
{
public:
bool IsStackSym() const;
StackSym * AsStackSym();
StackSym const * AsStackSym() const;
bool IsPropertySym() const;
PropertySym * AsPropertySym();
PropertySym const * AsPropertySym() const;
#if DBG_DUMP || defined(ENABLE_IR_VIEWER)
void Dump(IRDumpFlags flags, const ValueType valueType = ValueType::Uninitialized) const;
void Dump(const ValueType valueType = ValueType::Uninitialized) const;
void DumpSimple() const;
#endif
#if DBG_DUMP
// Having a VTable helps the VS debugger determine which derived class we have
void virtual DummyVirtualFunc() {};
#endif
public:
Sym * m_next;
SymID m_id;
SymKind m_kind;
};
class ObjectSymInfo
{
public:
static ObjectSymInfo * New(Func * func);
static ObjectSymInfo * New(StackSym * typeSym, Func * func);
ObjectSymInfo(): m_typeSym(nullptr), m_propertySymList(nullptr) {};
public:
StackSym * m_typeSym;
PropertySym * m_propertySymList;
};
///---------------------------------------------------------------------------
///
/// class StackSym
///
/// Used for stack symbols. These are the register candidates.
///
///---------------------------------------------------------------------------
class StackSym: public Sym
{
private:
static StackSym * New(SymID id, IRType type, Js::RegSlot byteCodeRegSlot, Func *func);
public:
static StackSym * NewArgSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType = TyVar);
static StackSym * NewArgSlotRegSym(Js::ArgSlot argSlotNum, Func * func, IRType = TyVar);
static StackSym * NewParamSlotSym(Js::ArgSlot argSlotNum, Func * func);
static StackSym * NewParamSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType type);
static StackSym *NewImplicitParamSym(Js::ArgSlot paramSlotNum, Func * func);
static StackSym * New(IRType type, Func *func);
static StackSym * New(Func *func);
static StackSym * FindOrCreate(SymID id, Js::RegSlot byteCodeRegSlot, Func *func, IRType type = TyVar);
IRType GetType() const { return this->m_type; }
bool IsArgSlotSym() const;
bool IsParamSlotSym() const;
bool IsImplicitParamSym() const { return this->m_isImplicitParamSym; }
bool IsAllocated() const;
int32 GetIntConstValue() const;
Js::Var GetFloatConstValueAsVar_PostGlobOpt() const;
void * GetConstAddress(bool useLocal = false) const;
StackSym * CloneDef(Func *func);
StackSym * CloneUse(Func *func);
void CopySymAttrs(StackSym *symSrc);
bool IsSingleDef() const { return this->m_isSingleDef && this->m_instrDef; }
bool IsConst() const;
bool IsIntConst() const;
bool IsInt64Const() const;
bool IsTaggableIntConst() const;
bool IsFloatConst() const;
// SIMD_JS
bool IsSimd128Const() const;
void SetIsConst();
void SetIsIntConst(IntConstType value);
void SetIsInt64Const();
void SetIsFloatConst();
// SIMD_JS
void SetIsSimd128Const();
intptr_t GetLiteralConstValue_PostGlobOpt() const;
IR::Opnd * GetConstOpnd() const;
BailoutConstantValue GetConstValueForBailout() const;
// SIMD_JS
StackSym * GetSimd128EquivSym(IRType type, Func *func);
StackSym * GetSimd128F4EquivSym(Func *func);
StackSym * GetSimd128I4EquivSym(Func *func);
StackSym * GetSimd128I16EquivSym(Func *func);
StackSym * GetSimd128D2EquivSym(Func *func);
bool IsSimd128() const { return IRType_IsSimd128(this->GetType()); }
bool IsSimd128F4() const { return this->GetType() == TySimd128F4; }
bool IsSimd128I4() const { return this->GetType() == TySimd128I4; }
bool IsSimd128I8() const { return this->GetType() == TySimd128I8; }
bool IsSimd128I16() const { return this->GetType() == TySimd128I16; }
bool IsSimd128U4() const { return this->GetType() == TySimd128U4; }
bool IsSimd128U8() const { return this->GetType() == TySimd128U8; }
bool IsSimd128U16() const { return this->GetType() == TySimd128U16; }
bool IsSimd128B4() const { return this->GetType() == TySimd128B4; }
bool IsSimd128B8() const { return this->GetType() == TySimd128B8; }
bool IsSimd128B16() const { return this->GetType() == TySimd128B16; }
bool IsSimd128D2() const { return this->GetType() == TySimd128D2; }
StackSym * GetFloat64EquivSym(Func *func);
bool IsFloat64() const { return this->GetType() == TyFloat64; }
bool IsFloat32() const { return this->GetType() == TyFloat32; }
StackSym * GetInt32EquivSym(Func *func);
bool IsInt32() const { return this->GetType() == TyInt32; }
bool IsUInt32() const { return this->GetType() == TyUint32; }
bool IsInt64() const { return this->GetType() == TyInt64; }
bool IsUint64() const { return this->GetType() == TyUint64; }
StackSym * GetVarEquivSym(Func *func);
StackSym * GetVarEquivSym_NoCreate();
StackSym const * GetVarEquivSym_NoCreate() const;
bool IsVar() const { return this->GetType() == TyVar; }
bool IsTypeSpec() const { return this->m_isTypeSpec; }
static StackSym *GetVarEquivStackSym_NoCreate(Sym * sym);
static StackSym const *GetVarEquivStackSym_NoCreate(Sym const * const sym);
bool HasByteCodeRegSlot() const { return m_hasByteCodeRegSlot; }
Func * GetByteCodeFunc() const;
Js::RegSlot GetByteCodeRegSlot() const;
bool IsTempReg(Func *const func) const;
bool IsFromByteCodeConstantTable() const { return m_isFromByteCodeConstantTable; }
void SetIsFromByteCodeConstantTable() { this->m_isFromByteCodeConstantTable = true; }
Js::ArgSlot GetArgSlotNum() const { Assert(HasArgSlotNum()); return m_slotNum; }
void SetArgSlotNum(Js::ArgSlot newNum) { m_slotNum = newNum; }
bool HasArgSlotNum() const { return !!(m_isArgSlotSym | m_isArgSlotRegSym); }
void IncrementArgSlotNum();
void DecrementArgSlotNum();
Js::ArgSlot GetParamSlotNum() const { Assert(IsParamSlotSym()); return m_slotNum; }
IR::Instr * GetInstrDef() const { return this->IsSingleDef() ? this->m_instrDef : nullptr; }
bool HasObjectInfo() const { Assert(!IsTypeSpec()); return this->m_objectInfo != nullptr; };
ObjectSymInfo * GetObjectInfo() const { Assert(this->m_objectInfo); return this->m_objectInfo; }
void SetObjectInfo(ObjectSymInfo * value) { this->m_objectInfo = value; }
ObjectSymInfo * EnsureObjectInfo(Func * func);
bool HasObjectTypeSym() const { return HasObjectInfo() && GetObjectInfo()->m_typeSym; }
StackSym * GetObjectTypeSym() const { Assert(HasObjectTypeSym()); return GetObjectInfo()->m_typeSym; }
int GetSymSize(){ return TySize[m_type]; }
void FixupStackOffset(Func * currentFunc);
private:
StackSym * GetTypeEquivSym(IRType type, Func *func);
StackSym * GetTypeEquivSym_NoCreate(IRType type);
StackSym const * GetTypeEquivSym_NoCreate(IRType type) const;
#if DBG
void VerifyConstFlags() const;
#endif
private:
Js::ArgSlot m_slotNum;
public:
uint8 m_isSingleDef:1; // the symbol only has a single definition in the IR
uint8 m_isNotInt:1;
uint8 m_isSafeThis : 1;
uint8 m_isConst : 1; // single def and it is a constant
uint8 m_isIntConst : 1; // a constant and it's value is an Int32
uint8 m_isTaggableIntConst : 1; // a constant and it's value is taggable (Int31 in 32-bit, Int32 in x64)
uint8 m_isEncodedConstant : 1; // the constant has
uint8 m_isInt64Const: 1;
uint8 m_isFltConst: 1;
uint8 m_isSimd128Const : 1;
uint8 m_isStrConst:1;
uint8 m_isStrEmpty:1;
uint8 m_allocated:1;
uint8 m_hasByteCodeRegSlot:1;
uint8 m_isInlinedArgSlot:1;
uint8 m_isOrphanedArg :1;
uint8 m_isTypeSpec:1;
uint8 m_requiresBailOnNotNumber:1;
uint8 m_isFromByteCodeConstantTable:1;
uint8 m_mayNotBeTempLastUse:1;
uint8 m_isArgSlotSym: 1; // When set this implies an argument stack slot with no lifetime for register allocation
uint8 m_isArgSlotRegSym : 1;
uint8 m_isParamSym : 1;
uint8 m_isImplicitParamSym : 1;
uint8 m_isBailOutReferenced: 1; // argument sym referenced by bailout
uint8 m_isArgCaptured: 1; // True if there is a ByteCodeArgOutCapture for this symbol
uint8 m_nonEscapingArgObjAlias : 1;
uint8 m_isCatchObjectSym : 1; // a catch object sym (used while jitting loop bodies)
uint m_isClosureSym : 1;
IRType m_type;
Js::BuiltinFunction m_builtInIndex;
int32 m_offset;
#ifdef _M_AMD64
// Only for AsmJs on x64. Argument position for ArgSyms.
int32 m_argPosition;
#endif
union
{
IR::Instr * m_instrDef; // m_isSingleDef
size_t constantValue; // !m_isSingleDef && m_isEncodedConstant
};
StackSym * m_tempNumberSym;
StackSym * m_equivNext;
ObjectSymInfo * m_objectInfo;
union {
struct GlobOpt
{
int numCompoundedAddSubUses;
} globOpt;
struct LinearScan
{
Lifetime * lifetime;
} linearScan;
struct Peeps
{
RegNum reg;
} peeps;
}scratch;
static const Js::ArgSlot InvalidSlot;
};
class ByteCodeStackSym : public StackSym
{
private:
ByteCodeStackSym(Js::RegSlot byteCodeRegSlot, Func * byteCodeFunc)
: byteCodeRegSlot(byteCodeRegSlot), byteCodeFunc(byteCodeFunc) {}
Js::RegSlot byteCodeRegSlot;
Func * byteCodeFunc;
friend class StackSym;
};
///---------------------------------------------------------------------------
///
/// class PropertySym
///
/// Used for field symbols. Property syms for a given objects are linked
/// together.
///
///---------------------------------------------------------------------------
enum PropertyKind : BYTE
{
PropertyKindData,
PropertyKindSlots,
PropertyKindLocalSlots,
PropertyKindSlotArray,
PropertyKindWriteGuard
};
class PropertySym: public Sym
{
friend class Sym;
public:
static PropertySym * New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
static PropertySym * New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
static PropertySym * Find(SymID stackSymID, int32 propertyId, Func *func);
static PropertySym * FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
Func *GetFunc() { return m_func; }
bool HasPropertyIdIndex() { return m_propertyIdIndex != -1; }
int32 GetPropertyIdIndex() { return m_propertyIdIndex; }
bool HasInlineCacheIndex() { return m_inlineCacheIndex != -1; }
int32 GetInlineCacheIndex() { return m_inlineCacheIndex; }
bool HasObjectTypeSym() const { return this->m_stackSym->HasObjectTypeSym(); }
bool HasWriteGuardSym() const { return this->m_writeGuardSym != nullptr; }
StackSym * GetObjectTypeSym() const { return this->m_stackSym->GetObjectTypeSym(); }
public:
PropertyKind m_fieldKind;
int32 m_propertyId;
StackSym * m_stackSym;
BVSparse<JitArenaAllocator> *m_propertyEquivSet; // Bit vector of all propertySyms with same propertyId
PropertySym * m_nextInStackSymList;
PropertySym * m_writeGuardSym;
Func * m_func;
Func * m_loadInlineCacheFunc;
uint m_loadInlineCacheIndex;
private:
uint32 m_propertyIdIndex;
uint m_inlineCacheIndex;
};