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

Side by Side Diff: src/builtins.cc

Issue 1309503003: Install js intrinsic fallbacks for array functions on the native context. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@context_intrinsics
Patch Set: 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 | « src/array.js ('k') | src/contexts.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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 276 }
277 } 277 }
278 if (target_kind != origin_kind) { 278 if (target_kind != origin_kind) {
279 JSObject::TransitionElementsKind(array, target_kind); 279 JSObject::TransitionElementsKind(array, target_kind);
280 return handle(array->elements(), isolate); 280 return handle(array->elements(), isolate);
281 } 281 }
282 return elms; 282 return elms;
283 } 283 }
284 284
285 285
286 MUST_USE_RESULT static Object* CallJsBuiltin( 286 MUST_USE_RESULT static Object* CallJsIntrinsic(
287 Isolate* isolate, 287 Isolate* isolate, Handle<JSFunction> function,
288 const char* name,
289 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 288 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
290 HandleScope handleScope(isolate); 289 HandleScope handleScope(isolate);
291
292 Handle<Object> js_builtin = Object::GetProperty(
293 isolate,
294 handle(isolate->native_context()->builtins(), isolate),
295 name).ToHandleChecked();
296 Handle<JSFunction> function = Handle<JSFunction>::cast(js_builtin);
297 int argc = args.length() - 1; 290 int argc = args.length() - 1;
298 ScopedVector<Handle<Object> > argv(argc); 291 ScopedVector<Handle<Object> > argv(argc);
299 for (int i = 0; i < argc; ++i) { 292 for (int i = 0; i < argc; ++i) {
300 argv[i] = args.at<Object>(i + 1); 293 argv[i] = args.at<Object>(i + 1);
301 } 294 }
302 Handle<Object> result; 295 Handle<Object> result;
303 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
304 isolate, result, 297 isolate, result,
305 Execution::Call(isolate, 298 Execution::Call(isolate,
306 function, 299 function,
307 args.receiver(), 300 args.receiver(),
308 argc, 301 argc,
309 argv.start())); 302 argv.start()));
310 return *result; 303 return *result;
311 } 304 }
312 305
313 306
314 BUILTIN(ArrayPush) { 307 BUILTIN(ArrayPush) {
315 HandleScope scope(isolate); 308 HandleScope scope(isolate);
316 Handle<Object> receiver = args.receiver(); 309 Handle<Object> receiver = args.receiver();
317 MaybeHandle<FixedArrayBase> maybe_elms_obj = 310 MaybeHandle<FixedArrayBase> maybe_elms_obj =
318 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 311 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
319 Handle<FixedArrayBase> elms_obj; 312 Handle<FixedArrayBase> elms_obj;
320 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 313 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
321 return CallJsBuiltin(isolate, "$arrayPush", args); 314 return CallJsIntrinsic(isolate, isolate->array_push(), args);
322 } 315 }
323 // Fast Elements Path 316 // Fast Elements Path
324 int push_size = args.length() - 1; 317 int push_size = args.length() - 1;
325 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 318 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
326 int len = Smi::cast(array->length())->value(); 319 int len = Smi::cast(array->length())->value();
327 if (push_size == 0) { 320 if (push_size == 0) {
328 return Smi::FromInt(len); 321 return Smi::FromInt(len);
329 } 322 }
330 if (push_size > 0 && 323 if (push_size > 0 &&
331 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) { 324 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
332 return CallJsBuiltin(isolate, "$arrayPush", args); 325 return CallJsIntrinsic(isolate, isolate->array_push(), args);
333 } 326 }
334 DCHECK(!array->map()->is_observed()); 327 DCHECK(!array->map()->is_observed());
335 ElementsAccessor* accessor = array->GetElementsAccessor(); 328 ElementsAccessor* accessor = array->GetElementsAccessor();
336 int new_length = accessor->Push(array, elms_obj, &args[1], push_size, 329 int new_length = accessor->Push(array, elms_obj, &args[1], push_size,
337 ElementsAccessor::kDirectionReverse); 330 ElementsAccessor::kDirectionReverse);
338 return Smi::FromInt(new_length); 331 return Smi::FromInt(new_length);
339 } 332 }
340 333
341 334
342 BUILTIN(ArrayPop) { 335 BUILTIN(ArrayPop) {
343 HandleScope scope(isolate); 336 HandleScope scope(isolate);
344 Handle<Object> receiver = args.receiver(); 337 Handle<Object> receiver = args.receiver();
345 MaybeHandle<FixedArrayBase> maybe_elms_obj = 338 MaybeHandle<FixedArrayBase> maybe_elms_obj =
346 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 339 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
347 Handle<FixedArrayBase> elms_obj; 340 Handle<FixedArrayBase> elms_obj;
348 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 341 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
349 return CallJsBuiltin(isolate, "$arrayPop", args); 342 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
350 } 343 }
351 344
352 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 345 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
353 DCHECK(!array->map()->is_observed()); 346 DCHECK(!array->map()->is_observed());
354 347
355 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value()); 348 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
356 if (len == 0) return isolate->heap()->undefined_value(); 349 if (len == 0) return isolate->heap()->undefined_value();
357 350
358 if (JSArray::HasReadOnlyLength(array)) { 351 if (JSArray::HasReadOnlyLength(array)) {
359 return CallJsBuiltin(isolate, "$arrayPop", args); 352 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
360 } 353 }
361 354
362 uint32_t new_length = len - 1; 355 uint32_t new_length = len - 1;
363 Handle<Object> element; 356 Handle<Object> element;
364 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
365 isolate, element, Object::GetElement(isolate, array, new_length)); 358 isolate, element, Object::GetElement(isolate, array, new_length));
366 359
367 JSArray::SetLength(array, new_length); 360 JSArray::SetLength(array, new_length);
368 return *element; 361 return *element;
369 } 362 }
370 363
371 364
372 BUILTIN(ArrayShift) { 365 BUILTIN(ArrayShift) {
373 HandleScope scope(isolate); 366 HandleScope scope(isolate);
374 Heap* heap = isolate->heap(); 367 Heap* heap = isolate->heap();
375 Handle<Object> receiver = args.receiver(); 368 Handle<Object> receiver = args.receiver();
376 MaybeHandle<FixedArrayBase> maybe_elms_obj = 369 MaybeHandle<FixedArrayBase> maybe_elms_obj =
377 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 370 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
378 Handle<FixedArrayBase> elms_obj; 371 Handle<FixedArrayBase> elms_obj;
379 if (!maybe_elms_obj.ToHandle(&elms_obj) || 372 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
380 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) { 373 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
381 return CallJsBuiltin(isolate, "$arrayShift", args); 374 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
382 } 375 }
383 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 376 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
384 DCHECK(!array->map()->is_observed()); 377 DCHECK(!array->map()->is_observed());
385 378
386 int len = Smi::cast(array->length())->value(); 379 int len = Smi::cast(array->length())->value();
387 if (len == 0) return heap->undefined_value(); 380 if (len == 0) return heap->undefined_value();
388 381
389 if (JSArray::HasReadOnlyLength(array)) { 382 if (JSArray::HasReadOnlyLength(array)) {
390 return CallJsBuiltin(isolate, "$arrayShift", args); 383 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
391 } 384 }
392 385
393 // Get first element 386 // Get first element
394 Handle<Object> first; 387 Handle<Object> first;
395 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first, 388 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first,
396 Object::GetElement(isolate, array, 0)); 389 Object::GetElement(isolate, array, 0));
397 390
398 if (heap->CanMoveObjectStart(*elms_obj)) { 391 if (heap->CanMoveObjectStart(*elms_obj)) {
399 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1)); 392 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
400 } else { 393 } else {
(...skipping 17 matching lines...) Expand all
418 } 411 }
419 412
420 413
421 BUILTIN(ArrayUnshift) { 414 BUILTIN(ArrayUnshift) {
422 HandleScope scope(isolate); 415 HandleScope scope(isolate);
423 Handle<Object> receiver = args.receiver(); 416 Handle<Object> receiver = args.receiver();
424 MaybeHandle<FixedArrayBase> maybe_elms_obj = 417 MaybeHandle<FixedArrayBase> maybe_elms_obj =
425 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 418 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
426 Handle<FixedArrayBase> elms_obj; 419 Handle<FixedArrayBase> elms_obj;
427 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 420 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
428 return CallJsBuiltin(isolate, "$arrayUnshift", args); 421 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
429 } 422 }
430 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 423 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
431 DCHECK(!array->map()->is_observed()); 424 DCHECK(!array->map()->is_observed());
432 if (!array->HasFastSmiOrObjectElements()) { 425 if (!array->HasFastSmiOrObjectElements()) {
433 return CallJsBuiltin(isolate, "$arrayUnshift", args); 426 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
434 } 427 }
435 int len = Smi::cast(array->length())->value(); 428 int len = Smi::cast(array->length())->value();
436 int to_add = args.length() - 1; 429 int to_add = args.length() - 1;
437 int new_length = len + to_add; 430 int new_length = len + to_add;
438 // Currently fixed arrays cannot grow too big, so 431 // Currently fixed arrays cannot grow too big, so
439 // we should never hit this case. 432 // we should never hit this case.
440 DCHECK(to_add <= (Smi::kMaxValue - len)); 433 DCHECK(to_add <= (Smi::kMaxValue - len));
441 434
442 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { 435 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
443 return CallJsBuiltin(isolate, "$arrayUnshift", args); 436 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
444 } 437 }
445 438
446 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); 439 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
447 440
448 if (new_length > elms->length()) { 441 if (new_length > elms->length()) {
449 // New backing storage is needed. 442 // New backing storage is needed.
450 int capacity = new_length + (new_length >> 1) + 16; 443 int capacity = new_length + (new_length >> 1) + 16;
451 Handle<FixedArray> new_elms = 444 Handle<FixedArray> new_elms =
452 isolate->factory()->NewUninitializedFixedArray(capacity); 445 isolate->factory()->NewUninitializedFixedArray(capacity);
453 446
(...skipping 29 matching lines...) Expand all
483 Handle<Object> receiver = args.receiver(); 476 Handle<Object> receiver = args.receiver();
484 int len = -1; 477 int len = -1;
485 int relative_start = 0; 478 int relative_start = 0;
486 int relative_end = 0; 479 int relative_end = 0;
487 { 480 {
488 DisallowHeapAllocation no_gc; 481 DisallowHeapAllocation no_gc;
489 if (receiver->IsJSArray()) { 482 if (receiver->IsJSArray()) {
490 JSArray* array = JSArray::cast(*receiver); 483 JSArray* array = JSArray::cast(*receiver);
491 if (!IsJSArrayFastElementMovingAllowed(isolate, array)) { 484 if (!IsJSArrayFastElementMovingAllowed(isolate, array)) {
492 AllowHeapAllocation allow_allocation; 485 AllowHeapAllocation allow_allocation;
493 return CallJsBuiltin(isolate, "$arraySlice", args); 486 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
494 } 487 }
495 488
496 if (!array->HasFastElements()) { 489 if (!array->HasFastElements()) {
497 AllowHeapAllocation allow_allocation; 490 AllowHeapAllocation allow_allocation;
498 return CallJsBuiltin(isolate, "$arraySlice", args); 491 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
499 } 492 }
500 493
501 len = Smi::cast(array->length())->value(); 494 len = Smi::cast(array->length())->value();
502 } else { 495 } else {
503 // Array.slice(arguments, ...) is quite a common idiom (notably more 496 // Array.slice(arguments, ...) is quite a common idiom (notably more
504 // than 50% of invocations in Web apps). Treat it in C++ as well. 497 // than 50% of invocations in Web apps). Treat it in C++ as well.
505 Map* arguments_map = 498 Map* arguments_map =
506 isolate->context()->native_context()->sloppy_arguments_map(); 499 isolate->context()->native_context()->sloppy_arguments_map();
507 500
508 bool is_arguments_object_with_fast_elements = 501 bool is_arguments_object_with_fast_elements =
509 receiver->IsJSObject() && 502 receiver->IsJSObject() &&
510 JSObject::cast(*receiver)->map() == arguments_map; 503 JSObject::cast(*receiver)->map() == arguments_map;
511 if (!is_arguments_object_with_fast_elements) { 504 if (!is_arguments_object_with_fast_elements) {
512 AllowHeapAllocation allow_allocation; 505 AllowHeapAllocation allow_allocation;
513 return CallJsBuiltin(isolate, "$arraySlice", args); 506 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
514 } 507 }
515 JSObject* object = JSObject::cast(*receiver); 508 JSObject* object = JSObject::cast(*receiver);
516 509
517 if (!object->HasFastElements()) { 510 if (!object->HasFastElements()) {
518 AllowHeapAllocation allow_allocation; 511 AllowHeapAllocation allow_allocation;
519 return CallJsBuiltin(isolate, "$arraySlice", args); 512 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
520 } 513 }
521 514
522 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 515 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
523 if (!len_obj->IsSmi()) { 516 if (!len_obj->IsSmi()) {
524 AllowHeapAllocation allow_allocation; 517 AllowHeapAllocation allow_allocation;
525 return CallJsBuiltin(isolate, "$arraySlice", args); 518 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
526 } 519 }
527 len = Smi::cast(len_obj)->value(); 520 len = Smi::cast(len_obj)->value();
528 if (len > object->elements()->length()) { 521 if (len > object->elements()->length()) {
529 AllowHeapAllocation allow_allocation; 522 AllowHeapAllocation allow_allocation;
530 return CallJsBuiltin(isolate, "$arraySlice", args); 523 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
531 } 524 }
532 } 525 }
533 526
534 DCHECK(len >= 0); 527 DCHECK(len >= 0);
535 int n_arguments = args.length() - 1; 528 int n_arguments = args.length() - 1;
536 529
537 // Note carefully choosen defaults---if argument is missing, 530 // Note carefully choosen defaults---if argument is missing,
538 // it's undefined which gets converted to 0 for relative_start 531 // it's undefined which gets converted to 0 for relative_start
539 // and to len for relative_end. 532 // and to len for relative_end.
540 relative_start = 0; 533 relative_start = 0;
541 relative_end = len; 534 relative_end = len;
542 if (n_arguments > 0) { 535 if (n_arguments > 0) {
543 Object* arg1 = args[1]; 536 Object* arg1 = args[1];
544 if (arg1->IsSmi()) { 537 if (arg1->IsSmi()) {
545 relative_start = Smi::cast(arg1)->value(); 538 relative_start = Smi::cast(arg1)->value();
546 } else if (arg1->IsHeapNumber()) { 539 } else if (arg1->IsHeapNumber()) {
547 double start = HeapNumber::cast(arg1)->value(); 540 double start = HeapNumber::cast(arg1)->value();
548 if (start < kMinInt || start > kMaxInt) { 541 if (start < kMinInt || start > kMaxInt) {
549 AllowHeapAllocation allow_allocation; 542 AllowHeapAllocation allow_allocation;
550 return CallJsBuiltin(isolate, "$arraySlice", args); 543 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
551 } 544 }
552 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); 545 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
553 } else if (!arg1->IsUndefined()) { 546 } else if (!arg1->IsUndefined()) {
554 AllowHeapAllocation allow_allocation; 547 AllowHeapAllocation allow_allocation;
555 return CallJsBuiltin(isolate, "$arraySlice", args); 548 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
556 } 549 }
557 if (n_arguments > 1) { 550 if (n_arguments > 1) {
558 Object* arg2 = args[2]; 551 Object* arg2 = args[2];
559 if (arg2->IsSmi()) { 552 if (arg2->IsSmi()) {
560 relative_end = Smi::cast(arg2)->value(); 553 relative_end = Smi::cast(arg2)->value();
561 } else if (arg2->IsHeapNumber()) { 554 } else if (arg2->IsHeapNumber()) {
562 double end = HeapNumber::cast(arg2)->value(); 555 double end = HeapNumber::cast(arg2)->value();
563 if (end < kMinInt || end > kMaxInt) { 556 if (end < kMinInt || end > kMaxInt) {
564 AllowHeapAllocation allow_allocation; 557 AllowHeapAllocation allow_allocation;
565 return CallJsBuiltin(isolate, "$arraySlice", args); 558 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
566 } 559 }
567 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); 560 relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
568 } else if (!arg2->IsUndefined()) { 561 } else if (!arg2->IsUndefined()) {
569 AllowHeapAllocation allow_allocation; 562 AllowHeapAllocation allow_allocation;
570 return CallJsBuiltin(isolate, "$arraySlice", args); 563 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
571 } 564 }
572 } 565 }
573 } 566 }
574 } 567 }
575 568
576 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 569 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
577 int k = (relative_start < 0) ? Max(len + relative_start, 0) 570 int k = (relative_start < 0) ? Max(len + relative_start, 0)
578 : Min(relative_start, len); 571 : Min(relative_start, len);
579 572
580 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 573 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
(...skipping 14 matching lines...) Expand all
595 for (int i = k; i < final; i++) { 588 for (int i = k; i < final; i++) {
596 if (!accessor->HasElement(object, i, elms)) { 589 if (!accessor->HasElement(object, i, elms)) {
597 packed = false; 590 packed = false;
598 break; 591 break;
599 } 592 }
600 } 593 }
601 if (packed) { 594 if (packed) {
602 kind = GetPackedElementsKind(kind); 595 kind = GetPackedElementsKind(kind);
603 } else if (!receiver->IsJSArray()) { 596 } else if (!receiver->IsJSArray()) {
604 AllowHeapAllocation allow_allocation; 597 AllowHeapAllocation allow_allocation;
605 return CallJsBuiltin(isolate, "$arraySlice", args); 598 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
606 } 599 }
607 } 600 }
608 601
609 Handle<JSArray> result_array = 602 Handle<JSArray> result_array =
610 isolate->factory()->NewJSArray(kind, result_len, result_len); 603 isolate->factory()->NewJSArray(kind, result_len, result_len);
611 604
612 DisallowHeapAllocation no_gc; 605 DisallowHeapAllocation no_gc;
613 if (result_len == 0) return *result_array; 606 if (result_len == 0) return *result_array;
614 607
615 ElementsAccessor* accessor = object->GetElementsAccessor(); 608 ElementsAccessor* accessor = object->GetElementsAccessor();
616 accessor->CopyElements( 609 accessor->CopyElements(
617 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len); 610 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
618 return *result_array; 611 return *result_array;
619 } 612 }
620 613
621 614
622 BUILTIN(ArraySplice) { 615 BUILTIN(ArraySplice) {
623 HandleScope scope(isolate); 616 HandleScope scope(isolate);
624 Heap* heap = isolate->heap(); 617 Heap* heap = isolate->heap();
625 Handle<Object> receiver = args.receiver(); 618 Handle<Object> receiver = args.receiver();
626 MaybeHandle<FixedArrayBase> maybe_elms_obj = 619 MaybeHandle<FixedArrayBase> maybe_elms_obj =
627 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 620 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
628 Handle<FixedArrayBase> elms_obj; 621 Handle<FixedArrayBase> elms_obj;
629 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 622 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
630 return CallJsBuiltin(isolate, "$arraySplice", args); 623 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
631 } 624 }
632 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 625 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
633 DCHECK(!array->map()->is_observed()); 626 DCHECK(!array->map()->is_observed());
634 627
635 int len = Smi::cast(array->length())->value(); 628 int len = Smi::cast(array->length())->value();
636 629
637 int n_arguments = args.length() - 1; 630 int n_arguments = args.length() - 1;
638 631
639 int relative_start = 0; 632 int relative_start = 0;
640 if (n_arguments > 0) { 633 if (n_arguments > 0) {
641 DisallowHeapAllocation no_gc; 634 DisallowHeapAllocation no_gc;
642 Object* arg1 = args[1]; 635 Object* arg1 = args[1];
643 if (arg1->IsSmi()) { 636 if (arg1->IsSmi()) {
644 relative_start = Smi::cast(arg1)->value(); 637 relative_start = Smi::cast(arg1)->value();
645 } else if (arg1->IsHeapNumber()) { 638 } else if (arg1->IsHeapNumber()) {
646 double start = HeapNumber::cast(arg1)->value(); 639 double start = HeapNumber::cast(arg1)->value();
647 if (start < kMinInt || start > kMaxInt) { 640 if (start < kMinInt || start > kMaxInt) {
648 AllowHeapAllocation allow_allocation; 641 AllowHeapAllocation allow_allocation;
649 return CallJsBuiltin(isolate, "$arraySplice", args); 642 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
650 } 643 }
651 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); 644 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
652 } else if (!arg1->IsUndefined()) { 645 } else if (!arg1->IsUndefined()) {
653 AllowHeapAllocation allow_allocation; 646 AllowHeapAllocation allow_allocation;
654 return CallJsBuiltin(isolate, "$arraySplice", args); 647 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
655 } 648 }
656 } 649 }
657 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 650 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
658 : Min(relative_start, len); 651 : Min(relative_start, len);
659 652
660 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 653 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
661 // given as a request to delete all the elements from the start. 654 // given as a request to delete all the elements from the start.
662 // And it differs from the case of undefined delete count. 655 // And it differs from the case of undefined delete count.
663 // This does not follow ECMA-262, but we do the same for 656 // This does not follow ECMA-262, but we do the same for
664 // compatibility. 657 // compatibility.
665 int actual_delete_count; 658 int actual_delete_count;
666 if (n_arguments == 1) { 659 if (n_arguments == 1) {
667 DCHECK(len - actual_start >= 0); 660 DCHECK(len - actual_start >= 0);
668 actual_delete_count = len - actual_start; 661 actual_delete_count = len - actual_start;
669 } else { 662 } else {
670 int value = 0; // ToInteger(undefined) == 0 663 int value = 0; // ToInteger(undefined) == 0
671 if (n_arguments > 1) { 664 if (n_arguments > 1) {
672 DisallowHeapAllocation no_gc; 665 DisallowHeapAllocation no_gc;
673 Object* arg2 = args[2]; 666 Object* arg2 = args[2];
674 if (arg2->IsSmi()) { 667 if (arg2->IsSmi()) {
675 value = Smi::cast(arg2)->value(); 668 value = Smi::cast(arg2)->value();
676 } else { 669 } else {
677 AllowHeapAllocation allow_allocation; 670 AllowHeapAllocation allow_allocation;
678 return CallJsBuiltin(isolate, "$arraySplice", args); 671 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
679 } 672 }
680 } 673 }
681 actual_delete_count = Min(Max(value, 0), len - actual_start); 674 actual_delete_count = Min(Max(value, 0), len - actual_start);
682 } 675 }
683 676
684 ElementsKind elements_kind = array->GetElementsKind(); 677 ElementsKind elements_kind = array->GetElementsKind();
685 678
686 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 679 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
687 int new_length = len - actual_delete_count + item_count; 680 int new_length = len - actual_delete_count + item_count;
688 681
689 // For double mode we do not support changing the length. 682 // For double mode we do not support changing the length.
690 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) { 683 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
691 return CallJsBuiltin(isolate, "$arraySplice", args); 684 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
692 } 685 }
693 686
694 if (new_length != len && JSArray::HasReadOnlyLength(array)) { 687 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
695 AllowHeapAllocation allow_allocation; 688 AllowHeapAllocation allow_allocation;
696 return CallJsBuiltin(isolate, "$arraySplice", args); 689 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
697 } 690 }
698 691
699 if (new_length == 0) { 692 if (new_length == 0) {
700 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( 693 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
701 elms_obj, elements_kind, actual_delete_count); 694 elms_obj, elements_kind, actual_delete_count);
702 array->set_elements(heap->empty_fixed_array()); 695 array->set_elements(heap->empty_fixed_array());
703 array->set_length(Smi::FromInt(0)); 696 array->set_length(Smi::FromInt(0));
704 return *result; 697 return *result;
705 } 698 }
706 699
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 ElementsKind elements_kind = GetInitialFastElementsKind(); 839 ElementsKind elements_kind = GetInitialFastElementsKind();
847 bool has_double = false; 840 bool has_double = false;
848 { 841 {
849 DisallowHeapAllocation no_gc; 842 DisallowHeapAllocation no_gc;
850 Context* native_context = isolate->context()->native_context(); 843 Context* native_context = isolate->context()->native_context();
851 Object* array_proto = native_context->array_function()->prototype(); 844 Object* array_proto = native_context->array_function()->prototype();
852 PrototypeIterator iter(isolate, array_proto, 845 PrototypeIterator iter(isolate, array_proto,
853 PrototypeIterator::START_AT_RECEIVER); 846 PrototypeIterator::START_AT_RECEIVER);
854 if (!ArrayPrototypeHasNoElements(&iter)) { 847 if (!ArrayPrototypeHasNoElements(&iter)) {
855 AllowHeapAllocation allow_allocation; 848 AllowHeapAllocation allow_allocation;
856 return CallJsBuiltin(isolate, "$arrayConcat", args); 849 return CallJsIntrinsic(isolate, isolate->array_concat(), args);
857 } 850 }
858 851
859 // Iterate through all the arguments performing checks 852 // Iterate through all the arguments performing checks
860 // and calculating total length. 853 // and calculating total length.
861 bool is_holey = false; 854 bool is_holey = false;
862 for (int i = 0; i < n_arguments; i++) { 855 for (int i = 0; i < n_arguments; i++) {
863 Object* arg = args[i]; 856 Object* arg = args[i];
864 PrototypeIterator iter(isolate, arg); 857 PrototypeIterator iter(isolate, arg);
865 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() || 858 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() ||
866 iter.GetCurrent() != array_proto) { 859 iter.GetCurrent() != array_proto) {
867 AllowHeapAllocation allow_allocation; 860 AllowHeapAllocation allow_allocation;
868 return CallJsBuiltin(isolate, "$arrayConcat", args); 861 return CallJsIntrinsic(isolate, isolate->array_concat(), args);
869 } 862 }
870 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 863 int len = Smi::cast(JSArray::cast(arg)->length())->value();
871 864
872 // We shouldn't overflow when adding another len. 865 // We shouldn't overflow when adding another len.
873 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 866 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
874 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 867 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
875 USE(kHalfOfMaxInt); 868 USE(kHalfOfMaxInt);
876 result_len += len; 869 result_len += len;
877 DCHECK(result_len >= 0); 870 DCHECK(result_len >= 0);
878 871
879 if (result_len > FixedDoubleArray::kMaxLength) { 872 if (result_len > FixedDoubleArray::kMaxLength) {
880 AllowHeapAllocation allow_allocation; 873 AllowHeapAllocation allow_allocation;
881 return CallJsBuiltin(isolate, "$arrayConcat", args); 874 return CallJsIntrinsic(isolate, isolate->array_concat(), args);
882 } 875 }
883 876
884 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); 877 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
885 has_double = has_double || IsFastDoubleElementsKind(arg_kind); 878 has_double = has_double || IsFastDoubleElementsKind(arg_kind);
886 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); 879 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
887 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { 880 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
888 elements_kind = arg_kind; 881 elements_kind = arg_kind;
889 } 882 }
890 } 883 }
891 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); 884 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1527 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1535 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1528 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1536 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 1529 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1537 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1530 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1538 #undef DEFINE_BUILTIN_ACCESSOR_C 1531 #undef DEFINE_BUILTIN_ACCESSOR_C
1539 #undef DEFINE_BUILTIN_ACCESSOR_A 1532 #undef DEFINE_BUILTIN_ACCESSOR_A
1540 1533
1541 1534
1542 } // namespace internal 1535 } // namespace internal
1543 } // namespace v8 1536 } // namespace v8
OLDNEW
« no previous file with comments | « src/array.js ('k') | src/contexts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698