CompactJITCodeMap.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright (C) 2011 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef CompactJITCodeMap_h
  29. #define CompactJITCodeMap_h
  30. #include <wtf/Assertions.h>
  31. #include <wtf/FastAllocBase.h>
  32. #include <wtf/FastMalloc.h>
  33. #include <wtf/OwnPtr.h>
  34. #include <wtf/PassOwnPtr.h>
  35. #include <wtf/Vector.h>
  36. namespace JSC {
  37. // Gives you a compressed map between between bytecode indices and machine code
  38. // entry points. The compression simply tries to use either 1, 2, or 4 bytes for
  39. // any given offset. The largest offset that can be stored is 2^30.
  40. // Example use:
  41. //
  42. // CompactJITCodeMap::Encoder encoder(map);
  43. // encoder.append(a, b);
  44. // encoder.append(c, d); // preconditions: c >= a, d >= b
  45. // OwnPtr<CompactJITCodeMap> map = encoder.finish();
  46. //
  47. // At some later time:
  48. //
  49. // Vector<BytecodeAndMachineOffset> decoded;
  50. // map->decode(decoded);
  51. struct BytecodeAndMachineOffset {
  52. BytecodeAndMachineOffset() { }
  53. BytecodeAndMachineOffset(unsigned bytecodeIndex, unsigned machineCodeOffset)
  54. : m_bytecodeIndex(bytecodeIndex)
  55. , m_machineCodeOffset(machineCodeOffset)
  56. {
  57. }
  58. unsigned m_bytecodeIndex;
  59. unsigned m_machineCodeOffset;
  60. static inline unsigned getBytecodeIndex(BytecodeAndMachineOffset* mapping)
  61. {
  62. return mapping->m_bytecodeIndex;
  63. }
  64. static inline unsigned getMachineCodeOffset(BytecodeAndMachineOffset* mapping)
  65. {
  66. return mapping->m_machineCodeOffset;
  67. }
  68. };
  69. class CompactJITCodeMap {
  70. #if ENABLE(DETACHED_JIT)
  71. DETACHED_JIT_MAKE_SHARED_DATA_ALLOCATED;
  72. #else
  73. WTF_MAKE_FAST_ALLOCATED;
  74. #endif
  75. public:
  76. ~CompactJITCodeMap()
  77. {
  78. if (m_buffer) {
  79. #if ENABLE(DETACHED_JIT)
  80. JITSharedDataMemory::shared_free(m_buffer);
  81. #else
  82. fastFree(m_buffer);
  83. #endif
  84. }
  85. }
  86. unsigned numberOfEntries() const
  87. {
  88. return m_numberOfEntries;
  89. }
  90. void decode(Vector<BytecodeAndMachineOffset>& result) const;
  91. private:
  92. CompactJITCodeMap(uint8_t* buffer, unsigned size, unsigned numberOfEntries)
  93. : m_buffer(buffer)
  94. #if !ASSERT_DISABLED
  95. , m_size(size)
  96. #endif
  97. , m_numberOfEntries(numberOfEntries)
  98. {
  99. UNUSED_PARAM(size);
  100. }
  101. uint8_t at(unsigned index) const
  102. {
  103. ASSERT(index < m_size);
  104. return m_buffer[index];
  105. }
  106. unsigned decodeNumber(unsigned& index) const
  107. {
  108. uint8_t headValue = at(index++);
  109. if (!(headValue & 128))
  110. return headValue;
  111. if (!(headValue & 64))
  112. return (static_cast<unsigned>(headValue & ~128) << 8) | at(index++);
  113. unsigned second = at(index++);
  114. unsigned third = at(index++);
  115. unsigned fourth = at(index++);
  116. return (static_cast<unsigned>(headValue & ~(128 + 64)) << 24) | (second << 16) | (third << 8) | fourth;
  117. }
  118. uint8_t* m_buffer;
  119. #if !ASSERT_DISABLED
  120. unsigned m_size;
  121. #endif
  122. unsigned m_numberOfEntries;
  123. public:
  124. class Encoder {
  125. WTF_MAKE_NONCOPYABLE(Encoder);
  126. public:
  127. Encoder();
  128. ~Encoder();
  129. void ensureCapacityFor(unsigned numberOfEntriesToAdd);
  130. void append(unsigned bytecodeIndex, unsigned machineCodeOffset);
  131. PassOwnPtr<CompactJITCodeMap> finish();
  132. private:
  133. void appendByte(uint8_t value);
  134. void encodeNumber(uint32_t value);
  135. uint8_t* m_buffer;
  136. unsigned m_size;
  137. unsigned m_capacity;
  138. unsigned m_numberOfEntries;
  139. unsigned m_previousBytecodeIndex;
  140. unsigned m_previousMachineCodeOffset;
  141. };
  142. class Decoder {
  143. WTF_MAKE_NONCOPYABLE(Decoder);
  144. public:
  145. Decoder(const CompactJITCodeMap*);
  146. unsigned numberOfEntriesRemaining() const;
  147. void read(unsigned& bytecodeIndex, unsigned& machineCodeOffset);
  148. private:
  149. const CompactJITCodeMap* m_jitCodeMap;
  150. unsigned m_previousBytecodeIndex;
  151. unsigned m_previousMachineCodeOffset;
  152. unsigned m_numberOfEntriesRemaining;
  153. unsigned m_bufferIndex;
  154. };
  155. private:
  156. friend class Encoder;
  157. friend class Decoder;
  158. };
  159. inline void CompactJITCodeMap::decode(Vector<BytecodeAndMachineOffset>& result) const
  160. {
  161. Decoder decoder(this);
  162. result.resize(decoder.numberOfEntriesRemaining());
  163. for (unsigned i = 0; i < result.size(); ++i)
  164. decoder.read(result[i].m_bytecodeIndex, result[i].m_machineCodeOffset);
  165. ASSERT(!decoder.numberOfEntriesRemaining());
  166. }
  167. inline CompactJITCodeMap::Encoder::Encoder()
  168. : m_buffer(0)
  169. , m_size(0)
  170. , m_capacity(0)
  171. , m_numberOfEntries(0)
  172. , m_previousBytecodeIndex(0)
  173. , m_previousMachineCodeOffset(0)
  174. {
  175. }
  176. inline CompactJITCodeMap::Encoder::~Encoder()
  177. {
  178. if (m_buffer) {
  179. #if ENABLE(DETACHED_JIT)
  180. JITSharedDataMemory::shared_free(m_buffer);
  181. #else
  182. fastFree(m_buffer);
  183. #endif
  184. }
  185. }
  186. inline void CompactJITCodeMap::Encoder::append(unsigned bytecodeIndex, unsigned machineCodeOffset)
  187. {
  188. ASSERT(bytecodeIndex >= m_previousBytecodeIndex);
  189. ASSERT(machineCodeOffset >= m_previousMachineCodeOffset);
  190. ensureCapacityFor(1);
  191. encodeNumber(bytecodeIndex - m_previousBytecodeIndex);
  192. encodeNumber(machineCodeOffset - m_previousMachineCodeOffset);
  193. m_previousBytecodeIndex = bytecodeIndex;
  194. m_previousMachineCodeOffset = machineCodeOffset;
  195. m_numberOfEntries++;
  196. }
  197. inline PassOwnPtr<CompactJITCodeMap> CompactJITCodeMap::Encoder::finish()
  198. {
  199. m_capacity = m_size;
  200. m_buffer = static_cast<uint8_t*>(
  201. #if ENABLE(DETACHED_JIT)
  202. JITSharedDataMemory::shared_realloc(m_buffer, m_capacity)
  203. #else
  204. fastRealloc(m_buffer, m_capacity)
  205. #endif
  206. );
  207. OwnPtr<CompactJITCodeMap> result = adoptPtr(new CompactJITCodeMap(m_buffer, m_size, m_numberOfEntries));
  208. m_buffer = 0;
  209. m_size = 0;
  210. m_capacity = 0;
  211. m_numberOfEntries = 0;
  212. m_previousBytecodeIndex = 0;
  213. m_previousMachineCodeOffset = 0;
  214. return result.release();
  215. }
  216. inline void CompactJITCodeMap::Encoder::appendByte(uint8_t value)
  217. {
  218. ASSERT(m_size + 1 <= m_capacity);
  219. m_buffer[m_size++] = value;
  220. }
  221. inline void CompactJITCodeMap::Encoder::encodeNumber(uint32_t value)
  222. {
  223. ASSERT(m_size + 4 <= m_capacity);
  224. ASSERT(value < (1 << 30));
  225. if (value <= 127) {
  226. uint8_t headValue = static_cast<uint8_t>(value);
  227. ASSERT(!(headValue & 128));
  228. appendByte(headValue);
  229. } else if (value <= 16383) {
  230. uint8_t headValue = static_cast<uint8_t>(value >> 8);
  231. ASSERT(!(headValue & 128));
  232. ASSERT(!(headValue & 64));
  233. appendByte(headValue | 128);
  234. appendByte(static_cast<uint8_t>(value));
  235. } else {
  236. uint8_t headValue = static_cast<uint8_t>(value >> 24);
  237. ASSERT(!(headValue & 128));
  238. ASSERT(!(headValue & 64));
  239. appendByte(headValue | 128 | 64);
  240. appendByte(static_cast<uint8_t>(value >> 16));
  241. appendByte(static_cast<uint8_t>(value >> 8));
  242. appendByte(static_cast<uint8_t>(value));
  243. }
  244. }
  245. inline void CompactJITCodeMap::Encoder::ensureCapacityFor(unsigned numberOfEntriesToAdd)
  246. {
  247. unsigned capacityNeeded = m_size + numberOfEntriesToAdd * 2 * 4;
  248. if (capacityNeeded > m_capacity) {
  249. m_capacity = capacityNeeded * 2;
  250. m_buffer = static_cast<uint8_t*>(
  251. #if ENABLE(DETACHED_JIT)
  252. JITSharedDataMemory::shared_realloc(m_buffer, m_capacity)
  253. #else
  254. fastRealloc(m_buffer, m_capacity)
  255. #endif
  256. );
  257. }
  258. }
  259. inline CompactJITCodeMap::Decoder::Decoder(const CompactJITCodeMap* jitCodeMap)
  260. : m_jitCodeMap(jitCodeMap)
  261. , m_previousBytecodeIndex(0)
  262. , m_previousMachineCodeOffset(0)
  263. , m_numberOfEntriesRemaining(jitCodeMap->m_numberOfEntries)
  264. , m_bufferIndex(0)
  265. {
  266. }
  267. inline unsigned CompactJITCodeMap::Decoder::numberOfEntriesRemaining() const
  268. {
  269. ASSERT(m_numberOfEntriesRemaining || m_bufferIndex == m_jitCodeMap->m_size);
  270. return m_numberOfEntriesRemaining;
  271. }
  272. inline void CompactJITCodeMap::Decoder::read(unsigned& bytecodeIndex, unsigned& machineCodeOffset)
  273. {
  274. ASSERT(numberOfEntriesRemaining());
  275. m_previousBytecodeIndex += m_jitCodeMap->decodeNumber(m_bufferIndex);
  276. m_previousMachineCodeOffset += m_jitCodeMap->decodeNumber(m_bufferIndex);
  277. bytecodeIndex = m_previousBytecodeIndex;
  278. machineCodeOffset = m_previousMachineCodeOffset;
  279. m_numberOfEntriesRemaining--;
  280. }
  281. } // namespace JSC
  282. #endif // CompactJITCodeMap_h