forked from chakra-core/ChakraCore
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctionInfo.h
More file actions
186 lines (168 loc) · 10.4 KB
/
Copy pathFunctionInfo.h
File metadata and controls
186 lines (168 loc) · 10.4 KB
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
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
namespace Js
{
class FunctionProxy;
class FunctionBody;
class ParseableFunctionInfo;
class DeferDeserializeFunctionInfo;
class FunctionInfo
{
friend class RemoteFunctionBody;
public:
enum Attributes : uint32
{
None = 0x00000,
ErrorOnNew = 0x00001,
SkipDefaultNewObject = 0x00002,
DoNotProfile = 0x00004,
HasNoSideEffect = 0x00008, // calling function doesn't cause an implicit flags to be set,
// the callee will detect and set implicit flags on its individual operations
NeedCrossSiteSecurityCheck = 0x00010,
DeferredDeserialize = 0x00020, // The function represents something that needs to be deserialized on use
DeferredParse = 0x00040, // The function represents something that needs to be parsed on use
CanBeHoisted = 0x00080, // The function return value won't be changed in a loop so the evaluation can be hoisted.
SuperReference = 0x00100,
ClassMethod = 0x00200, // The function is a class method
ClassConstructor = 0x00400, // The function is a class constructor
Lambda = 0x01000,
CapturesThis = 0x02000, // Only lambdas will set this; denotes whether the lambda referred to this, used by debugger
Generator = 0x04000,
BuiltInInlinableAsLdFldInlinee = 0x08000,
Async = 0x10000,
Module = 0x20000, // The function is the function body wrapper for a module
EnclosedByGlobalFunc = 0x40000,
CanDefer = 0x80000,
AllowDirectSuper = 0x100000,
BaseConstructorKind = 0x200000,
Method = 0x400000, // The function is a method
ComputedName = 0x800000,
ActiveScript = 0x1000000,
HomeObj = 0x2000000,
GeneratorWithComplexParams = 0x8000000 // Generator function with non-simple params needs startup yield
};
FunctionInfo(JavascriptMethod entryPoint, Attributes attributes = None, LocalFunctionId functionId = Js::Constants::NoFunctionId, FunctionProxy* functionBodyImpl = nullptr);
FunctionInfo(JavascriptMethod entryPoint, _no_write_barrier_tag, Attributes attributes = None, LocalFunctionId functionId = Js::Constants::NoFunctionId, FunctionProxy* functionBodyImpl = nullptr);
FunctionInfo(FunctionInfo& that); // Todo: (leish)(swb) find a way to prevent non-static initializer calling this ctor
static DWORD GetFunctionBodyImplOffset() { return offsetof(FunctionInfo, functionBodyImpl); }
static BYTE GetOffsetOfFunctionProxy()
{
CompileAssert(offsetof(FunctionInfo, functionBodyImpl) <= UCHAR_MAX);
return offsetof(FunctionInfo, functionBodyImpl);
}
static DWORD GetAttributesOffset() { return offsetof(FunctionInfo, attributes); }
void VerifyOriginalEntryPoint() const;
JavascriptMethod GetOriginalEntryPoint() const;
JavascriptMethod GetOriginalEntryPoint_Unchecked() const;
void SetOriginalEntryPoint(const JavascriptMethod originalEntryPoint);
bool IsAsync() const { return ((this->attributes & Async) != 0); }
bool IsDeferred() const { return ((this->attributes & (DeferredDeserialize | DeferredParse)) != 0); }
static bool IsLambda(Attributes attributes) { return ((attributes & Lambda) != 0); }
bool IsLambda() const { return IsLambda(this->attributes); }
bool IsConstructor() const { return ((this->attributes & ErrorOnNew) == 0); }
static bool IsGenerator(Attributes attributes) { return ((attributes & Generator) != 0); }
bool IsGenerator() const { return IsGenerator(this->attributes); }
bool IsClassConstructor() const { return ((this->attributes & ClassConstructor) != 0); }
bool IsClassMethod() const { return ((this->attributes & ClassMethod) != 0); }
bool IsMethod() const { return ((this->attributes & Method) != 0); }
bool IsModule() const { return ((this->attributes & Module) != 0); }
bool HasSuperReference() const { return ((this->attributes & SuperReference) != 0); }
bool CanBeDeferred() const { return ((this->attributes & CanDefer) != 0); }
static bool IsCoroutine(Attributes attributes) { return ((attributes & (Async | Generator)) != 0); }
bool IsCoroutine() const { return IsCoroutine(this->attributes); }
static bool HasComputedName(Attributes attributes) { return (attributes & Attributes::ComputedName) != 0; }
bool HasComputedName() const { return HasComputedName(this->attributes); }
static bool HasHomeObj(Attributes attributes) { return (attributes & Attributes::HomeObj) != 0; }
bool HasHomeObj() const { return HasHomeObj(this->attributes); }
BOOL HasBody() const { return functionBodyImpl != NULL; }
BOOL HasParseableInfo() const { return this->HasBody() && !this->IsDeferredDeserializeFunction(); }
FunctionProxy * GetFunctionProxy() const
{
return functionBodyImpl;
}
void SetFunctionProxy(FunctionProxy * proxy)
{
functionBodyImpl = proxy;
}
ParseableFunctionInfo* GetParseableFunctionInfo() const
{
Assert(functionBodyImpl == nullptr || !IsDeferredDeserializeFunction());
return (ParseableFunctionInfo*)GetFunctionProxy();
}
void SetParseableFunctionInfo(ParseableFunctionInfo* func)
{
Assert(functionBodyImpl == nullptr || !IsDeferredDeserializeFunction());
SetFunctionProxy((FunctionProxy*)func);
}
DeferDeserializeFunctionInfo* GetDeferDeserializeFunctionInfo() const
{
Assert(functionBodyImpl == nullptr || IsDeferredDeserializeFunction());
return (DeferDeserializeFunctionInfo*)PointerValue(functionBodyImpl);
}
FunctionBody * GetFunctionBody() const;
Attributes GetAttributes() const { return attributes; }
static Attributes GetAttributes(Js::RecyclableObject * function);
void SetAttributes(Attributes attr) { attributes = attr; }
LocalFunctionId GetLocalFunctionId() const { return functionId; }
void SetLocalFunctionId(LocalFunctionId functionId) { this->functionId = functionId; }
uint GetCompileCount() const { return compileCount; }
void SetCompileCount(uint count) { compileCount = count; }
bool IsBuiltInApplyFunction();
bool IsBuiltInCallFunction();
BOOL IsDeferredDeserializeFunction() const { return ((this->attributes & DeferredDeserialize) == DeferredDeserialize); }
BOOL IsDeferredParseFunction() const { return ((this->attributes & DeferredParse) == DeferredParse); }
void SetCapturesThis() { attributes = (Attributes)(attributes | Attributes::CapturesThis); }
bool GetCapturesThis() const { return (attributes & Attributes::CapturesThis) != 0; }
void SetEnclosedByGlobalFunc() { attributes = (Attributes)(attributes | Attributes::EnclosedByGlobalFunc ); }
bool GetEnclosedByGlobalFunc() const { return (attributes & Attributes::EnclosedByGlobalFunc) != 0; }
void SetAllowDirectSuper() { attributes = (Attributes)(attributes | Attributes::AllowDirectSuper); }
bool GetAllowDirectSuper() const { return (attributes & Attributes::AllowDirectSuper) != 0; }
void SetBaseConstructorKind() { attributes = (Attributes)(attributes | Attributes::BaseConstructorKind); }
bool GetBaseConstructorKind() const { return (attributes & Attributes::BaseConstructorKind) != 0; }
bool IsActiveScript() const { return ((this->attributes & Attributes::ActiveScript) != 0); }
void SetIsActiveScript() { attributes = (Attributes)(attributes | Attributes::ActiveScript); }
bool GetGeneratorWithComplexParams() {return (attributes & Attributes::GeneratorWithComplexParams) != 0; }
protected:
FieldNoBarrier(JavascriptMethod) originalEntryPoint;
FieldWithBarrier(FunctionProxy *) functionBodyImpl; // Implementation of the function- null if the function doesn't have a body
Field(LocalFunctionId) functionId; // Per host source context (source file) function Id
Field(uint) compileCount;
Field(Attributes) attributes;
};
// Helper FunctionInfo for builtins that we don't want to profile (script profiler).
class NoProfileFunctionInfo : public FunctionInfo
{
public:
NoProfileFunctionInfo(JavascriptMethod entryPoint)
: FunctionInfo(entryPoint, Attributes::DoNotProfile)
{}
NoProfileFunctionInfo(JavascriptMethod entryPoint, _no_write_barrier_tag)
: FunctionInfo(FORCE_NO_WRITE_BARRIER_TAG(entryPoint), Attributes::DoNotProfile)
{}
};
class AutoDisableRedeferral
{
public:
AutoDisableRedeferral(FunctionInfo * functionInfo) : functionInfo(functionInfo), canDefer(false)
{
if (functionInfo)
{
canDefer = functionInfo->CanBeDeferred();
functionInfo->SetAttributes((FunctionInfo::Attributes)(functionInfo->GetAttributes() & ~FunctionInfo::Attributes::CanDefer));
}
}
~AutoDisableRedeferral()
{
if (functionInfo && canDefer)
{
functionInfo->SetAttributes((FunctionInfo::Attributes)(functionInfo->GetAttributes() | FunctionInfo::Attributes::CanDefer));
}
}
private:
FunctionInfo * functionInfo;
bool canDefer;
};
};