StructureInlines.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (C) 2013 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 COMPUTER, 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 COMPUTER, 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 StructureInlines_h
  26. #define StructureInlines_h
  27. #include "PropertyMapHashTable.h"
  28. #include "Structure.h"
  29. namespace JSC {
  30. #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  31. inline Structure* Structure::create(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
  32. {
  33. ASSERT(vm.structureStructure);
  34. ASSERT(classInfo);
  35. Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
  36. structure->finishCreation(vm);
  37. return structure;
  38. }
  39. inline Structure* Structure::createStructure(VM& vm)
  40. {
  41. ASSERT(!vm.structureStructure);
  42. Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm);
  43. structure->finishCreation(vm, CreatingEarlyCell);
  44. return structure;
  45. }
  46. inline Structure* Structure::create(VM& vm, const Structure* structure)
  47. {
  48. ASSERT(vm.structureStructure);
  49. Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
  50. newStructure->finishCreation(vm);
  51. return newStructure;
  52. }
  53. inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
  54. {
  55. ASSERT(structure()->classInfo() == &s_info);
  56. materializePropertyMapIfNecessary(vm);
  57. if (!propertyTable())
  58. return invalidOffset;
  59. PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
  60. return entry ? entry->offset : invalidOffset;
  61. }
  62. inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
  63. {
  64. ASSERT(structure()->classInfo() == &s_info);
  65. materializePropertyMapIfNecessary(vm);
  66. if (!propertyTable())
  67. return invalidOffset;
  68. PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
  69. return entry ? entry->offset : invalidOffset;
  70. }
  71. #endif // #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  72. inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
  73. {
  74. return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
  75. }
  76. #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  77. ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
  78. {
  79. ASSERT(!m_isCheckingForDefaultMarkViolation);
  80. if (!cell)
  81. return;
  82. #if ENABLE(GC_VALIDATION)
  83. validate(cell);
  84. #endif
  85. if (Heap::testAndSetMarked(cell) || !cell->structure())
  86. return;
  87. m_visitCount++;
  88. MARK_LOG_CHILD(*this, cell);
  89. // Should never attempt to mark something that is zapped.
  90. ASSERT(!cell->isZapped());
  91. m_stack.append(cell);
  92. }
  93. inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
  94. {
  95. for (Structure* current = this; current; current = current->previousID()) {
  96. if (current == structureToFind)
  97. return true;
  98. }
  99. return false;
  100. }
  101. inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
  102. {
  103. ASSERT(!isDictionary());
  104. if (!typeInfo().structureHasRareData())
  105. allocateRareData(vm);
  106. rareData()->setEnumerationCache(vm, this, enumerationCache);
  107. }
  108. inline JSPropertyNameIterator* Structure::enumerationCache()
  109. {
  110. if (!typeInfo().structureHasRareData())
  111. return 0;
  112. return rareData()->enumerationCache();
  113. }
  114. #endif // #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  115. inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
  116. {
  117. if (isObject())
  118. return m_prototype.get();
  119. ASSERT(typeInfo().type() == StringType);
  120. return globalObject->stringPrototype();
  121. }
  122. inline JSValue Structure::prototypeForLookup(ExecState* exec) const
  123. {
  124. return prototypeForLookup(exec->lexicalGlobalObject());
  125. }
  126. inline StructureChain* Structure::prototypeChain(VM& vm, JSGlobalObject* globalObject) const
  127. {
  128. // We cache our prototype chain so our clients can share it.
  129. if (!isValid(globalObject, m_cachedPrototypeChain.get())) {
  130. JSValue prototype = prototypeForLookup(globalObject);
  131. m_cachedPrototypeChain.set(vm, this, StructureChain::create(vm, prototype.isNull() ? 0 : asObject(prototype)->structure()));
  132. }
  133. return m_cachedPrototypeChain.get();
  134. }
  135. inline StructureChain* Structure::prototypeChain(ExecState* exec) const
  136. {
  137. return prototypeChain(exec->vm(), exec->lexicalGlobalObject());
  138. }
  139. inline bool Structure::isValid(JSGlobalObject* globalObject, StructureChain* cachedPrototypeChain) const
  140. {
  141. if (!cachedPrototypeChain)
  142. return false;
  143. JSValue prototype = prototypeForLookup(globalObject);
  144. WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
  145. while (*cachedStructure && !prototype.isNull()) {
  146. if (asObject(prototype)->structure() != cachedStructure->get())
  147. return false;
  148. ++cachedStructure;
  149. prototype = asObject(prototype)->prototype();
  150. }
  151. return prototype.isNull() && !*cachedStructure;
  152. }
  153. inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
  154. {
  155. return isValid(exec->lexicalGlobalObject(), cachedPrototypeChain);
  156. }
  157. #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  158. inline bool Structure::putWillGrowOutOfLineStorage()
  159. {
  160. checkOffsetConsistency();
  161. ASSERT(outOfLineCapacity() >= outOfLineSize());
  162. if (!propertyTable()) {
  163. unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
  164. ASSERT(outOfLineCapacity() >= currentSize);
  165. return currentSize == outOfLineCapacity();
  166. }
  167. ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize());
  168. if (propertyTable()->hasDeletedOffset())
  169. return false;
  170. ASSERT(totalStorageCapacity() >= propertyTable()->size());
  171. return propertyTable()->size() == totalStorageCapacity();
  172. }
  173. #endif // #if !(ENABLE(DETACHED_JIT) && BUILDING_DETACHED_JIT)
  174. ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
  175. {
  176. ASSERT(!globalObject() || !globalObject()->vm().heap.isBusy());
  177. return m_propertyTableUnsafe;
  178. }
  179. ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
  180. {
  181. PropertyTable* propertyTable = m_propertyTableUnsafe.get();
  182. if (!propertyTable) {
  183. ASSERT(!m_isPinnedPropertyTable);
  184. return true;
  185. }
  186. RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
  187. unsigned totalSize = propertyTable->propertyStorageSize();
  188. RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
  189. return true;
  190. }
  191. } // namespace JSC
  192. #endif // StructureInlines_h