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

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

Issue 214051: Pushed 1.3.12 to trunk. (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 11 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 | « src/heap-profiler.cc ('k') | src/log.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-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 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 ParameterCount actual(eax); 651 ParameterCount actual(eax);
652 __ shr(eax, kSmiTagSize); 652 __ shr(eax, kSmiTagSize);
653 __ mov(edi, Operand(ebp, 4 * kPointerSize)); 653 __ mov(edi, Operand(ebp, 4 * kPointerSize));
654 __ InvokeFunction(edi, actual, CALL_FUNCTION); 654 __ InvokeFunction(edi, actual, CALL_FUNCTION);
655 655
656 __ LeaveInternalFrame(); 656 __ LeaveInternalFrame();
657 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 657 __ ret(3 * kPointerSize); // remove this, receiver, and arguments
658 } 658 }
659 659
660 660
661 // Load the built-in Array function from the current context.
662 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
663 // Load the global context.
664 __ mov(result, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
665 __ mov(result, FieldOperand(result, GlobalObject::kGlobalContextOffset));
666 // Load the Array function from the global context.
667 __ mov(result,
668 Operand(result, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
669 }
670
671
672 // Number of empty elements to allocate for an empty array.
673 static const int kPreallocatedArrayElements = 4;
674
675
676 // Allocate an empty JSArray. The allocated array is put into the result
677 // register. If the parameter holes is larger than zero an elements backing
678 // store is allocated with this size and filled with the hole values. Otherwise
679 // the elements backing store is set to the empty FixedArray.
680 static void AllocateEmptyJSArray(MacroAssembler* masm,
681 Register array_function,
682 Register result,
683 Register scratch1,
684 Register scratch2,
685 Register scratch3,
686 int holes,
687 Label* gc_required) {
688 ASSERT(holes >= 0);
689
690 // Load the initial map from the array function.
691 __ mov(scratch1, FieldOperand(array_function,
692 JSFunction::kPrototypeOrInitialMapOffset));
693
694 // Allocate the JSArray object together with space for a fixed array with the
695 // requested elements.
696 int size = JSArray::kSize;
697 if (holes > 0) {
698 size += FixedArray::SizeFor(holes);
699 }
700 __ AllocateObjectInNewSpace(size,
701 result,
702 scratch2,
703 scratch3,
704 gc_required,
705 TAG_OBJECT);
706
707 // Allocated the JSArray. Now initialize the fields except for the elements
708 // array.
709 // result: JSObject
710 // scratch1: initial map
711 // scratch2: start of next object
712 __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1);
713 __ mov(FieldOperand(result, JSArray::kPropertiesOffset),
714 Factory::empty_fixed_array());
715 // Field JSArray::kElementsOffset is initialized later.
716 __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0));
717
718 // If no storage is requested for the elements array just set the empty
719 // fixed array.
720 if (holes == 0) {
721 __ mov(FieldOperand(result, JSArray::kElementsOffset),
722 Factory::empty_fixed_array());
723 return;
724 }
725
726 // Calculate the location of the elements array and set elements array member
727 // of the JSArray.
728 // result: JSObject
729 // scratch2: start of next object
730 __ lea(scratch1, Operand(result, JSArray::kSize));
731 __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1);
732
733 // Initialize the FixedArray and fill it with holes. FixedArray length is not
734 // stored as a smi.
735 // result: JSObject
736 // scratch1: elements array
737 // scratch2: start of next object
738 __ mov(FieldOperand(scratch1, JSObject::kMapOffset),
739 Factory::fixed_array_map());
740 __ mov(FieldOperand(scratch1, Array::kLengthOffset), Immediate(holes));
741
742 // Fill the FixedArray with the hole value. Inline the code if short.
743 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed.
744 static const int kLoopUnfoldLimit = 4;
745 ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
746 if (holes <= kLoopUnfoldLimit) {
747 // Use a scratch register here to have only one reloc info when unfolding
748 // the loop.
749 __ mov(scratch3, Factory::the_hole_value());
750 for (int i = 0; i < holes; i++) {
751 __ mov(FieldOperand(scratch1,
752 FixedArray::kHeaderSize + i * kPointerSize),
753 scratch3);
754 }
755 } else {
756 Label loop, entry;
757 __ jmp(&entry);
758 __ bind(&loop);
759 __ mov(Operand(scratch1, 0), Factory::the_hole_value());
760 __ add(Operand(scratch1), Immediate(kPointerSize));
761 __ bind(&entry);
762 __ cmp(scratch1, Operand(scratch2));
763 __ j(below, &loop);
764 }
765 }
766
767
768 // Allocate a JSArray with the number of elements stored in a register. The
769 // register array_function holds the built-in Array function and the register
770 // array_size holds the size of the array as a smi. The allocated array is put
771 // into the result register and beginning and end of the FixedArray elements
772 // storage is put into registers elements_array and elements_array_end (see
773 // below for when that is not the case). If the parameter fill_with_holes is
774 // true the allocated elements backing store is filled with the hole values
775 // otherwise it is left uninitialized. When the backing store is filled the
776 // register elements_array is scratched.
777 static void AllocateJSArray(MacroAssembler* masm,
778 Register array_function, // Array function.
779 Register array_size, // As a smi.
780 Register result,
781 Register elements_array,
782 Register elements_array_end,
783 Register scratch,
784 bool fill_with_hole,
785 Label* gc_required) {
786 Label not_empty, allocated;
787
788 // Load the initial map from the array function.
789 __ mov(elements_array,
790 FieldOperand(array_function,
791 JSFunction::kPrototypeOrInitialMapOffset));
792
793 // Check whether an empty sized array is requested.
794 __ test(array_size, Operand(array_size));
795 __ j(not_zero, &not_empty);
796
797 // If an empty array is requested allocate a small elements array anyway. This
798 // keeps the code below free of special casing for the empty array.
799 int size = JSArray::kSize + FixedArray::SizeFor(kPreallocatedArrayElements);
800 __ AllocateObjectInNewSpace(size,
801 result,
802 elements_array_end,
803 scratch,
804 gc_required,
805 TAG_OBJECT);
806 __ jmp(&allocated);
807
808 // Allocate the JSArray object together with space for a FixedArray with the
809 // requested elements.
810 __ bind(&not_empty);
811 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
812 __ AllocateObjectInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
813 times_half_pointer_size, // array_size is a smi.
814 array_size,
815 result,
816 elements_array_end,
817 scratch,
818 gc_required,
819 TAG_OBJECT);
820
821 // Allocated the JSArray. Now initialize the fields except for the elements
822 // array.
823 // result: JSObject
824 // elements_array: initial map
825 // elements_array_end: start of next object
826 // array_size: size of array (smi)
827 __ bind(&allocated);
828 __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array);
829 __ mov(elements_array, Factory::empty_fixed_array());
830 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
831 // Field JSArray::kElementsOffset is initialized later.
832 __ mov(FieldOperand(result, JSArray::kLengthOffset), array_size);
833
834 // Calculate the location of the elements array and set elements array member
835 // of the JSArray.
836 // result: JSObject
837 // elements_array_end: start of next object
838 // array_size: size of array (smi)
839 __ lea(elements_array, Operand(result, JSArray::kSize));
840 __ mov(FieldOperand(result, JSArray::kElementsOffset), elements_array);
841
842 // Initialize the fixed array. FixedArray length is not stored as a smi.
843 // result: JSObject
844 // elements_array: elements array
845 // elements_array_end: start of next object
846 // array_size: size of array (smi)
847 ASSERT(kSmiTag == 0);
848 __ shr(array_size, kSmiTagSize); // Convert from smi to value.
849 __ mov(FieldOperand(elements_array, JSObject::kMapOffset),
850 Factory::fixed_array_map());
851 Label not_empty_2, fill_array;
852 __ test(array_size, Operand(array_size));
853 __ j(not_zero, &not_empty_2);
854 // Length of the FixedArray is the number of pre-allocated elements even
855 // though the actual JSArray has length 0.
856 __ mov(FieldOperand(elements_array, Array::kLengthOffset),
857 Immediate(kPreallocatedArrayElements));
858 __ jmp(&fill_array);
859 __ bind(&not_empty_2);
860 // For non-empty JSArrays the length of the FixedArray and the JSArray is the
861 // same.
862 __ mov(FieldOperand(elements_array, Array::kLengthOffset), array_size);
863
864 // Fill the allocated FixedArray with the hole value if requested.
865 // result: JSObject
866 // elements_array: elements array
867 // elements_array_end: start of next object
868 __ bind(&fill_array);
869 if (fill_with_hole) {
870 Label loop, entry;
871 __ mov(scratch, Factory::the_hole_value());
872 __ lea(elements_array, Operand(elements_array,
873 FixedArray::kHeaderSize - kHeapObjectTag));
874 __ jmp(&entry);
875 __ bind(&loop);
876 __ mov(Operand(elements_array, 0), scratch);
877 __ add(Operand(elements_array), Immediate(kPointerSize));
878 __ bind(&entry);
879 __ cmp(elements_array, Operand(elements_array_end));
880 __ j(below, &loop);
881 }
882 }
883
884
885 // Create a new array for the built-in Array function. This function allocates
886 // the JSArray object and the FixedArray elements array and initializes these.
887 // If the Array cannot be constructed in native code the runtime is called. This
888 // function assumes the following state:
889 // edi: constructor (built-in Array function)
890 // eax: argc
891 // esp[0]: return address
892 // esp[4]: last argument
893 // This function is used for both construct and normal calls of Array. Whether
894 // it is a construct call or not is indicated by the construct_call parameter.
895 // The only difference between handling a construct call and a normal call is
896 // that for a construct call the constructor function in edi needs to be
897 // preserved for entering the generic code. In both cases argc in eax needs to
898 // be preserved.
899 static void ArrayNativeCode(MacroAssembler* masm,
900 bool construct_call,
901 Label *call_generic_code) {
902 Label argc_one_or_more, argc_two_or_more, prepare_generic_code_call;
903
904 // Push the constructor and argc. No need to tag argc as a smi, as there will
905 // be no garbage collection with this on the stack.
906 int push_count = 0;
907 if (construct_call) {
908 push_count++;
909 __ push(edi);
910 }
911 push_count++;
912 __ push(eax);
913
914 // Check for array construction with zero arguments.
915 __ test(eax, Operand(eax));
916 __ j(not_zero, &argc_one_or_more);
917
918 // Handle construction of an empty array.
919 AllocateEmptyJSArray(masm,
920 edi,
921 eax,
922 ebx,
923 ecx,
924 edi,
925 kPreallocatedArrayElements,
926 &prepare_generic_code_call);
927 __ IncrementCounter(&Counters::array_function_native, 1);
928 __ pop(ebx);
929 if (construct_call) {
930 __ pop(edi);
931 }
932 __ ret(kPointerSize);
933
934 // Check for one argument. Bail out if argument is not smi or if it is
935 // negative.
936 __ bind(&argc_one_or_more);
937 __ cmp(eax, 1);
938 __ j(not_equal, &argc_two_or_more);
939 ASSERT(kSmiTag == 0);
940 __ test(Operand(esp, (push_count + 1) * kPointerSize),
941 Immediate(kIntptrSignBit | kSmiTagMask));
942 __ j(not_zero, &prepare_generic_code_call);
943
944 // Handle construction of an empty array of a certain size. Get the size from
945 // the stack and bail out if size is to large to actually allocate an elements
946 // array.
947 __ mov(edx, Operand(esp, (push_count + 1) * kPointerSize));
948 ASSERT(kSmiTag == 0);
949 __ cmp(edx, JSObject::kInitialMaxFastElementArray << kSmiTagSize);
950 __ j(greater_equal, &prepare_generic_code_call);
951
952 // edx: array_size (smi)
953 // edi: constructor
954 // esp[0]: argc
955 // esp[4]: constructor (only if construct_call)
956 // esp[8]: return address
957 // esp[C]: argument
958 AllocateJSArray(masm,
959 edi,
960 edx,
961 eax,
962 ebx,
963 ecx,
964 edi,
965 true,
966 &prepare_generic_code_call);
967 __ IncrementCounter(&Counters::array_function_native, 1);
968 __ pop(ebx);
969 if (construct_call) {
970 __ pop(edi);
971 }
972 __ ret(2 * kPointerSize);
973
974 // Handle construction of an array from a list of arguments.
975 __ bind(&argc_two_or_more);
976 ASSERT(kSmiTag == 0);
977 __ shl(eax, kSmiTagSize); // Convet argc to a smi.
978 // eax: array_size (smi)
979 // edi: constructor
980 // esp[0] : argc
981 // esp[4]: constructor (only if construct_call)
982 // esp[8] : return address
983 // esp[C] : last argument
984 AllocateJSArray(masm,
985 edi,
986 eax,
987 ebx,
988 ecx,
989 edx,
990 edi,
991 false,
992 &prepare_generic_code_call);
993 __ IncrementCounter(&Counters::array_function_native, 1);
994 __ mov(eax, ebx);
995 __ pop(ebx);
996 if (construct_call) {
997 __ pop(edi);
998 }
999 __ push(eax);
1000 // eax: JSArray
1001 // ebx: argc
1002 // edx: elements_array_end (untagged)
1003 // esp[0]: JSArray
1004 // esp[4]: return address
1005 // esp[8]: last argument
1006
1007 // Location of the last argument
1008 __ lea(edi, Operand(esp, 2 * kPointerSize));
1009
1010 // Location of the first array element (Parameter fill_with_holes to
1011 // AllocateJSArrayis false, so the FixedArray is returned in ecx).
1012 __ lea(edx, Operand(ecx, FixedArray::kHeaderSize - kHeapObjectTag));
1013
1014 // ebx: argc
1015 // edx: location of the first array element
1016 // edi: location of the last argument
1017 // esp[0]: JSArray
1018 // esp[4]: return address
1019 // esp[8]: last argument
1020 Label loop, entry;
1021 __ mov(ecx, ebx);
1022 __ jmp(&entry);
1023 __ bind(&loop);
1024 __ mov(eax, Operand(edi, ecx, times_pointer_size, 0));
1025 __ mov(Operand(edx, 0), eax);
1026 __ add(Operand(edx), Immediate(kPointerSize));
1027 __ bind(&entry);
1028 __ dec(ecx);
1029 __ j(greater_equal, &loop);
1030
1031 // Remove caller arguments from the stack and return.
1032 // ebx: argc
1033 // esp[0]: JSArray
1034 // esp[4]: return address
1035 // esp[8]: last argument
1036 __ pop(eax);
1037 __ pop(ecx);
1038 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
1039 __ push(ecx);
1040 __ ret(0);
1041
1042 // Restore argc and constructor before running the generic code.
1043 __ bind(&prepare_generic_code_call);
1044 __ pop(eax);
1045 if (construct_call) {
1046 __ pop(edi);
1047 }
1048 __ jmp(call_generic_code);
1049 }
1050
1051
1052 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1053 // ----------- S t a t e -------------
1054 // -- eax : argc
1055 // -- esp[0] : return address
1056 // -- esp[4] : last argument
1057 // -----------------------------------
1058 Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
1059
1060 // Get the Array function.
1061 GenerateLoadArrayFunction(masm, edi);
1062
1063 if (FLAG_debug_code) {
1064 // Initial map for the builtin Array function shoud be a map.
1065 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1066 // Will both indicate a NULL and a Smi.
1067 __ test(ebx, Immediate(kSmiTagMask));
1068 __ Assert(not_zero, "Unexpected initial map for Array function");
1069 __ CmpObjectType(ebx, MAP_TYPE, ecx);
1070 __ Assert(equal, "Unexpected initial map for Array function");
1071 }
1072
1073 // Run the native code for the Array function called as a normal function.
1074 ArrayNativeCode(masm, false, &generic_array_code);
1075
1076 // Jump to the generic array code in case the specialized code cannot handle
1077 // the construction.
1078 __ bind(&generic_array_code);
1079 Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
1080 Handle<Code> array_code(code);
1081 __ jmp(array_code, RelocInfo::CODE_TARGET);
1082 }
1083
1084
1085 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
1086 // ----------- S t a t e -------------
1087 // -- eax : argc
1088 // -- edi : constructor
1089 // -- esp[0] : return address
1090 // -- esp[4] : last argument
1091 // -----------------------------------
1092 Label generic_constructor;
1093
1094 if (FLAG_debug_code) {
1095 // The array construct code is only set for the builtin Array function which
1096 // does always have a map.
1097 GenerateLoadArrayFunction(masm, ebx);
1098 __ cmp(edi, Operand(ebx));
1099 __ Assert(equal, "Unexpected Array function");
1100 // Initial map for the builtin Array function should be a map.
1101 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1102 // Will both indicate a NULL and a Smi.
1103 __ test(ebx, Immediate(kSmiTagMask));
1104 __ Assert(not_zero, "Unexpected initial map for Array function");
1105 __ CmpObjectType(ebx, MAP_TYPE, ecx);
1106 __ Assert(equal, "Unexpected initial map for Array function");
1107 }
1108
1109 // Run the native code for the Array function called as constructor.
1110 ArrayNativeCode(masm, true, &generic_constructor);
1111
1112 // Jump to the generic construct code in case the specialized code cannot
1113 // handle the construction.
1114 __ bind(&generic_constructor);
1115 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
1116 Handle<Code> generic_construct_stub(code);
1117 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
1118 }
1119
1120
661 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1121 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
662 __ push(ebp); 1122 __ push(ebp);
663 __ mov(ebp, Operand(esp)); 1123 __ mov(ebp, Operand(esp));
664 1124
665 // Store the arguments adaptor context sentinel. 1125 // Store the arguments adaptor context sentinel.
666 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1126 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
667 1127
668 // Push the function on the stack. 1128 // Push the function on the stack.
669 __ push(edi); 1129 __ push(edi);
670 1130
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 // Dont adapt arguments. 1228 // Dont adapt arguments.
769 // ------------------------------------------- 1229 // -------------------------------------------
770 __ bind(&dont_adapt_arguments); 1230 __ bind(&dont_adapt_arguments);
771 __ jmp(Operand(edx)); 1231 __ jmp(Operand(edx));
772 } 1232 }
773 1233
774 1234
775 #undef __ 1235 #undef __
776 1236
777 } } // namespace v8::internal 1237 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap-profiler.cc ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698