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

Side by Side Diff: src/builtins.cc

Issue 857002: Reland 4068 which wrapped Array methods into native builtins (reverted in 4075). (Closed)
Patch Set: Created 10 years, 9 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/bootstrapper.cc ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 ASSERT(proto->elements() == Heap::empty_fixed_array()); 312 ASSERT(proto->elements() == Heap::empty_fixed_array());
313 // Object.prototype 313 // Object.prototype
314 proto = JSObject::cast(proto->GetPrototype()); 314 proto = JSObject::cast(proto->GetPrototype());
315 if (proto != global_context->initial_object_prototype()) return false; 315 if (proto != global_context->initial_object_prototype()) return false;
316 if (proto->elements() != Heap::empty_fixed_array()) return false; 316 if (proto->elements() != Heap::empty_fixed_array()) return false;
317 ASSERT(proto->GetPrototype()->IsNull()); 317 ASSERT(proto->GetPrototype()->IsNull());
318 return true; 318 return true;
319 } 319 }
320 320
321 321
322 static bool IsJSArrayWithFastElements(Object* receiver,
323 FixedArray** elements) {
324 if (!receiver->IsJSArray()) {
325 return false;
326 }
327
328 JSArray* array = JSArray::cast(receiver);
329
330 HeapObject* elms = HeapObject::cast(array->elements());
331 if (elms->map() != Heap::fixed_array_map()) {
332 return false;
333 }
334
335 *elements = FixedArray::cast(elms);
336 return true;
337 }
338
339
322 static Object* CallJsBuiltin(const char* name, 340 static Object* CallJsBuiltin(const char* name,
323 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 341 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
324 HandleScope handleScope; 342 HandleScope handleScope;
325 343
326 Handle<Object> js_builtin = 344 Handle<Object> js_builtin =
327 GetProperty(Handle<JSObject>(Top::global_context()->builtins()), 345 GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
328 name); 346 name);
329 ASSERT(js_builtin->IsJSFunction()); 347 ASSERT(js_builtin->IsJSFunction());
330 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); 348 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
331 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1)); 349 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
332 int n_args = args.length() - 1; 350 int n_args = args.length() - 1;
333 for (int i = 0; i < n_args; i++) { 351 for (int i = 0; i < n_args; i++) {
334 argv[i] = &args[i + 1]; 352 argv[i] = args.at<Object>(i + 1).location();
335 } 353 }
336 bool pending_exception = false; 354 bool pending_exception = false;
337 Handle<Object> result = Execution::Call(function, 355 Handle<Object> result = Execution::Call(function,
338 args.receiver(), 356 args.receiver(),
339 n_args, 357 n_args,
340 argv.start(), 358 argv.start(),
341 &pending_exception); 359 &pending_exception);
342 argv.Dispose(); 360 argv.Dispose();
343 if (pending_exception) return Failure::Exception(); 361 if (pending_exception) return Failure::Exception();
344 return *result; 362 return *result;
345 } 363 }
346 364
347 365
348 BUILTIN(ArrayPush) { 366 BUILTIN(ArrayPush) {
349 JSArray* array = JSArray::cast(*args.receiver()); 367 Object* receiver = *args.receiver();
350 ASSERT(array->HasFastElements()); 368 FixedArray* elms = NULL;
369 if (!IsJSArrayWithFastElements(receiver, &elms)) {
370 return CallJsBuiltin("ArrayPush", args);
371 }
372 JSArray* array = JSArray::cast(receiver);
351 373
352 int len = Smi::cast(array->length())->value(); 374 int len = Smi::cast(array->length())->value();
353 int to_add = args.length() - 1; 375 int to_add = args.length() - 1;
354 if (to_add == 0) { 376 if (to_add == 0) {
355 return Smi::FromInt(len); 377 return Smi::FromInt(len);
356 } 378 }
357 // Currently fixed arrays cannot grow too big, so 379 // Currently fixed arrays cannot grow too big, so
358 // we should never hit this case. 380 // we should never hit this case.
359 ASSERT(to_add <= (Smi::kMaxValue - len)); 381 ASSERT(to_add <= (Smi::kMaxValue - len));
360 382
361 int new_length = len + to_add; 383 int new_length = len + to_add;
362 FixedArray* elms = FixedArray::cast(array->elements());
363 384
364 if (new_length > elms->length()) { 385 if (new_length > elms->length()) {
365 // New backing storage is needed. 386 // New backing storage is needed.
366 int capacity = new_length + (new_length >> 1) + 16; 387 int capacity = new_length + (new_length >> 1) + 16;
367 Object* obj = Heap::AllocateUninitializedFixedArray(capacity); 388 Object* obj = Heap::AllocateUninitializedFixedArray(capacity);
368 if (obj->IsFailure()) return obj; 389 if (obj->IsFailure()) return obj;
369 FixedArray* new_elms = FixedArray::cast(obj); 390 FixedArray* new_elms = FixedArray::cast(obj);
370 391
371 AssertNoAllocation no_gc; 392 AssertNoAllocation no_gc;
372 CopyElements(&no_gc, new_elms, 0, elms, 0, len); 393 CopyElements(&no_gc, new_elms, 0, elms, 0, len);
(...skipping 10 matching lines...) Expand all
383 elms->set(index + len, args[index + 1], mode); 404 elms->set(index + len, args[index + 1], mode);
384 } 405 }
385 406
386 // Set the length. 407 // Set the length.
387 array->set_length(Smi::FromInt(new_length)); 408 array->set_length(Smi::FromInt(new_length));
388 return Smi::FromInt(new_length); 409 return Smi::FromInt(new_length);
389 } 410 }
390 411
391 412
392 BUILTIN(ArrayPop) { 413 BUILTIN(ArrayPop) {
393 JSArray* array = JSArray::cast(*args.receiver()); 414 Object* receiver = *args.receiver();
394 ASSERT(array->HasFastElements()); 415 FixedArray* elms = NULL;
416 if (!IsJSArrayWithFastElements(receiver, &elms)) {
417 return CallJsBuiltin("ArrayPop", args);
418 }
419 JSArray* array = JSArray::cast(receiver);
395 420
396 int len = Smi::cast(array->length())->value(); 421 int len = Smi::cast(array->length())->value();
397 if (len == 0) return Heap::undefined_value(); 422 if (len == 0) return Heap::undefined_value();
398 423
399 // Get top element 424 // Get top element
400 FixedArray* elms = FixedArray::cast(array->elements());
401 Object* top = elms->get(len - 1); 425 Object* top = elms->get(len - 1);
402 426
403 // Set the length. 427 // Set the length.
404 array->set_length(Smi::FromInt(len - 1)); 428 array->set_length(Smi::FromInt(len - 1));
405 429
406 if (!top->IsTheHole()) { 430 if (!top->IsTheHole()) {
407 // Delete the top element. 431 // Delete the top element.
408 elms->set_the_hole(len - 1); 432 elms->set_the_hole(len - 1);
409 return top; 433 return top;
410 } 434 }
411 435
412 // Remember to check the prototype chain. 436 // Remember to check the prototype chain.
413 JSFunction* array_function = 437 JSFunction* array_function =
414 Top::context()->global_context()->array_function(); 438 Top::context()->global_context()->array_function();
415 JSObject* prototype = JSObject::cast(array_function->prototype()); 439 JSObject* prototype = JSObject::cast(array_function->prototype());
416 top = prototype->GetElement(len - 1); 440 top = prototype->GetElement(len - 1);
417 441
418 return top; 442 return top;
419 } 443 }
420 444
421 445
422 BUILTIN(ArrayShift) { 446 BUILTIN(ArrayShift) {
423 if (!ArrayPrototypeHasNoElements()) { 447 Object* receiver = *args.receiver();
448 FixedArray* elms = NULL;
449 if (!IsJSArrayWithFastElements(receiver, &elms)
450 || !ArrayPrototypeHasNoElements()) {
424 return CallJsBuiltin("ArrayShift", args); 451 return CallJsBuiltin("ArrayShift", args);
425 } 452 }
426 453 JSArray* array = JSArray::cast(receiver);
427 JSArray* array = JSArray::cast(*args.receiver());
428 ASSERT(array->HasFastElements()); 454 ASSERT(array->HasFastElements());
429 455
430 int len = Smi::cast(array->length())->value(); 456 int len = Smi::cast(array->length())->value();
431 if (len == 0) return Heap::undefined_value(); 457 if (len == 0) return Heap::undefined_value();
432 458
433 FixedArray* elms = FixedArray::cast(array->elements());
434
435 // Get first element 459 // Get first element
436 Object* first = elms->get(0); 460 Object* first = elms->get(0);
437 if (first->IsTheHole()) { 461 if (first->IsTheHole()) {
438 first = Heap::undefined_value(); 462 first = Heap::undefined_value();
439 } 463 }
440 464
441 // Shift the elements. 465 // Shift the elements.
442 AssertNoAllocation no_gc; 466 AssertNoAllocation no_gc;
443 MoveElements(&no_gc, elms, 0, elms, 1, len - 1); 467 MoveElements(&no_gc, elms, 0, elms, 1, len - 1);
444 elms->set(len - 1, Heap::the_hole_value()); 468 elms->set(len - 1, Heap::the_hole_value());
445 469
446 // Set the length. 470 // Set the length.
447 array->set_length(Smi::FromInt(len - 1)); 471 array->set_length(Smi::FromInt(len - 1));
448 472
449 return first; 473 return first;
450 } 474 }
451 475
452 476
453 BUILTIN(ArrayUnshift) { 477 BUILTIN(ArrayUnshift) {
454 if (!ArrayPrototypeHasNoElements()) { 478 Object* receiver = *args.receiver();
479 FixedArray* elms = NULL;
480 if (!IsJSArrayWithFastElements(receiver, &elms)
481 || !ArrayPrototypeHasNoElements()) {
455 return CallJsBuiltin("ArrayUnshift", args); 482 return CallJsBuiltin("ArrayUnshift", args);
456 } 483 }
457 484 JSArray* array = JSArray::cast(receiver);
458 JSArray* array = JSArray::cast(*args.receiver());
459 ASSERT(array->HasFastElements()); 485 ASSERT(array->HasFastElements());
460 486
461 int len = Smi::cast(array->length())->value(); 487 int len = Smi::cast(array->length())->value();
462 int to_add = args.length() - 1; 488 int to_add = args.length() - 1;
463 // Note that we cannot quit early if to_add == 0 as 489 // Note that we cannot quit early if to_add == 0 as
464 // values should be lifted from prototype into 490 // values should be lifted from prototype into
465 // the array. 491 // the array.
466 492
467 int new_length = len + to_add; 493 int new_length = len + to_add;
468 // Currently fixed arrays cannot grow too big, so 494 // Currently fixed arrays cannot grow too big, so
469 // we should never hit this case. 495 // we should never hit this case.
470 ASSERT(to_add <= (Smi::kMaxValue - len)); 496 ASSERT(to_add <= (Smi::kMaxValue - len));
471 497
472 FixedArray* elms = FixedArray::cast(array->elements());
473
474 if (new_length > elms->length()) { 498 if (new_length > elms->length()) {
475 // New backing storage is needed. 499 // New backing storage is needed.
476 int capacity = new_length + (new_length >> 1) + 16; 500 int capacity = new_length + (new_length >> 1) + 16;
477 Object* obj = Heap::AllocateUninitializedFixedArray(capacity); 501 Object* obj = Heap::AllocateUninitializedFixedArray(capacity);
478 if (obj->IsFailure()) return obj; 502 if (obj->IsFailure()) return obj;
479 FixedArray* new_elms = FixedArray::cast(obj); 503 FixedArray* new_elms = FixedArray::cast(obj);
480 504
481 AssertNoAllocation no_gc; 505 AssertNoAllocation no_gc;
482 CopyElements(&no_gc, new_elms, to_add, elms, 0, len); 506 CopyElements(&no_gc, new_elms, to_add, elms, 0, len);
483 FillWithHoles(new_elms, new_length, capacity); 507 FillWithHoles(new_elms, new_length, capacity);
(...skipping 12 matching lines...) Expand all
496 elms->set(i, args[i + 1], mode); 520 elms->set(i, args[i + 1], mode);
497 } 521 }
498 522
499 // Set the length. 523 // Set the length.
500 array->set_length(Smi::FromInt(new_length)); 524 array->set_length(Smi::FromInt(new_length));
501 return Smi::FromInt(new_length); 525 return Smi::FromInt(new_length);
502 } 526 }
503 527
504 528
505 BUILTIN(ArraySlice) { 529 BUILTIN(ArraySlice) {
506 if (!ArrayPrototypeHasNoElements()) { 530 Object* receiver = *args.receiver();
531 FixedArray* elms = NULL;
532 if (!IsJSArrayWithFastElements(receiver, &elms)
533 || !ArrayPrototypeHasNoElements()) {
507 return CallJsBuiltin("ArraySlice", args); 534 return CallJsBuiltin("ArraySlice", args);
508 } 535 }
509 536 JSArray* array = JSArray::cast(receiver);
510 JSArray* array = JSArray::cast(*args.receiver());
511 ASSERT(array->HasFastElements()); 537 ASSERT(array->HasFastElements());
512 538
513 int len = Smi::cast(array->length())->value(); 539 int len = Smi::cast(array->length())->value();
514 540
515 int n_arguments = args.length() - 1; 541 int n_arguments = args.length() - 1;
516 542
517 // Note carefully choosen defaults---if argument is missing, 543 // Note carefully choosen defaults---if argument is missing,
518 // it's undefined which gets converted to 0 for relative_start 544 // it's undefined which gets converted to 0 for relative_start
519 // and to len for relative_end. 545 // and to len for relative_end.
520 int relative_start = 0; 546 int relative_start = 0;
(...skipping 30 matching lines...) Expand all
551 } 577 }
552 578
553 Object* result = AllocateJSArray(); 579 Object* result = AllocateJSArray();
554 if (result->IsFailure()) return result; 580 if (result->IsFailure()) return result;
555 JSArray* result_array = JSArray::cast(result); 581 JSArray* result_array = JSArray::cast(result);
556 582
557 result = Heap::AllocateUninitializedFixedArray(result_len); 583 result = Heap::AllocateUninitializedFixedArray(result_len);
558 if (result->IsFailure()) return result; 584 if (result->IsFailure()) return result;
559 FixedArray* result_elms = FixedArray::cast(result); 585 FixedArray* result_elms = FixedArray::cast(result);
560 586
561 FixedArray* elms = FixedArray::cast(array->elements());
562
563 AssertNoAllocation no_gc; 587 AssertNoAllocation no_gc;
564 CopyElements(&no_gc, result_elms, 0, elms, k, result_len); 588 CopyElements(&no_gc, result_elms, 0, elms, k, result_len);
565 589
566 // Set elements. 590 // Set elements.
567 result_array->set_elements(result_elms); 591 result_array->set_elements(result_elms);
568 592
569 // Set the length. 593 // Set the length.
570 result_array->set_length(Smi::FromInt(result_len)); 594 result_array->set_length(Smi::FromInt(result_len));
571 return result_array; 595 return result_array;
572 } 596 }
573 597
574 598
575 BUILTIN(ArraySplice) { 599 BUILTIN(ArraySplice) {
576 if (!ArrayPrototypeHasNoElements()) { 600 Object* receiver = *args.receiver();
601 FixedArray* elms = NULL;
602 if (!IsJSArrayWithFastElements(receiver, &elms)
603 || !ArrayPrototypeHasNoElements()) {
577 return CallJsBuiltin("ArraySplice", args); 604 return CallJsBuiltin("ArraySplice", args);
578 } 605 }
579 606 JSArray* array = JSArray::cast(receiver);
580 JSArray* array = JSArray::cast(*args.receiver());
581 ASSERT(array->HasFastElements()); 607 ASSERT(array->HasFastElements());
582 608
583 int len = Smi::cast(array->length())->value(); 609 int len = Smi::cast(array->length())->value();
584 610
585 int n_arguments = args.length() - 1; 611 int n_arguments = args.length() - 1;
586 612
587 // SpiderMonkey and JSC return undefined in the case where no 613 // SpiderMonkey and JSC return undefined in the case where no
588 // arguments are given instead of using the implicit undefined 614 // arguments are given instead of using the implicit undefined
589 // arguments. This does not follow ECMA-262, but we do the same for 615 // arguments. This does not follow ECMA-262, but we do the same for
590 // compatibility. 616 // compatibility.
(...skipping 20 matching lines...) Expand all
611 if (n_arguments > 1) { 637 if (n_arguments > 1) {
612 Object* arg2 = args[2]; 638 Object* arg2 = args[2];
613 if (arg2->IsSmi()) { 639 if (arg2->IsSmi()) {
614 delete_count = Smi::cast(arg2)->value(); 640 delete_count = Smi::cast(arg2)->value();
615 } else { 641 } else {
616 return CallJsBuiltin("ArraySplice", args); 642 return CallJsBuiltin("ArraySplice", args);
617 } 643 }
618 } 644 }
619 int actual_delete_count = Min(Max(delete_count, 0), len - actual_start); 645 int actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
620 646
621 FixedArray* elms = FixedArray::cast(array->elements());
622
623 JSArray* result_array = NULL; 647 JSArray* result_array = NULL;
624 if (actual_delete_count == 0) { 648 if (actual_delete_count == 0) {
625 Object* result = AllocateEmptyJSArray(); 649 Object* result = AllocateEmptyJSArray();
626 if (result->IsFailure()) return result; 650 if (result->IsFailure()) return result;
627 result_array = JSArray::cast(result); 651 result_array = JSArray::cast(result);
628 } else { 652 } else {
629 // Allocate result array. 653 // Allocate result array.
630 Object* result = AllocateJSArray(); 654 Object* result = AllocateJSArray();
631 if (result->IsFailure()) return result; 655 if (result->IsFailure()) return result;
632 result_array = JSArray::cast(result); 656 result_array = JSArray::cast(result);
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 if (entry->contains(pc)) { 1375 if (entry->contains(pc)) {
1352 return names_[i]; 1376 return names_[i];
1353 } 1377 }
1354 } 1378 }
1355 } 1379 }
1356 return NULL; 1380 return NULL;
1357 } 1381 }
1358 1382
1359 1383
1360 } } // namespace v8::internal 1384 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/contexts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698