SparseArrayValueMap.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (C) 2011, 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. #include "config.h"
  26. #include "SparseArrayValueMap.h"
  27. #include "ClassInfo.h"
  28. #include "GetterSetter.h"
  29. #include "JSObject.h"
  30. #include "Operations.h"
  31. #include "PropertySlot.h"
  32. #include "Reject.h"
  33. #include "SlotVisitor.h"
  34. #include "Structure.h"
  35. namespace JSC {
  36. const ClassInfo SparseArrayValueMap::s_info = { "SparseArrayValueMap", 0, 0, 0, CREATE_METHOD_TABLE(SparseArrayValueMap) };
  37. SparseArrayValueMap::SparseArrayValueMap(VM& vm)
  38. : Base(vm, vm.sparseArrayValueMapStructure.get())
  39. , m_flags(Normal)
  40. , m_reportedCapacity(0)
  41. {
  42. }
  43. SparseArrayValueMap::~SparseArrayValueMap()
  44. {
  45. }
  46. void SparseArrayValueMap::finishCreation(VM& vm)
  47. {
  48. Base::finishCreation(vm);
  49. }
  50. SparseArrayValueMap* SparseArrayValueMap::create(VM& vm)
  51. {
  52. SparseArrayValueMap* result = new (NotNull, allocateCell<SparseArrayValueMap>(vm.heap)) SparseArrayValueMap(vm);
  53. result->finishCreation(vm);
  54. return result;
  55. }
  56. void SparseArrayValueMap::destroy(JSCell* cell)
  57. {
  58. static_cast<SparseArrayValueMap*>(cell)->SparseArrayValueMap::~SparseArrayValueMap();
  59. }
  60. Structure* SparseArrayValueMap::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
  61. {
  62. return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info);
  63. }
  64. SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSObject* array, unsigned i)
  65. {
  66. SparseArrayEntry entry;
  67. entry.setWithoutWriteBarrier(jsUndefined());
  68. AddResult result = m_map.add(i, entry);
  69. size_t capacity = m_map.capacity();
  70. if (capacity != m_reportedCapacity) {
  71. Heap::heap(array)->reportExtraMemoryCost((capacity - m_reportedCapacity) * (sizeof(unsigned) + sizeof(WriteBarrier<Unknown>)));
  72. m_reportedCapacity = capacity;
  73. }
  74. return result;
  75. }
  76. void SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i, JSValue value, bool shouldThrow)
  77. {
  78. AddResult result = add(array, i);
  79. SparseArrayEntry& entry = result.iterator->value;
  80. // To save a separate find & add, we first always add to the sparse map.
  81. // In the uncommon case that this is a new property, and the array is not
  82. // extensible, this is not the right thing to have done - so remove again.
  83. if (result.isNewEntry && !array->isExtensible()) {
  84. remove(result.iterator);
  85. if (shouldThrow)
  86. throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
  87. return;
  88. }
  89. entry.put(exec, array, this, value, shouldThrow);
  90. }
  91. bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
  92. {
  93. AddResult result = add(array, i);
  94. SparseArrayEntry& entry = result.iterator->value;
  95. // To save a separate find & add, we first always add to the sparse map.
  96. // In the uncommon case that this is a new property, and the array is not
  97. // extensible, this is not the right thing to have done - so remove again.
  98. if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isExtensible()) {
  99. remove(result.iterator);
  100. return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
  101. }
  102. entry.attributes = attributes;
  103. entry.set(exec->vm(), this, value);
  104. return true;
  105. }
  106. void SparseArrayEntry::get(PropertySlot& slot) const
  107. {
  108. JSValue value = Base::get();
  109. ASSERT(value);
  110. if (LIKELY(!value.isGetterSetter())) {
  111. slot.setValue(value);
  112. return;
  113. }
  114. JSObject* getter = asGetterSetter(value)->getter();
  115. if (!getter) {
  116. slot.setUndefined();
  117. return;
  118. }
  119. slot.setGetterSlot(getter);
  120. }
  121. void SparseArrayEntry::get(PropertyDescriptor& descriptor) const
  122. {
  123. descriptor.setDescriptor(Base::get(), attributes);
  124. }
  125. JSValue SparseArrayEntry::get(ExecState* exec, JSObject* array) const
  126. {
  127. JSValue result = Base::get();
  128. ASSERT(result);
  129. if (LIKELY(!result.isGetterSetter()))
  130. return result;
  131. JSObject* getter = asGetterSetter(result)->getter();
  132. if (!getter)
  133. return jsUndefined();
  134. CallData callData;
  135. CallType callType = getter->methodTable()->getCallData(getter, callData);
  136. return call(exec, getter, callType, callData, array->methodTable()->toThisObject(array, exec), exec->emptyList());
  137. }
  138. void SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueMap* map, JSValue value, bool shouldThrow)
  139. {
  140. if (!(attributes & Accessor)) {
  141. if (attributes & ReadOnly) {
  142. if (shouldThrow)
  143. throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
  144. return;
  145. }
  146. set(exec->vm(), map, value);
  147. return;
  148. }
  149. JSValue accessor = Base::get();
  150. ASSERT(accessor.isGetterSetter());
  151. JSObject* setter = asGetterSetter(accessor)->setter();
  152. if (!setter) {
  153. if (shouldThrow)
  154. throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
  155. return;
  156. }
  157. CallData callData;
  158. CallType callType = setter->methodTable()->getCallData(setter, callData);
  159. MarkedArgumentBuffer args;
  160. args.append(value);
  161. if (thisValue.isObject())
  162. thisValue = asObject(thisValue)->methodTable()->toThisObject(asObject(thisValue), exec);
  163. call(exec, setter, callType, callData, thisValue, args);
  164. }
  165. JSValue SparseArrayEntry::getNonSparseMode() const
  166. {
  167. ASSERT(!attributes);
  168. return Base::get();
  169. }
  170. void SparseArrayValueMap::visitChildren(JSCell* thisObject, SlotVisitor& visitor)
  171. {
  172. Base::visitChildren(thisObject, visitor);
  173. SparseArrayValueMap* thisMap = jsCast<SparseArrayValueMap*>(thisObject);
  174. iterator end = thisMap->m_map.end();
  175. for (iterator it = thisMap->m_map.begin(); it != end; ++it)
  176. visitor.append(&it->value);
  177. }
  178. } // namespace JSC