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