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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 | 139 |
140 | 140 |
141 static Failure* ThrowArrayLengthRangeError(Heap* heap) { | 141 static Failure* ThrowArrayLengthRangeError(Heap* heap) { |
142 HandleScope scope(heap->isolate()); | 142 HandleScope scope(heap->isolate()); |
143 return heap->isolate()->Throw( | 143 return heap->isolate()->Throw( |
144 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | 144 *heap->isolate()->factory()->NewRangeError("invalid_array_length", |
145 HandleVector<Object>(NULL, 0))); | 145 HandleVector<Object>(NULL, 0))); |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 static void CopyObjectToObjectElements(FixedArray* from, | 149 static void CopyObjectToObjectElements(FixedArrayBase* from_base, |
150 ElementsKind from_kind, | 150 ElementsKind from_kind, |
151 uint32_t from_start, | 151 uint32_t from_start, |
152 FixedArray* to, | 152 FixedArrayBase* to_base, |
153 ElementsKind to_kind, | 153 ElementsKind to_kind, |
154 uint32_t to_start, | 154 uint32_t to_start, |
155 int raw_copy_size) { | 155 int raw_copy_size) { |
156 ASSERT(to->map() != HEAP->fixed_cow_array_map()); | 156 ASSERT(to_base->map() != HEAP->fixed_cow_array_map()); |
157 AssertNoAllocation no_allocation; | 157 AssertNoAllocation no_allocation; |
158 int copy_size = raw_copy_size; | 158 int copy_size = raw_copy_size; |
159 if (raw_copy_size < 0) { | 159 if (raw_copy_size < 0) { |
160 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 160 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
161 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 161 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
162 copy_size = Min(from->length() - from_start, | 162 copy_size = Min(from_base->length() - from_start, |
163 to->length() - to_start); | 163 to_base->length() - to_start); |
164 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 164 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
165 int start = to_start + copy_size; | 165 int start = to_start + copy_size; |
166 int length = to->length() - start; | 166 int length = to_base->length() - start; |
167 if (length > 0) { | 167 if (length > 0) { |
168 Heap* heap = from->GetHeap(); | 168 Heap* heap = from_base->GetHeap(); |
169 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 169 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 170 heap->the_hole_value(), length); |
170 } | 171 } |
171 } | 172 } |
172 } | 173 } |
173 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 174 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
174 (copy_size + static_cast<int>(from_start)) <= from->length()); | 175 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
175 if (copy_size == 0) return; | 176 if (copy_size == 0) return; |
| 177 FixedArray* from = FixedArray::cast(from_base); |
| 178 FixedArray* to = FixedArray::cast(to_base); |
176 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); | 179 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); |
177 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 180 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
178 Address to_address = to->address() + FixedArray::kHeaderSize; | 181 Address to_address = to->address() + FixedArray::kHeaderSize; |
179 Address from_address = from->address() + FixedArray::kHeaderSize; | 182 Address from_address = from->address() + FixedArray::kHeaderSize; |
180 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, | 183 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, |
181 reinterpret_cast<Object**>(from_address) + from_start, | 184 reinterpret_cast<Object**>(from_address) + from_start, |
182 copy_size); | 185 copy_size); |
183 if (IsFastObjectElementsKind(from_kind) && | 186 if (IsFastObjectElementsKind(from_kind) && |
184 IsFastObjectElementsKind(to_kind)) { | 187 IsFastObjectElementsKind(to_kind)) { |
185 Heap* heap = from->GetHeap(); | 188 Heap* heap = from->GetHeap(); |
186 if (!heap->InNewSpace(to)) { | 189 if (!heap->InNewSpace(to)) { |
187 heap->RecordWrites(to->address(), | 190 heap->RecordWrites(to->address(), |
188 to->OffsetOfElementAt(to_start), | 191 to->OffsetOfElementAt(to_start), |
189 copy_size); | 192 copy_size); |
190 } | 193 } |
191 heap->incremental_marking()->RecordWrites(to); | 194 heap->incremental_marking()->RecordWrites(to); |
192 } | 195 } |
193 } | 196 } |
194 | 197 |
195 | 198 |
196 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, | 199 static void CopyDictionaryToObjectElements(FixedArrayBase* from_base, |
197 uint32_t from_start, | 200 uint32_t from_start, |
198 FixedArray* to, | 201 FixedArrayBase* to_base, |
199 ElementsKind to_kind, | 202 ElementsKind to_kind, |
200 uint32_t to_start, | 203 uint32_t to_start, |
201 int raw_copy_size) { | 204 int raw_copy_size) { |
| 205 SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base); |
202 AssertNoAllocation no_allocation; | 206 AssertNoAllocation no_allocation; |
203 int copy_size = raw_copy_size; | 207 int copy_size = raw_copy_size; |
204 Heap* heap = from->GetHeap(); | 208 Heap* heap = from->GetHeap(); |
205 if (raw_copy_size < 0) { | 209 if (raw_copy_size < 0) { |
206 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 210 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
207 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 211 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
208 copy_size = from->max_number_key() + 1 - from_start; | 212 copy_size = from->max_number_key() + 1 - from_start; |
209 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 213 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
210 int start = to_start + copy_size; | 214 int start = to_start + copy_size; |
211 int length = to->length() - start; | 215 int length = to_base->length() - start; |
212 if (length > 0) { | 216 if (length > 0) { |
213 Heap* heap = from->GetHeap(); | 217 Heap* heap = from->GetHeap(); |
214 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 218 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 219 heap->the_hole_value(), length); |
215 } | 220 } |
216 } | 221 } |
217 } | 222 } |
218 ASSERT(to != from); | 223 ASSERT(to_base != from_base); |
219 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 224 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
220 if (copy_size == 0) return; | 225 if (copy_size == 0) return; |
| 226 FixedArray* to = FixedArray::cast(to_base); |
221 uint32_t to_length = to->length(); | 227 uint32_t to_length = to->length(); |
222 if (to_start + copy_size > to_length) { | 228 if (to_start + copy_size > to_length) { |
223 copy_size = to_length - to_start; | 229 copy_size = to_length - to_start; |
224 } | 230 } |
225 for (int i = 0; i < copy_size; i++) { | 231 for (int i = 0; i < copy_size; i++) { |
226 int entry = from->FindEntry(i + from_start); | 232 int entry = from->FindEntry(i + from_start); |
227 if (entry != SeededNumberDictionary::kNotFound) { | 233 if (entry != SeededNumberDictionary::kNotFound) { |
228 Object* value = from->ValueAt(entry); | 234 Object* value = from->ValueAt(entry); |
229 ASSERT(!value->IsTheHole()); | 235 ASSERT(!value->IsTheHole()); |
230 to->set(i + to_start, value, SKIP_WRITE_BARRIER); | 236 to->set(i + to_start, value, SKIP_WRITE_BARRIER); |
231 } else { | 237 } else { |
232 to->set_the_hole(i + to_start); | 238 to->set_the_hole(i + to_start); |
233 } | 239 } |
234 } | 240 } |
235 if (IsFastObjectElementsKind(to_kind)) { | 241 if (IsFastObjectElementsKind(to_kind)) { |
236 if (!heap->InNewSpace(to)) { | 242 if (!heap->InNewSpace(to)) { |
237 heap->RecordWrites(to->address(), | 243 heap->RecordWrites(to->address(), |
238 to->OffsetOfElementAt(to_start), | 244 to->OffsetOfElementAt(to_start), |
239 copy_size); | 245 copy_size); |
240 } | 246 } |
241 heap->incremental_marking()->RecordWrites(to); | 247 heap->incremental_marking()->RecordWrites(to); |
242 } | 248 } |
243 } | 249 } |
244 | 250 |
245 | 251 |
246 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( | 252 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
247 FixedDoubleArray* from, | 253 FixedArrayBase* from_base, |
248 uint32_t from_start, | 254 uint32_t from_start, |
249 FixedArray* to, | 255 FixedArrayBase* to_base, |
250 ElementsKind to_kind, | 256 ElementsKind to_kind, |
251 uint32_t to_start, | 257 uint32_t to_start, |
252 int raw_copy_size) { | 258 int raw_copy_size) { |
253 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 259 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
254 int copy_size = raw_copy_size; | 260 int copy_size = raw_copy_size; |
255 if (raw_copy_size < 0) { | 261 if (raw_copy_size < 0) { |
256 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 262 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
257 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 263 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
258 copy_size = Min(from->length() - from_start, | 264 copy_size = Min(from_base->length() - from_start, |
259 to->length() - to_start); | 265 to_base->length() - to_start); |
260 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 266 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
261 // Also initialize the area that will be copied over since HeapNumber | 267 // Also initialize the area that will be copied over since HeapNumber |
262 // allocation below can cause an incremental marking step, requiring all | 268 // allocation below can cause an incremental marking step, requiring all |
263 // existing heap objects to be propertly initialized. | 269 // existing heap objects to be propertly initialized. |
264 int start = to_start; | 270 int start = to_start; |
265 int length = to->length() - start; | 271 int length = to_base->length() - start; |
266 if (length > 0) { | 272 if (length > 0) { |
267 Heap* heap = from->GetHeap(); | 273 Heap* heap = from_base->GetHeap(); |
268 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 274 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 275 heap->the_hole_value(), length); |
269 } | 276 } |
270 } | 277 } |
271 } | 278 } |
272 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 279 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
273 (copy_size + static_cast<int>(from_start)) <= from->length()); | 280 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
274 if (copy_size == 0) return from; | 281 if (copy_size == 0) return from_base; |
| 282 FixedDoubleArray* from = FixedDoubleArray::cast(from_base); |
| 283 FixedArray* to = FixedArray::cast(to_base); |
275 for (int i = 0; i < copy_size; ++i) { | 284 for (int i = 0; i < copy_size; ++i) { |
276 if (IsFastSmiElementsKind(to_kind)) { | 285 if (IsFastSmiElementsKind(to_kind)) { |
277 UNIMPLEMENTED(); | 286 UNIMPLEMENTED(); |
278 return Failure::Exception(); | 287 return Failure::Exception(); |
279 } else { | 288 } else { |
280 MaybeObject* maybe_value = from->get(i + from_start); | 289 MaybeObject* maybe_value = from->get(i + from_start); |
281 Object* value; | 290 Object* value; |
282 ASSERT(IsFastObjectElementsKind(to_kind)); | 291 ASSERT(IsFastObjectElementsKind(to_kind)); |
283 // Because Double -> Object elements transitions allocate HeapObjects | 292 // Because Double -> Object elements transitions allocate HeapObjects |
284 // iteratively, the allocate must succeed within a single GC cycle, | 293 // iteratively, the allocate must succeed within a single GC cycle, |
285 // otherwise the retry after the GC will also fail. In order to ensure | 294 // otherwise the retry after the GC will also fail. In order to ensure |
286 // that no GC is triggered, allocate HeapNumbers from old space if they | 295 // that no GC is triggered, allocate HeapNumbers from old space if they |
287 // can't be taken from new space. | 296 // can't be taken from new space. |
288 if (!maybe_value->ToObject(&value)) { | 297 if (!maybe_value->ToObject(&value)) { |
289 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); | 298 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); |
290 Heap* heap = from->GetHeap(); | 299 Heap* heap = from->GetHeap(); |
291 MaybeObject* maybe_value_object = | 300 MaybeObject* maybe_value_object = |
292 heap->AllocateHeapNumber(from->get_scalar(i + from_start), | 301 heap->AllocateHeapNumber(from->get_scalar(i + from_start), |
293 TENURED); | 302 TENURED); |
294 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 303 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
295 } | 304 } |
296 to->set(i + to_start, value, UPDATE_WRITE_BARRIER); | 305 to->set(i + to_start, value, UPDATE_WRITE_BARRIER); |
297 } | 306 } |
298 } | 307 } |
299 return to; | 308 return to; |
300 } | 309 } |
301 | 310 |
302 | 311 |
303 static void CopyDoubleToDoubleElements(FixedDoubleArray* from, | 312 static void CopyDoubleToDoubleElements(FixedArrayBase* from_base, |
304 uint32_t from_start, | 313 uint32_t from_start, |
305 FixedDoubleArray* to, | 314 FixedArrayBase* to_base, |
306 uint32_t to_start, | 315 uint32_t to_start, |
307 int raw_copy_size) { | 316 int raw_copy_size) { |
308 int copy_size = raw_copy_size; | 317 int copy_size = raw_copy_size; |
309 if (raw_copy_size < 0) { | 318 if (raw_copy_size < 0) { |
310 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 319 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
311 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 320 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
312 copy_size = Min(from->length() - from_start, | 321 copy_size = Min(from_base->length() - from_start, |
313 to->length() - to_start); | 322 to_base->length() - to_start); |
314 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 323 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
315 for (int i = to_start + copy_size; i < to->length(); ++i) { | 324 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
316 to->set_the_hole(i); | 325 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
317 } | 326 } |
318 } | 327 } |
319 } | 328 } |
320 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 329 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
321 (copy_size + static_cast<int>(from_start)) <= from->length()); | 330 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
322 if (copy_size == 0) return; | 331 if (copy_size == 0) return; |
| 332 FixedDoubleArray* from = FixedDoubleArray::cast(from_base); |
| 333 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
323 Address to_address = to->address() + FixedDoubleArray::kHeaderSize; | 334 Address to_address = to->address() + FixedDoubleArray::kHeaderSize; |
324 Address from_address = from->address() + FixedDoubleArray::kHeaderSize; | 335 Address from_address = from->address() + FixedDoubleArray::kHeaderSize; |
325 to_address += kDoubleSize * to_start; | 336 to_address += kDoubleSize * to_start; |
326 from_address += kDoubleSize * from_start; | 337 from_address += kDoubleSize * from_start; |
327 int words_per_double = (kDoubleSize / kPointerSize); | 338 int words_per_double = (kDoubleSize / kPointerSize); |
328 CopyWords(reinterpret_cast<Object**>(to_address), | 339 CopyWords(reinterpret_cast<Object**>(to_address), |
329 reinterpret_cast<Object**>(from_address), | 340 reinterpret_cast<Object**>(from_address), |
330 words_per_double * copy_size); | 341 words_per_double * copy_size); |
331 } | 342 } |
332 | 343 |
333 | 344 |
334 static void CopySmiToDoubleElements(FixedArray* from, | 345 static void CopySmiToDoubleElements(FixedArrayBase* from_base, |
335 uint32_t from_start, | 346 uint32_t from_start, |
336 FixedDoubleArray* to, | 347 FixedArrayBase* to_base, |
337 uint32_t to_start, | 348 uint32_t to_start, |
338 int raw_copy_size) { | 349 int raw_copy_size) { |
339 int copy_size = raw_copy_size; | 350 int copy_size = raw_copy_size; |
340 if (raw_copy_size < 0) { | 351 if (raw_copy_size < 0) { |
341 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 352 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
342 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 353 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
343 copy_size = from->length() - from_start; | 354 copy_size = from_base->length() - from_start; |
344 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 355 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
345 for (int i = to_start + copy_size; i < to->length(); ++i) { | 356 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
346 to->set_the_hole(i); | 357 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
347 } | 358 } |
348 } | 359 } |
349 } | 360 } |
350 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 361 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
351 (copy_size + static_cast<int>(from_start)) <= from->length()); | 362 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
352 if (copy_size == 0) return; | 363 if (copy_size == 0) return; |
| 364 FixedArray* from = FixedArray::cast(from_base); |
| 365 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
353 Object* the_hole = from->GetHeap()->the_hole_value(); | 366 Object* the_hole = from->GetHeap()->the_hole_value(); |
354 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size); | 367 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size); |
355 from_start < from_end; from_start++, to_start++) { | 368 from_start < from_end; from_start++, to_start++) { |
356 Object* hole_or_smi = from->get(from_start); | 369 Object* hole_or_smi = from->get(from_start); |
357 if (hole_or_smi == the_hole) { | 370 if (hole_or_smi == the_hole) { |
358 to->set_the_hole(to_start); | 371 to->set_the_hole(to_start); |
359 } else { | 372 } else { |
360 to->set(to_start, Smi::cast(hole_or_smi)->value()); | 373 to->set(to_start, Smi::cast(hole_or_smi)->value()); |
361 } | 374 } |
362 } | 375 } |
363 } | 376 } |
364 | 377 |
365 | 378 |
366 static void CopyPackedSmiToDoubleElements(FixedArray* from, | 379 static void CopyPackedSmiToDoubleElements(FixedArrayBase* from_base, |
367 uint32_t from_start, | 380 uint32_t from_start, |
368 FixedDoubleArray* to, | 381 FixedArrayBase* to_base, |
369 uint32_t to_start, | 382 uint32_t to_start, |
370 int packed_size, | 383 int packed_size, |
371 int raw_copy_size) { | 384 int raw_copy_size) { |
372 int copy_size = raw_copy_size; | 385 int copy_size = raw_copy_size; |
373 uint32_t to_end; | 386 uint32_t to_end; |
374 if (raw_copy_size < 0) { | 387 if (raw_copy_size < 0) { |
375 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 388 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
376 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 389 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
377 copy_size = from->length() - from_start; | 390 copy_size = from_base->length() - from_start; |
378 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 391 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
379 to_end = to->length(); | 392 to_end = to_base->length(); |
380 for (uint32_t i = to_start + copy_size; i < to_end; ++i) { | 393 for (uint32_t i = to_start + copy_size; i < to_end; ++i) { |
381 to->set_the_hole(i); | 394 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
382 } | 395 } |
383 } else { | 396 } else { |
384 to_end = to_start + static_cast<uint32_t>(copy_size); | 397 to_end = to_start + static_cast<uint32_t>(copy_size); |
385 } | 398 } |
386 } else { | 399 } else { |
387 to_end = to_start + static_cast<uint32_t>(copy_size); | 400 to_end = to_start + static_cast<uint32_t>(copy_size); |
388 } | 401 } |
389 ASSERT(static_cast<int>(to_end) <= to->length()); | 402 ASSERT(static_cast<int>(to_end) <= to_base->length()); |
390 ASSERT(packed_size >= 0 && packed_size <= copy_size); | 403 ASSERT(packed_size >= 0 && packed_size <= copy_size); |
391 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 404 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
392 (copy_size + static_cast<int>(from_start)) <= from->length()); | 405 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
393 if (copy_size == 0) return; | 406 if (copy_size == 0) return; |
| 407 FixedArray* from = FixedArray::cast(from_base); |
| 408 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
394 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size); | 409 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size); |
395 from_start < from_end; from_start++, to_start++) { | 410 from_start < from_end; from_start++, to_start++) { |
396 Object* smi = from->get(from_start); | 411 Object* smi = from->get(from_start); |
397 ASSERT(!smi->IsTheHole()); | 412 ASSERT(!smi->IsTheHole()); |
398 to->set(to_start, Smi::cast(smi)->value()); | 413 to->set(to_start, Smi::cast(smi)->value()); |
399 } | 414 } |
400 } | 415 } |
401 | 416 |
402 | 417 |
403 static void CopyObjectToDoubleElements(FixedArray* from, | 418 static void CopyObjectToDoubleElements(FixedArrayBase* from_base, |
404 uint32_t from_start, | 419 uint32_t from_start, |
405 FixedDoubleArray* to, | 420 FixedArrayBase* to_base, |
406 uint32_t to_start, | 421 uint32_t to_start, |
407 int raw_copy_size) { | 422 int raw_copy_size) { |
408 int copy_size = raw_copy_size; | 423 int copy_size = raw_copy_size; |
409 if (raw_copy_size < 0) { | 424 if (raw_copy_size < 0) { |
410 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 425 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
411 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 426 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
412 copy_size = from->length() - from_start; | 427 copy_size = from_base->length() - from_start; |
413 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 428 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
414 for (int i = to_start + copy_size; i < to->length(); ++i) { | 429 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
415 to->set_the_hole(i); | 430 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
416 } | 431 } |
417 } | 432 } |
418 } | 433 } |
419 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 434 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
420 (copy_size + static_cast<int>(from_start)) <= from->length()); | 435 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
421 if (copy_size == 0) return; | 436 if (copy_size == 0) return; |
| 437 FixedArray* from = FixedArray::cast(from_base); |
| 438 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
422 Object* the_hole = from->GetHeap()->the_hole_value(); | 439 Object* the_hole = from->GetHeap()->the_hole_value(); |
423 for (uint32_t from_end = from_start + copy_size; | 440 for (uint32_t from_end = from_start + copy_size; |
424 from_start < from_end; from_start++, to_start++) { | 441 from_start < from_end; from_start++, to_start++) { |
425 Object* hole_or_object = from->get(from_start); | 442 Object* hole_or_object = from->get(from_start); |
426 if (hole_or_object == the_hole) { | 443 if (hole_or_object == the_hole) { |
427 to->set_the_hole(to_start); | 444 to->set_the_hole(to_start); |
428 } else { | 445 } else { |
429 to->set(to_start, hole_or_object->Number()); | 446 to->set(to_start, hole_or_object->Number()); |
430 } | 447 } |
431 } | 448 } |
432 } | 449 } |
433 | 450 |
434 | 451 |
435 static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from, | 452 static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base, |
436 uint32_t from_start, | 453 uint32_t from_start, |
437 FixedDoubleArray* to, | 454 FixedArrayBase* to_base, |
438 uint32_t to_start, | 455 uint32_t to_start, |
439 int raw_copy_size) { | 456 int raw_copy_size) { |
| 457 SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base); |
440 int copy_size = raw_copy_size; | 458 int copy_size = raw_copy_size; |
441 if (copy_size < 0) { | 459 if (copy_size < 0) { |
442 ASSERT(copy_size == ElementsAccessor::kCopyToEnd || | 460 ASSERT(copy_size == ElementsAccessor::kCopyToEnd || |
443 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 461 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
444 copy_size = from->max_number_key() + 1 - from_start; | 462 copy_size = from->max_number_key() + 1 - from_start; |
445 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 463 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
446 for (int i = to_start + copy_size; i < to->length(); ++i) { | 464 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
447 to->set_the_hole(i); | 465 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
448 } | 466 } |
449 } | 467 } |
450 } | 468 } |
451 if (copy_size == 0) return; | 469 if (copy_size == 0) return; |
| 470 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
452 uint32_t to_length = to->length(); | 471 uint32_t to_length = to->length(); |
453 if (to_start + copy_size > to_length) { | 472 if (to_start + copy_size > to_length) { |
454 copy_size = to_length - to_start; | 473 copy_size = to_length - to_start; |
455 } | 474 } |
456 for (int i = 0; i < copy_size; i++) { | 475 for (int i = 0; i < copy_size; i++) { |
457 int entry = from->FindEntry(i + from_start); | 476 int entry = from->FindEntry(i + from_start); |
458 if (entry != SeededNumberDictionary::kNotFound) { | 477 if (entry != SeededNumberDictionary::kNotFound) { |
459 to->set(i + to_start, from->ValueAt(entry)->Number()); | 478 to->set(i + to_start, from->ValueAt(entry)->Number()); |
460 } else { | 479 } else { |
461 to->set_the_hole(i + to_start); | 480 to->set_the_hole(i + to_start); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 } | 553 } |
535 | 554 |
536 virtual bool HasElement(Object* receiver, | 555 virtual bool HasElement(Object* receiver, |
537 JSObject* holder, | 556 JSObject* holder, |
538 uint32_t key, | 557 uint32_t key, |
539 FixedArrayBase* backing_store) { | 558 FixedArrayBase* backing_store) { |
540 if (backing_store == NULL) { | 559 if (backing_store == NULL) { |
541 backing_store = holder->elements(); | 560 backing_store = holder->elements(); |
542 } | 561 } |
543 return ElementsAccessorSubclass::HasElementImpl( | 562 return ElementsAccessorSubclass::HasElementImpl( |
544 receiver, holder, key, BackingStore::cast(backing_store)); | 563 receiver, holder, key, backing_store); |
545 } | 564 } |
546 | 565 |
547 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver, | 566 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver, |
548 JSObject* holder, | 567 JSObject* holder, |
549 uint32_t key, | 568 uint32_t key, |
550 FixedArrayBase* backing_store) { | 569 FixedArrayBase* backing_store) { |
551 if (backing_store == NULL) { | 570 if (backing_store == NULL) { |
552 backing_store = holder->elements(); | 571 backing_store = holder->elements(); |
553 } | 572 } |
554 return ElementsAccessorSubclass::GetImpl( | 573 return ElementsAccessorSubclass::GetImpl( |
555 receiver, holder, key, BackingStore::cast(backing_store)); | 574 receiver, holder, key, backing_store); |
556 } | 575 } |
557 | 576 |
558 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 577 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
559 JSObject* obj, | 578 JSObject* obj, |
560 uint32_t key, | 579 uint32_t key, |
561 BackingStore* backing_store) { | 580 FixedArrayBase* backing_store) { |
562 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) | 581 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) |
563 ? backing_store->get(key) | 582 ? BackingStore::cast(backing_store)->get(key) |
564 : backing_store->GetHeap()->the_hole_value(); | 583 : backing_store->GetHeap()->the_hole_value(); |
565 } | 584 } |
566 | 585 |
567 MUST_USE_RESULT virtual PropertyAttributes GetAttributes( | 586 MUST_USE_RESULT virtual PropertyAttributes GetAttributes( |
568 Object* receiver, | 587 Object* receiver, |
569 JSObject* holder, | 588 JSObject* holder, |
570 uint32_t key, | 589 uint32_t key, |
571 FixedArrayBase* backing_store) { | 590 FixedArrayBase* backing_store) { |
572 if (backing_store == NULL) { | 591 if (backing_store == NULL) { |
573 backing_store = holder->elements(); | 592 backing_store = holder->elements(); |
(...skipping 15 matching lines...) Expand all Loading... |
589 | 608 |
590 MUST_USE_RESULT virtual PropertyType GetType( | 609 MUST_USE_RESULT virtual PropertyType GetType( |
591 Object* receiver, | 610 Object* receiver, |
592 JSObject* holder, | 611 JSObject* holder, |
593 uint32_t key, | 612 uint32_t key, |
594 FixedArrayBase* backing_store) { | 613 FixedArrayBase* backing_store) { |
595 if (backing_store == NULL) { | 614 if (backing_store == NULL) { |
596 backing_store = holder->elements(); | 615 backing_store = holder->elements(); |
597 } | 616 } |
598 return ElementsAccessorSubclass::GetTypeImpl( | 617 return ElementsAccessorSubclass::GetTypeImpl( |
599 receiver, holder, key, BackingStore::cast(backing_store)); | 618 receiver, holder, key, backing_store); |
600 } | 619 } |
601 | 620 |
602 MUST_USE_RESULT static PropertyType GetTypeImpl( | 621 MUST_USE_RESULT static PropertyType GetTypeImpl( |
603 Object* receiver, | 622 Object* receiver, |
604 JSObject* obj, | 623 JSObject* obj, |
605 uint32_t key, | 624 uint32_t key, |
606 BackingStore* backing_store) { | 625 FixedArrayBase* backing_store) { |
607 if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { | 626 if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { |
608 return NONEXISTENT; | 627 return NONEXISTENT; |
609 } | 628 } |
610 return backing_store->is_the_hole(key) ? NONEXISTENT : FIELD; | 629 return BackingStore::cast(backing_store)->is_the_hole(key) |
| 630 ? NONEXISTENT : FIELD; |
611 } | 631 } |
612 | 632 |
613 MUST_USE_RESULT virtual AccessorPair* GetAccessorPair( | 633 MUST_USE_RESULT virtual AccessorPair* GetAccessorPair( |
614 Object* receiver, | 634 Object* receiver, |
615 JSObject* holder, | 635 JSObject* holder, |
616 uint32_t key, | 636 uint32_t key, |
617 FixedArrayBase* backing_store) { | 637 FixedArrayBase* backing_store) { |
618 if (backing_store == NULL) { | 638 if (backing_store == NULL) { |
619 backing_store = holder->elements(); | 639 backing_store = holder->elements(); |
620 } | 640 } |
621 return ElementsAccessorSubclass::GetAccessorPairImpl( | 641 return ElementsAccessorSubclass::GetAccessorPairImpl( |
622 receiver, holder, key, BackingStore::cast(backing_store)); | 642 receiver, holder, key, backing_store); |
623 } | 643 } |
624 | 644 |
625 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 645 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
626 Object* receiver, | 646 Object* receiver, |
627 JSObject* obj, | 647 JSObject* obj, |
628 uint32_t key, | 648 uint32_t key, |
629 BackingStore* backing_store) { | 649 FixedArrayBase* backing_store) { |
630 return NULL; | 650 return NULL; |
631 } | 651 } |
632 | 652 |
633 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, | 653 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, |
634 Object* length) { | 654 Object* length) { |
635 return ElementsAccessorSubclass::SetLengthImpl( | 655 return ElementsAccessorSubclass::SetLengthImpl( |
636 array, length, BackingStore::cast(array->elements())); | 656 array, length, array->elements()); |
637 } | 657 } |
638 | 658 |
639 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 659 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
640 JSObject* obj, | 660 JSObject* obj, |
641 Object* length, | 661 Object* length, |
642 BackingStore* backing_store); | 662 FixedArrayBase* backing_store); |
643 | 663 |
644 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( | 664 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( |
645 JSArray* array, | 665 JSArray* array, |
646 int capacity, | 666 int capacity, |
647 int length) { | 667 int length) { |
648 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 668 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
649 array, | 669 array, |
650 capacity, | 670 capacity, |
651 length); | 671 length); |
652 } | 672 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 #ifdef DEBUG | 730 #ifdef DEBUG |
711 if (FLAG_enable_slow_asserts) { | 731 if (FLAG_enable_slow_asserts) { |
712 for (int i = 0; i < len0; i++) { | 732 for (int i = 0; i < len0; i++) { |
713 ASSERT(!to->get(i)->IsTheHole()); | 733 ASSERT(!to->get(i)->IsTheHole()); |
714 } | 734 } |
715 } | 735 } |
716 #endif | 736 #endif |
717 if (from == NULL) { | 737 if (from == NULL) { |
718 from = holder->elements(); | 738 from = holder->elements(); |
719 } | 739 } |
720 BackingStore* backing_store = BackingStore::cast(from); | |
721 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); | |
722 | 740 |
723 // Optimize if 'other' is empty. | 741 // Optimize if 'other' is empty. |
724 // We cannot optimize if 'this' is empty, as other may have holes. | 742 // We cannot optimize if 'this' is empty, as other may have holes. |
| 743 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(from); |
725 if (len1 == 0) return to; | 744 if (len1 == 0) return to; |
726 | 745 |
727 // Compute how many elements are not in other. | 746 // Compute how many elements are not in other. |
728 uint32_t extra = 0; | 747 uint32_t extra = 0; |
729 for (uint32_t y = 0; y < len1; y++) { | 748 for (uint32_t y = 0; y < len1; y++) { |
730 uint32_t key = | 749 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); |
731 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | |
732 if (ElementsAccessorSubclass::HasElementImpl( | 750 if (ElementsAccessorSubclass::HasElementImpl( |
733 receiver, holder, key, backing_store)) { | 751 receiver, holder, key, from)) { |
734 MaybeObject* maybe_value = | 752 MaybeObject* maybe_value = |
735 ElementsAccessorSubclass::GetImpl(receiver, holder, | 753 ElementsAccessorSubclass::GetImpl(receiver, holder, key, from); |
736 key, backing_store); | |
737 Object* value; | 754 Object* value; |
738 if (!maybe_value->ToObject(&value)) return maybe_value; | 755 if (!maybe_value->To(&value)) return maybe_value; |
739 ASSERT(!value->IsTheHole()); | 756 ASSERT(!value->IsTheHole()); |
740 if (!HasKey(to, value)) { | 757 if (!HasKey(to, value)) { |
741 extra++; | 758 extra++; |
742 } | 759 } |
743 } | 760 } |
744 } | 761 } |
745 | 762 |
746 if (extra == 0) return to; | 763 if (extra == 0) return to; |
747 | 764 |
748 // Allocate the result | 765 // Allocate the result |
749 FixedArray* result; | 766 FixedArray* result; |
750 MaybeObject* maybe_obj = | 767 MaybeObject* maybe_obj = from->GetHeap()->AllocateFixedArray(len0 + extra); |
751 backing_store->GetHeap()->AllocateFixedArray(len0 + extra); | 768 if (!maybe_obj->To(&result)) return maybe_obj; |
752 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; | |
753 | 769 |
754 // Fill in the content | 770 // Fill in the content |
755 { | 771 { |
756 AssertNoAllocation no_gc; | 772 AssertNoAllocation no_gc; |
757 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 773 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
758 for (int i = 0; i < len0; i++) { | 774 for (int i = 0; i < len0; i++) { |
759 Object* e = to->get(i); | 775 Object* e = to->get(i); |
760 ASSERT(e->IsString() || e->IsNumber()); | 776 ASSERT(e->IsString() || e->IsNumber()); |
761 result->set(i, e, mode); | 777 result->set(i, e, mode); |
762 } | 778 } |
763 } | 779 } |
764 // Fill in the extra values. | 780 // Fill in the extra values. |
765 uint32_t index = 0; | 781 uint32_t index = 0; |
766 for (uint32_t y = 0; y < len1; y++) { | 782 for (uint32_t y = 0; y < len1; y++) { |
767 uint32_t key = | 783 uint32_t key = |
768 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | 784 ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); |
769 if (ElementsAccessorSubclass::HasElementImpl( | 785 if (ElementsAccessorSubclass::HasElementImpl( |
770 receiver, holder, key, backing_store)) { | 786 receiver, holder, key, from)) { |
771 MaybeObject* maybe_value = | 787 MaybeObject* maybe_value = |
772 ElementsAccessorSubclass::GetImpl(receiver, holder, | 788 ElementsAccessorSubclass::GetImpl(receiver, holder, key, from); |
773 key, backing_store); | |
774 Object* value; | 789 Object* value; |
775 if (!maybe_value->ToObject(&value)) return maybe_value; | 790 if (!maybe_value->To(&value)) return maybe_value; |
776 if (!value->IsTheHole() && !HasKey(to, value)) { | 791 if (!value->IsTheHole() && !HasKey(to, value)) { |
777 result->set(len0 + index, value); | 792 result->set(len0 + index, value); |
778 index++; | 793 index++; |
779 } | 794 } |
780 } | 795 } |
781 } | 796 } |
782 ASSERT(extra == index); | 797 ASSERT(extra == index); |
783 return result; | 798 return result; |
784 } | 799 } |
785 | 800 |
786 protected: | 801 protected: |
787 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { | 802 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { |
788 return backing_store->length(); | 803 return backing_store->length(); |
789 } | 804 } |
790 | 805 |
791 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { | 806 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { |
792 return ElementsAccessorSubclass::GetCapacityImpl(backing_store); | 807 return ElementsAccessorSubclass::GetCapacityImpl(backing_store); |
793 } | 808 } |
794 | 809 |
795 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store, | 810 static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store, |
796 uint32_t index) { | 811 uint32_t index) { |
797 return index; | 812 return index; |
798 } | 813 } |
799 | 814 |
800 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 815 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, |
801 uint32_t index) { | 816 uint32_t index) { |
802 return ElementsAccessorSubclass::GetKeyForIndexImpl( | 817 return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); |
803 BackingStore::cast(backing_store), index); | |
804 } | 818 } |
805 | 819 |
806 private: | 820 private: |
807 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 821 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
808 }; | 822 }; |
809 | 823 |
810 | 824 |
811 // Super class for all fast element arrays. | 825 // Super class for all fast element arrays. |
812 template<typename FastElementsAccessorSubclass, | 826 template<typename FastElementsAccessorSubclass, |
813 typename KindTraits, | 827 typename KindTraits, |
814 int ElementSize> | 828 int ElementSize> |
815 class FastElementsAccessor | 829 class FastElementsAccessor |
816 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 830 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
817 public: | 831 public: |
818 explicit FastElementsAccessor(const char* name) | 832 explicit FastElementsAccessor(const char* name) |
819 : ElementsAccessorBase<FastElementsAccessorSubclass, | 833 : ElementsAccessorBase<FastElementsAccessorSubclass, |
820 KindTraits>(name) {} | 834 KindTraits>(name) {} |
821 protected: | 835 protected: |
822 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 836 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
823 friend class NonStrictArgumentsElementsAccessor; | 837 friend class NonStrictArgumentsElementsAccessor; |
824 | 838 |
825 typedef typename KindTraits::BackingStore BackingStore; | 839 typedef typename KindTraits::BackingStore BackingStore; |
826 | 840 |
827 // Adjusts the length of the fast backing store or returns the new length or | 841 // Adjusts the length of the fast backing store or returns the new length or |
828 // undefined in case conversion to a slow backing store should be performed. | 842 // undefined in case conversion to a slow backing store should be performed. |
829 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 843 static MaybeObject* SetLengthWithoutNormalize(FixedArrayBase* backing_store, |
830 JSArray* array, | 844 JSArray* array, |
831 Object* length_object, | 845 Object* length_object, |
832 uint32_t length) { | 846 uint32_t length) { |
833 uint32_t old_capacity = backing_store->length(); | 847 uint32_t old_capacity = backing_store->length(); |
834 Object* old_length = array->length(); | 848 Object* old_length = array->length(); |
835 bool same_or_smaller_size = old_length->IsSmi() && | 849 bool same_or_smaller_size = old_length->IsSmi() && |
836 static_cast<uint32_t>(Smi::cast(old_length)->value()) >= length; | 850 static_cast<uint32_t>(Smi::cast(old_length)->value()) >= length; |
837 ElementsKind kind = array->GetElementsKind(); | 851 ElementsKind kind = array->GetElementsKind(); |
838 | 852 |
839 if (!same_or_smaller_size && IsFastElementsKind(kind) && | 853 if (!same_or_smaller_size && IsFastElementsKind(kind) && |
(...skipping 17 matching lines...) Expand all Loading... |
857 backing_store->set_length(length); | 871 backing_store->set_length(length); |
858 Address filler_start = backing_store->address() + | 872 Address filler_start = backing_store->address() + |
859 BackingStore::OffsetOfElementAt(length); | 873 BackingStore::OffsetOfElementAt(length); |
860 int filler_size = (old_capacity - length) * ElementSize; | 874 int filler_size = (old_capacity - length) * ElementSize; |
861 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 875 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
862 } | 876 } |
863 } else { | 877 } else { |
864 // Otherwise, fill the unused tail with holes. | 878 // Otherwise, fill the unused tail with holes. |
865 int old_length = FastD2IChecked(array->length()->Number()); | 879 int old_length = FastD2IChecked(array->length()->Number()); |
866 for (int i = length; i < old_length; i++) { | 880 for (int i = length; i < old_length; i++) { |
867 backing_store->set_the_hole(i); | 881 BackingStore::cast(backing_store)->set_the_hole(i); |
868 } | 882 } |
869 } | 883 } |
870 return length_object; | 884 return length_object; |
871 } | 885 } |
872 | 886 |
873 // Check whether the backing store should be expanded. | 887 // Check whether the backing store should be expanded. |
874 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 888 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
875 uint32_t new_capacity = length > min ? length : min; | 889 uint32_t new_capacity = length > min ? length : min; |
876 if (!array->ShouldConvertToSlowElements(new_capacity)) { | 890 if (!array->ShouldConvertToSlowElements(new_capacity)) { |
877 MaybeObject* result = FastElementsAccessorSubclass:: | 891 MaybeObject* result = FastElementsAccessorSubclass:: |
(...skipping 16 matching lines...) Expand all Loading... |
894 Heap* heap = obj->GetHeap(); | 908 Heap* heap = obj->GetHeap(); |
895 Object* elements = obj->elements(); | 909 Object* elements = obj->elements(); |
896 if (elements == heap->empty_fixed_array()) { | 910 if (elements == heap->empty_fixed_array()) { |
897 return heap->true_value(); | 911 return heap->true_value(); |
898 } | 912 } |
899 typename KindTraits::BackingStore* backing_store = | 913 typename KindTraits::BackingStore* backing_store = |
900 KindTraits::BackingStore::cast(elements); | 914 KindTraits::BackingStore::cast(elements); |
901 bool is_non_strict_arguments_elements_map = | 915 bool is_non_strict_arguments_elements_map = |
902 backing_store->map() == heap->non_strict_arguments_elements_map(); | 916 backing_store->map() == heap->non_strict_arguments_elements_map(); |
903 if (is_non_strict_arguments_elements_map) { | 917 if (is_non_strict_arguments_elements_map) { |
904 backing_store = | 918 backing_store = KindTraits::BackingStore::cast( |
905 KindTraits::BackingStore::cast( | 919 FixedArray::cast(backing_store)->get(1)); |
906 FixedArray::cast(backing_store)->get(1)); | |
907 } | 920 } |
908 uint32_t length = static_cast<uint32_t>( | 921 uint32_t length = static_cast<uint32_t>( |
909 obj->IsJSArray() | 922 obj->IsJSArray() |
910 ? Smi::cast(JSArray::cast(obj)->length())->value() | 923 ? Smi::cast(JSArray::cast(obj)->length())->value() |
911 : backing_store->length()); | 924 : backing_store->length()); |
912 if (key < length) { | 925 if (key < length) { |
913 if (!is_non_strict_arguments_elements_map) { | 926 if (!is_non_strict_arguments_elements_map) { |
914 ElementsKind kind = KindTraits::Kind; | 927 ElementsKind kind = KindTraits::Kind; |
915 if (IsFastPackedElementsKind(kind)) { | 928 if (IsFastPackedElementsKind(kind)) { |
916 MaybeObject* transitioned = | 929 MaybeObject* transitioned = |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 virtual MaybeObject* Delete(JSObject* obj, | 965 virtual MaybeObject* Delete(JSObject* obj, |
953 uint32_t key, | 966 uint32_t key, |
954 JSReceiver::DeleteMode mode) { | 967 JSReceiver::DeleteMode mode) { |
955 return DeleteCommon(obj, key, mode); | 968 return DeleteCommon(obj, key, mode); |
956 } | 969 } |
957 | 970 |
958 static bool HasElementImpl( | 971 static bool HasElementImpl( |
959 Object* receiver, | 972 Object* receiver, |
960 JSObject* holder, | 973 JSObject* holder, |
961 uint32_t key, | 974 uint32_t key, |
962 typename KindTraits::BackingStore* backing_store) { | 975 FixedArrayBase* backing_store) { |
963 if (key >= static_cast<uint32_t>(backing_store->length())) { | 976 if (key >= static_cast<uint32_t>(backing_store->length())) { |
964 return false; | 977 return false; |
965 } | 978 } |
966 return !backing_store->is_the_hole(key); | 979 return !BackingStore::cast(backing_store)->is_the_hole(key); |
967 } | 980 } |
968 | 981 |
969 static void ValidateContents(JSObject* holder, int length) { | 982 static void ValidateContents(JSObject* holder, int length) { |
970 #if DEBUG | 983 #if DEBUG |
971 FixedArrayBase* elements = holder->elements(); | 984 FixedArrayBase* elements = holder->elements(); |
972 Heap* heap = elements->GetHeap(); | 985 Heap* heap = elements->GetHeap(); |
973 Map* map = elements->map(); | 986 Map* map = elements->map(); |
974 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | 987 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && |
975 (map == heap->fixed_array_map() || | 988 (map == heap->fixed_array_map() || |
976 map == heap->fixed_cow_array_map())) || | 989 map == heap->fixed_cow_array_map())) || |
(...skipping 27 matching lines...) Expand all Loading... |
1004 | 1017 |
1005 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1018 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1006 uint32_t from_start, | 1019 uint32_t from_start, |
1007 FixedArrayBase* to, | 1020 FixedArrayBase* to, |
1008 ElementsKind to_kind, | 1021 ElementsKind to_kind, |
1009 uint32_t to_start, | 1022 uint32_t to_start, |
1010 int packed_size, | 1023 int packed_size, |
1011 int copy_size) { | 1024 int copy_size) { |
1012 if (IsFastSmiOrObjectElementsKind(to_kind)) { | 1025 if (IsFastSmiOrObjectElementsKind(to_kind)) { |
1013 CopyObjectToObjectElements( | 1026 CopyObjectToObjectElements( |
1014 FixedArray::cast(from), KindTraits::Kind, from_start, | 1027 from, KindTraits::Kind, from_start, to, to_kind, to_start, copy_size); |
1015 FixedArray::cast(to), to_kind, to_start, copy_size); | |
1016 } else if (IsFastDoubleElementsKind(to_kind)) { | 1028 } else if (IsFastDoubleElementsKind(to_kind)) { |
1017 if (IsFastSmiElementsKind(KindTraits::Kind)) { | 1029 if (IsFastSmiElementsKind(KindTraits::Kind)) { |
1018 if (IsFastPackedElementsKind(KindTraits::Kind) && | 1030 if (IsFastPackedElementsKind(KindTraits::Kind) && |
1019 packed_size != kPackedSizeNotKnown) { | 1031 packed_size != kPackedSizeNotKnown) { |
1020 CopyPackedSmiToDoubleElements( | 1032 CopyPackedSmiToDoubleElements( |
1021 FixedArray::cast(from), from_start, | 1033 from, from_start, to, to_start, packed_size, copy_size); |
1022 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, | |
1023 packed_size, copy_size); | |
1024 } else { | 1034 } else { |
1025 CopySmiToDoubleElements( | 1035 CopySmiToDoubleElements(from, from_start, to, to_start, copy_size); |
1026 FixedArray::cast(from), from_start, | |
1027 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | |
1028 } | 1036 } |
1029 } else { | 1037 } else { |
1030 CopyObjectToDoubleElements( | 1038 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); |
1031 FixedArray::cast(from), from_start, | |
1032 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | |
1033 } | 1039 } |
1034 } else { | 1040 } else { |
1035 UNREACHABLE(); | 1041 UNREACHABLE(); |
1036 } | 1042 } |
1037 return to->GetHeap()->undefined_value(); | 1043 return to->GetHeap()->undefined_value(); |
1038 } | 1044 } |
1039 | 1045 |
1040 | 1046 |
1041 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 1047 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
1042 uint32_t capacity, | 1048 uint32_t capacity, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 ElementsKind to_kind, | 1132 ElementsKind to_kind, |
1127 uint32_t to_start, | 1133 uint32_t to_start, |
1128 int packed_size, | 1134 int packed_size, |
1129 int copy_size) { | 1135 int copy_size) { |
1130 switch (to_kind) { | 1136 switch (to_kind) { |
1131 case FAST_SMI_ELEMENTS: | 1137 case FAST_SMI_ELEMENTS: |
1132 case FAST_ELEMENTS: | 1138 case FAST_ELEMENTS: |
1133 case FAST_HOLEY_SMI_ELEMENTS: | 1139 case FAST_HOLEY_SMI_ELEMENTS: |
1134 case FAST_HOLEY_ELEMENTS: | 1140 case FAST_HOLEY_ELEMENTS: |
1135 return CopyDoubleToObjectElements( | 1141 return CopyDoubleToObjectElements( |
1136 FixedDoubleArray::castOrEmptyFixedArray(from), from_start, | 1142 from, from_start, to, to_kind, to_start, copy_size); |
1137 FixedArray::cast(to), to_kind, to_start, copy_size); | |
1138 case FAST_DOUBLE_ELEMENTS: | 1143 case FAST_DOUBLE_ELEMENTS: |
1139 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1144 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1140 CopyDoubleToDoubleElements( | 1145 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); |
1141 FixedDoubleArray::castOrEmptyFixedArray(from), from_start, | |
1142 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | |
1143 return from; | 1146 return from; |
1144 default: | 1147 default: |
1145 UNREACHABLE(); | 1148 UNREACHABLE(); |
1146 } | 1149 } |
1147 return to->GetHeap()->undefined_value(); | 1150 return to->GetHeap()->undefined_value(); |
1148 } | 1151 } |
1149 }; | 1152 }; |
1150 | 1153 |
1151 | 1154 |
1152 class FastPackedDoubleElementsAccessor | 1155 class FastPackedDoubleElementsAccessor |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 | 1194 |
1192 protected: | 1195 protected: |
1193 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1196 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
1194 | 1197 |
1195 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, | 1198 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, |
1196 ElementsKindTraits<Kind> >; | 1199 ElementsKindTraits<Kind> >; |
1197 | 1200 |
1198 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 1201 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
1199 JSObject* obj, | 1202 JSObject* obj, |
1200 uint32_t key, | 1203 uint32_t key, |
1201 BackingStore* backing_store) { | 1204 FixedArrayBase* backing_store) { |
1202 return | 1205 return |
1203 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1206 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
1204 ? backing_store->get(key) | 1207 ? BackingStore::cast(backing_store)->get(key) |
1205 : backing_store->GetHeap()->undefined_value(); | 1208 : backing_store->GetHeap()->undefined_value(); |
1206 } | 1209 } |
1207 | 1210 |
1208 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 1211 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( |
1209 Object* receiver, | 1212 Object* receiver, |
1210 JSObject* obj, | 1213 JSObject* obj, |
1211 uint32_t key, | 1214 uint32_t key, |
1212 FixedArrayBase* backing_store) { | 1215 FixedArrayBase* backing_store) { |
1213 return | 1216 return |
1214 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1217 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
1215 ? NONE : ABSENT; | 1218 ? NONE : ABSENT; |
1216 } | 1219 } |
1217 | 1220 |
1218 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1221 MUST_USE_RESULT static PropertyType GetTypeImpl( |
1219 Object* receiver, | 1222 Object* receiver, |
1220 JSObject* obj, | 1223 JSObject* obj, |
1221 uint32_t key, | 1224 uint32_t key, |
1222 BackingStore* backing_store) { | 1225 FixedArrayBase* backing_store) { |
1223 return | 1226 return |
1224 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1227 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
1225 ? FIELD : NONEXISTENT; | 1228 ? FIELD : NONEXISTENT; |
1226 } | 1229 } |
1227 | 1230 |
1228 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1231 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
1229 JSObject* obj, | 1232 JSObject* obj, |
1230 Object* length, | 1233 Object* length, |
1231 BackingStore* backing_store) { | 1234 FixedArrayBase* backing_store) { |
1232 // External arrays do not support changing their length. | 1235 // External arrays do not support changing their length. |
1233 UNREACHABLE(); | 1236 UNREACHABLE(); |
1234 return obj; | 1237 return obj; |
1235 } | 1238 } |
1236 | 1239 |
1237 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1240 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
1238 uint32_t key, | 1241 uint32_t key, |
1239 JSReceiver::DeleteMode mode) { | 1242 JSReceiver::DeleteMode mode) { |
1240 // External arrays always ignore deletes. | 1243 // External arrays always ignore deletes. |
1241 return obj->GetHeap()->true_value(); | 1244 return obj->GetHeap()->true_value(); |
1242 } | 1245 } |
1243 | 1246 |
1244 static bool HasElementImpl(Object* receiver, | 1247 static bool HasElementImpl(Object* receiver, |
1245 JSObject* holder, | 1248 JSObject* holder, |
1246 uint32_t key, | 1249 uint32_t key, |
1247 BackingStore* backing_store) { | 1250 FixedArrayBase* backing_store) { |
1248 uint32_t capacity = | 1251 uint32_t capacity = |
1249 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); | 1252 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); |
1250 return key < capacity; | 1253 return key < capacity; |
1251 } | 1254 } |
1252 }; | 1255 }; |
1253 | 1256 |
1254 | 1257 |
1255 class ExternalByteElementsAccessor | 1258 class ExternalByteElementsAccessor |
1256 : public ExternalElementsAccessor<ExternalByteElementsAccessor, | 1259 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
1257 EXTERNAL_BYTE_ELEMENTS> { | 1260 EXTERNAL_BYTE_ELEMENTS> { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 : public ElementsAccessorBase<DictionaryElementsAccessor, | 1349 : public ElementsAccessorBase<DictionaryElementsAccessor, |
1347 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 1350 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
1348 public: | 1351 public: |
1349 explicit DictionaryElementsAccessor(const char* name) | 1352 explicit DictionaryElementsAccessor(const char* name) |
1350 : ElementsAccessorBase<DictionaryElementsAccessor, | 1353 : ElementsAccessorBase<DictionaryElementsAccessor, |
1351 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 1354 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
1352 | 1355 |
1353 // Adjusts the length of the dictionary backing store and returns the new | 1356 // Adjusts the length of the dictionary backing store and returns the new |
1354 // length according to ES5 section 15.4.5.2 behavior. | 1357 // length according to ES5 section 15.4.5.2 behavior. |
1355 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize( | 1358 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize( |
1356 SeededNumberDictionary* dict, | 1359 FixedArrayBase* store, |
1357 JSArray* array, | 1360 JSArray* array, |
1358 Object* length_object, | 1361 Object* length_object, |
1359 uint32_t length) { | 1362 uint32_t length) { |
| 1363 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
1360 Heap* heap = array->GetHeap(); | 1364 Heap* heap = array->GetHeap(); |
1361 int capacity = dict->Capacity(); | 1365 int capacity = dict->Capacity(); |
1362 uint32_t new_length = length; | 1366 uint32_t new_length = length; |
1363 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); | 1367 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); |
1364 if (new_length < old_length) { | 1368 if (new_length < old_length) { |
1365 // Find last non-deletable element in range of elements to be | 1369 // Find last non-deletable element in range of elements to be |
1366 // deleted and adjust range accordingly. | 1370 // deleted and adjust range accordingly. |
1367 for (int i = 0; i < capacity; i++) { | 1371 for (int i = 0; i < capacity; i++) { |
1368 Object* key = dict->KeyAt(i); | 1372 Object* key = dict->KeyAt(i); |
1369 if (key->IsNumber()) { | 1373 if (key->IsNumber()) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 ElementsKind to_kind, | 1463 ElementsKind to_kind, |
1460 uint32_t to_start, | 1464 uint32_t to_start, |
1461 int packed_size, | 1465 int packed_size, |
1462 int copy_size) { | 1466 int copy_size) { |
1463 switch (to_kind) { | 1467 switch (to_kind) { |
1464 case FAST_SMI_ELEMENTS: | 1468 case FAST_SMI_ELEMENTS: |
1465 case FAST_ELEMENTS: | 1469 case FAST_ELEMENTS: |
1466 case FAST_HOLEY_SMI_ELEMENTS: | 1470 case FAST_HOLEY_SMI_ELEMENTS: |
1467 case FAST_HOLEY_ELEMENTS: | 1471 case FAST_HOLEY_ELEMENTS: |
1468 CopyDictionaryToObjectElements( | 1472 CopyDictionaryToObjectElements( |
1469 SeededNumberDictionary::cast(from), from_start, | 1473 from, from_start, to, to_kind, to_start, copy_size); |
1470 FixedArray::cast(to), to_kind, to_start, copy_size); | |
1471 return from; | 1474 return from; |
1472 case FAST_DOUBLE_ELEMENTS: | 1475 case FAST_DOUBLE_ELEMENTS: |
1473 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1476 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1474 CopyDictionaryToDoubleElements( | 1477 CopyDictionaryToDoubleElements( |
1475 SeededNumberDictionary::cast(from), from_start, | 1478 from, from_start, to, to_start, copy_size); |
1476 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, | |
1477 copy_size); | |
1478 return from; | 1479 return from; |
1479 default: | 1480 default: |
1480 UNREACHABLE(); | 1481 UNREACHABLE(); |
1481 } | 1482 } |
1482 return to->GetHeap()->undefined_value(); | 1483 return to->GetHeap()->undefined_value(); |
1483 } | 1484 } |
1484 | 1485 |
1485 | 1486 |
1486 protected: | 1487 protected: |
1487 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 1488 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
1488 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | 1489 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
1489 | 1490 |
1490 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1491 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
1491 uint32_t key, | 1492 uint32_t key, |
1492 JSReceiver::DeleteMode mode) { | 1493 JSReceiver::DeleteMode mode) { |
1493 return DeleteCommon(obj, key, mode); | 1494 return DeleteCommon(obj, key, mode); |
1494 } | 1495 } |
1495 | 1496 |
1496 MUST_USE_RESULT static MaybeObject* GetImpl( | 1497 MUST_USE_RESULT static MaybeObject* GetImpl( |
1497 Object* receiver, | 1498 Object* receiver, |
1498 JSObject* obj, | 1499 JSObject* obj, |
1499 uint32_t key, | 1500 uint32_t key, |
1500 SeededNumberDictionary* backing_store) { | 1501 FixedArrayBase* store) { |
| 1502 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
1501 int entry = backing_store->FindEntry(key); | 1503 int entry = backing_store->FindEntry(key); |
1502 if (entry != SeededNumberDictionary::kNotFound) { | 1504 if (entry != SeededNumberDictionary::kNotFound) { |
1503 Object* element = backing_store->ValueAt(entry); | 1505 Object* element = backing_store->ValueAt(entry); |
1504 PropertyDetails details = backing_store->DetailsAt(entry); | 1506 PropertyDetails details = backing_store->DetailsAt(entry); |
1505 if (details.type() == CALLBACKS) { | 1507 if (details.type() == CALLBACKS) { |
1506 return obj->GetElementWithCallback(receiver, | 1508 return obj->GetElementWithCallback(receiver, |
1507 element, | 1509 element, |
1508 key, | 1510 key, |
1509 obj); | 1511 obj); |
1510 } else { | 1512 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
1525 if (entry != SeededNumberDictionary::kNotFound) { | 1527 if (entry != SeededNumberDictionary::kNotFound) { |
1526 return dictionary->DetailsAt(entry).attributes(); | 1528 return dictionary->DetailsAt(entry).attributes(); |
1527 } | 1529 } |
1528 return ABSENT; | 1530 return ABSENT; |
1529 } | 1531 } |
1530 | 1532 |
1531 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1533 MUST_USE_RESULT static PropertyType GetTypeImpl( |
1532 Object* receiver, | 1534 Object* receiver, |
1533 JSObject* obj, | 1535 JSObject* obj, |
1534 uint32_t key, | 1536 uint32_t key, |
1535 SeededNumberDictionary* backing_store) { | 1537 FixedArrayBase* store) { |
| 1538 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
1536 int entry = backing_store->FindEntry(key); | 1539 int entry = backing_store->FindEntry(key); |
1537 if (entry != SeededNumberDictionary::kNotFound) { | 1540 if (entry != SeededNumberDictionary::kNotFound) { |
1538 return backing_store->DetailsAt(entry).type(); | 1541 return backing_store->DetailsAt(entry).type(); |
1539 } | 1542 } |
1540 return NONEXISTENT; | 1543 return NONEXISTENT; |
1541 } | 1544 } |
1542 | 1545 |
1543 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 1546 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
1544 Object* receiver, | 1547 Object* receiver, |
1545 JSObject* obj, | 1548 JSObject* obj, |
1546 uint32_t key, | 1549 uint32_t key, |
1547 BackingStore* backing_store) { | 1550 FixedArrayBase* store) { |
| 1551 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
1548 int entry = backing_store->FindEntry(key); | 1552 int entry = backing_store->FindEntry(key); |
1549 if (entry != SeededNumberDictionary::kNotFound && | 1553 if (entry != SeededNumberDictionary::kNotFound && |
1550 backing_store->DetailsAt(entry).type() == CALLBACKS && | 1554 backing_store->DetailsAt(entry).type() == CALLBACKS && |
1551 backing_store->ValueAt(entry)->IsAccessorPair()) { | 1555 backing_store->ValueAt(entry)->IsAccessorPair()) { |
1552 return AccessorPair::cast(backing_store->ValueAt(entry)); | 1556 return AccessorPair::cast(backing_store->ValueAt(entry)); |
1553 } | 1557 } |
1554 return NULL; | 1558 return NULL; |
1555 } | 1559 } |
1556 | 1560 |
1557 static bool HasElementImpl(Object* receiver, | 1561 static bool HasElementImpl(Object* receiver, |
1558 JSObject* holder, | 1562 JSObject* holder, |
1559 uint32_t key, | 1563 uint32_t key, |
1560 SeededNumberDictionary* backing_store) { | 1564 FixedArrayBase* backing_store) { |
1561 return backing_store->FindEntry(key) != | 1565 return SeededNumberDictionary::cast(backing_store)->FindEntry(key) != |
1562 SeededNumberDictionary::kNotFound; | 1566 SeededNumberDictionary::kNotFound; |
1563 } | 1567 } |
1564 | 1568 |
1565 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, | 1569 static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, |
1566 uint32_t index) { | 1570 uint32_t index) { |
| 1571 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
1567 Object* key = dict->KeyAt(index); | 1572 Object* key = dict->KeyAt(index); |
1568 return Smi::cast(key)->value(); | 1573 return Smi::cast(key)->value(); |
1569 } | 1574 } |
1570 }; | 1575 }; |
1571 | 1576 |
1572 | 1577 |
1573 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< | 1578 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< |
1574 NonStrictArgumentsElementsAccessor, | 1579 NonStrictArgumentsElementsAccessor, |
1575 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { | 1580 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { |
1576 public: | 1581 public: |
1577 explicit NonStrictArgumentsElementsAccessor(const char* name) | 1582 explicit NonStrictArgumentsElementsAccessor(const char* name) |
1578 : ElementsAccessorBase< | 1583 : ElementsAccessorBase< |
1579 NonStrictArgumentsElementsAccessor, | 1584 NonStrictArgumentsElementsAccessor, |
1580 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} | 1585 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} |
1581 protected: | 1586 protected: |
1582 friend class ElementsAccessorBase< | 1587 friend class ElementsAccessorBase< |
1583 NonStrictArgumentsElementsAccessor, | 1588 NonStrictArgumentsElementsAccessor, |
1584 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; | 1589 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; |
1585 | 1590 |
1586 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 1591 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
1587 JSObject* obj, | 1592 JSObject* obj, |
1588 uint32_t key, | 1593 uint32_t key, |
1589 FixedArray* parameter_map) { | 1594 FixedArrayBase* parameters) { |
| 1595 FixedArray* parameter_map = FixedArray::cast(parameters); |
1590 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1596 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
1591 if (!probe->IsTheHole()) { | 1597 if (!probe->IsTheHole()) { |
1592 Context* context = Context::cast(parameter_map->get(0)); | 1598 Context* context = Context::cast(parameter_map->get(0)); |
1593 int context_index = Smi::cast(probe)->value(); | 1599 int context_index = Smi::cast(probe)->value(); |
1594 ASSERT(!context->get(context_index)->IsTheHole()); | 1600 ASSERT(!context->get(context_index)->IsTheHole()); |
1595 return context->get(context_index); | 1601 return context->get(context_index); |
1596 } else { | 1602 } else { |
1597 // Object is not mapped, defer to the arguments. | 1603 // Object is not mapped, defer to the arguments. |
1598 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1604 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1599 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( | 1605 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( |
(...skipping 27 matching lines...) Expand all Loading... |
1627 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1633 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1628 return ElementsAccessor::ForArray(arguments)->GetAttributes( | 1634 return ElementsAccessor::ForArray(arguments)->GetAttributes( |
1629 receiver, obj, key, arguments); | 1635 receiver, obj, key, arguments); |
1630 } | 1636 } |
1631 } | 1637 } |
1632 | 1638 |
1633 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1639 MUST_USE_RESULT static PropertyType GetTypeImpl( |
1634 Object* receiver, | 1640 Object* receiver, |
1635 JSObject* obj, | 1641 JSObject* obj, |
1636 uint32_t key, | 1642 uint32_t key, |
1637 FixedArray* parameter_map) { | 1643 FixedArrayBase* parameters) { |
| 1644 FixedArray* parameter_map = FixedArray::cast(parameters); |
1638 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1645 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
1639 if (!probe->IsTheHole()) { | 1646 if (!probe->IsTheHole()) { |
1640 return FIELD; | 1647 return FIELD; |
1641 } else { | 1648 } else { |
1642 // If not aliased, check the arguments. | 1649 // If not aliased, check the arguments. |
1643 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1650 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1644 return ElementsAccessor::ForArray(arguments)->GetType( | 1651 return ElementsAccessor::ForArray(arguments)->GetType( |
1645 receiver, obj, key, arguments); | 1652 receiver, obj, key, arguments); |
1646 } | 1653 } |
1647 } | 1654 } |
1648 | 1655 |
1649 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 1656 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
1650 Object* receiver, | 1657 Object* receiver, |
1651 JSObject* obj, | 1658 JSObject* obj, |
1652 uint32_t key, | 1659 uint32_t key, |
1653 FixedArray* parameter_map) { | 1660 FixedArrayBase* parameters) { |
| 1661 FixedArray* parameter_map = FixedArray::cast(parameters); |
1654 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1662 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
1655 if (!probe->IsTheHole()) { | 1663 if (!probe->IsTheHole()) { |
1656 return NULL; | 1664 return NULL; |
1657 } else { | 1665 } else { |
1658 // If not aliased, check the arguments. | 1666 // If not aliased, check the arguments. |
1659 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1667 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1660 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( | 1668 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( |
1661 receiver, obj, key, arguments); | 1669 receiver, obj, key, arguments); |
1662 } | 1670 } |
1663 } | 1671 } |
1664 | 1672 |
1665 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1673 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
1666 JSObject* obj, | 1674 JSObject* obj, |
1667 Object* length, | 1675 Object* length, |
1668 FixedArray* parameter_map) { | 1676 FixedArrayBase* parameter_map) { |
1669 // TODO(mstarzinger): This was never implemented but will be used once we | 1677 // TODO(mstarzinger): This was never implemented but will be used once we |
1670 // correctly implement [[DefineOwnProperty]] on arrays. | 1678 // correctly implement [[DefineOwnProperty]] on arrays. |
1671 UNIMPLEMENTED(); | 1679 UNIMPLEMENTED(); |
1672 return obj; | 1680 return obj; |
1673 } | 1681 } |
1674 | 1682 |
1675 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1683 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
1676 uint32_t key, | 1684 uint32_t key, |
1677 JSReceiver::DeleteMode mode) { | 1685 JSReceiver::DeleteMode mode) { |
1678 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 1686 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
(...skipping 18 matching lines...) Expand all Loading... |
1697 } | 1705 } |
1698 | 1706 |
1699 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1707 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1700 uint32_t from_start, | 1708 uint32_t from_start, |
1701 FixedArrayBase* to, | 1709 FixedArrayBase* to, |
1702 ElementsKind to_kind, | 1710 ElementsKind to_kind, |
1703 uint32_t to_start, | 1711 uint32_t to_start, |
1704 int packed_size, | 1712 int packed_size, |
1705 int copy_size) { | 1713 int copy_size) { |
1706 FixedArray* parameter_map = FixedArray::cast(from); | 1714 FixedArray* parameter_map = FixedArray::cast(from); |
1707 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1715 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1708 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | 1716 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
1709 return accessor->CopyElements(NULL, from_start, to, to_kind, | 1717 return accessor->CopyElements(NULL, from_start, to, to_kind, |
1710 to_start, copy_size, arguments); | 1718 to_start, copy_size, arguments); |
1711 } | 1719 } |
1712 | 1720 |
1713 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { | 1721 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { |
1714 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1722 FixedArray* parameter_map = FixedArray::cast(backing_store); |
1715 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1723 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
1716 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 1724 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
1717 ForArray(arguments)->GetCapacity(arguments)); | 1725 ForArray(arguments)->GetCapacity(arguments)); |
1718 } | 1726 } |
1719 | 1727 |
1720 static uint32_t GetKeyForIndexImpl(FixedArray* dict, | 1728 static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, |
1721 uint32_t index) { | 1729 uint32_t index) { |
1722 return index; | 1730 return index; |
1723 } | 1731 } |
1724 | 1732 |
1725 static bool HasElementImpl(Object* receiver, | 1733 static bool HasElementImpl(Object* receiver, |
1726 JSObject* holder, | 1734 JSObject* holder, |
1727 uint32_t key, | 1735 uint32_t key, |
1728 FixedArray* parameter_map) { | 1736 FixedArrayBase* parameters) { |
| 1737 FixedArray* parameter_map = FixedArray::cast(parameters); |
1729 Object* probe = GetParameterMapArg(holder, parameter_map, key); | 1738 Object* probe = GetParameterMapArg(holder, parameter_map, key); |
1730 if (!probe->IsTheHole()) { | 1739 if (!probe->IsTheHole()) { |
1731 return true; | 1740 return true; |
1732 } else { | 1741 } else { |
1733 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1742 FixedArrayBase* arguments = |
| 1743 FixedArrayBase::cast(FixedArray::cast(parameter_map)->get(1)); |
1734 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | 1744 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
1735 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole(); | 1745 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole(); |
1736 } | 1746 } |
1737 } | 1747 } |
1738 | 1748 |
1739 private: | 1749 private: |
1740 static Object* GetParameterMapArg(JSObject* holder, | 1750 static Object* GetParameterMapArg(JSObject* holder, |
1741 FixedArray* parameter_map, | 1751 FixedArray* parameter_map, |
1742 uint32_t key) { | 1752 uint32_t key) { |
1743 uint32_t length = holder->IsJSArray() | 1753 uint32_t length = holder->IsJSArray() |
1744 ? Smi::cast(JSArray::cast(holder)->length())->value() | 1754 ? Smi::cast(JSArray::cast(holder)->length())->value() |
1745 : parameter_map->length(); | 1755 : parameter_map->length(); |
1746 return key < (length - 2 ) | 1756 return key < (length - 2) |
1747 ? parameter_map->get(key + 2) | 1757 ? parameter_map->get(key + 2) |
1748 : parameter_map->GetHeap()->the_hole_value(); | 1758 : parameter_map->GetHeap()->the_hole_value(); |
1749 } | 1759 } |
1750 }; | 1760 }; |
1751 | 1761 |
1752 | 1762 |
1753 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1763 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
1754 switch (array->map()->instance_type()) { | 1764 switch (array->map()->instance_type()) { |
1755 case FIXED_ARRAY_TYPE: | 1765 case FIXED_ARRAY_TYPE: |
1756 if (array->IsDictionary()) { | 1766 if (array->IsDictionary()) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1803 #undef ACCESSOR_DELETE | 1813 #undef ACCESSOR_DELETE |
1804 elements_accessors_ = NULL; | 1814 elements_accessors_ = NULL; |
1805 } | 1815 } |
1806 | 1816 |
1807 | 1817 |
1808 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1818 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
1809 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, | 1819 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, |
1810 ElementsKindTraits>:: | 1820 ElementsKindTraits>:: |
1811 SetLengthImpl(JSObject* obj, | 1821 SetLengthImpl(JSObject* obj, |
1812 Object* length, | 1822 Object* length, |
1813 typename ElementsKindTraits::BackingStore* backing_store) { | 1823 FixedArrayBase* backing_store) { |
1814 JSArray* array = JSArray::cast(obj); | 1824 JSArray* array = JSArray::cast(obj); |
1815 | 1825 |
1816 // Fast case: The new length fits into a Smi. | 1826 // Fast case: The new length fits into a Smi. |
1817 MaybeObject* maybe_smi_length = length->ToSmi(); | 1827 MaybeObject* maybe_smi_length = length->ToSmi(); |
1818 Object* smi_length = Smi::FromInt(0); | 1828 Object* smi_length = Smi::FromInt(0); |
1819 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 1829 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
1820 const int value = Smi::cast(smi_length)->value(); | 1830 const int value = Smi::cast(smi_length)->value(); |
1821 if (value >= 0) { | 1831 if (value >= 0) { |
1822 Object* new_length; | 1832 Object* new_length; |
1823 MaybeObject* result = ElementsAccessorSubclass:: | 1833 MaybeObject* result = ElementsAccessorSubclass:: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1860 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1870 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
1861 new_backing_store->set(0, length); | 1871 new_backing_store->set(0, length); |
1862 { MaybeObject* result = array->SetContent(new_backing_store); | 1872 { MaybeObject* result = array->SetContent(new_backing_store); |
1863 if (result->IsFailure()) return result; | 1873 if (result->IsFailure()) return result; |
1864 } | 1874 } |
1865 return array; | 1875 return array; |
1866 } | 1876 } |
1867 | 1877 |
1868 | 1878 |
1869 } } // namespace v8::internal | 1879 } } // namespace v8::internal |
OLD | NEW |