OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 // Need to ensure that the arguments passed in args can be contained in | 255 // Need to ensure that the arguments passed in args can be contained in |
256 // the array. | 256 // the array. |
257 int args_length = args->length(); | 257 int args_length = args->length(); |
258 if (first_added_arg >= args_length) return handle(array->elements(), isolate); | 258 if (first_added_arg >= args_length) return handle(array->elements(), isolate); |
259 | 259 |
260 ElementsKind origin_kind = array->map()->elements_kind(); | 260 ElementsKind origin_kind = array->map()->elements_kind(); |
261 DCHECK(!IsFastObjectElementsKind(origin_kind)); | 261 DCHECK(!IsFastObjectElementsKind(origin_kind)); |
262 ElementsKind target_kind = origin_kind; | 262 ElementsKind target_kind = origin_kind; |
263 { | 263 { |
264 DisallowHeapAllocation no_gc; | 264 DisallowHeapAllocation no_gc; |
265 int arg_count = args->length() - first_added_arg; | 265 int arg_count = args_length - first_added_arg; |
266 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); | 266 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); |
267 for (int i = 0; i < arg_count; i++) { | 267 for (int i = 0; i < arg_count; i++) { |
268 Object* arg = arguments[i]; | 268 Object* arg = arguments[i]; |
269 if (arg->IsHeapObject()) { | 269 if (arg->IsHeapObject()) { |
270 if (arg->IsHeapNumber()) { | 270 if (arg->IsHeapNumber()) { |
271 target_kind = FAST_DOUBLE_ELEMENTS; | 271 target_kind = FAST_DOUBLE_ELEMENTS; |
272 } else { | 272 } else { |
273 target_kind = FAST_ELEMENTS; | 273 target_kind = FAST_ELEMENTS; |
274 break; | 274 break; |
275 } | 275 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 | 314 |
315 BUILTIN(ArrayPush) { | 315 BUILTIN(ArrayPush) { |
316 HandleScope scope(isolate); | 316 HandleScope scope(isolate); |
317 Handle<Object> receiver = args.receiver(); | 317 Handle<Object> receiver = args.receiver(); |
318 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 318 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
319 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 319 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
320 Handle<FixedArrayBase> elms_obj; | 320 Handle<FixedArrayBase> elms_obj; |
321 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 321 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
322 return CallJsBuiltin(isolate, "$arrayPush", args); | 322 return CallJsBuiltin(isolate, "$arrayPush", args); |
323 } | 323 } |
324 | 324 // Fast Elements Path |
| 325 int push_size = args.length() - 1; |
325 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 326 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
326 int len = Smi::cast(array->length())->value(); | 327 int len = Smi::cast(array->length())->value(); |
327 int to_add = args.length() - 1; | 328 if (push_size == 0) { |
328 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { | 329 return Smi::FromInt(len); |
| 330 } |
| 331 if (push_size > 0 && |
| 332 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) { |
329 return CallJsBuiltin(isolate, "$arrayPush", args); | 333 return CallJsBuiltin(isolate, "$arrayPush", args); |
330 } | 334 } |
331 DCHECK(!array->map()->is_observed()); | 335 DCHECK(!array->map()->is_observed()); |
332 | 336 ElementsAccessor* accessor = array->GetElementsAccessor(); |
333 ElementsKind kind = array->GetElementsKind(); | 337 int new_length = accessor->Push(array, elms_obj, &args[1], push_size, |
334 | 338 ElementsAccessor::kDirectionReverse); |
335 if (IsFastSmiOrObjectElementsKind(kind)) { | 339 return Smi::FromInt(new_length); |
336 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | |
337 if (to_add == 0) { | |
338 return Smi::FromInt(len); | |
339 } | |
340 // Currently fixed arrays cannot grow too big, so | |
341 // we should never hit this case. | |
342 DCHECK(to_add <= (Smi::kMaxValue - len)); | |
343 | |
344 int new_length = len + to_add; | |
345 | |
346 if (new_length > elms->length()) { | |
347 // New backing storage is needed. | |
348 int capacity = new_length + (new_length >> 1) + 16; | |
349 Handle<FixedArray> new_elms = | |
350 isolate->factory()->NewUninitializedFixedArray(capacity); | |
351 | |
352 ElementsAccessor* accessor = array->GetElementsAccessor(); | |
353 accessor->CopyElements( | |
354 elms_obj, 0, kind, new_elms, 0, | |
355 ElementsAccessor::kCopyToEndAndInitializeToHole); | |
356 | |
357 elms = new_elms; | |
358 } | |
359 | |
360 // Add the provided values. | |
361 DisallowHeapAllocation no_gc; | |
362 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | |
363 for (int index = 0; index < to_add; index++) { | |
364 elms->set(index + len, args[index + 1], mode); | |
365 } | |
366 | |
367 if (*elms != array->elements()) { | |
368 array->set_elements(*elms); | |
369 } | |
370 | |
371 // Set the length. | |
372 array->set_length(Smi::FromInt(new_length)); | |
373 return Smi::FromInt(new_length); | |
374 } else { | |
375 int elms_len = elms_obj->length(); | |
376 if (to_add == 0) { | |
377 return Smi::FromInt(len); | |
378 } | |
379 // Currently fixed arrays cannot grow too big, so | |
380 // we should never hit this case. | |
381 DCHECK(to_add <= (Smi::kMaxValue - len)); | |
382 | |
383 int new_length = len + to_add; | |
384 | |
385 Handle<FixedDoubleArray> new_elms; | |
386 | |
387 if (new_length > elms_len) { | |
388 // New backing storage is needed. | |
389 int capacity = new_length + (new_length >> 1) + 16; | |
390 // Create new backing store; since capacity > 0, we can | |
391 // safely cast to FixedDoubleArray. | |
392 new_elms = Handle<FixedDoubleArray>::cast( | |
393 isolate->factory()->NewFixedDoubleArray(capacity)); | |
394 | |
395 ElementsAccessor* accessor = array->GetElementsAccessor(); | |
396 accessor->CopyElements( | |
397 elms_obj, 0, kind, new_elms, 0, | |
398 ElementsAccessor::kCopyToEndAndInitializeToHole); | |
399 | |
400 } else { | |
401 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the | |
402 // empty_fixed_array. | |
403 new_elms = Handle<FixedDoubleArray>::cast(elms_obj); | |
404 } | |
405 | |
406 // Add the provided values. | |
407 DisallowHeapAllocation no_gc; | |
408 int index; | |
409 for (index = 0; index < to_add; index++) { | |
410 Object* arg = args[index + 1]; | |
411 new_elms->set(index + len, arg->Number()); | |
412 } | |
413 | |
414 if (*new_elms != array->elements()) { | |
415 array->set_elements(*new_elms); | |
416 } | |
417 | |
418 // Set the length. | |
419 array->set_length(Smi::FromInt(new_length)); | |
420 return Smi::FromInt(new_length); | |
421 } | |
422 } | 340 } |
423 | 341 |
424 | 342 |
425 BUILTIN(ArrayPop) { | 343 BUILTIN(ArrayPop) { |
426 HandleScope scope(isolate); | 344 HandleScope scope(isolate); |
427 Handle<Object> receiver = args.receiver(); | 345 Handle<Object> receiver = args.receiver(); |
428 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 346 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
429 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 347 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
430 Handle<FixedArrayBase> elms_obj; | 348 Handle<FixedArrayBase> elms_obj; |
431 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 349 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 | 414 |
497 // Set the length. | 415 // Set the length. |
498 array->set_length(Smi::FromInt(len - 1)); | 416 array->set_length(Smi::FromInt(len - 1)); |
499 | 417 |
500 return *first; | 418 return *first; |
501 } | 419 } |
502 | 420 |
503 | 421 |
504 BUILTIN(ArrayUnshift) { | 422 BUILTIN(ArrayUnshift) { |
505 HandleScope scope(isolate); | 423 HandleScope scope(isolate); |
506 Heap* heap = isolate->heap(); | |
507 Handle<Object> receiver = args.receiver(); | 424 Handle<Object> receiver = args.receiver(); |
508 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 425 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
509 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 426 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
510 Handle<FixedArrayBase> elms_obj; | 427 Handle<FixedArrayBase> elms_obj; |
511 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 428 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
512 return CallJsBuiltin(isolate, "$arrayUnshift", args); | 429 return CallJsBuiltin(isolate, "$arrayUnshift", args); |
513 } | 430 } |
514 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 431 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
515 DCHECK(!array->map()->is_observed()); | 432 DCHECK(!array->map()->is_observed()); |
516 if (!array->HasFastSmiOrObjectElements()) { | 433 if (!array->HasFastSmiOrObjectElements()) { |
(...skipping 21 matching lines...) Expand all Loading... |
538 ElementsKind kind = array->GetElementsKind(); | 455 ElementsKind kind = array->GetElementsKind(); |
539 ElementsAccessor* accessor = array->GetElementsAccessor(); | 456 ElementsAccessor* accessor = array->GetElementsAccessor(); |
540 accessor->CopyElements( | 457 accessor->CopyElements( |
541 elms, 0, kind, new_elms, to_add, | 458 elms, 0, kind, new_elms, to_add, |
542 ElementsAccessor::kCopyToEndAndInitializeToHole); | 459 ElementsAccessor::kCopyToEndAndInitializeToHole); |
543 | 460 |
544 elms = new_elms; | 461 elms = new_elms; |
545 array->set_elements(*elms); | 462 array->set_elements(*elms); |
546 } else { | 463 } else { |
547 DisallowHeapAllocation no_gc; | 464 DisallowHeapAllocation no_gc; |
| 465 Heap* heap = isolate->heap(); |
548 heap->MoveElements(*elms, to_add, 0, len); | 466 heap->MoveElements(*elms, to_add, 0, len); |
549 } | 467 } |
550 | 468 |
551 // Add the provided values. | 469 // Add the provided values. |
552 DisallowHeapAllocation no_gc; | 470 DisallowHeapAllocation no_gc; |
553 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 471 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
554 for (int i = 0; i < to_add; i++) { | 472 for (int i = 0; i < to_add; i++) { |
555 elms->set(i, args[i + 1], mode); | 473 elms->set(i, args[i + 1], mode); |
556 } | 474 } |
557 | 475 |
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1617 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1535 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1618 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1536 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1619 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1537 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
1620 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1538 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1621 #undef DEFINE_BUILTIN_ACCESSOR_C | 1539 #undef DEFINE_BUILTIN_ACCESSOR_C |
1622 #undef DEFINE_BUILTIN_ACCESSOR_A | 1540 #undef DEFINE_BUILTIN_ACCESSOR_A |
1623 | 1541 |
1624 | 1542 |
1625 } // namespace internal | 1543 } // namespace internal |
1626 } // namespace v8 | 1544 } // namespace v8 |
OLD | NEW |