ArgumentsObject.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. #pragma once
  6. namespace Js
  7. {
  8. class ArgumentsObject : public DynamicObject
  9. {
  10. private:
  11. static PropertyId specialPropertyIds[];
  12. protected:
  13. DEFINE_VTABLE_CTOR_ABSTRACT(ArgumentsObject, DynamicObject);
  14. public:
  15. ArgumentsObject(DynamicType * type) : DynamicObject(type)
  16. {
  17. Assert(type->GetTypeId() == TypeIds_Arguments);
  18. }
  19. static bool Is(Var aValue);
  20. virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  21. virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  22. virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, EnumeratorCache * enumeratorCache = nullptr) override;
  23. virtual uint32 GetNumberOfArguments() const = 0;
  24. virtual uint32 GetNextFormalArgIndex(uint32 index, BOOL enumNonEnumerable = FALSE, PropertyAttributes* attributes = nullptr) const = 0;
  25. virtual Var GetHeapArguments() = 0;
  26. virtual void SetHeapArguments(HeapArgumentsObject *args) = 0;
  27. virtual BOOL AdvanceWalkerToArgsFrame(JavascriptStackWalker *walker) = 0;
  28. };
  29. class ES5HeapArgumentsObject;
  30. // The arguments passed to a function are cached as follows:
  31. // 1) any formal (i.e. named) arguments are copied to the ActivationObject hung off
  32. // a HeapArgumentObject where they can be referenced by name
  33. // 2) any additional actual arguments are stored as an index property on that HeapArgumentObject
  34. //
  35. // See JavascriptOperators::LoadHeapArguments for details of HeapArgumentObject creation.
  36. //
  37. // If a function has named arguments, the array elements of the Arguments object are synonymous for
  38. // the local variables that hold the function arguments. This no longer holds true, however, if an
  39. // array element of the Argument object is deleted.
  40. class HeapArgumentsObject : public ArgumentsObject
  41. {
  42. friend class ::ActiveScriptProfilerHeapEnum;
  43. protected:
  44. DEFINE_VTABLE_CTOR(HeapArgumentsObject, ArgumentsObject);
  45. private:
  46. // We currently support only 2^24 arguments
  47. Field(uint32) numOfArguments:31;
  48. Field(uint32) callerDeleted:1;
  49. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(HeapArgumentsObject);
  50. protected:
  51. Field(uint32) formalCount;
  52. Field(ActivationObject*) frameObject;
  53. Field(BVSparse<Recycler>*) deletedArgs;
  54. public:
  55. HeapArgumentsObject(DynamicType * type);
  56. HeapArgumentsObject(Recycler *recycler, ActivationObject* obj, uint32 formalCount, DynamicType * type);
  57. void SetNumberOfArguments(uint32 len);
  58. static HeapArgumentsObject* As(Var aValue);
  59. BOOL HasItemAt(uint32 index);
  60. virtual BOOL GetItemAt(uint32 index, Var *value, ScriptContext * scriptContext);
  61. virtual BOOL SetItemAt(uint32 index, Var value);
  62. virtual BOOL DeleteItemAt(uint32 index);
  63. virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId, _Inout_opt_ PropertyValueInfo* info) override;
  64. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  65. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  66. virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  67. virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  68. virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  69. virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
  70. virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  71. virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  72. virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
  73. virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
  74. virtual uint32 GetNumberOfArguments() const override;
  75. virtual uint32 GetNextFormalArgIndex(uint32 index, BOOL enumNonEnumerable = FALSE, PropertyAttributes* attributes = nullptr) const override;
  76. virtual Var GetHeapArguments() { return this; }
  77. virtual void SetHeapArguments(HeapArgumentsObject *args)
  78. {
  79. AssertMsg(false, "Should never get here");
  80. }
  81. virtual BOOL AdvanceWalkerToArgsFrame(JavascriptStackWalker *walker) override;
  82. virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
  83. virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
  84. virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
  85. virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None) override;
  86. virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
  87. virtual BOOL PreventExtensions() override;
  88. virtual BOOL Seal() override;
  89. virtual BOOL Freeze() override;
  90. uint32 GetFormalCount() const
  91. {
  92. return this->formalCount;
  93. }
  94. void SetFormalCount(uint32 value)
  95. {
  96. this->formalCount = value;
  97. }
  98. ES5HeapArgumentsObject* ConvertToUnmappedArgumentsObject(bool overwriteArgsUsingFrameObject = true);
  99. const ActivationObject* const GetFrameObject() { return frameObject; }
  100. void SetFrameObject(ActivationObject * value)
  101. {
  102. AssertMsg(frameObject == nullptr, "Setting the frame object again?");
  103. Assert(!value || ActivationObject::Is(value));
  104. frameObject = value;
  105. }
  106. private:
  107. ES5HeapArgumentsObject* ConvertToES5HeapArgumentsObject(bool overwriteArgsUsingFrameObject = true);
  108. protected:
  109. BOOL IsFormalArgument(uint32 index);
  110. BOOL IsFormalArgument(PropertyId propertyId);
  111. BOOL IsFormalArgument(PropertyId propertyId, uint32* pIndex); // Checks whether property is numeric, and on success sets that index.
  112. BOOL IsArgumentDeleted(uint32 index) const;
  113. #if ENABLE_TTD
  114. public:
  115. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
  116. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  117. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  118. template <TTD::NSSnapObjects::SnapObjectType argsKind>
  119. void ExtractSnapObjectDataInto_Helper(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc);
  120. ES5HeapArgumentsObject* ConvertToES5HeapArgumentsObject_TTD();
  121. #endif
  122. };
  123. // ES5 version of the HeapArgumentsObject: support for attributes on formal arguments.
  124. // - Unless the user deals with SetWritable/Enumerable/Configurable/Accessors, regular HeapArgumentsObject is used.
  125. // - When SetWritable/Enumerable/Configurable/Accessors is called, convert HeapArgumentsObject to ES5HeapArgumentsObject by swapping vtable.
  126. // - Override GetItemAt/SetItemAt -- for disconnected items force GetItem/SetItem to use "this" rather than from frameObject.
  127. // - Override GetEnumerator -- take care of enumerable = false arguments.
  128. // - The "disconnect" happens when (as ES5 spec says) setting writable to false and setting accessors.
  129. // Note: This implementation depends on v-table swapping so that HeapArgumentsObject instance can be
  130. // converted to ES5HeapArgumentsObject at runtime when ES5 attribute/getter/setter support is needed.
  131. // Thus, CAUTION: as a result, this class can't add any new instance fields,
  132. // as the size of the instance must be same.
  133. class ES5HeapArgumentsObject : public HeapArgumentsObject
  134. {
  135. friend struct AutoObjectArrayItemExistsValidator;
  136. friend class ES5ArgumentsObjectEnumerator;
  137. // Helper class to make sure that object array item exists for ES5HeapArgumentsObject
  138. // and remove the item to roll back to original state if something fails/throws.
  139. struct AutoObjectArrayItemExistsValidator
  140. {
  141. ES5HeapArgumentsObject* m_args;
  142. bool m_isReleaseItemNeeded;
  143. uint32 m_index;
  144. AutoObjectArrayItemExistsValidator(ES5HeapArgumentsObject* args, uint32 index);
  145. ~AutoObjectArrayItemExistsValidator();
  146. };
  147. private:
  148. DEFINE_VTABLE_CTOR(ES5HeapArgumentsObject, HeapArgumentsObject);
  149. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(ES5HeapArgumentsObject);
  150. uint32 GetNextFormalArgIndexHelper(uint32 index, BOOL enumNonEnumerable, PropertyAttributes* attributes = nullptr) const;
  151. public:
  152. ES5HeapArgumentsObject(Recycler *recycler, ActivationObject* obj, uint32 formalCount, DynamicType * type)
  153. : HeapArgumentsObject(recycler, obj, formalCount, type)
  154. {
  155. }
  156. virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
  157. virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
  158. virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
  159. virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags) override;
  160. virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
  161. virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, EnumeratorCache * enumeratorCache = nullptr) override;
  162. virtual BOOL PreventExtensions() override;
  163. virtual BOOL Seal() override;
  164. virtual BOOL Freeze() override;
  165. virtual uint32 GetNextFormalArgIndex(uint32 index, BOOL enumNonEnumerable = FALSE, PropertyAttributes* attributes = nullptr) const override;
  166. virtual BOOL GetItemAt(uint32 index, Var *value, ScriptContext * scriptContext) override;
  167. virtual BOOL SetItemAt(uint32 index, Var value) override;
  168. virtual BOOL DeleteItemAt(uint32 index) override;
  169. void DisconnectFormalFromNamedArgument(uint32 index);
  170. BOOL IsFormalDisconnectedFromNamedArgument(uint32 index);
  171. BOOL IsEnumerableByIndex(uint32 index);
  172. BOOL SetConfigurableForFormal(uint32 index, PropertyId propertyId, BOOL value);
  173. BOOL SetEnumerableForFormal(uint32 index, PropertyId propertyId, BOOL value);
  174. BOOL SetWritableForFormal(uint32 index, PropertyId propertyId, BOOL value);
  175. BOOL SetAccessorsForFormal(uint32 index, PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None);
  176. BOOL SetPropertyWithAttributesForFormal(uint32 index, PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any);
  177. #if ENABLE_TTD
  178. public:
  179. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  180. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  181. #endif
  182. };
  183. }