ByteCodeSerializer.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #pragma pack(pop)
  91. // Holds information about the deserialized bytecode cache. Contains fast inline functions
  92. // for the lookup hit case. The slower deserialization of VarArray, etc are in the .cpp.
  93. class ByteCodeCache
  94. {
  95. ByteCodeBufferReader * reader;
  96. const byte * raw;
  97. PropertyId * propertyIds;
  98. int propertyCount;
  99. int builtInPropertyCount;
  100. public:
  101. ByteCodeCache(ScriptContext * scriptContext, ByteCodeBufferReader * reader, int builtInPropertyCount);
  102. void PopulateLookupPropertyId(ScriptContext * scriptContext, int realArrayOffset);
  103. ByteCodeBufferReader* GetReader()
  104. {
  105. return reader;
  106. }
  107. // Convert a serialized propertyID into a real one.
  108. inline PropertyId LookupPropertyId(PropertyId obscuredIdInCache) const
  109. {
  110. auto unobscured = obscuredIdInCache ^ SERIALIZER_OBSCURE_PROPERTY_ID;
  111. if (unobscured < builtInPropertyCount || unobscured==/*nil*/0xffffffff)
  112. {
  113. return unobscured; // This is a built in property id
  114. }
  115. auto realOffset = unobscured - builtInPropertyCount;
  116. Assert(realOffset<propertyCount);
  117. Assert(propertyIds[realOffset]!=-1);
  118. return propertyIds[realOffset];
  119. }
  120. // Convert a serialized propertyID into a real one.
  121. inline PropertyId LookupNonBuiltinPropertyId(PropertyId obscuredIdInCache) const
  122. {
  123. auto realOffset = obscuredIdInCache ^ SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID;
  124. Assert(realOffset<propertyCount);
  125. Assert(propertyIds[realOffset]!=-1);
  126. return propertyIds[realOffset];
  127. }
  128. // Get the raw byte code buffer.
  129. inline const byte * GetBuffer() const
  130. {
  131. return raw;
  132. }
  133. };
  134. // Methods for serializing and deserializing function bodies.
  135. struct ByteCodeSerializer
  136. {
  137. // Serialize a function body.
  138. static HRESULT SerializeToBuffer(ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD sourceCodeLength, LPCUTF8 utf8Source, FunctionBody * function, SRCINFO const* srcInfo, bool allocateBuffer, byte ** buffer, DWORD * bufferBytes, DWORD dwFlags = 0);
  139. // Deserialize a function body. The content of utf8Source must be the same as was originally passed to SerializeToBuffer
  140. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, LPCUTF8 utf8Source, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  141. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, uint32 scriptFlags, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, Field(FunctionBody*)* function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  142. static FunctionBody* DeserializeFunction(ScriptContext* scriptContext, DeferDeserializeFunctionInfo* deferredFunction);
  143. // This lib doesn't directly depend on the generated interfaces. Ensure the same codes with a C_ASSERT
  144. static const HRESULT CantGenerate = 0x80020201L;
  145. static const HRESULT InvalidByteCode = 0x80020202L;
  146. static void ReadSourceInfo(const DeferDeserializeFunctionInfo* deferredFunction, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction);
  147. private:
  148. 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);
  149. };
  150. }