OLD | NEW |
(Empty) | |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #include "v8.h" |
| 29 |
| 30 #include "objects.h" |
| 31 #include "elements.h" |
| 32 |
| 33 namespace v8 { |
| 34 namespace internal { |
| 35 |
| 36 |
| 37 ElementsAccessor** ElementsAccessor::elements_accessors_; |
| 38 |
| 39 |
| 40 // Base class for element handler implementations. Contains the |
| 41 // the common logic for objects with different ElementsKinds. |
| 42 // Subclasses must specialize method for which the element |
| 43 // implementation differs from the base class implementation. |
| 44 // |
| 45 // This class is intended to be used in the following way: |
| 46 // |
| 47 // class SomeElementsAccessor : |
| 48 // public ElementsAccessorBase<SomeElementsAccessor, |
| 49 // BackingStoreClass> { |
| 50 // ... |
| 51 // } |
| 52 // |
| 53 // This is an example of the Curiously Recurring Template Pattern (see |
| 54 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
| 55 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
| 56 // specialization of SomeElementsAccessor methods). |
| 57 template <typename ElementsAccessorSubclass, typename BackingStoreClass> |
| 58 class ElementsAccessorBase : public ElementsAccessor { |
| 59 public: |
| 60 ElementsAccessorBase() { } |
| 61 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 62 Object* receiver, |
| 63 uint32_t index) { |
| 64 if (index < ElementsAccessorSubclass::GetLength(obj)) { |
| 65 BackingStoreClass* backing_store = |
| 66 ElementsAccessorSubclass::GetBackingStore(obj); |
| 67 return backing_store->get(index); |
| 68 } |
| 69 return obj->GetHeap()->the_hole_value(); |
| 70 } |
| 71 |
| 72 protected: |
| 73 static BackingStoreClass* GetBackingStore(JSObject* obj) { |
| 74 return BackingStoreClass::cast(obj->elements()); |
| 75 } |
| 76 |
| 77 static uint32_t GetLength(JSObject* obj) { |
| 78 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); |
| 79 } |
| 80 |
| 81 private: |
| 82 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 83 }; |
| 84 |
| 85 |
| 86 class FastElementsAccessor |
| 87 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { |
| 88 }; |
| 89 |
| 90 |
| 91 class FastDoubleElementsAccessor |
| 92 : public ElementsAccessorBase<FastDoubleElementsAccessor, |
| 93 FixedDoubleArray> { |
| 94 }; |
| 95 |
| 96 |
| 97 // Super class for all external element arrays. |
| 98 template<typename ExternalElementsAccessorSubclass, |
| 99 typename ExternalArray> |
| 100 class ExternalElementsAccessor |
| 101 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 102 ExternalArray> { |
| 103 public: |
| 104 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 105 Object* receiver, |
| 106 uint32_t index) { |
| 107 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) { |
| 108 ExternalArray* backing_store = |
| 109 ExternalElementsAccessorSubclass::GetBackingStore(obj); |
| 110 return backing_store->get(index); |
| 111 } else { |
| 112 return obj->GetHeap()->undefined_value(); |
| 113 } |
| 114 } |
| 115 }; |
| 116 |
| 117 |
| 118 class ExternalByteElementsAccessor |
| 119 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
| 120 ExternalByteArray> { |
| 121 }; |
| 122 |
| 123 |
| 124 class ExternalUnsignedByteElementsAccessor |
| 125 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, |
| 126 ExternalUnsignedByteArray> { |
| 127 }; |
| 128 |
| 129 |
| 130 class ExternalShortElementsAccessor |
| 131 : public ExternalElementsAccessor<ExternalShortElementsAccessor, |
| 132 ExternalShortArray> { |
| 133 }; |
| 134 |
| 135 |
| 136 class ExternalUnsignedShortElementsAccessor |
| 137 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, |
| 138 ExternalUnsignedShortArray> { |
| 139 }; |
| 140 |
| 141 |
| 142 class ExternalIntElementsAccessor |
| 143 : public ExternalElementsAccessor<ExternalIntElementsAccessor, |
| 144 ExternalIntArray> { |
| 145 }; |
| 146 |
| 147 |
| 148 class ExternalUnsignedIntElementsAccessor |
| 149 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, |
| 150 ExternalUnsignedIntArray> { |
| 151 }; |
| 152 |
| 153 |
| 154 class ExternalFloatElementsAccessor |
| 155 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, |
| 156 ExternalFloatArray> { |
| 157 }; |
| 158 |
| 159 |
| 160 class ExternalDoubleElementsAccessor |
| 161 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, |
| 162 ExternalDoubleArray> { |
| 163 }; |
| 164 |
| 165 |
| 166 class PixelElementsAccessor |
| 167 : public ExternalElementsAccessor<PixelElementsAccessor, |
| 168 ExternalPixelArray> { |
| 169 }; |
| 170 |
| 171 |
| 172 class DictionaryElementsAccessor |
| 173 : public ElementsAccessorBase<DictionaryElementsAccessor, |
| 174 NumberDictionary> { |
| 175 public: |
| 176 static MaybeObject* GetNumberDictionaryElement( |
| 177 JSObject* obj, |
| 178 Object* receiver, |
| 179 NumberDictionary* backing_store, |
| 180 uint32_t index) { |
| 181 int entry = backing_store->FindEntry(index); |
| 182 if (entry != NumberDictionary::kNotFound) { |
| 183 Object* element = backing_store->ValueAt(entry); |
| 184 PropertyDetails details = backing_store->DetailsAt(entry); |
| 185 if (details.type() == CALLBACKS) { |
| 186 return obj->GetElementWithCallback(receiver, |
| 187 element, |
| 188 index, |
| 189 obj); |
| 190 } else { |
| 191 return element; |
| 192 } |
| 193 } |
| 194 return obj->GetHeap()->the_hole_value(); |
| 195 } |
| 196 |
| 197 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 198 Object* receiver, |
| 199 uint32_t index) { |
| 200 return GetNumberDictionaryElement(obj, |
| 201 receiver, |
| 202 obj->element_dictionary(), |
| 203 index); |
| 204 } |
| 205 }; |
| 206 |
| 207 |
| 208 class NonStrictArgumentsElementsAccessor |
| 209 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, |
| 210 FixedArray> { |
| 211 public: |
| 212 virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| 213 Object* receiver, |
| 214 uint32_t index) { |
| 215 FixedArray* parameter_map = GetBackingStore(obj); |
| 216 uint32_t length = parameter_map->length(); |
| 217 Object* probe = |
| 218 (index < length - 2) ? parameter_map->get(index + 2) : NULL; |
| 219 if (probe != NULL && !probe->IsTheHole()) { |
| 220 Context* context = Context::cast(parameter_map->get(0)); |
| 221 int context_index = Smi::cast(probe)->value(); |
| 222 ASSERT(!context->get(context_index)->IsTheHole()); |
| 223 return context->get(context_index); |
| 224 } else { |
| 225 // Object is not mapped, defer to the arguments. |
| 226 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 227 if (arguments->IsDictionary()) { |
| 228 return DictionaryElementsAccessor::GetNumberDictionaryElement( |
| 229 obj, |
| 230 receiver, |
| 231 NumberDictionary::cast(arguments), |
| 232 index); |
| 233 } else if (index < static_cast<uint32_t>(arguments->length())) { |
| 234 return arguments->get(index); |
| 235 } |
| 236 } |
| 237 return obj->GetHeap()->the_hole_value(); |
| 238 } |
| 239 }; |
| 240 |
| 241 |
| 242 void ElementsAccessor::InitializeOncePerProcess() { |
| 243 static struct ConcreteElementsAccessors { |
| 244 FastElementsAccessor fast_elements_handler; |
| 245 FastDoubleElementsAccessor fast_double_elements_handler; |
| 246 DictionaryElementsAccessor dictionary_elements_handler; |
| 247 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; |
| 248 ExternalByteElementsAccessor byte_elements_handler; |
| 249 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler; |
| 250 ExternalShortElementsAccessor short_elements_handler; |
| 251 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler; |
| 252 ExternalIntElementsAccessor int_elements_handler; |
| 253 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler; |
| 254 ExternalFloatElementsAccessor float_elements_handler; |
| 255 ExternalDoubleElementsAccessor double_elements_handler; |
| 256 PixelElementsAccessor pixel_elements_handler; |
| 257 } element_accessors; |
| 258 |
| 259 static ElementsAccessor* accessor_array[] = { |
| 260 &element_accessors.fast_elements_handler, |
| 261 &element_accessors.fast_double_elements_handler, |
| 262 &element_accessors.dictionary_elements_handler, |
| 263 &element_accessors.non_strict_arguments_elements_handler, |
| 264 &element_accessors.byte_elements_handler, |
| 265 &element_accessors.unsigned_byte_elements_handler, |
| 266 &element_accessors.short_elements_handler, |
| 267 &element_accessors.unsigned_short_elements_handler, |
| 268 &element_accessors.int_elements_handler, |
| 269 &element_accessors.unsigned_int_elements_handler, |
| 270 &element_accessors.float_elements_handler, |
| 271 &element_accessors.double_elements_handler, |
| 272 &element_accessors.pixel_elements_handler |
| 273 }; |
| 274 |
| 275 elements_accessors_ = accessor_array; |
| 276 } |
| 277 |
| 278 |
| 279 } } // namespace v8::internal |
OLD | NEW |