| 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/builtins.h" | 5 #include "src/builtins.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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 *out = 0; | 188 *out = 0; |
| 189 return true; | 189 return true; |
| 190 } else if (object->IsBoolean()) { | 190 } else if (object->IsBoolean()) { |
| 191 *out = object->IsTrue(); | 191 *out = object->IsTrue(); |
| 192 return true; | 192 return true; |
| 193 } | 193 } |
| 194 return false; | 194 return false; |
| 195 } | 195 } |
| 196 | 196 |
| 197 | 197 |
| 198 void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, | |
| 199 FixedDoubleArray* src, int src_index, int len) { | |
| 200 if (len == 0) return; | |
| 201 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, | |
| 202 len * kDoubleSize); | |
| 203 } | |
| 204 | |
| 205 | |
| 206 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object, | 198 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object, |
| 207 int* out) { | 199 int* out) { |
| 208 Map* arguments_map = | 200 Map* arguments_map = |
| 209 isolate->context()->native_context()->sloppy_arguments_map(); | 201 isolate->context()->native_context()->sloppy_arguments_map(); |
| 210 if (object->map() != arguments_map || !object->HasFastElements()) { | 202 if (object->map() != arguments_map || !object->HasFastElements()) { |
| 211 return false; | 203 return false; |
| 212 } | 204 } |
| 213 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); | 205 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); |
| 214 if (!len_obj->IsSmi()) { | 206 if (!len_obj->IsSmi()) { |
| 215 return false; | 207 return false; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 417 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 426 DCHECK(!array->map()->is_observed()); | 418 DCHECK(!array->map()->is_observed()); |
| 427 | 419 |
| 428 int len = Smi::cast(array->length())->value(); | 420 int len = Smi::cast(array->length())->value(); |
| 429 if (len == 0) return heap->undefined_value(); | 421 if (len == 0) return heap->undefined_value(); |
| 430 | 422 |
| 431 if (JSArray::HasReadOnlyLength(array)) { | 423 if (JSArray::HasReadOnlyLength(array)) { |
| 432 return CallJsIntrinsic(isolate, isolate->array_shift(), args); | 424 return CallJsIntrinsic(isolate, isolate->array_shift(), args); |
| 433 } | 425 } |
| 434 | 426 |
| 435 // Get first element | 427 Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj); |
| 436 Handle<Object> first; | |
| 437 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first, | |
| 438 Object::GetElement(isolate, array, 0)); | |
| 439 | |
| 440 if (heap->CanMoveObjectStart(*elms_obj)) { | |
| 441 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1)); | |
| 442 } else { | |
| 443 // Shift the elements. | |
| 444 if (elms_obj->IsFixedArray()) { | |
| 445 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | |
| 446 DisallowHeapAllocation no_gc; | |
| 447 heap->MoveElements(*elms, 0, 1, len - 1); | |
| 448 elms->set(len - 1, heap->the_hole_value()); | |
| 449 } else { | |
| 450 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj); | |
| 451 MoveDoubleElements(*elms, 0, *elms, 1, len - 1); | |
| 452 elms->set_the_hole(len - 1); | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 // Set the length. | |
| 457 array->set_length(Smi::FromInt(len - 1)); | |
| 458 | |
| 459 return *first; | 428 return *first; |
| 460 } | 429 } |
| 461 | 430 |
| 462 | 431 |
| 463 BUILTIN(ArrayUnshift) { | 432 BUILTIN(ArrayUnshift) { |
| 464 HandleScope scope(isolate); | 433 HandleScope scope(isolate); |
| 465 Handle<Object> receiver = args.receiver(); | 434 Handle<Object> receiver = args.receiver(); |
| 466 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 435 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 467 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 436 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 468 Handle<FixedArrayBase> elms_obj; | 437 Handle<FixedArrayBase> elms_obj; |
| 469 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 438 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 470 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); | 439 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); |
| 471 } | 440 } |
| 472 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 441 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 473 DCHECK(!array->map()->is_observed()); | 442 DCHECK(!array->map()->is_observed()); |
| 474 int to_add = args.length() - 1; | 443 int to_add = args.length() - 1; |
| 444 if (to_add == 0) { |
| 445 return array->length(); |
| 446 } |
| 475 // Currently fixed arrays cannot grow too big, so | 447 // Currently fixed arrays cannot grow too big, so |
| 476 // we should never hit this case. | 448 // we should never hit this case. |
| 477 DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value())); | 449 DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value())); |
| 478 | 450 |
| 479 if (to_add > 0 && JSArray::HasReadOnlyLength(array)) { | 451 if (to_add > 0 && JSArray::HasReadOnlyLength(array)) { |
| 480 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); | 452 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); |
| 481 } | 453 } |
| 482 | 454 |
| 483 ElementsAccessor* accessor = array->GetElementsAccessor(); | 455 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 484 int new_length = accessor->Unshift(array, elms_obj, &args, to_add); | 456 int new_length = accessor->Unshift(array, elms_obj, &args, to_add); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 518 } |
| 547 | 519 |
| 548 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. | 520 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
| 549 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0) | 521 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0) |
| 550 : Min(relative_start, len); | 522 : Min(relative_start, len); |
| 551 | 523 |
| 552 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. | 524 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
| 553 uint32_t actual_end = | 525 uint32_t actual_end = |
| 554 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len); | 526 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len); |
| 555 | 527 |
| 528 if (actual_end <= actual_start) { |
| 529 Handle<JSArray> result_array = |
| 530 isolate->factory()->NewJSArray(GetInitialFastElementsKind(), 0, 0); |
| 531 return *result_array; |
| 532 } |
| 533 |
| 556 ElementsAccessor* accessor = object->GetElementsAccessor(); | 534 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 557 if (is_sloppy_arguments && | 535 if (is_sloppy_arguments && |
| 558 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) { | 536 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) { |
| 559 // Don't deal with arguments with holes in C++ | 537 // Don't deal with arguments with holes in C++ |
| 560 AllowHeapAllocation allow_allocation; | 538 AllowHeapAllocation allow_allocation; |
| 561 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | 539 return CallJsIntrinsic(isolate, isolate->array_slice(), args); |
| 562 } | 540 } |
| 563 Handle<JSArray> result_array = | 541 Handle<JSArray> result_array = |
| 564 accessor->Slice(object, elms_obj, actual_start, actual_end); | 542 accessor->Slice(object, elms_obj, actual_start, actual_end); |
| 565 return *result_array; | 543 return *result_array; |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1313 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1336 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1314 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1337 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1315 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1338 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1316 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1339 #undef DEFINE_BUILTIN_ACCESSOR_C | 1317 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1340 #undef DEFINE_BUILTIN_ACCESSOR_A | 1318 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1341 | 1319 |
| 1342 | 1320 |
| 1343 } // namespace internal | 1321 } // namespace internal |
| 1344 } // namespace v8 | 1322 } // namespace v8 |
| OLD | NEW |