ByteCodeSerializer.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. // Turn this on to enable magic constants in byte code (useful for debugging)
  7. //#define BYTE_CODE_MAGIC_CONSTANTS
  8. #include "ByteCode/ByteCodeSerializeFlags.h"
  9. namespace Js
  10. {
  11. // Some things are obscured by xor. This helps catch cases in which, for example, indirect property ids
  12. // are mistakenly mixed with actual property IDs.
  13. #if DBG & VALIDATE_SERIALIZED_BYTECODE
  14. #define SERIALIZER_OBSCURE_PROPERTY_ID 0xdef00000
  15. #define SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID 0xdeb00000
  16. #define SERIALIZER_OBSCURE_LITERAL_OBJECT_ID 0xded00000
  17. #else
  18. #define SERIALIZER_OBSCURE_PROPERTY_ID 0x00000000
  19. #define SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID 0x00000000
  20. #define SERIALIZER_OBSCURE_LITERAL_OBJECT_ID 0x00000000
  21. #endif
  22. class ByteCodeBufferReader;
  23. enum SerializedAuxiliaryKind : byte
  24. {
  25. sakVarArrayIntCount = 1,
  26. sakVarArrayVarCount = 2,
  27. sakPropertyIdArray = 3,
  28. sakFuncInfoArray = 4,
  29. sakIntArray = 5,
  30. sakFloatArray = 6
  31. };
  32. // Tightly pack serialized structures
  33. #pragma pack(push, 1)
  34. // Describes the kind of auxiliary
  35. struct SerializedAuxiliary
  36. {
  37. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  38. int auxMagic; // magicStartOfAux
  39. #endif
  40. uint offset;
  41. SerializedAuxiliaryKind kind;
  42. SerializedAuxiliary(uint offset, SerializedAuxiliaryKind kind);
  43. };
  44. // The in-memory layout of the serialized analog of VarArray
  45. struct SerializedVarArray : SerializedAuxiliary
  46. {
  47. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  48. int magic; // magicStartOfAuxVarArray
  49. #endif
  50. int varCount;
  51. SerializedVarArray(uint offset, bool isVarCount, int varCount);
  52. };
  53. struct SerializedIntArray : SerializedAuxiliary
  54. {
  55. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  56. int magic; // magicStartOfAuxIntArray
  57. #endif
  58. int intCount;
  59. SerializedIntArray(uint offset, int intCount);
  60. };
  61. struct SerializedFloatArray : SerializedAuxiliary
  62. {
  63. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  64. int magic; // magicStartOfAuxFltArray
  65. #endif
  66. int floatCount;
  67. SerializedFloatArray(uint offset, int floatCount);
  68. };
  69. // The in-memory layout of the serialized analog of PropertyIdArray
  70. struct SerializedPropertyIdArray : SerializedAuxiliary
  71. {
  72. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  73. int magic; // magicStartOfAuxPropIdArray
  74. #endif
  75. int propertyCount;
  76. byte extraSlots;
  77. bool hadDuplicates;
  78. bool has__proto__;
  79. SerializedPropertyIdArray(uint offset, int propertyCount, byte extraSlots, bool hadDuplicates, bool has__proto__);
  80. };
  81. // The in-memory layout of the serialized analog of FuncInfoArray
  82. struct SerializedFuncInfoArray : SerializedAuxiliary
  83. {
  84. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  85. int magic; // magicStartOfAuxFuncInfoArray
  86. #endif
  87. int count;
  88. SerializedFuncInfoArray(uint offset, int count);
  89. };
  90. typedef uint LocalScopeInfoId;
  91. #pragma pack(pop)
  92. // Holds information about the deserialized bytecode cache. Contains fast inline functions
  93. // for the lookup hit case. The slower deserialization of VarArray, etc are in the .cpp.
  94. class ByteCodeCache
  95. {
  96. ByteCodeBufferReader * reader;
  97. const byte * raw;
  98. PropertyId * propertyIds;
  99. int propertyCount;
  100. int builtInPropertyCount;
  101. uint scopeInfoCount;
  102. const byte** scopeInfoRelativeOffsets;
  103. typedef JsUtil::BaseDictionary<Js::LocalFunctionId, FunctionInfo*, ArenaAllocator> LocalFunctionIdToFunctionInfoMap;
  104. LocalFunctionIdToFunctionInfoMap* localFunctionIdToFunctionInfoMap;
  105. typedef JsUtil::BaseDictionary<LocalScopeInfoId, ScopeInfo*, ArenaAllocator> LocalScopeInfoIdToScopeInfoMap;
  106. LocalScopeInfoIdToScopeInfoMap* localScopeInfoIdToScopeInfoMap;
  107. private:
  108. LocalFunctionIdToFunctionInfoMap * EnsureLocalFunctionIdToFunctionInfoMap(ScriptContext * scriptContext);
  109. LocalScopeInfoIdToScopeInfoMap * EnsureLocalScopeInfoIdToScopeInfoMap(ScriptContext * scriptContext);
  110. public:
  111. ByteCodeCache(ScriptContext * scriptContext, int builtInPropertyCount);
  112. ByteCodeCache(ScriptContext * scriptContext, ByteCodeBufferReader * reader, int builtInPropertyCount);
  113. void PopulateLookupPropertyId(ScriptContext * scriptContext, int realArrayOffset);
  114. void SetReader(ScriptContext * scriptContext, ByteCodeBufferReader * reader);
  115. void Initialize(ScriptContext * scriptContext);
  116. void RegisterFunctionIdToFunctionInfo(ScriptContext * scriptContext, LocalFunctionId functionId, FunctionInfo* functionInfo);
  117. FunctionInfo* LookupFunctionInfo(ScriptContext * scriptContext, LocalFunctionId functionId);
  118. ScopeInfo* LookupScopeInfo(ScriptContext * scriptContext, LocalScopeInfoId scopeInfoId);
  119. ByteCodeBufferReader* GetReader()
  120. {
  121. return reader;
  122. }
  123. // Convert a serialized propertyID into a real one.
  124. inline PropertyId LookupPropertyId(PropertyId obscuredIdInCache) const
  125. {
  126. auto unobscured = obscuredIdInCache ^ SERIALIZER_OBSCURE_PROPERTY_ID;
  127. if (unobscured < builtInPropertyCount || unobscured==/*nil*/0xffffffff)
  128. {
  129. return unobscured; // This is a built in property id
  130. }
  131. auto realOffset = unobscured - builtInPropertyCount;
  132. Assert(realOffset<propertyCount);
  133. Assert(propertyIds[realOffset]!=-1);
  134. return propertyIds[realOffset];
  135. }
  136. // Convert a serialized propertyID into a real one.
  137. inline PropertyId LookupNonBuiltinPropertyId(PropertyId obscuredIdInCache) const
  138. {
  139. auto realOffset = obscuredIdInCache ^ SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID;
  140. Assert(realOffset<propertyCount);
  141. Assert(propertyIds[realOffset]!=-1);
  142. return propertyIds[realOffset];
  143. }
  144. // Get the raw byte code buffer.
  145. inline const byte * GetBuffer() const
  146. {
  147. return raw;
  148. }
  149. };
  150. // Methods for serializing and deserializing function bodies.
  151. struct ByteCodeSerializer
  152. {
  153. // Serialize a function body.
  154. static HRESULT SerializeToBuffer(ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD sourceByteLength, LPCUTF8 utf8Source, FunctionBody * function, SRCINFO const* srcInfo, byte ** buffer, DWORD * bufferBytes, DWORD dwFlags = 0);
  155. // Deserialize a function body. The content of utf8Source must be the same as was originally passed to SerializeToBuffer
  156. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, LPCUTF8 utf8Source, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  157. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  158. static FunctionBody* DeserializeFunction(ScriptContext* scriptContext, DeferDeserializeFunctionInfo* deferredFunction);
  159. // Deserialize a string from the string table based on the stringId.
  160. // Note: Returns the count of characters (not bytes) of the string via the stringLength argument.
  161. static LPCWSTR DeserializeString(const DeferredFunctionStub* deferredStub, uint stringId, uint32& stringLength);
  162. // This lib doesn't directly depend on the generated interfaces. Ensure the same codes with a C_ASSERT
  163. static const HRESULT CantGenerate = 0x80020201L;
  164. static const HRESULT InvalidByteCode = 0x80020202L;
  165. static void ReadSourceInfo(const DeferDeserializeFunctionInfo* deferredFunction, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction);
  166. private:
  167. static HRESULT DeserializeFromBufferInternal(ScriptContext * scriptContext, uint32 scriptFlags, LPCUTF8 utf8Source, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  168. };
  169. }