FunctionInfo.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. namespace Js
  6. {
  7. class FunctionProxy;
  8. class FunctionBody;
  9. class ParseableFunctionInfo;
  10. class DeferDeserializeFunctionInfo;
  11. class FunctionInfo
  12. {
  13. friend class RemoteFunctionBody;
  14. public:
  15. enum Attributes : uint32
  16. {
  17. None = 0x00000,
  18. ErrorOnNew = 0x00001,
  19. SkipDefaultNewObject = 0x00002,
  20. DoNotProfile = 0x00004,
  21. HasNoSideEffect = 0x00008, // calling function doesn't cause an implicit flags to be set,
  22. // the callee will detect and set implicit flags on its individual operations
  23. NeedCrossSiteSecurityCheck = 0x00010,
  24. DeferredDeserialize = 0x00020, // The function represents something that needs to be deserialized on use
  25. DeferredParse = 0x00040, // The function represents something that needs to be parsed on use
  26. CanBeHoisted = 0x00080, // The function return value won't be changed in a loop so the evaluation can be hoisted.
  27. SuperReference = 0x00100,
  28. ClassMethod = 0x00200, // The function is a class method
  29. ClassConstructor = 0x00400, // The function is a class constructor
  30. Lambda = 0x01000,
  31. CapturesThis = 0x02000, // Only lambdas will set this; denotes whether the lambda referred to this, used by debugger
  32. Generator = 0x04000,
  33. BuiltInInlinableAsLdFldInlinee = 0x08000,
  34. Async = 0x10000,
  35. Module = 0x20000, // The function is the function body wrapper for a module
  36. EnclosedByGlobalFunc = 0x40000,
  37. CanDefer = 0x80000,
  38. AllowDirectSuper = 0x100000,
  39. BaseConstructorKind = 0x200000,
  40. Method = 0x400000, // The function is a method
  41. ComputedName = 0x800000,
  42. ActiveScript = 0x1000000,
  43. HomeObj = 0x2000000
  44. };
  45. FunctionInfo(JavascriptMethod entryPoint, Attributes attributes = None, LocalFunctionId functionId = Js::Constants::NoFunctionId, FunctionProxy* functionBodyImpl = nullptr);
  46. FunctionInfo(JavascriptMethod entryPoint, _no_write_barrier_tag, Attributes attributes = None, LocalFunctionId functionId = Js::Constants::NoFunctionId, FunctionProxy* functionBodyImpl = nullptr);
  47. FunctionInfo(FunctionInfo& that); // Todo: (leish)(swb) find a way to prevent non-static initializer calling this ctor
  48. static DWORD GetFunctionBodyImplOffset() { return offsetof(FunctionInfo, functionBodyImpl); }
  49. static BYTE GetOffsetOfFunctionProxy()
  50. {
  51. CompileAssert(offsetof(FunctionInfo, functionBodyImpl) <= UCHAR_MAX);
  52. return offsetof(FunctionInfo, functionBodyImpl);
  53. }
  54. static DWORD GetAttributesOffset() { return offsetof(FunctionInfo, attributes); }
  55. void VerifyOriginalEntryPoint() const;
  56. JavascriptMethod GetOriginalEntryPoint() const;
  57. JavascriptMethod GetOriginalEntryPoint_Unchecked() const;
  58. void SetOriginalEntryPoint(const JavascriptMethod originalEntryPoint);
  59. bool IsAsync() const { return ((this->attributes & Async) != 0); }
  60. bool IsDeferred() const { return ((this->attributes & (DeferredDeserialize | DeferredParse)) != 0); }
  61. static bool IsLambda(Attributes attributes) { return ((attributes & Lambda) != 0); }
  62. bool IsLambda() const { return IsLambda(this->attributes); }
  63. bool IsConstructor() const { return ((this->attributes & ErrorOnNew) == 0); }
  64. static bool IsGenerator(Attributes attributes) { return ((attributes & Generator) != 0); }
  65. bool IsGenerator() const { return IsGenerator(this->attributes); }
  66. bool IsClassConstructor() const { return ((this->attributes & ClassConstructor) != 0); }
  67. bool IsClassMethod() const { return ((this->attributes & ClassMethod) != 0); }
  68. bool IsMethod() const { return ((this->attributes & Method) != 0); }
  69. bool IsModule() const { return ((this->attributes & Module) != 0); }
  70. bool HasSuperReference() const { return ((this->attributes & SuperReference) != 0); }
  71. bool CanBeDeferred() const { return ((this->attributes & CanDefer) != 0); }
  72. static bool IsCoroutine(Attributes attributes) { return ((attributes & (Async | Generator)) != 0); }
  73. bool IsCoroutine() const { return IsCoroutine(this->attributes); }
  74. static bool HasComputedName(Attributes attributes) { return (attributes & Attributes::ComputedName) != 0; }
  75. bool HasComputedName() const { return HasComputedName(this->attributes); }
  76. static bool HasHomeObj(Attributes attributes) { return (attributes & Attributes::HomeObj) != 0; }
  77. bool HasHomeObj() const { return HasHomeObj(this->attributes); }
  78. BOOL HasBody() const { return functionBodyImpl != NULL; }
  79. BOOL HasParseableInfo() const { return this->HasBody() && !this->IsDeferredDeserializeFunction(); }
  80. FunctionProxy * GetFunctionProxy() const
  81. {
  82. return functionBodyImpl;
  83. }
  84. void SetFunctionProxy(FunctionProxy * proxy)
  85. {
  86. functionBodyImpl = proxy;
  87. }
  88. ParseableFunctionInfo* GetParseableFunctionInfo() const
  89. {
  90. Assert(functionBodyImpl == nullptr || !IsDeferredDeserializeFunction());
  91. return (ParseableFunctionInfo*)GetFunctionProxy();
  92. }
  93. void SetParseableFunctionInfo(ParseableFunctionInfo* func)
  94. {
  95. Assert(functionBodyImpl == nullptr || !IsDeferredDeserializeFunction());
  96. SetFunctionProxy((FunctionProxy*)func);
  97. }
  98. DeferDeserializeFunctionInfo* GetDeferDeserializeFunctionInfo() const
  99. {
  100. Assert(functionBodyImpl == nullptr || IsDeferredDeserializeFunction());
  101. return (DeferDeserializeFunctionInfo*)PointerValue(functionBodyImpl);
  102. }
  103. FunctionBody * GetFunctionBody() const;
  104. Attributes GetAttributes() const { return attributes; }
  105. static Attributes GetAttributes(Js::RecyclableObject * function);
  106. void SetAttributes(Attributes attr) { attributes = attr; }
  107. LocalFunctionId GetLocalFunctionId() const { return functionId; }
  108. void SetLocalFunctionId(LocalFunctionId functionId) { this->functionId = functionId; }
  109. uint GetCompileCount() const { return compileCount; }
  110. void SetCompileCount(uint count) { compileCount = count; }
  111. BOOL IsDeferredDeserializeFunction() const { return ((this->attributes & DeferredDeserialize) == DeferredDeserialize); }
  112. BOOL IsDeferredParseFunction() const { return ((this->attributes & DeferredParse) == DeferredParse); }
  113. void SetCapturesThis() { attributes = (Attributes)(attributes | Attributes::CapturesThis); }
  114. bool GetCapturesThis() const { return (attributes & Attributes::CapturesThis) != 0; }
  115. void SetEnclosedByGlobalFunc() { attributes = (Attributes)(attributes | Attributes::EnclosedByGlobalFunc ); }
  116. bool GetEnclosedByGlobalFunc() const { return (attributes & Attributes::EnclosedByGlobalFunc) != 0; }
  117. void SetAllowDirectSuper() { attributes = (Attributes)(attributes | Attributes::AllowDirectSuper); }
  118. bool GetAllowDirectSuper() const { return (attributes & Attributes::AllowDirectSuper) != 0; }
  119. void SetBaseConstructorKind() { attributes = (Attributes)(attributes | Attributes::BaseConstructorKind); }
  120. bool GetBaseConstructorKind() const { return (attributes & Attributes::BaseConstructorKind) != 0; }
  121. bool IsActiveScript() const { return ((this->attributes & Attributes::ActiveScript) != 0); }
  122. void SetIsActiveScript() { attributes = (Attributes)(attributes | Attributes::ActiveScript); }
  123. protected:
  124. FieldNoBarrier(JavascriptMethod) originalEntryPoint;
  125. FieldWithBarrier(FunctionProxy *) functionBodyImpl; // Implementation of the function- null if the function doesn't have a body
  126. Field(LocalFunctionId) functionId; // Per host source context (source file) function Id
  127. Field(uint) compileCount;
  128. Field(Attributes) attributes;
  129. };
  130. // Helper FunctionInfo for builtins that we don't want to profile (script profiler).
  131. class NoProfileFunctionInfo : public FunctionInfo
  132. {
  133. public:
  134. NoProfileFunctionInfo(JavascriptMethod entryPoint)
  135. : FunctionInfo(entryPoint, Attributes::DoNotProfile)
  136. {}
  137. NoProfileFunctionInfo(JavascriptMethod entryPoint, _no_write_barrier_tag)
  138. : FunctionInfo(FORCE_NO_WRITE_BARRIER_TAG(entryPoint), Attributes::DoNotProfile)
  139. {}
  140. };
  141. class AutoDisableRedeferral
  142. {
  143. public:
  144. AutoDisableRedeferral(FunctionInfo * functionInfo) : functionInfo(functionInfo), canDefer(false)
  145. {
  146. if (functionInfo)
  147. {
  148. canDefer = functionInfo->CanBeDeferred();
  149. functionInfo->SetAttributes((FunctionInfo::Attributes)(functionInfo->GetAttributes() & ~FunctionInfo::Attributes::CanDefer));
  150. }
  151. }
  152. ~AutoDisableRedeferral()
  153. {
  154. if (functionInfo && canDefer)
  155. {
  156. functionInfo->SetAttributes((FunctionInfo::Attributes)(functionInfo->GetAttributes() | FunctionInfo::Attributes::CanDefer));
  157. }
  158. }
  159. private:
  160. FunctionInfo * functionInfo;
  161. bool canDefer;
  162. };
  163. };