Butterfly.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (C) 2012 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. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef Butterfly_h
  26. #define Butterfly_h
  27. #include "IndexingHeader.h"
  28. #include "PropertyOffset.h"
  29. #include "PropertyStorage.h"
  30. #include <wtf/Noncopyable.h>
  31. #include <wtf/Platform.h>
  32. namespace JSC {
  33. class VM;
  34. class CopyVisitor;
  35. struct ArrayStorage;
  36. template <typename T> struct ContiguousData {
  37. ContiguousData()
  38. : m_data(0)
  39. #if !ASSERT_DISABLED
  40. , m_length(0)
  41. #endif
  42. {
  43. }
  44. ContiguousData(T* data, size_t length)
  45. : m_data(data)
  46. #if !ASSERT_DISABLED
  47. , m_length(length)
  48. #endif
  49. {
  50. UNUSED_PARAM(length);
  51. }
  52. const T& operator[](size_t index) const { ASSERT(index < m_length); return m_data[index]; }
  53. T& operator[](size_t index) { ASSERT(index < m_length); return m_data[index]; }
  54. T* data() const { return m_data; }
  55. #if !ASSERT_DISABLED
  56. size_t length() const { return m_length; }
  57. #endif
  58. private:
  59. T* m_data;
  60. #if !ASSERT_DISABLED
  61. size_t m_length;
  62. #endif
  63. };
  64. typedef ContiguousData<double> ContiguousDoubles;
  65. typedef ContiguousData<WriteBarrier<Unknown> > ContiguousJSValues;
  66. class Butterfly {
  67. WTF_MAKE_NONCOPYABLE(Butterfly);
  68. private:
  69. Butterfly() { } // Not instantiable.
  70. public:
  71. static size_t totalSize(size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
  72. {
  73. ASSERT(indexingPayloadSizeInBytes ? hasIndexingHeader : true);
  74. ASSERT(sizeof(EncodedJSValue) == sizeof(IndexingHeader));
  75. return (preCapacity + propertyCapacity) * sizeof(EncodedJSValue) + (hasIndexingHeader ? sizeof(IndexingHeader) : 0) + indexingPayloadSizeInBytes;
  76. }
  77. static Butterfly* fromBase(void* base, size_t preCapacity, size_t propertyCapacity)
  78. {
  79. return reinterpret_cast<Butterfly*>(static_cast<EncodedJSValue*>(base) + preCapacity + propertyCapacity + 1);
  80. }
  81. // This method is here not just because it's handy, but to remind you that
  82. // the whole point of butterflies is to do evil pointer arithmetic.
  83. static Butterfly* fromPointer(char* ptr)
  84. {
  85. return reinterpret_cast<Butterfly*>(ptr);
  86. }
  87. char* pointer() { return reinterpret_cast<char*>(this); }
  88. static ptrdiff_t offsetOfIndexingHeader() { return IndexingHeader::offsetOfIndexingHeader(); }
  89. static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); }
  90. static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); }
  91. static Butterfly* createUninitialized(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes);
  92. static Butterfly* create(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes);
  93. static Butterfly* create(VM&, Structure*);
  94. static Butterfly* createUninitializedDuringCollection(CopyVisitor&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes);
  95. IndexingHeader* indexingHeader() { return IndexingHeader::from(this); }
  96. const IndexingHeader* indexingHeader() const { return IndexingHeader::from(this); }
  97. PropertyStorage propertyStorage() { return indexingHeader()->propertyStorage(); }
  98. ConstPropertyStorage propertyStorage() const { return indexingHeader()->propertyStorage(); }
  99. uint32_t publicLength() { return indexingHeader()->publicLength(); }
  100. uint32_t vectorLength() { return indexingHeader()->vectorLength(); }
  101. void setPublicLength(uint32_t value) { indexingHeader()->setPublicLength(value); }
  102. void setVectorLength(uint32_t value) { indexingHeader()->setVectorLength(value); }
  103. template<typename T>
  104. T* indexingPayload() { return reinterpret_cast_ptr<T*>(this); }
  105. ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); }
  106. ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
  107. ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload<double>(), vectorLength()); }
  108. ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
  109. static Butterfly* fromContiguous(WriteBarrier<Unknown>* contiguous)
  110. {
  111. return reinterpret_cast<Butterfly*>(contiguous);
  112. }
  113. static Butterfly* fromContiguous(double* contiguous)
  114. {
  115. return reinterpret_cast<Butterfly*>(contiguous);
  116. }
  117. static ptrdiff_t offsetOfPropertyStorage() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
  118. static int indexOfPropertyStorage()
  119. {
  120. ASSERT(sizeof(IndexingHeader) == sizeof(EncodedJSValue));
  121. return -1;
  122. }
  123. void* base(size_t preCapacity, size_t propertyCapacity) { return propertyStorage() - propertyCapacity - preCapacity; }
  124. void* base(Structure*);
  125. static Butterfly* createOrGrowArrayRight(Butterfly*, VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes);
  126. // The butterfly reallocation methods perform the reallocation itself but do not change any
  127. // of the meta-data to reflect that the reallocation occurred. Note that this set of
  128. // methods is not exhaustive and is not intended to encapsulate all possible allocation
  129. // modes of butterflies - there are code paths that allocate butterflies by calling
  130. // directly into Heap::tryAllocateStorage.
  131. Butterfly* growPropertyStorage(VM&, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity);
  132. Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t oldPropertyCapacity, size_t newPropertyCapacity);
  133. Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t newPropertyCapacity);
  134. Butterfly* growArrayRight(VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much.
  135. Butterfly* growArrayRight(VM&, Structure*, size_t newIndexingPayloadSizeInBytes);
  136. Butterfly* resizeArray(VM&, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes);
  137. Butterfly* resizeArray(VM&, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header.
  138. Butterfly* unshift(Structure*, size_t numberOfSlots);
  139. Butterfly* shift(Structure*, size_t numberOfSlots);
  140. };
  141. } // namespace JSC
  142. #endif // Butterfly_h