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

Side by Side Diff: src/arm/builtins-arm.cc

Issue 3329019: Dynamically determine optimal instance size.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/builtins.h » ('j') | src/ia32/assembler-ia32.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 __ bind(&non_function_call); 514 __ bind(&non_function_call);
515 // Set expected number of arguments to zero (not changing r0). 515 // Set expected number of arguments to zero (not changing r0).
516 __ mov(r2, Operand(0, RelocInfo::NONE)); 516 __ mov(r2, Operand(0, RelocInfo::NONE));
517 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 517 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
518 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 518 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
519 RelocInfo::CODE_TARGET); 519 RelocInfo::CODE_TARGET);
520 } 520 }
521 521
522 522
523 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 523 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
524 bool is_api_function) { 524 bool is_api_function,
525 bool count_constructions) {
526 // Should never count constructions for api objects.
527 ASSERT(!is_api_function || !count_constructions);
528
525 // Enter a construct frame. 529 // Enter a construct frame.
526 __ EnterConstructFrame(); 530 __ EnterConstructFrame();
527 531
528 // Preserve the two incoming parameters on the stack. 532 // Preserve the two incoming parameters on the stack.
529 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 533 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
530 __ push(r0); // Smi-tagged arguments count. 534 __ push(r0); // Smi-tagged arguments count.
531 __ push(r1); // Constructor function. 535 __ push(r1); // Constructor function.
532 536
533 // Use r7 for holding undefined which is used in several places below.
534 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
535
536 // Try to allocate the object without transitioning into C code. If any of the 537 // Try to allocate the object without transitioning into C code. If any of the
537 // preconditions is not met, the code bails out to the runtime call. 538 // preconditions is not met, the code bails out to the runtime call.
538 Label rt_call, allocated; 539 Label rt_call, allocated;
539 if (FLAG_inline_new) { 540 if (FLAG_inline_new) {
540 Label undo_allocation; 541 Label undo_allocation;
541 #ifdef ENABLE_DEBUGGER_SUPPORT 542 #ifdef ENABLE_DEBUGGER_SUPPORT
542 ExternalReference debug_step_in_fp = 543 ExternalReference debug_step_in_fp =
543 ExternalReference::debug_step_in_fp_address(); 544 ExternalReference::debug_step_in_fp_address();
544 __ mov(r2, Operand(debug_step_in_fp)); 545 __ mov(r2, Operand(debug_step_in_fp));
545 __ ldr(r2, MemOperand(r2)); 546 __ ldr(r2, MemOperand(r2));
546 __ tst(r2, r2); 547 __ tst(r2, r2);
547 __ b(nz, &rt_call); 548 __ b(nz, &rt_call);
548 #endif 549 #endif
549 550
550 // Load the initial map and verify that it is in fact a map. 551 // Load the initial map and verify that it is in fact a map.
551 // r1: constructor function 552 // r1: constructor function
552 // r7: undefined value
553 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 553 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
554 __ tst(r2, Operand(kSmiTagMask)); 554 __ tst(r2, Operand(kSmiTagMask));
555 __ b(eq, &rt_call); 555 __ b(eq, &rt_call);
556 __ CompareObjectType(r2, r3, r4, MAP_TYPE); 556 __ CompareObjectType(r2, r3, r4, MAP_TYPE);
557 __ b(ne, &rt_call); 557 __ b(ne, &rt_call);
558 558
559 // Check that the constructor is not constructing a JSFunction (see comments 559 // Check that the constructor is not constructing a JSFunction (see comments
560 // in Runtime_NewObject in runtime.cc). In which case the initial map's 560 // in Runtime_NewObject in runtime.cc). In which case the initial map's
561 // instance type would be JS_FUNCTION_TYPE. 561 // instance type would be JS_FUNCTION_TYPE.
562 // r1: constructor function 562 // r1: constructor function
563 // r2: initial map 563 // r2: initial map
564 // r7: undefined value
565 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 564 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
566 __ b(eq, &rt_call); 565 __ b(eq, &rt_call);
567 566
567 if (count_constructions) {
568 Label allocate;
569 // Decrease generous allocation count.
570 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
571 MemOperand constructor_count =
572 FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
573 __ ldrb(r4, constructor_count);
574 __ sub(r4, r4, Operand(1), SetCC);
575 __ strb(r4, constructor_count);
576 __ b(ne, &allocate);
577
578 __ Push(r1, r2);
579
580 __ push(r1); // constructor
581 // The call will replace the stub, so the countdown is only done once.
582 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
583
584 __ pop(r2);
585 __ pop(r1);
586
587 __ bind(&allocate);
588 }
589
568 // Now allocate the JSObject on the heap. 590 // Now allocate the JSObject on the heap.
569 // r1: constructor function 591 // r1: constructor function
570 // r2: initial map 592 // r2: initial map
571 // r7: undefined value
572 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 593 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
573 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); 594 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
574 595
575 // Allocated the JSObject, now initialize the fields. Map is set to initial 596 // Allocated the JSObject, now initialize the fields. Map is set to initial
576 // map and properties and elements are set to empty fixed array. 597 // map and properties and elements are set to empty fixed array.
577 // r1: constructor function 598 // r1: constructor function
578 // r2: initial map 599 // r2: initial map
579 // r3: object size 600 // r3: object size
580 // r4: JSObject (not tagged) 601 // r4: JSObject (not tagged)
581 // r7: undefined value
582 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 602 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
583 __ mov(r5, r4); 603 __ mov(r5, r4);
584 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 604 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
585 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 605 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
586 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 606 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
587 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 607 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
588 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 608 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
589 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 609 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
590 610
591 // Fill all the in-object properties with undefined. 611 // Fill all the in-object properties with the appropriate filler.
592 // r1: constructor function 612 // r1: constructor function
593 // r2: initial map 613 // r2: initial map
594 // r3: object size (in words) 614 // r3: object size (in words)
595 // r4: JSObject (not tagged) 615 // r4: JSObject (not tagged)
596 // r5: First in-object property of JSObject (not tagged) 616 // r5: First in-object property of JSObject (not tagged)
597 // r7: undefined value
598 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 617 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
599 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 618 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
600 { Label loop, entry; 619 { Label loop, entry;
620 if (count_constructions) {
621 // To allow for truncation.
622 __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
623 } else {
624 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
625 }
601 __ b(&entry); 626 __ b(&entry);
602 __ bind(&loop); 627 __ bind(&loop);
603 __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 628 __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
604 __ bind(&entry); 629 __ bind(&entry);
605 __ cmp(r5, r6); 630 __ cmp(r5, r6);
606 __ b(lt, &loop); 631 __ b(lt, &loop);
607 } 632 }
608 633
609 // Add the object tag to make the JSObject real, so that we can continue and 634 // Add the object tag to make the JSObject real, so that we can continue and
610 // jump into the continuation code at any time from now on. Any failures 635 // jump into the continuation code at any time from now on. Any failures
611 // need to undo the allocation, so that the heap is in a consistent state 636 // need to undo the allocation, so that the heap is in a consistent state
612 // and verifiable. 637 // and verifiable.
613 __ add(r4, r4, Operand(kHeapObjectTag)); 638 __ add(r4, r4, Operand(kHeapObjectTag));
614 639
615 // Check if a non-empty properties array is needed. Continue with allocated 640 // Check if a non-empty properties array is needed. Continue with allocated
616 // object if not fall through to runtime call if it is. 641 // object if not fall through to runtime call if it is.
617 // r1: constructor function 642 // r1: constructor function
618 // r4: JSObject 643 // r4: JSObject
619 // r5: start of next object (not tagged) 644 // r5: start of next object (not tagged)
620 // r7: undefined value
621 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 645 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
622 // The field instance sizes contains both pre-allocated property fields and 646 // The field instance sizes contains both pre-allocated property fields and
623 // in-object properties. 647 // in-object properties.
624 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 648 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
625 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8); 649 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8);
626 __ add(r3, r3, Operand(r6)); 650 __ add(r3, r3, Operand(r6));
627 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8); 651 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8);
628 __ sub(r3, r3, Operand(r6), SetCC); 652 __ sub(r3, r3, Operand(r6), SetCC);
629 653
630 // Done if no extra properties are to be allocated. 654 // Done if no extra properties are to be allocated.
631 __ b(eq, &allocated); 655 __ b(eq, &allocated);
632 __ Assert(pl, "Property allocation count failed."); 656 __ Assert(pl, "Property allocation count failed.");
633 657
634 // Scale the number of elements by pointer size and add the header for 658 // Scale the number of elements by pointer size and add the header for
635 // FixedArrays to the start of the next object calculation from above. 659 // FixedArrays to the start of the next object calculation from above.
636 // r1: constructor 660 // r1: constructor
637 // r3: number of elements in properties array 661 // r3: number of elements in properties array
638 // r4: JSObject 662 // r4: JSObject
639 // r5: start of next object 663 // r5: start of next object
640 // r7: undefined value
641 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 664 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
642 __ AllocateInNewSpace( 665 __ AllocateInNewSpace(
643 r0, 666 r0,
644 r5, 667 r5,
645 r6, 668 r6,
646 r2, 669 r2,
647 &undo_allocation, 670 &undo_allocation,
648 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 671 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
649 672
650 // Initialize the FixedArray. 673 // Initialize the FixedArray.
651 // r1: constructor 674 // r1: constructor
652 // r3: number of elements in properties array 675 // r3: number of elements in properties array
653 // r4: JSObject 676 // r4: JSObject
654 // r5: FixedArray (not tagged) 677 // r5: FixedArray (not tagged)
655 // r7: undefined value
656 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 678 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
657 __ mov(r2, r5); 679 __ mov(r2, r5);
658 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 680 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
659 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 681 __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
660 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 682 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
661 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 683 __ mov(r0, Operand(r3, LSL, kSmiTagSize));
662 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 684 __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
663 685
664 // Initialize the fields to undefined. 686 // Initialize the fields to undefined.
665 // r1: constructor function 687 // r1: constructor function
666 // r2: First element of FixedArray (not tagged) 688 // r2: First element of FixedArray (not tagged)
667 // r3: number of elements in properties array 689 // r3: number of elements in properties array
668 // r4: JSObject 690 // r4: JSObject
669 // r5: FixedArray (not tagged) 691 // r5: FixedArray (not tagged)
670 // r7: undefined
671 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 692 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
672 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 693 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
673 { Label loop, entry; 694 { Label loop, entry;
695 if (count_constructions) {
696 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
697 } else if (FLAG_debug_code) {
698 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
699 __ cmp(r7, r8);
700 __ Assert(eq, "Undefined value not loaded.");
701 }
674 __ b(&entry); 702 __ b(&entry);
675 __ bind(&loop); 703 __ bind(&loop);
676 __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); 704 __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
677 __ bind(&entry); 705 __ bind(&entry);
678 __ cmp(r2, r6); 706 __ cmp(r2, r6);
679 __ b(lt, &loop); 707 __ b(lt, &loop);
680 } 708 }
681 709
682 // Store the initialized FixedArray into the properties field of 710 // Store the initialized FixedArray into the properties field of
683 // the JSObject 711 // the JSObject
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 // sp[2]: number of arguments (smi-tagged) 843 // sp[2]: number of arguments (smi-tagged)
816 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 844 __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
817 __ LeaveConstructFrame(); 845 __ LeaveConstructFrame();
818 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 846 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
819 __ add(sp, sp, Operand(kPointerSize)); 847 __ add(sp, sp, Operand(kPointerSize));
820 __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2); 848 __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
821 __ Jump(lr); 849 __ Jump(lr);
822 } 850 }
823 851
824 852
853 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
854 Generate_JSConstructStubHelper(masm, false, true);
855 }
856
857
825 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 858 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
826 Generate_JSConstructStubHelper(masm, false); 859 Generate_JSConstructStubHelper(masm, false, false);
827 } 860 }
828 861
829 862
830 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 863 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
831 Generate_JSConstructStubHelper(masm, true); 864 Generate_JSConstructStubHelper(masm, true, false);
832 } 865 }
833 866
834 867
835 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 868 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
836 bool is_construct) { 869 bool is_construct) {
837 // Called from Generate_JS_Entry 870 // Called from Generate_JS_Entry
838 // r0: code entry 871 // r0: code entry
839 // r1: function 872 // r1: function
840 // r2: receiver 873 // r2: receiver
841 // r3: argc 874 // r3: argc
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 __ bind(&dont_adapt_arguments); 1370 __ bind(&dont_adapt_arguments);
1338 __ Jump(r3); 1371 __ Jump(r3);
1339 } 1372 }
1340 1373
1341 1374
1342 #undef __ 1375 #undef __
1343 1376
1344 } } // namespace v8::internal 1377 } } // namespace v8::internal
1345 1378
1346 #endif // V8_TARGET_ARCH_ARM 1379 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/builtins.h » ('j') | src/ia32/assembler-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698