ByteCodeSerializer.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. sakPropertyIdArrayForCachedScope = 7, // serialization only type, indiciate extra slots
  32. };
  33. // Tightly pack serialized structures
  34. #pragma pack(push, 1)
  35. // Describes the kind of auxiliary
  36. struct SerializedAuxiliary
  37. {
  38. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  39. int auxMagic; // magicStartOfAux
  40. #endif
  41. uint offset;
  42. SerializedAuxiliaryKind kind;
  43. SerializedAuxiliary(uint offset, SerializedAuxiliaryKind kind);
  44. };
  45. // The in-memory layout of the serialized analog of VarArray
  46. struct SerializedVarArray : SerializedAuxiliary
  47. {
  48. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  49. int magic; // magicStartOfAuxVarArray
  50. #endif
  51. int varCount;
  52. SerializedVarArray(uint offset, bool isVarCount, int varCount);
  53. };
  54. struct SerializedIntArray : SerializedAuxiliary
  55. {
  56. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  57. int magic; // magicStartOfAuxIntArray
  58. #endif
  59. int intCount;
  60. SerializedIntArray(uint offset, int intCount);
  61. };
  62. struct SerializedFloatArray : SerializedAuxiliary
  63. {
  64. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  65. int magic; // magicStartOfAuxFltArray
  66. #endif
  67. int floatCount;
  68. SerializedFloatArray(uint offset, int floatCount);
  69. };
  70. // The in-memory layout of the serialized analog of PropertyIdArray
  71. struct SerializedPropertyIdArray : SerializedAuxiliary
  72. {
  73. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  74. int magic; // magicStartOfAuxPropIdArray
  75. #endif
  76. int propertyCount;
  77. int extraSlots;
  78. bool hadDuplicates;
  79. bool has__proto__;
  80. SerializedPropertyIdArray(uint offset, int propertyCount, int extraSlots, bool hadDuplicates, bool has__proto__);
  81. };
  82. // The in-memory layout of the serialized analog of FuncInfoArray
  83. struct SerializedFuncInfoArray : SerializedAuxiliary
  84. {
  85. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  86. int magic; // magicStartOfAuxFuncInfoArray
  87. #endif
  88. int count;
  89. SerializedFuncInfoArray(uint offset, int count);
  90. };
  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. public:
  102. ByteCodeCache(ScriptContext * scriptContext, ByteCodeBufferReader * reader, int builtInPropertyCount);
  103. void PopulateLookupPropertyId(ScriptContext * scriptContext, int realArrayOffset);
  104. ByteCodeBufferReader* GetReader()
  105. {
  106. return reader;
  107. }
  108. // Convert a serialized propertyID into a real one.
  109. inline PropertyId LookupPropertyId(PropertyId obscuredIdInCache) const
  110. {
  111. auto unobscured = obscuredIdInCache ^ SERIALIZER_OBSCURE_PROPERTY_ID;
  112. if (unobscured < builtInPropertyCount || unobscured==/*nil*/0xffffffff)
  113. {
  114. return unobscured; // This is a built in property id
  115. }
  116. auto realOffset = unobscured - builtInPropertyCount;
  117. Assert(realOffset<propertyCount);
  118. Assert(propertyIds[realOffset]!=-1);
  119. return propertyIds[realOffset];
  120. }
  121. // Convert a serialized propertyID into a real one.
  122. inline PropertyId LookupNonBuiltinPropertyId(PropertyId obscuredIdInCache) const
  123. {
  124. auto realOffset = obscuredIdInCache ^ SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID;
  125. Assert(realOffset<propertyCount);
  126. Assert(propertyIds[realOffset]!=-1);
  127. return propertyIds[realOffset];
  128. }
  129. // Get the raw byte code buffer.
  130. inline const byte * GetBuffer() const
  131. {
  132. return raw;
  133. }
  134. };
  135. // Methods for serializing and deserializing function bodies.
  136. struct ByteCodeSerializer
  137. {
  138. // Serialize a function body.
  139. static HRESULT SerializeToBuffer(ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD sourceCodeLength, LPCUTF8 utf8Source, DWORD dwFunctionTableLength, BYTE * functionTable, FunctionBody * function, SRCINFO const* srcInfo, bool allocateBuffer, byte ** buffer, DWORD * bufferBytes, DWORD dwFlags = 0);
  140. // Deserialize a function body. The content of utf8Source must be the same as was originally passed to SerializeToBuffer
  141. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, ulong scriptFlags, LPCUTF8 utf8Source, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  142. static HRESULT DeserializeFromBuffer(ScriptContext * scriptContext, ulong scriptFlags, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  143. static FunctionBody* DeserializeFunction(ScriptContext* scriptContext, DeferDeserializeFunctionInfo* deferredFunction);
  144. // This lib doesn't directly depend on the generated interfaces. Ensure the same codes with a C_ASSERT
  145. static const HRESULT CantGenerate = 0x80020201L;
  146. static const HRESULT InvalidByteCode = 0x80020202L;
  147. static void ReadSourceInfo(const DeferDeserializeFunctionInfo* deferredFunction, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction);
  148. private:
  149. static HRESULT DeserializeFromBufferInternal(ScriptContext * scriptContext, ulong scriptFlags, LPCUTF8 utf8Source, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex = Js::Constants::InvalidSourceIndex);
  150. };
  151. }