| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 // - ExternalDoubleElementsAccessor | 52 // - ExternalDoubleElementsAccessor |
| 53 // - PixelElementsAccessor | 53 // - PixelElementsAccessor |
| 54 // - DictionaryElementsAccessor | 54 // - DictionaryElementsAccessor |
| 55 // - NonStrictArgumentsElementsAccessor | 55 // - NonStrictArgumentsElementsAccessor |
| 56 | 56 |
| 57 | 57 |
| 58 namespace v8 { | 58 namespace v8 { |
| 59 namespace internal { | 59 namespace internal { |
| 60 | 60 |
| 61 | 61 |
| 62 // First argument in list is the accessor class, the second argument is the |
| 63 // accessor ElementsKind, and the third is the backing store class. Use the |
| 64 // fast element handler for smi-only arrays. The implementation is currently |
| 65 // identical. Note that the order must match that of the ElementsKind enum for |
| 66 // the |accessor_array[]| below to work. |
| 67 #define ELEMENTS_LIST(V) \ |
| 68 V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray) \ |
| 69 V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ |
| 70 V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \ |
| 71 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ |
| 72 SeededNumberDictionary) \ |
| 73 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \ |
| 74 FixedArray) \ |
| 75 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \ |
| 76 ExternalByteArray) \ |
| 77 V(ExternalUnsignedByteElementsAccessor, \ |
| 78 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \ |
| 79 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \ |
| 80 ExternalShortArray) \ |
| 81 V(ExternalUnsignedShortElementsAccessor, \ |
| 82 EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \ |
| 83 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \ |
| 84 ExternalIntArray) \ |
| 85 V(ExternalUnsignedIntElementsAccessor, \ |
| 86 EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \ |
| 87 V(ExternalFloatElementsAccessor, \ |
| 88 EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \ |
| 89 V(ExternalDoubleElementsAccessor, \ |
| 90 EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \ |
| 91 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray) |
| 92 |
| 93 |
| 94 template<ElementsKind Kind> class ElementsKindTraits { |
| 95 public: |
| 96 typedef FixedArrayBase BackingStore; |
| 97 }; |
| 98 |
| 99 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ |
| 100 template<> class ElementsKindTraits<KindParam> { \ |
| 101 public: \ |
| 102 static const ElementsKind Kind = KindParam; \ |
| 103 typedef Store BackingStore; \ |
| 104 }; |
| 105 ELEMENTS_LIST(ELEMENTS_TRAITS) |
| 106 #undef ELEMENTS_TRAITS |
| 107 |
| 108 |
| 62 ElementsAccessor** ElementsAccessor::elements_accessors_; | 109 ElementsAccessor** ElementsAccessor::elements_accessors_; |
| 63 | 110 |
| 64 | 111 |
| 65 static bool HasKey(FixedArray* array, Object* key) { | 112 static bool HasKey(FixedArray* array, Object* key) { |
| 66 int len0 = array->length(); | 113 int len0 = array->length(); |
| 67 for (int i = 0; i < len0; i++) { | 114 for (int i = 0; i < len0; i++) { |
| 68 Object* element = array->get(i); | 115 Object* element = array->get(i); |
| 69 if (element->IsSmi() && element == key) return true; | 116 if (element->IsSmi() && element == key) return true; |
| 70 if (element->IsString() && | 117 if (element->IsString() && |
| 71 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 118 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
| 72 return true; | 119 return true; |
| 73 } | 120 } |
| 74 } | 121 } |
| 75 return false; | 122 return false; |
| 76 } | 123 } |
| 77 | 124 |
| 78 | 125 |
| 79 static Failure* ThrowArrayLengthRangeError(Heap* heap) { | 126 static Failure* ThrowArrayLengthRangeError(Heap* heap) { |
| 80 HandleScope scope(heap->isolate()); | 127 HandleScope scope(heap->isolate()); |
| 81 return heap->isolate()->Throw( | 128 return heap->isolate()->Throw( |
| 82 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | 129 *heap->isolate()->factory()->NewRangeError("invalid_array_length", |
| 83 HandleVector<Object>(NULL, 0))); | 130 HandleVector<Object>(NULL, 0))); |
| 84 } | 131 } |
| 85 | 132 |
| 86 | 133 |
| 134 void CopyObjectToObjectElements(AssertNoAllocation* no_gc, |
| 135 FixedArray* from_obj, |
| 136 ElementsKind from_kind, |
| 137 uint32_t from_start, |
| 138 FixedArray* to_obj, |
| 139 ElementsKind to_kind, |
| 140 uint32_t to_start, |
| 141 int copy_size) { |
| 142 ASSERT(to_obj->map() != HEAP->fixed_cow_array_map()); |
| 143 ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS); |
| 144 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| 145 if (copy_size == -1) { |
| 146 copy_size = Min(from_obj->length() - from_start, |
| 147 to_obj->length() - to_start); |
| 148 } |
| 149 ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| 150 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| 151 if (copy_size == 0) return; |
| 152 Address to = to_obj->address() + FixedArray::kHeaderSize; |
| 153 Address from = from_obj->address() + FixedArray::kHeaderSize; |
| 154 CopyWords(reinterpret_cast<Object**>(to) + to_start, |
| 155 reinterpret_cast<Object**>(from) + from_start, |
| 156 copy_size); |
| 157 if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) { |
| 158 Heap* heap = from_obj->GetHeap(); |
| 159 WriteBarrierMode mode = to_obj->GetWriteBarrierMode(*no_gc); |
| 160 if (mode == UPDATE_WRITE_BARRIER) { |
| 161 heap->RecordWrites(to_obj->address(), |
| 162 to_obj->OffsetOfElementAt(to_start), |
| 163 copy_size); |
| 164 } |
| 165 heap->incremental_marking()->RecordWrites(to_obj); |
| 166 } |
| 167 } |
| 168 |
| 169 |
| 170 |
| 171 |
| 172 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, |
| 173 uint32_t from_start, |
| 174 FixedArray* to, |
| 175 ElementsKind to_kind, |
| 176 uint32_t to_start, |
| 177 int copy_size) { |
| 178 ASSERT(to != from); |
| 179 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| 180 ASSERT(copy_size == -1 || |
| 181 (copy_size + static_cast<int>(to_start)) <= to->length()); |
| 182 WriteBarrierMode mode = to_kind == FAST_ELEMENTS |
| 183 ? UPDATE_WRITE_BARRIER |
| 184 : SKIP_WRITE_BARRIER; |
| 185 uint32_t copy_limit = (copy_size == -1) |
| 186 ? to->length() |
| 187 : Min(to_start + copy_size, static_cast<uint32_t>(to->length())); |
| 188 for (int i = 0; i < from->Capacity(); ++i) { |
| 189 Object* key = from->KeyAt(i); |
| 190 if (key->IsNumber()) { |
| 191 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 192 if (entry >= to_start && entry < copy_limit) { |
| 193 Object* value = from->ValueAt(i); |
| 194 ASSERT(to_kind == FAST_ELEMENTS || value->IsSmi()); |
| 195 to->set(entry, value, mode); |
| 196 } |
| 197 } |
| 198 } |
| 199 } |
| 200 |
| 201 |
| 202 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
| 203 FixedDoubleArray* from_obj, |
| 204 uint32_t from_start, |
| 205 FixedArray* to_obj, |
| 206 ElementsKind to_kind, |
| 207 uint32_t to_start, |
| 208 int copy_size) { |
| 209 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
| 210 if (copy_size == -1) { |
| 211 copy_size = Min(from_obj->length() - from_start, |
| 212 to_obj->length() - to_start); |
| 213 } |
| 214 ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| 215 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| 216 if (copy_size == 0) return from_obj; |
| 217 for (int i = 0; i < copy_size; ++i) { |
| 218 if (to_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 219 UNIMPLEMENTED(); |
| 220 return Failure::Exception(); |
| 221 } else { |
| 222 MaybeObject* maybe_value = from_obj->get(i + from_start); |
| 223 Object* value; |
| 224 ASSERT(to_kind == FAST_ELEMENTS); |
| 225 // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects |
| 226 // iteratively, the allocate must succeed within a single GC cycle, |
| 227 // otherwise the retry after the GC will also fail. In order to ensure |
| 228 // that no GC is triggered, allocate HeapNumbers from old space if they |
| 229 // can't be taken from new space. |
| 230 if (!maybe_value->ToObject(&value)) { |
| 231 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); |
| 232 Heap* heap = from_obj->GetHeap(); |
| 233 MaybeObject* maybe_value_object = |
| 234 heap->AllocateHeapNumber(from_obj->get_scalar(i + from_start), |
| 235 TENURED); |
| 236 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 237 } |
| 238 to_obj->set(i + to_start, value, UPDATE_WRITE_BARRIER); |
| 239 } |
| 240 } |
| 241 return to_obj; |
| 242 } |
| 243 |
| 244 |
| 245 static void CopyDoubleToDoubleElements(FixedDoubleArray* from_obj, |
| 246 uint32_t from_start, |
| 247 FixedDoubleArray* to_obj, |
| 248 uint32_t to_start, |
| 249 int copy_size) { |
| 250 if (copy_size == -1) { |
| 251 copy_size = Min(from_obj->length() - from_start, |
| 252 to_obj->length() - to_start); |
| 253 } |
| 254 ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() && |
| 255 (copy_size + static_cast<int>(from_start)) <= from_obj->length())); |
| 256 if (copy_size == 0) return; |
| 257 Address to = to_obj->address() + FixedDoubleArray::kHeaderSize; |
| 258 Address from = from_obj->address() + FixedDoubleArray::kHeaderSize; |
| 259 to += kDoubleSize * to_start; |
| 260 from += kDoubleSize * from_start; |
| 261 int words_per_double = (kDoubleSize / kPointerSize); |
| 262 CopyWords(reinterpret_cast<Object**>(to), |
| 263 reinterpret_cast<Object**>(from), |
| 264 words_per_double * copy_size); |
| 265 } |
| 266 |
| 267 |
| 87 // Base class for element handler implementations. Contains the | 268 // Base class for element handler implementations. Contains the |
| 88 // the common logic for objects with different ElementsKinds. | 269 // the common logic for objects with different ElementsKinds. |
| 89 // Subclasses must specialize method for which the element | 270 // Subclasses must specialize method for which the element |
| 90 // implementation differs from the base class implementation. | 271 // implementation differs from the base class implementation. |
| 91 // | 272 // |
| 92 // This class is intended to be used in the following way: | 273 // This class is intended to be used in the following way: |
| 93 // | 274 // |
| 94 // class SomeElementsAccessor : | 275 // class SomeElementsAccessor : |
| 95 // public ElementsAccessorBase<SomeElementsAccessor, | 276 // public ElementsAccessorBase<SomeElementsAccessor, |
| 96 // BackingStoreClass> { | 277 // BackingStoreClass> { |
| 97 // ... | 278 // ... |
| 98 // } | 279 // } |
| 99 // | 280 // |
| 100 // This is an example of the Curiously Recurring Template Pattern (see | 281 // This is an example of the Curiously Recurring Template Pattern (see |
| 101 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use | 282 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
| 102 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and | 283 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
| 103 // specialization of SomeElementsAccessor methods). | 284 // specialization of SomeElementsAccessor methods). |
| 104 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | 285 template <typename ElementsAccessorSubclass, |
| 286 typename ElementsTraitsParam> |
| 105 class ElementsAccessorBase : public ElementsAccessor { | 287 class ElementsAccessorBase : public ElementsAccessor { |
| 106 protected: | 288 protected: |
| 107 explicit ElementsAccessorBase(const char* name) : ElementsAccessor(name) { } | 289 explicit ElementsAccessorBase(const char* name) |
| 290 : ElementsAccessor(name) { } |
| 291 |
| 292 typedef ElementsTraitsParam ElementsTraits; |
| 293 typedef typename ElementsTraitsParam::BackingStore BackingStore; |
| 294 |
| 295 virtual ElementsKind kind() const { return ElementsTraits::Kind; } |
| 108 | 296 |
| 109 static bool HasElementImpl(Object* receiver, | 297 static bool HasElementImpl(Object* receiver, |
| 110 JSObject* holder, | 298 JSObject* holder, |
| 111 uint32_t key, | 299 uint32_t key, |
| 112 BackingStoreClass* backing_store) { | 300 BackingStore* backing_store) { |
| 113 MaybeObject* element = | 301 MaybeObject* element = |
| 114 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); | 302 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); |
| 115 return !element->IsTheHole(); | 303 return !element->IsTheHole(); |
| 116 } | 304 } |
| 117 | 305 |
| 118 virtual bool HasElement(Object* receiver, | 306 virtual bool HasElement(Object* receiver, |
| 119 JSObject* holder, | 307 JSObject* holder, |
| 120 uint32_t key, | 308 uint32_t key, |
| 121 FixedArrayBase* backing_store) { | 309 FixedArrayBase* backing_store) { |
| 122 if (backing_store == NULL) { | 310 if (backing_store == NULL) { |
| 123 backing_store = holder->elements(); | 311 backing_store = holder->elements(); |
| 124 } | 312 } |
| 125 return ElementsAccessorSubclass::HasElementImpl( | 313 return ElementsAccessorSubclass::HasElementImpl( |
| 126 receiver, holder, key, BackingStoreClass::cast(backing_store)); | 314 receiver, holder, key, BackingStore::cast(backing_store)); |
| 127 } | 315 } |
| 128 | 316 |
| 129 virtual MaybeObject* Get(Object* receiver, | 317 virtual MaybeObject* Get(Object* receiver, |
| 130 JSObject* holder, | 318 JSObject* holder, |
| 131 uint32_t key, | 319 uint32_t key, |
| 132 FixedArrayBase* backing_store) { | 320 FixedArrayBase* backing_store) { |
| 133 if (backing_store == NULL) { | 321 if (backing_store == NULL) { |
| 134 backing_store = holder->elements(); | 322 backing_store = holder->elements(); |
| 135 } | 323 } |
| 136 return ElementsAccessorSubclass::GetImpl( | 324 return ElementsAccessorSubclass::GetImpl( |
| 137 receiver, holder, key, BackingStoreClass::cast(backing_store)); | 325 receiver, holder, key, BackingStore::cast(backing_store)); |
| 138 } | 326 } |
| 139 | 327 |
| 140 static MaybeObject* GetImpl(Object* receiver, | 328 static MaybeObject* GetImpl(Object* receiver, |
| 141 JSObject* obj, | 329 JSObject* obj, |
| 142 uint32_t key, | 330 uint32_t key, |
| 143 BackingStoreClass* backing_store) { | 331 BackingStore* backing_store) { |
| 144 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) | 332 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) |
| 145 ? backing_store->get(key) | 333 ? backing_store->get(key) |
| 146 : backing_store->GetHeap()->the_hole_value(); | 334 : backing_store->GetHeap()->the_hole_value(); |
| 147 } | 335 } |
| 148 | 336 |
| 149 virtual MaybeObject* SetLength(JSArray* array, | 337 virtual MaybeObject* SetLength(JSArray* array, |
| 150 Object* length) { | 338 Object* length) { |
| 151 return ElementsAccessorSubclass::SetLengthImpl( | 339 return ElementsAccessorSubclass::SetLengthImpl( |
| 152 array, length, BackingStoreClass::cast(array->elements())); | 340 array, length, BackingStore::cast(array->elements())); |
| 153 } | 341 } |
| 154 | 342 |
| 155 static MaybeObject* SetLengthImpl(JSObject* obj, | 343 static MaybeObject* SetLengthImpl(JSObject* obj, |
| 156 Object* length, | 344 Object* length, |
| 157 BackingStoreClass* backing_store); | 345 BackingStore* backing_store); |
| 158 | 346 |
| 159 virtual MaybeObject* SetCapacityAndLength(JSArray* array, | 347 virtual MaybeObject* SetCapacityAndLength(JSArray* array, |
| 160 int capacity, | 348 int capacity, |
| 161 int length) { | 349 int length) { |
| 162 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 350 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
| 163 array, | 351 array, |
| 164 capacity, | 352 capacity, |
| 165 length); | 353 length); |
| 166 } | 354 } |
| 167 | 355 |
| 168 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 356 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
| 169 int capacity, | 357 int capacity, |
| 170 int length) { | 358 int length) { |
| 171 UNIMPLEMENTED(); | 359 UNIMPLEMENTED(); |
| 172 return obj; | 360 return obj; |
| 173 } | 361 } |
| 174 | 362 |
| 175 virtual MaybeObject* Delete(JSObject* obj, | 363 virtual MaybeObject* Delete(JSObject* obj, |
| 176 uint32_t key, | 364 uint32_t key, |
| 177 JSReceiver::DeleteMode mode) = 0; | 365 JSReceiver::DeleteMode mode) = 0; |
| 178 | 366 |
| 367 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 368 uint32_t from_start, |
| 369 FixedArrayBase* to, |
| 370 ElementsKind to_kind, |
| 371 uint32_t to_start, |
| 372 int copy_size) { |
| 373 UNREACHABLE(); |
| 374 return NULL; |
| 375 } |
| 376 |
| 377 virtual MaybeObject* CopyElements(JSObject* from_holder, |
| 378 uint32_t from_start, |
| 379 FixedArrayBase* to, |
| 380 ElementsKind to_kind, |
| 381 uint32_t to_start, |
| 382 int copy_size, |
| 383 FixedArrayBase* from) { |
| 384 if (from == NULL) { |
| 385 from = from_holder->elements(); |
| 386 } |
| 387 return ElementsAccessorSubclass::CopyElementsImpl( |
| 388 from, from_start, to, to_kind, to_start, copy_size); |
| 389 } |
| 390 |
| 179 virtual MaybeObject* AddElementsToFixedArray(Object* receiver, | 391 virtual MaybeObject* AddElementsToFixedArray(Object* receiver, |
| 180 JSObject* holder, | 392 JSObject* holder, |
| 181 FixedArray* to, | 393 FixedArray* to, |
| 182 FixedArrayBase* from) { | 394 FixedArrayBase* from) { |
| 183 int len0 = to->length(); | 395 int len0 = to->length(); |
| 184 #ifdef DEBUG | 396 #ifdef DEBUG |
| 185 if (FLAG_enable_slow_asserts) { | 397 if (FLAG_enable_slow_asserts) { |
| 186 for (int i = 0; i < len0; i++) { | 398 for (int i = 0; i < len0; i++) { |
| 187 ASSERT(!to->get(i)->IsTheHole()); | 399 ASSERT(!to->get(i)->IsTheHole()); |
| 188 } | 400 } |
| 189 } | 401 } |
| 190 #endif | 402 #endif |
| 191 if (from == NULL) { | 403 if (from == NULL) { |
| 192 from = holder->elements(); | 404 from = holder->elements(); |
| 193 } | 405 } |
| 194 BackingStoreClass* backing_store = BackingStoreClass::cast(from); | 406 BackingStore* backing_store = BackingStore::cast(from); |
| 195 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); | 407 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 196 | 408 |
| 197 // Optimize if 'other' is empty. | 409 // Optimize if 'other' is empty. |
| 198 // We cannot optimize if 'this' is empty, as other may have holes. | 410 // We cannot optimize if 'this' is empty, as other may have holes. |
| 199 if (len1 == 0) return to; | 411 if (len1 == 0) return to; |
| 200 | 412 |
| 201 // Compute how many elements are not in other. | 413 // Compute how many elements are not in other. |
| 202 uint32_t extra = 0; | 414 uint32_t extra = 0; |
| 203 for (uint32_t y = 0; y < len1; y++) { | 415 for (uint32_t y = 0; y < len1; y++) { |
| 204 uint32_t key = | 416 uint32_t key = |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 result->set(len0 + index, value); | 463 result->set(len0 + index, value); |
| 252 index++; | 464 index++; |
| 253 } | 465 } |
| 254 } | 466 } |
| 255 } | 467 } |
| 256 ASSERT(extra == index); | 468 ASSERT(extra == index); |
| 257 return result; | 469 return result; |
| 258 } | 470 } |
| 259 | 471 |
| 260 protected: | 472 protected: |
| 261 static uint32_t GetCapacityImpl(BackingStoreClass* backing_store) { | 473 static uint32_t GetCapacityImpl(BackingStore* backing_store) { |
| 262 return backing_store->length(); | 474 return backing_store->length(); |
| 263 } | 475 } |
| 264 | 476 |
| 265 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { | 477 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { |
| 266 return ElementsAccessorSubclass::GetCapacityImpl( | 478 return ElementsAccessorSubclass::GetCapacityImpl( |
| 267 BackingStoreClass::cast(backing_store)); | 479 BackingStore::cast(backing_store)); |
| 268 } | 480 } |
| 269 | 481 |
| 270 static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store, | 482 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store, |
| 271 uint32_t index) { | 483 uint32_t index) { |
| 272 return index; | 484 return index; |
| 273 } | 485 } |
| 274 | 486 |
| 275 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 487 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, |
| 276 uint32_t index) { | 488 uint32_t index) { |
| 277 return ElementsAccessorSubclass::GetKeyForIndexImpl( | 489 return ElementsAccessorSubclass::GetKeyForIndexImpl( |
| 278 BackingStoreClass::cast(backing_store), index); | 490 BackingStore::cast(backing_store), index); |
| 279 } | 491 } |
| 280 | 492 |
| 281 private: | 493 private: |
| 282 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 494 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 283 }; | 495 }; |
| 284 | 496 |
| 285 | 497 |
| 286 // Super class for all fast element arrays. | 498 // Super class for all fast element arrays. |
| 287 template<typename FastElementsAccessorSubclass, | 499 template<typename FastElementsAccessorSubclass, |
| 288 typename BackingStore, | 500 typename KindTraits, |
| 289 int ElementSize> | 501 int ElementSize> |
| 290 class FastElementsAccessor | 502 class FastElementsAccessor |
| 291 : public ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore> { | 503 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
| 292 public: | 504 public: |
| 293 explicit FastElementsAccessor(const char* name) | 505 explicit FastElementsAccessor(const char* name) |
| 294 : ElementsAccessorBase<FastElementsAccessorSubclass, | 506 : ElementsAccessorBase<FastElementsAccessorSubclass, |
| 295 BackingStore>(name) {} | 507 KindTraits>(name) {} |
| 296 protected: | 508 protected: |
| 297 friend class ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore>; | 509 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
| 510 |
| 511 typedef typename KindTraits::BackingStore BackingStore; |
| 298 | 512 |
| 299 // Adjusts the length of the fast backing store or returns the new length or | 513 // Adjusts the length of the fast backing store or returns the new length or |
| 300 // undefined in case conversion to a slow backing store should be performed. | 514 // undefined in case conversion to a slow backing store should be performed. |
| 301 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 515 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, |
| 302 JSArray* array, | 516 JSArray* array, |
| 303 Object* length_object, | 517 Object* length_object, |
| 304 uint32_t length) { | 518 uint32_t length) { |
| 305 uint32_t old_capacity = backing_store->length(); | 519 uint32_t old_capacity = backing_store->length(); |
| 306 | 520 |
| 307 // Check whether the backing store should be shrunk. | 521 // Check whether the backing store should be shrunk. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 } | 556 } |
| 343 | 557 |
| 344 // Request conversion to slow elements. | 558 // Request conversion to slow elements. |
| 345 return array->GetHeap()->undefined_value(); | 559 return array->GetHeap()->undefined_value(); |
| 346 } | 560 } |
| 347 }; | 561 }; |
| 348 | 562 |
| 349 | 563 |
| 350 class FastObjectElementsAccessor | 564 class FastObjectElementsAccessor |
| 351 : public FastElementsAccessor<FastObjectElementsAccessor, | 565 : public FastElementsAccessor<FastObjectElementsAccessor, |
| 352 FixedArray, | 566 ElementsKindTraits<FAST_ELEMENTS>, |
| 353 kPointerSize> { | 567 kPointerSize> { |
| 354 public: | 568 public: |
| 355 explicit FastObjectElementsAccessor(const char* name) | 569 explicit FastObjectElementsAccessor(const char* name) |
| 356 : FastElementsAccessor<FastObjectElementsAccessor, | 570 : FastElementsAccessor<FastObjectElementsAccessor, |
| 357 FixedArray, | 571 ElementsKindTraits<FAST_ELEMENTS>, |
| 358 kPointerSize>(name) {} | 572 kPointerSize>(name) {} |
| 359 | 573 |
| 360 static MaybeObject* DeleteCommon(JSObject* obj, | 574 static MaybeObject* DeleteCommon(JSObject* obj, |
| 361 uint32_t key) { | 575 uint32_t key) { |
| 362 ASSERT(obj->HasFastElements() || | 576 ASSERT(obj->HasFastElements() || |
| 363 obj->HasFastSmiOnlyElements() || | 577 obj->HasFastSmiOnlyElements() || |
| 364 obj->HasFastArgumentsElements()); | 578 obj->HasFastArgumentsElements()); |
| 365 Heap* heap = obj->GetHeap(); | 579 Heap* heap = obj->GetHeap(); |
| 366 FixedArray* backing_store = FixedArray::cast(obj->elements()); | 580 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
| 367 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { | 581 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 396 } | 610 } |
| 397 if (4 * num_used <= backing_store->length()) { | 611 if (4 * num_used <= backing_store->length()) { |
| 398 MaybeObject* result = obj->NormalizeElements(); | 612 MaybeObject* result = obj->NormalizeElements(); |
| 399 if (result->IsFailure()) return result; | 613 if (result->IsFailure()) return result; |
| 400 } | 614 } |
| 401 } | 615 } |
| 402 } | 616 } |
| 403 return heap->true_value(); | 617 return heap->true_value(); |
| 404 } | 618 } |
| 405 | 619 |
| 620 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 621 uint32_t from_start, |
| 622 FixedArrayBase* to, |
| 623 ElementsKind to_kind, |
| 624 uint32_t to_start, |
| 625 int copy_size) { |
| 626 switch (to_kind) { |
| 627 case FAST_SMI_ONLY_ELEMENTS: |
| 628 case FAST_ELEMENTS: { |
| 629 AssertNoAllocation no_gc; |
| 630 CopyObjectToObjectElements( |
| 631 &no_gc, FixedArray::cast(from), ElementsTraits::Kind, from_start, |
| 632 FixedArray::cast(to), to_kind, to_start, copy_size); |
| 633 return from; |
| 634 } |
| 635 default: |
| 636 UNREACHABLE(); |
| 637 } |
| 638 return to->GetHeap()->undefined_value(); |
| 639 } |
| 640 |
| 641 |
| 406 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 642 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
| 407 uint32_t capacity, | 643 uint32_t capacity, |
| 408 uint32_t length) { | 644 uint32_t length) { |
| 409 JSObject::SetFastElementsCapacityMode set_capacity_mode = | 645 JSObject::SetFastElementsCapacityMode set_capacity_mode = |
| 410 obj->HasFastSmiOnlyElements() | 646 obj->HasFastSmiOnlyElements() |
| 411 ? JSObject::kAllowSmiOnlyElements | 647 ? JSObject::kAllowSmiOnlyElements |
| 412 : JSObject::kDontAllowSmiOnlyElements; | 648 : JSObject::kDontAllowSmiOnlyElements; |
| 413 return obj->SetFastElementsCapacityAndLength(capacity, | 649 return obj->SetFastElementsCapacityAndLength(capacity, |
| 414 length, | 650 length, |
| 415 set_capacity_mode); | 651 set_capacity_mode); |
| 416 } | 652 } |
| 417 | 653 |
| 418 protected: | 654 protected: |
| 419 friend class FastElementsAccessor<FastObjectElementsAccessor, | 655 friend class FastElementsAccessor<FastObjectElementsAccessor, |
| 420 FixedArray, | 656 ElementsKindTraits<FAST_ELEMENTS>, |
| 421 kPointerSize>; | 657 kPointerSize>; |
| 422 | 658 |
| 423 virtual MaybeObject* Delete(JSObject* obj, | 659 virtual MaybeObject* Delete(JSObject* obj, |
| 424 uint32_t key, | 660 uint32_t key, |
| 425 JSReceiver::DeleteMode mode) { | 661 JSReceiver::DeleteMode mode) { |
| 426 return DeleteCommon(obj, key); | 662 return DeleteCommon(obj, key); |
| 427 } | 663 } |
| 428 }; | 664 }; |
| 429 | 665 |
| 430 | 666 |
| 431 class FastDoubleElementsAccessor | 667 class FastDoubleElementsAccessor |
| 432 : public FastElementsAccessor<FastDoubleElementsAccessor, | 668 : public FastElementsAccessor<FastDoubleElementsAccessor, |
| 433 FixedDoubleArray, | 669 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
| 434 kDoubleSize> { | 670 kDoubleSize> { |
| 435 public: | 671 public: |
| 436 explicit FastDoubleElementsAccessor(const char* name) | 672 explicit FastDoubleElementsAccessor(const char* name) |
| 437 : FastElementsAccessor<FastDoubleElementsAccessor, | 673 : FastElementsAccessor<FastDoubleElementsAccessor, |
| 438 FixedDoubleArray, | 674 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
| 439 kDoubleSize>(name) {} | 675 kDoubleSize>(name) {} |
| 440 | 676 |
| 441 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 677 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
| 442 uint32_t capacity, | 678 uint32_t capacity, |
| 443 uint32_t length) { | 679 uint32_t length) { |
| 444 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); | 680 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); |
| 445 } | 681 } |
| 446 | 682 |
| 447 protected: | 683 protected: |
| 448 friend class ElementsAccessorBase<FastDoubleElementsAccessor, | 684 friend class ElementsAccessorBase<FastDoubleElementsAccessor, |
| 449 FixedDoubleArray>; | 685 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; |
| 450 friend class FastElementsAccessor<FastDoubleElementsAccessor, | 686 friend class FastElementsAccessor<FastDoubleElementsAccessor, |
| 451 FixedDoubleArray, | 687 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
| 452 kDoubleSize>; | 688 kDoubleSize>; |
| 453 | 689 |
| 690 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 691 uint32_t from_start, |
| 692 FixedArrayBase* to, |
| 693 ElementsKind to_kind, |
| 694 uint32_t to_start, |
| 695 int copy_size) { |
| 696 switch (to_kind) { |
| 697 case FAST_SMI_ONLY_ELEMENTS: |
| 698 case FAST_ELEMENTS: |
| 699 return CopyDoubleToObjectElements( |
| 700 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), |
| 701 to_kind, to_start, copy_size); |
| 702 case FAST_DOUBLE_ELEMENTS: |
| 703 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, |
| 704 FixedDoubleArray::cast(to), |
| 705 to_start, copy_size); |
| 706 return from; |
| 707 default: |
| 708 UNREACHABLE(); |
| 709 } |
| 710 return to->GetHeap()->undefined_value(); |
| 711 } |
| 712 |
| 454 virtual MaybeObject* Delete(JSObject* obj, | 713 virtual MaybeObject* Delete(JSObject* obj, |
| 455 uint32_t key, | 714 uint32_t key, |
| 456 JSReceiver::DeleteMode mode) { | 715 JSReceiver::DeleteMode mode) { |
| 457 int length = obj->IsJSArray() | 716 int length = obj->IsJSArray() |
| 458 ? Smi::cast(JSArray::cast(obj)->length())->value() | 717 ? Smi::cast(JSArray::cast(obj)->length())->value() |
| 459 : FixedDoubleArray::cast(obj->elements())->length(); | 718 : FixedDoubleArray::cast(obj->elements())->length(); |
| 460 if (key < static_cast<uint32_t>(length)) { | 719 if (key < static_cast<uint32_t>(length)) { |
| 461 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); | 720 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); |
| 462 } | 721 } |
| 463 return obj->GetHeap()->true_value(); | 722 return obj->GetHeap()->true_value(); |
| 464 } | 723 } |
| 465 | 724 |
| 466 static bool HasElementImpl(Object* receiver, | 725 static bool HasElementImpl(Object* receiver, |
| 467 JSObject* holder, | 726 JSObject* holder, |
| 468 uint32_t key, | 727 uint32_t key, |
| 469 FixedDoubleArray* backing_store) { | 728 FixedDoubleArray* backing_store) { |
| 470 return !backing_store->is_the_hole(key); | 729 return !backing_store->is_the_hole(key); |
| 471 } | 730 } |
| 472 }; | 731 }; |
| 473 | 732 |
| 474 | 733 |
| 475 // Super class for all external element arrays. | 734 // Super class for all external element arrays. |
| 476 template<typename ExternalElementsAccessorSubclass, | 735 template<typename ExternalElementsAccessorSubclass, |
| 477 typename ExternalArray> | 736 ElementsKind Kind> |
| 478 class ExternalElementsAccessor | 737 class ExternalElementsAccessor |
| 479 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 738 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 480 ExternalArray> { | 739 ElementsKindTraits<Kind> > { |
| 481 public: | 740 public: |
| 482 explicit ExternalElementsAccessor(const char* name) | 741 explicit ExternalElementsAccessor(const char* name) |
| 483 : ElementsAccessorBase<ExternalElementsAccessorSubclass, | 742 : ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 484 ExternalArray>(name) {} | 743 ElementsKindTraits<Kind> >(name) {} |
| 485 | 744 |
| 486 protected: | 745 protected: |
| 746 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 747 |
| 487 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, | 748 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 488 ExternalArray>; | 749 ElementsKindTraits<Kind> >; |
| 489 | 750 |
| 490 static MaybeObject* GetImpl(Object* receiver, | 751 static MaybeObject* GetImpl(Object* receiver, |
| 491 JSObject* obj, | 752 JSObject* obj, |
| 492 uint32_t key, | 753 uint32_t key, |
| 493 ExternalArray* backing_store) { | 754 BackingStore* backing_store) { |
| 494 return | 755 return |
| 495 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 756 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
| 496 ? backing_store->get(key) | 757 ? backing_store->get(key) |
| 497 : backing_store->GetHeap()->undefined_value(); | 758 : backing_store->GetHeap()->undefined_value(); |
| 498 } | 759 } |
| 499 | 760 |
| 500 static MaybeObject* SetLengthImpl(JSObject* obj, | 761 static MaybeObject* SetLengthImpl(JSObject* obj, |
| 501 Object* length, | 762 Object* length, |
| 502 ExternalArray* backing_store) { | 763 BackingStore* backing_store) { |
| 503 // External arrays do not support changing their length. | 764 // External arrays do not support changing their length. |
| 504 UNREACHABLE(); | 765 UNREACHABLE(); |
| 505 return obj; | 766 return obj; |
| 506 } | 767 } |
| 507 | 768 |
| 508 virtual MaybeObject* Delete(JSObject* obj, | 769 virtual MaybeObject* Delete(JSObject* obj, |
| 509 uint32_t key, | 770 uint32_t key, |
| 510 JSReceiver::DeleteMode mode) { | 771 JSReceiver::DeleteMode mode) { |
| 511 // External arrays always ignore deletes. | 772 // External arrays always ignore deletes. |
| 512 return obj->GetHeap()->true_value(); | 773 return obj->GetHeap()->true_value(); |
| 513 } | 774 } |
| 514 | 775 |
| 515 static bool HasElementImpl(Object* receiver, | 776 static bool HasElementImpl(Object* receiver, |
| 516 JSObject* holder, | 777 JSObject* holder, |
| 517 uint32_t key, | 778 uint32_t key, |
| 518 ExternalArray* backing_store) { | 779 BackingStore* backing_store) { |
| 519 uint32_t capacity = | 780 uint32_t capacity = |
| 520 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); | 781 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 521 return key < capacity; | 782 return key < capacity; |
| 522 } | 783 } |
| 523 }; | 784 }; |
| 524 | 785 |
| 525 | 786 |
| 526 class ExternalByteElementsAccessor | 787 class ExternalByteElementsAccessor |
| 527 : public ExternalElementsAccessor<ExternalByteElementsAccessor, | 788 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
| 528 ExternalByteArray> { | 789 EXTERNAL_BYTE_ELEMENTS> { |
| 529 public: | 790 public: |
| 530 explicit ExternalByteElementsAccessor(const char* name) | 791 explicit ExternalByteElementsAccessor(const char* name) |
| 531 : ExternalElementsAccessor<ExternalByteElementsAccessor, | 792 : ExternalElementsAccessor<ExternalByteElementsAccessor, |
| 532 ExternalByteArray>(name) {} | 793 EXTERNAL_BYTE_ELEMENTS>(name) {} |
| 533 }; | 794 }; |
| 534 | 795 |
| 535 | 796 |
| 536 class ExternalUnsignedByteElementsAccessor | 797 class ExternalUnsignedByteElementsAccessor |
| 537 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, | 798 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, |
| 538 ExternalUnsignedByteArray> { | 799 EXTERNAL_UNSIGNED_BYTE_ELEMENTS> { |
| 539 public: | 800 public: |
| 540 explicit ExternalUnsignedByteElementsAccessor(const char* name) | 801 explicit ExternalUnsignedByteElementsAccessor(const char* name) |
| 541 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, | 802 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, |
| 542 ExternalUnsignedByteArray>(name) {} | 803 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {} |
| 543 }; | 804 }; |
| 544 | 805 |
| 545 | 806 |
| 546 class ExternalShortElementsAccessor | 807 class ExternalShortElementsAccessor |
| 547 : public ExternalElementsAccessor<ExternalShortElementsAccessor, | 808 : public ExternalElementsAccessor<ExternalShortElementsAccessor, |
| 548 ExternalShortArray> { | 809 EXTERNAL_SHORT_ELEMENTS> { |
| 549 public: | 810 public: |
| 550 explicit ExternalShortElementsAccessor(const char* name) | 811 explicit ExternalShortElementsAccessor(const char* name) |
| 551 : ExternalElementsAccessor<ExternalShortElementsAccessor, | 812 : ExternalElementsAccessor<ExternalShortElementsAccessor, |
| 552 ExternalShortArray>(name) {} | 813 EXTERNAL_SHORT_ELEMENTS>(name) {} |
| 553 }; | 814 }; |
| 554 | 815 |
| 555 | 816 |
| 556 class ExternalUnsignedShortElementsAccessor | 817 class ExternalUnsignedShortElementsAccessor |
| 557 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, | 818 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, |
| 558 ExternalUnsignedShortArray> { | 819 EXTERNAL_UNSIGNED_SHORT_ELEMENTS> { |
| 559 public: | 820 public: |
| 560 explicit ExternalUnsignedShortElementsAccessor(const char* name) | 821 explicit ExternalUnsignedShortElementsAccessor(const char* name) |
| 561 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, | 822 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, |
| 562 ExternalUnsignedShortArray>(name) {} | 823 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {} |
| 563 }; | 824 }; |
| 564 | 825 |
| 565 | 826 |
| 566 class ExternalIntElementsAccessor | 827 class ExternalIntElementsAccessor |
| 567 : public ExternalElementsAccessor<ExternalIntElementsAccessor, | 828 : public ExternalElementsAccessor<ExternalIntElementsAccessor, |
| 568 ExternalIntArray> { | 829 EXTERNAL_INT_ELEMENTS> { |
| 569 public: | 830 public: |
| 570 explicit ExternalIntElementsAccessor(const char* name) | 831 explicit ExternalIntElementsAccessor(const char* name) |
| 571 : ExternalElementsAccessor<ExternalIntElementsAccessor, | 832 : ExternalElementsAccessor<ExternalIntElementsAccessor, |
| 572 ExternalIntArray>(name) {} | 833 EXTERNAL_INT_ELEMENTS>(name) {} |
| 573 }; | 834 }; |
| 574 | 835 |
| 575 | 836 |
| 576 class ExternalUnsignedIntElementsAccessor | 837 class ExternalUnsignedIntElementsAccessor |
| 577 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, | 838 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, |
| 578 ExternalUnsignedIntArray> { | 839 EXTERNAL_UNSIGNED_INT_ELEMENTS> { |
| 579 public: | 840 public: |
| 580 explicit ExternalUnsignedIntElementsAccessor(const char* name) | 841 explicit ExternalUnsignedIntElementsAccessor(const char* name) |
| 581 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, | 842 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, |
| 582 ExternalUnsignedIntArray>(name) {} | 843 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {} |
| 583 }; | 844 }; |
| 584 | 845 |
| 585 | 846 |
| 586 class ExternalFloatElementsAccessor | 847 class ExternalFloatElementsAccessor |
| 587 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, | 848 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, |
| 588 ExternalFloatArray> { | 849 EXTERNAL_FLOAT_ELEMENTS> { |
| 589 public: | 850 public: |
| 590 explicit ExternalFloatElementsAccessor(const char* name) | 851 explicit ExternalFloatElementsAccessor(const char* name) |
| 591 : ExternalElementsAccessor<ExternalFloatElementsAccessor, | 852 : ExternalElementsAccessor<ExternalFloatElementsAccessor, |
| 592 ExternalFloatArray>(name) {} | 853 EXTERNAL_FLOAT_ELEMENTS>(name) {} |
| 593 }; | 854 }; |
| 594 | 855 |
| 595 | 856 |
| 596 class ExternalDoubleElementsAccessor | 857 class ExternalDoubleElementsAccessor |
| 597 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, | 858 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, |
| 598 ExternalDoubleArray> { | 859 EXTERNAL_DOUBLE_ELEMENTS> { |
| 599 public: | 860 public: |
| 600 explicit ExternalDoubleElementsAccessor(const char* name) | 861 explicit ExternalDoubleElementsAccessor(const char* name) |
| 601 : ExternalElementsAccessor<ExternalDoubleElementsAccessor, | 862 : ExternalElementsAccessor<ExternalDoubleElementsAccessor, |
| 602 ExternalDoubleArray>(name) {} | 863 EXTERNAL_DOUBLE_ELEMENTS>(name) {} |
| 603 }; | 864 }; |
| 604 | 865 |
| 605 | 866 |
| 606 class PixelElementsAccessor | 867 class PixelElementsAccessor |
| 607 : public ExternalElementsAccessor<PixelElementsAccessor, | 868 : public ExternalElementsAccessor<PixelElementsAccessor, |
| 608 ExternalPixelArray> { | 869 EXTERNAL_PIXEL_ELEMENTS> { |
| 609 public: | 870 public: |
| 610 explicit PixelElementsAccessor(const char* name) | 871 explicit PixelElementsAccessor(const char* name) |
| 611 : ExternalElementsAccessor<PixelElementsAccessor, | 872 : ExternalElementsAccessor<PixelElementsAccessor, |
| 612 ExternalPixelArray>(name) {} | 873 EXTERNAL_PIXEL_ELEMENTS>(name) {} |
| 613 }; | 874 }; |
| 614 | 875 |
| 615 | 876 |
| 616 class DictionaryElementsAccessor | 877 class DictionaryElementsAccessor |
| 617 : public ElementsAccessorBase<DictionaryElementsAccessor, | 878 : public ElementsAccessorBase<DictionaryElementsAccessor, |
| 618 SeededNumberDictionary> { | 879 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
| 619 public: | 880 public: |
| 620 explicit DictionaryElementsAccessor(const char* name) | 881 explicit DictionaryElementsAccessor(const char* name) |
| 621 : ElementsAccessorBase<DictionaryElementsAccessor, | 882 : ElementsAccessorBase<DictionaryElementsAccessor, |
| 622 SeededNumberDictionary>(name) {} | 883 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
| 623 | 884 |
| 624 // Adjusts the length of the dictionary backing store and returns the new | 885 // Adjusts the length of the dictionary backing store and returns the new |
| 625 // length according to ES5 section 15.4.5.2 behavior. | 886 // length according to ES5 section 15.4.5.2 behavior. |
| 626 static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, | 887 static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, |
| 627 JSArray* array, | 888 JSArray* array, |
| 628 Object* length_object, | 889 Object* length_object, |
| 629 uint32_t length) { | 890 uint32_t length) { |
| 630 if (length == 0) { | 891 if (length == 0) { |
| 631 // If the length of a slow array is reset to zero, we clear | 892 // If the length of a slow array is reset to zero, we clear |
| 632 // the array and flush backing storage. This has the added | 893 // the array and flush backing storage. This has the added |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 Handle<Object> args[2] = { name, holder }; | 977 Handle<Object> args[2] = { name, holder }; |
| 717 Handle<Object> error = | 978 Handle<Object> error = |
| 718 isolate->factory()->NewTypeError("strict_delete_property", | 979 isolate->factory()->NewTypeError("strict_delete_property", |
| 719 HandleVector(args, 2)); | 980 HandleVector(args, 2)); |
| 720 return isolate->Throw(*error); | 981 return isolate->Throw(*error); |
| 721 } | 982 } |
| 722 } | 983 } |
| 723 return heap->true_value(); | 984 return heap->true_value(); |
| 724 } | 985 } |
| 725 | 986 |
| 987 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 988 uint32_t from_start, |
| 989 FixedArrayBase* to, |
| 990 ElementsKind to_kind, |
| 991 uint32_t to_start, |
| 992 int copy_size) { |
| 993 switch (to_kind) { |
| 994 case FAST_SMI_ONLY_ELEMENTS: |
| 995 case FAST_ELEMENTS: |
| 996 CopyDictionaryToObjectElements( |
| 997 SeededNumberDictionary::cast(from), from_start, |
| 998 FixedArray::cast(to), to_kind, to_start, copy_size); |
| 999 return from; |
| 1000 default: |
| 1001 UNREACHABLE(); |
| 1002 } |
| 1003 return to->GetHeap()->undefined_value(); |
| 1004 } |
| 1005 |
| 1006 |
| 726 protected: | 1007 protected: |
| 727 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 1008 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
| 728 SeededNumberDictionary>; | 1009 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
| 729 | 1010 |
| 730 virtual MaybeObject* Delete(JSObject* obj, | 1011 virtual MaybeObject* Delete(JSObject* obj, |
| 731 uint32_t key, | 1012 uint32_t key, |
| 732 JSReceiver::DeleteMode mode) { | 1013 JSReceiver::DeleteMode mode) { |
| 733 return DeleteCommon(obj, key, mode); | 1014 return DeleteCommon(obj, key, mode); |
| 734 } | 1015 } |
| 735 | 1016 |
| 736 static MaybeObject* GetImpl(Object* receiver, | 1017 static MaybeObject* GetImpl(Object* receiver, |
| 737 JSObject* obj, | 1018 JSObject* obj, |
| 738 uint32_t key, | 1019 uint32_t key, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 762 } | 1043 } |
| 763 | 1044 |
| 764 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, | 1045 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, |
| 765 uint32_t index) { | 1046 uint32_t index) { |
| 766 Object* key = dict->KeyAt(index); | 1047 Object* key = dict->KeyAt(index); |
| 767 return Smi::cast(key)->value(); | 1048 return Smi::cast(key)->value(); |
| 768 } | 1049 } |
| 769 }; | 1050 }; |
| 770 | 1051 |
| 771 | 1052 |
| 772 class NonStrictArgumentsElementsAccessor | 1053 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< |
| 773 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1054 NonStrictArgumentsElementsAccessor, |
| 774 FixedArray> { | 1055 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { |
| 775 public: | 1056 public: |
| 776 explicit NonStrictArgumentsElementsAccessor(const char* name) | 1057 explicit NonStrictArgumentsElementsAccessor(const char* name) |
| 777 : ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1058 : ElementsAccessorBase< |
| 778 FixedArray>(name) {} | 1059 NonStrictArgumentsElementsAccessor, |
| 1060 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} |
| 779 protected: | 1061 protected: |
| 780 friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor, | 1062 friend class ElementsAccessorBase< |
| 781 FixedArray>; | 1063 NonStrictArgumentsElementsAccessor, |
| 1064 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; |
| 782 | 1065 |
| 783 static MaybeObject* GetImpl(Object* receiver, | 1066 static MaybeObject* GetImpl(Object* receiver, |
| 784 JSObject* obj, | 1067 JSObject* obj, |
| 785 uint32_t key, | 1068 uint32_t key, |
| 786 FixedArray* parameter_map) { | 1069 FixedArray* parameter_map) { |
| 787 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1070 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 788 if (!probe->IsTheHole()) { | 1071 if (!probe->IsTheHole()) { |
| 789 Context* context = Context::cast(parameter_map->get(0)); | 1072 Context* context = Context::cast(parameter_map->get(0)); |
| 790 int context_index = Smi::cast(probe)->value(); | 1073 int context_index = Smi::cast(probe)->value(); |
| 791 ASSERT(!context->get(context_index)->IsTheHole()); | 1074 ASSERT(!context->get(context_index)->IsTheHole()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1116 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 834 if (arguments->IsDictionary()) { | 1117 if (arguments->IsDictionary()) { |
| 835 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 1118 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
| 836 } else { | 1119 } else { |
| 837 return FastObjectElementsAccessor::DeleteCommon(obj, key); | 1120 return FastObjectElementsAccessor::DeleteCommon(obj, key); |
| 838 } | 1121 } |
| 839 } | 1122 } |
| 840 return obj->GetHeap()->true_value(); | 1123 return obj->GetHeap()->true_value(); |
| 841 } | 1124 } |
| 842 | 1125 |
| 1126 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 1127 uint32_t from_start, |
| 1128 FixedArrayBase* to, |
| 1129 ElementsKind to_kind, |
| 1130 uint32_t to_start, |
| 1131 int copy_size) { |
| 1132 FixedArray* parameter_map = FixedArray::cast(from); |
| 1133 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1134 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
| 1135 return accessor->CopyElements(NULL, from_start, to, to_kind, |
| 1136 to_start, copy_size, arguments); |
| 1137 } |
| 1138 |
| 843 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { | 1139 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { |
| 844 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1140 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 845 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 1141 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
| 846 ForArray(arguments)->GetCapacity(arguments)); | 1142 ForArray(arguments)->GetCapacity(arguments)); |
| 847 } | 1143 } |
| 848 | 1144 |
| 849 static uint32_t GetKeyForIndexImpl(FixedArray* dict, | 1145 static uint32_t GetKeyForIndexImpl(FixedArray* dict, |
| 850 uint32_t index) { | 1146 uint32_t index) { |
| 851 return index; | 1147 return index; |
| 852 } | 1148 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 case EXTERNAL_PIXEL_ARRAY_TYPE: | 1202 case EXTERNAL_PIXEL_ARRAY_TYPE: |
| 907 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; | 1203 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; |
| 908 default: | 1204 default: |
| 909 UNREACHABLE(); | 1205 UNREACHABLE(); |
| 910 return NULL; | 1206 return NULL; |
| 911 } | 1207 } |
| 912 } | 1208 } |
| 913 | 1209 |
| 914 | 1210 |
| 915 void ElementsAccessor::InitializeOncePerProcess() { | 1211 void ElementsAccessor::InitializeOncePerProcess() { |
| 916 // First argument in list is the accessor class, the second argument is can | |
| 917 // be any arbitrary unique identifier, in this case chosen to be the | |
| 918 // corresponding enum. Use the fast element handler for smi-only arrays. | |
| 919 // The implementation is currently identical. Note that the order must match | |
| 920 // that of the ElementsKind enum for the |accessor_array[]| below to work. | |
| 921 #define ELEMENTS_LIST(V) \ | |
| 922 V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS) \ | |
| 923 V(FastObjectElementsAccessor, FAST_ELEMENTS) \ | |
| 924 V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS) \ | |
| 925 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS) \ | |
| 926 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS) \ | |
| 927 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS) \ | |
| 928 V(ExternalUnsignedByteElementsAccessor, EXTERNAL_UNSIGNED_BYTE_ELEMENTS) \ | |
| 929 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS) \ | |
| 930 V(ExternalUnsignedShortElementsAccessor, EXTERNAL_UNSIGNED_SHORT_ELEMENTS) \ | |
| 931 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS) \ | |
| 932 V(ExternalUnsignedIntElementsAccessor, EXTERNAL_UNSIGNED_INT_ELEMENTS) \ | |
| 933 V(ExternalFloatElementsAccessor, EXTERNAL_FLOAT_ELEMENTS) \ | |
| 934 V(ExternalDoubleElementsAccessor, EXTERNAL_DOUBLE_ELEMENTS) \ | |
| 935 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS) | |
| 936 | |
| 937 static struct ConcreteElementsAccessors { | 1212 static struct ConcreteElementsAccessors { |
| 938 #define ACCESSOR_STRUCT(Class, Name) Class* Name##_handler; | 1213 #define ACCESSOR_STRUCT(Class, Kind, Store) Class* Kind##_handler; |
| 939 ELEMENTS_LIST(ACCESSOR_STRUCT) | 1214 ELEMENTS_LIST(ACCESSOR_STRUCT) |
| 940 #undef ACCESSOR_STRUCT | 1215 #undef ACCESSOR_STRUCT |
| 941 } element_accessors = { | 1216 } element_accessors = { |
| 942 #define ACCESSOR_INIT(Class, Name) new Class(#Name), | 1217 #define ACCESSOR_INIT(Class, Kind, Store) new Class(#Kind), |
| 943 ELEMENTS_LIST(ACCESSOR_INIT) | 1218 ELEMENTS_LIST(ACCESSOR_INIT) |
| 944 #undef ACCESSOR_INIT | 1219 #undef ACCESSOR_INIT |
| 945 }; | 1220 }; |
| 946 | 1221 |
| 947 static ElementsAccessor* accessor_array[] = { | 1222 static ElementsAccessor* accessor_array[] = { |
| 948 #define ACCESSOR_ARRAY(Class, Name) element_accessors.Name##_handler, | 1223 #define ACCESSOR_ARRAY(Class, Kind, Store) element_accessors.Kind##_handler, |
| 949 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1224 ELEMENTS_LIST(ACCESSOR_ARRAY) |
| 950 #undef ACCESSOR_ARRAY | 1225 #undef ACCESSOR_ARRAY |
| 951 }; | 1226 }; |
| 952 | 1227 |
| 953 #undef ELEMENTS_LIST | |
| 954 | |
| 955 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 1228 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
| 956 kElementsKindCount); | 1229 kElementsKindCount); |
| 957 | 1230 |
| 958 elements_accessors_ = accessor_array; | 1231 elements_accessors_ = accessor_array; |
| 959 } | 1232 } |
| 960 | 1233 |
| 961 | 1234 |
| 962 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | 1235 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
| 963 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>:: | 1236 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, |
| 1237 ElementsKindTraits>:: |
| 964 SetLengthImpl(JSObject* obj, | 1238 SetLengthImpl(JSObject* obj, |
| 965 Object* length, | 1239 Object* length, |
| 966 BackingStoreClass* backing_store) { | 1240 typename ElementsKindTraits::BackingStore* backing_store) { |
| 967 JSArray* array = JSArray::cast(obj); | 1241 JSArray* array = JSArray::cast(obj); |
| 968 | 1242 |
| 969 // Fast case: The new length fits into a Smi. | 1243 // Fast case: The new length fits into a Smi. |
| 970 MaybeObject* maybe_smi_length = length->ToSmi(); | 1244 MaybeObject* maybe_smi_length = length->ToSmi(); |
| 971 Object* smi_length = Smi::FromInt(0); | 1245 Object* smi_length = Smi::FromInt(0); |
| 972 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 1246 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 973 const int value = Smi::cast(smi_length)->value(); | 1247 const int value = Smi::cast(smi_length)->value(); |
| 974 if (value >= 0) { | 1248 if (value >= 0) { |
| 975 Object* new_length; | 1249 Object* new_length; |
| 976 MaybeObject* result = ElementsAccessorSubclass:: | 1250 MaybeObject* result = ElementsAccessorSubclass:: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1287 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
| 1014 new_backing_store->set(0, length); | 1288 new_backing_store->set(0, length); |
| 1015 { MaybeObject* result = array->SetContent(new_backing_store); | 1289 { MaybeObject* result = array->SetContent(new_backing_store); |
| 1016 if (result->IsFailure()) return result; | 1290 if (result->IsFailure()) return result; |
| 1017 } | 1291 } |
| 1018 return array; | 1292 return array; |
| 1019 } | 1293 } |
| 1020 | 1294 |
| 1021 | 1295 |
| 1022 } } // namespace v8::internal | 1296 } } // namespace v8::internal |
| OLD | NEW |