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

Side by Side Diff: src/builtins.cc

Issue 660298: Always invoke C++ ArrayPush builtin. (Closed)
Patch Set: Next round 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[i + 1];
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 if (pending_exception) return Failure::Exception(); 360 if (pending_exception) return Failure::Exception();
343 return *result; 361 return *result;
344 } 362 }
345 363
346 364
347 BUILTIN(ArrayPush) { 365 BUILTIN(ArrayPush) {
348 JSArray* array = JSArray::cast(*args.receiver()); 366 Object* receiver = *args.receiver();
349 ASSERT(array->HasFastElements()); 367 FixedArray* elms = NULL;
368 if (!IsJSArrayWithFastElements(receiver, &elms)) {
369 return CallJsBuiltin("ArrayPush", args);
370 }
371 JSArray* array = JSArray::cast(receiver);
350 372
351 int len = Smi::cast(array->length())->value(); 373 int len = Smi::cast(array->length())->value();
352 int to_add = args.length() - 1; 374 int to_add = args.length() - 1;
353 if (to_add == 0) { 375 if (to_add == 0) {
354 return Smi::FromInt(len); 376 return Smi::FromInt(len);
355 } 377 }
356 // Currently fixed arrays cannot grow too big, so 378 // Currently fixed arrays cannot grow too big, so
357 // we should never hit this case. 379 // we should never hit this case.
358 ASSERT(to_add <= (Smi::kMaxValue - len)); 380 ASSERT(to_add <= (Smi::kMaxValue - len));
359 381
360 int new_length = len + to_add; 382 int new_length = len + to_add;
361 FixedArray* elms = FixedArray::cast(array->elements());
362 383
363 if (new_length > elms->length()) { 384 if (new_length > elms->length()) {
364 // New backing storage is needed. 385 // New backing storage is needed.
365 int capacity = new_length + (new_length >> 1) + 16; 386 int capacity = new_length + (new_length >> 1) + 16;
366 Object* obj = AllocateUninitializedFixedArray(capacity); 387 Object* obj = AllocateUninitializedFixedArray(capacity);
367 if (obj->IsFailure()) return obj; 388 if (obj->IsFailure()) return obj;
368 FixedArray* new_elms = FixedArray::cast(obj); 389 FixedArray* new_elms = FixedArray::cast(obj);
369 390
370 AssertNoAllocation no_gc; 391 AssertNoAllocation no_gc;
371 CopyElements(&no_gc, new_elms, 0, elms, 0, len); 392 CopyElements(&no_gc, new_elms, 0, elms, 0, len);
(...skipping 10 matching lines...) Expand all
382 elms->set(index + len, args[index + 1], mode); 403 elms->set(index + len, args[index + 1], mode);
383 } 404 }
384 405
385 // Set the length. 406 // Set the length.
386 array->set_length(Smi::FromInt(new_length)); 407 array->set_length(Smi::FromInt(new_length));
387 return Smi::FromInt(new_length); 408 return Smi::FromInt(new_length);
388 } 409 }
389 410
390 411
391 BUILTIN(ArrayPop) { 412 BUILTIN(ArrayPop) {
392 JSArray* array = JSArray::cast(*args.receiver()); 413 Object* receiver = *args.receiver();
393 ASSERT(array->HasFastElements()); 414 FixedArray* elms = NULL;
415 if (!IsJSArrayWithFastElements(receiver, &elms)) {
416 return CallJsBuiltin("ArrayPop", args);
417 }
418 JSArray* array = JSArray::cast(receiver);
394 419
395 int len = Smi::cast(array->length())->value(); 420 int len = Smi::cast(array->length())->value();
396 if (len == 0) return Heap::undefined_value(); 421 if (len == 0) return Heap::undefined_value();
397 422
398 // Get top element 423 // Get top element
399 FixedArray* elms = FixedArray::cast(array->elements());
400 Object* top = elms->get(len - 1); 424 Object* top = elms->get(len - 1);
401 425
402 // Set the length. 426 // Set the length.
403 array->set_length(Smi::FromInt(len - 1)); 427 array->set_length(Smi::FromInt(len - 1));
404 428
405 if (!top->IsTheHole()) { 429 if (!top->IsTheHole()) {
406 // Delete the top element. 430 // Delete the top element.
407 elms->set_the_hole(len - 1); 431 elms->set_the_hole(len - 1);
408 return top; 432 return top;
409 } 433 }
410 434
411 // Remember to check the prototype chain. 435 // Remember to check the prototype chain.
412 JSFunction* array_function = 436 JSFunction* array_function =
413 Top::context()->global_context()->array_function(); 437 Top::context()->global_context()->array_function();
414 JSObject* prototype = JSObject::cast(array_function->prototype()); 438 JSObject* prototype = JSObject::cast(array_function->prototype());
415 top = prototype->GetElement(len - 1); 439 top = prototype->GetElement(len - 1);
416 440
417 return top; 441 return top;
418 } 442 }
419 443
420 444
421 BUILTIN(ArrayShift) { 445 BUILTIN(ArrayShift) {
422 if (!ArrayPrototypeHasNoElements()) { 446 Object* receiver = *args.receiver();
447 FixedArray* elms = NULL;
448 if (!IsJSArrayWithFastElements(receiver, &elms)
449 || !ArrayPrototypeHasNoElements()) {
423 return CallJsBuiltin("ArrayShift", args); 450 return CallJsBuiltin("ArrayShift", args);
424 } 451 }
425 452 JSArray* array = JSArray::cast(receiver);
426 JSArray* array = JSArray::cast(*args.receiver());
427 ASSERT(array->HasFastElements()); 453 ASSERT(array->HasFastElements());
428 454
429 int len = Smi::cast(array->length())->value(); 455 int len = Smi::cast(array->length())->value();
430 if (len == 0) return Heap::undefined_value(); 456 if (len == 0) return Heap::undefined_value();
431 457
432 FixedArray* elms = FixedArray::cast(array->elements());
433
434 // Get first element 458 // Get first element
435 Object* first = elms->get(0); 459 Object* first = elms->get(0);
436 if (first->IsTheHole()) { 460 if (first->IsTheHole()) {
437 first = Heap::undefined_value(); 461 first = Heap::undefined_value();
438 } 462 }
439 463
440 // Shift the elements. 464 // Shift the elements.
441 AssertNoAllocation no_gc; 465 AssertNoAllocation no_gc;
442 MoveElements(&no_gc, elms, 0, elms, 1, len - 1); 466 MoveElements(&no_gc, elms, 0, elms, 1, len - 1);
443 elms->set(len - 1, Heap::the_hole_value()); 467 elms->set(len - 1, Heap::the_hole_value());
444 468
445 // Set the length. 469 // Set the length.
446 array->set_length(Smi::FromInt(len - 1)); 470 array->set_length(Smi::FromInt(len - 1));
447 471
448 return first; 472 return first;
449 } 473 }
450 474
451 475
452 BUILTIN(ArrayUnshift) { 476 BUILTIN(ArrayUnshift) {
453 if (!ArrayPrototypeHasNoElements()) { 477 Object* receiver = *args.receiver();
478 FixedArray* elms = NULL;
479 if (!IsJSArrayWithFastElements(receiver, &elms)
480 || !ArrayPrototypeHasNoElements()) {
454 return CallJsBuiltin("ArrayUnshift", args); 481 return CallJsBuiltin("ArrayUnshift", args);
455 } 482 }
456 483 JSArray* array = JSArray::cast(receiver);
457 JSArray* array = JSArray::cast(*args.receiver());
458 ASSERT(array->HasFastElements()); 484 ASSERT(array->HasFastElements());
459 485
460 int len = Smi::cast(array->length())->value(); 486 int len = Smi::cast(array->length())->value();
461 int to_add = args.length() - 1; 487 int to_add = args.length() - 1;
462 // Note that we cannot quit early if to_add == 0 as 488 // Note that we cannot quit early if to_add == 0 as
463 // values should be lifted from prototype into 489 // values should be lifted from prototype into
464 // the array. 490 // the array.
465 491
466 int new_length = len + to_add; 492 int new_length = len + to_add;
467 // Currently fixed arrays cannot grow too big, so 493 // Currently fixed arrays cannot grow too big, so
468 // we should never hit this case. 494 // we should never hit this case.
469 ASSERT(to_add <= (Smi::kMaxValue - len)); 495 ASSERT(to_add <= (Smi::kMaxValue - len));
470 496
471 FixedArray* elms = FixedArray::cast(array->elements());
472
473 if (new_length > elms->length()) { 497 if (new_length > elms->length()) {
474 // New backing storage is needed. 498 // New backing storage is needed.
475 int capacity = new_length + (new_length >> 1) + 16; 499 int capacity = new_length + (new_length >> 1) + 16;
476 Object* obj = AllocateUninitializedFixedArray(capacity); 500 Object* obj = AllocateUninitializedFixedArray(capacity);
477 if (obj->IsFailure()) return obj; 501 if (obj->IsFailure()) return obj;
478 FixedArray* new_elms = FixedArray::cast(obj); 502 FixedArray* new_elms = FixedArray::cast(obj);
479 503
480 AssertNoAllocation no_gc; 504 AssertNoAllocation no_gc;
481 CopyElements(&no_gc, new_elms, to_add, elms, 0, len); 505 CopyElements(&no_gc, new_elms, to_add, elms, 0, len);
482 FillWithHoles(new_elms, new_length, capacity); 506 FillWithHoles(new_elms, new_length, capacity);
(...skipping 12 matching lines...) Expand all
495 elms->set(i, args[i + 1], mode); 519 elms->set(i, args[i + 1], mode);
496 } 520 }
497 521
498 // Set the length. 522 // Set the length.
499 array->set_length(Smi::FromInt(new_length)); 523 array->set_length(Smi::FromInt(new_length));
500 return Smi::FromInt(new_length); 524 return Smi::FromInt(new_length);
501 } 525 }
502 526
503 527
504 BUILTIN(ArraySlice) { 528 BUILTIN(ArraySlice) {
505 if (!ArrayPrototypeHasNoElements()) { 529 Object* receiver = *args.receiver();
530 FixedArray* elms = NULL;
531 if (!IsJSArrayWithFastElements(receiver, &elms)
532 || !ArrayPrototypeHasNoElements()) {
506 return CallJsBuiltin("ArraySlice", args); 533 return CallJsBuiltin("ArraySlice", args);
507 } 534 }
508 535 JSArray* array = JSArray::cast(receiver);
509 JSArray* array = JSArray::cast(*args.receiver());
510 ASSERT(array->HasFastElements()); 536 ASSERT(array->HasFastElements());
511 537
512 int len = Smi::cast(array->length())->value(); 538 int len = Smi::cast(array->length())->value();
513 539
514 int n_arguments = args.length() - 1; 540 int n_arguments = args.length() - 1;
515 541
516 // Note carefully choosen defaults---if argument is missing, 542 // Note carefully choosen defaults---if argument is missing,
517 // it's undefined which gets converted to 0 for relativeStart 543 // it's undefined which gets converted to 0 for relativeStart
518 // and to len for relativeEnd. 544 // and to len for relativeEnd.
519 int relativeStart = 0; 545 int relativeStart = 0;
(...skipping 30 matching lines...) Expand all
550 } 576 }
551 577
552 Object* result = AllocateJSArray(); 578 Object* result = AllocateJSArray();
553 if (result->IsFailure()) return result; 579 if (result->IsFailure()) return result;
554 JSArray* result_array = JSArray::cast(result); 580 JSArray* result_array = JSArray::cast(result);
555 581
556 result = AllocateUninitializedFixedArray(result_len); 582 result = AllocateUninitializedFixedArray(result_len);
557 if (result->IsFailure()) return result; 583 if (result->IsFailure()) return result;
558 FixedArray* result_elms = FixedArray::cast(result); 584 FixedArray* result_elms = FixedArray::cast(result);
559 585
560 FixedArray* elms = FixedArray::cast(array->elements());
561
562 AssertNoAllocation no_gc; 586 AssertNoAllocation no_gc;
563 CopyElements(&no_gc, result_elms, 0, elms, k, result_len); 587 CopyElements(&no_gc, result_elms, 0, elms, k, result_len);
564 588
565 // Set elements. 589 // Set elements.
566 result_array->set_elements(result_elms); 590 result_array->set_elements(result_elms);
567 591
568 // Set the length. 592 // Set the length.
569 result_array->set_length(Smi::FromInt(result_len)); 593 result_array->set_length(Smi::FromInt(result_len));
570 return result_array; 594 return result_array;
571 } 595 }
572 596
573 597
574 BUILTIN(ArraySplice) { 598 BUILTIN(ArraySplice) {
575 if (!ArrayPrototypeHasNoElements()) { 599 Object* receiver = *args.receiver();
600 FixedArray* elms = NULL;
601 if (!IsJSArrayWithFastElements(receiver, &elms)
602 || !ArrayPrototypeHasNoElements()) {
576 return CallJsBuiltin("ArraySplice", args); 603 return CallJsBuiltin("ArraySplice", args);
577 } 604 }
578 605 JSArray* array = JSArray::cast(receiver);
579 JSArray* array = JSArray::cast(*args.receiver());
580 ASSERT(array->HasFastElements()); 606 ASSERT(array->HasFastElements());
581 607
582 int len = Smi::cast(array->length())->value(); 608 int len = Smi::cast(array->length())->value();
583 609
584 int n_arguments = args.length() - 1; 610 int n_arguments = args.length() - 1;
585 611
586 // SpiderMonkey and JSC return undefined in the case where no 612 // SpiderMonkey and JSC return undefined in the case where no
587 // arguments are given instead of using the implicit undefined 613 // arguments are given instead of using the implicit undefined
588 // arguments. This does not follow ECMA-262, but we do the same for 614 // arguments. This does not follow ECMA-262, but we do the same for
589 // compatibility. 615 // compatibility.
(...skipping 29 matching lines...) Expand all
619 645
620 // Allocate result array. 646 // Allocate result array.
621 Object* result = AllocateJSArray(); 647 Object* result = AllocateJSArray();
622 if (result->IsFailure()) return result; 648 if (result->IsFailure()) return result;
623 JSArray* result_array = JSArray::cast(result); 649 JSArray* result_array = JSArray::cast(result);
624 650
625 result = AllocateUninitializedFixedArray(actualDeleteCount); 651 result = AllocateUninitializedFixedArray(actualDeleteCount);
626 if (result->IsFailure()) return result; 652 if (result->IsFailure()) return result;
627 FixedArray* result_elms = FixedArray::cast(result); 653 FixedArray* result_elms = FixedArray::cast(result);
628 654
629 FixedArray* elms = FixedArray::cast(array->elements());
630
631 AssertNoAllocation no_gc; 655 AssertNoAllocation no_gc;
632 // Fill newly created array. 656 // Fill newly created array.
633 CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount); 657 CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount);
634 658
635 // Set elements. 659 // Set elements.
636 result_array->set_elements(result_elms); 660 result_array->set_elements(result_elms);
637 661
638 // Set the length. 662 // Set the length.
639 result_array->set_length(Smi::FromInt(actualDeleteCount)); 663 result_array->set_length(Smi::FromInt(actualDeleteCount));
640 664
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 if (entry->contains(pc)) { 1359 if (entry->contains(pc)) {
1336 return names_[i]; 1360 return names_[i];
1337 } 1361 }
1338 } 1362 }
1339 } 1363 }
1340 return NULL; 1364 return NULL;
1341 } 1365 }
1342 1366
1343 1367
1344 } } // namespace v8::internal 1368 } } // 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