Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: src/builtins.cc

Issue 1311343002: Array.prototype.unshift builtin improvements (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: signedness Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 BUILTIN(Illegal) { 168 BUILTIN(Illegal) {
169 UNREACHABLE(); 169 UNREACHABLE();
170 return isolate->heap()->undefined_value(); // Make compiler happy. 170 return isolate->heap()->undefined_value(); // Make compiler happy.
171 } 171 }
172 172
173 173
174 BUILTIN(EmptyFunction) { 174 BUILTIN(EmptyFunction) {
175 return isolate->heap()->undefined_value(); 175 return isolate->heap()->undefined_value();
176 } 176 }
177 177
178 namespace {
178 179
179 // TODO(cbruni): check if this is a suitable method on Object 180 bool ObjectToClampedInteger(Object* object, int* out) {
180 bool ClampedToInteger(Object* object, int* out) {
181 // This is an extended version of ECMA-262 9.4, but additionally 181 // This is an extended version of ECMA-262 9.4, but additionally
182 // clamps values to [kMinInt, kMaxInt] 182 // clamps values to [kMinInt, kMaxInt]
183 if (object->IsSmi()) { 183 if (object->IsSmi()) {
184 *out = Smi::cast(object)->value(); 184 *out = Smi::cast(object)->value();
185 return true; 185 return true;
186 } else if (object->IsHeapNumber()) { 186 } else if (object->IsHeapNumber()) {
187 *out = FastD2IChecked(HeapNumber::cast(object)->value()); 187 *out = FastD2IChecked(HeapNumber::cast(object)->value());
188 return true; 188 return true;
189 } else if (object->IsUndefined()) { 189 } else if (object->IsUndefined()) {
190 *out = 0; 190 *out = 0;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 324 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
325 isolate, result, 325 isolate, result,
326 Execution::Call(isolate, 326 Execution::Call(isolate,
327 function, 327 function,
328 args.receiver(), 328 args.receiver(),
329 argc, 329 argc,
330 argv.start())); 330 argv.start()));
331 return *result; 331 return *result;
332 } 332 }
333 333
334 } // namespace
334 335
335 BUILTIN(ArrayPush) { 336 BUILTIN(ArrayPush) {
336 HandleScope scope(isolate); 337 HandleScope scope(isolate);
337 Handle<Object> receiver = args.receiver(); 338 Handle<Object> receiver = args.receiver();
338 MaybeHandle<FixedArrayBase> maybe_elms_obj = 339 MaybeHandle<FixedArrayBase> maybe_elms_obj =
339 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 340 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
340 Handle<FixedArrayBase> elms_obj; 341 Handle<FixedArrayBase> elms_obj;
341 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 342 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
342 return CallJsBuiltin(isolate, "$arrayPush", args); 343 return CallJsBuiltin(isolate, "$arrayPush", args);
343 } 344 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 DisallowHeapAllocation no_gc; 426 DisallowHeapAllocation no_gc;
426 heap->MoveElements(*elms, 0, 1, len - 1); 427 heap->MoveElements(*elms, 0, 1, len - 1);
427 elms->set(len - 1, heap->the_hole_value()); 428 elms->set(len - 1, heap->the_hole_value());
428 } else { 429 } else {
429 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj); 430 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
430 MoveDoubleElements(*elms, 0, *elms, 1, len - 1); 431 MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
431 elms->set_the_hole(len - 1); 432 elms->set_the_hole(len - 1);
432 } 433 }
433 } 434 }
434 435
435 // Set the length.
436 array->set_length(Smi::FromInt(len - 1)); 436 array->set_length(Smi::FromInt(len - 1));
437 437
438 return *first; 438 return *first;
439 } 439 }
440 440
441 441
442 BUILTIN(ArrayUnshift) { 442 BUILTIN(ArrayUnshift) {
443 HandleScope scope(isolate); 443 HandleScope scope(isolate);
444 Handle<Object> receiver = args.receiver(); 444 Handle<Object> receiver = args.receiver();
445 MaybeHandle<FixedArrayBase> maybe_elms_obj = 445 MaybeHandle<FixedArrayBase> maybe_elms_obj =
446 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 446 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
447 Handle<FixedArrayBase> elms_obj; 447 Handle<FixedArrayBase> elms_obj;
448 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 448 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
449 return CallJsBuiltin(isolate, "$arrayUnshift", args); 449 return CallJsBuiltin(isolate, "$arrayUnshift", args);
450 } 450 }
451 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 451 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
452 DCHECK(!array->map()->is_observed()); 452 DCHECK(!array->map()->is_observed());
453 if (!array->HasFastSmiOrObjectElements()) {
454 return CallJsBuiltin(isolate, "$arrayUnshift", args);
455 }
456 int len = Smi::cast(array->length())->value(); 453 int len = Smi::cast(array->length())->value();
457 int to_add = args.length() - 1; 454 int to_add = args.length() - 1;
458 int new_length = len + to_add;
459 // Currently fixed arrays cannot grow too big, so
460 // we should never hit this case.
461 DCHECK(to_add <= (Smi::kMaxValue - len));
462 455
463 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { 456 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
464 return CallJsBuiltin(isolate, "$arrayUnshift", args); 457 return CallJsBuiltin(isolate, "$arrayUnshift", args);
465 } 458 }
466 459
467 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); 460 ElementsAccessor* accessor = array->GetElementsAccessor();
468 461 int new_length = accessor->Unshift(array, elms_obj, args, to_add);
469 if (new_length > elms->length()) {
470 // New backing storage is needed.
471 int capacity = new_length + (new_length >> 1) + 16;
472 Handle<FixedArray> new_elms =
473 isolate->factory()->NewUninitializedFixedArray(capacity);
474
475 ElementsKind kind = array->GetElementsKind();
476 ElementsAccessor* accessor = array->GetElementsAccessor();
477 accessor->CopyElements(
478 elms, 0, kind, new_elms, to_add,
479 ElementsAccessor::kCopyToEndAndInitializeToHole);
480
481 elms = new_elms;
482 array->set_elements(*elms);
483 } else {
484 DisallowHeapAllocation no_gc;
485 Heap* heap = isolate->heap();
486 heap->MoveElements(*elms, to_add, 0, len);
487 }
488
489 // Add the provided values.
490 DisallowHeapAllocation no_gc;
491 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
492 for (int i = 0; i < to_add; i++) {
493 elms->set(i, args[i + 1], mode);
494 }
495
496 // Set the length.
497 array->set_length(Smi::FromInt(new_length));
498 return Smi::FromInt(new_length); 462 return Smi::FromInt(new_length);
499 } 463 }
500 464
501 465
502 BUILTIN(ArraySlice) { 466 BUILTIN(ArraySlice) {
503 HandleScope scope(isolate); 467 HandleScope scope(isolate);
504 Handle<Object> receiver = args.receiver(); 468 Handle<Object> receiver = args.receiver();
505 int len = -1; 469 int len = -1;
506 int relative_start = 0; 470 int relative_start = 0;
507 int relative_end = 0; 471 int relative_end = 0;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 613 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
650 return CallJsBuiltin(isolate, "$arraySplice", args); 614 return CallJsBuiltin(isolate, "$arraySplice", args);
651 } 615 }
652 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 616 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
653 DCHECK(!array->map()->is_observed()); 617 DCHECK(!array->map()->is_observed());
654 618
655 int argument_count = args.length() - 1; 619 int argument_count = args.length() - 1;
656 int relative_start = 0; 620 int relative_start = 0;
657 if (argument_count > 0) { 621 if (argument_count > 0) {
658 DisallowHeapAllocation no_gc; 622 DisallowHeapAllocation no_gc;
659 if (!ClampedToInteger(args[1], &relative_start)) { 623 if (!ObjectToClampedInteger(args[1], &relative_start)) {
660 AllowHeapAllocation allow_allocation; 624 AllowHeapAllocation allow_allocation;
661 return CallJsBuiltin(isolate, "$arraySplice", args); 625 return CallJsBuiltin(isolate, "$arraySplice", args);
662 } 626 }
663 } 627 }
664 int len = Smi::cast(array->length())->value(); 628 int len = Smi::cast(array->length())->value();
665 // clip relative start to [0, len] 629 // clip relative start to [0, len]
666 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 630 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
667 : Min(relative_start, len); 631 : Min(relative_start, len);
668 632
669 int actual_delete_count; 633 int actual_delete_count;
670 if (argument_count == 1) { 634 if (argument_count == 1) {
671 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 635 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
672 // given as a request to delete all the elements from the start. 636 // given as a request to delete all the elements from the start.
673 // And it differs from the case of undefined delete count. 637 // And it differs from the case of undefined delete count.
674 // This does not follow ECMA-262, but we do the same for compatibility. 638 // This does not follow ECMA-262, but we do the same for compatibility.
675 DCHECK(len - actual_start >= 0); 639 DCHECK(len - actual_start >= 0);
676 actual_delete_count = len - actual_start; 640 actual_delete_count = len - actual_start;
677 } else { 641 } else {
678 int delete_count = 0; 642 int delete_count = 0;
679 DisallowHeapAllocation no_gc; 643 DisallowHeapAllocation no_gc;
680 if (argument_count > 1) { 644 if (argument_count > 1) {
681 if (!ClampedToInteger(args[2], &delete_count)) { 645 if (!ObjectToClampedInteger(args[2], &delete_count)) {
682 AllowHeapAllocation allow_allocation; 646 AllowHeapAllocation allow_allocation;
683 return CallJsBuiltin(isolate, "$arraySplice", args); 647 return CallJsBuiltin(isolate, "$arraySplice", args);
684 } 648 }
685 } 649 }
686 actual_delete_count = Min(Max(delete_count, 0), len - actual_start); 650 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
687 } 651 }
688 652
689 int add_count = (argument_count > 1) ? (argument_count - 2) : 0; 653 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
690 int new_length = len - actual_delete_count + add_count; 654 int new_length = len - actual_delete_count + add_count;
691 655
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1360 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1397 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1361 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1398 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 1362 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1399 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1363 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1400 #undef DEFINE_BUILTIN_ACCESSOR_C 1364 #undef DEFINE_BUILTIN_ACCESSOR_C
1401 #undef DEFINE_BUILTIN_ACCESSOR_A 1365 #undef DEFINE_BUILTIN_ACCESSOR_A
1402 1366
1403 1367
1404 } // namespace internal 1368 } // namespace internal
1405 } // namespace v8 1369 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698