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