OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 908 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
909 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 909 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
910 RelocInfo::CODE_TARGET); | 910 RelocInfo::CODE_TARGET); |
911 | 911 |
912 // Leave internal frame. | 912 // Leave internal frame. |
913 } | 913 } |
914 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 914 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
915 } | 915 } |
916 | 916 |
917 | 917 |
918 // Number of empty elements to allocate for an empty array. | |
919 static const int kPreallocatedArrayElements = 4; | |
920 | |
921 | |
922 // Allocate an empty JSArray. The allocated array is put into the result | 918 // Allocate an empty JSArray. The allocated array is put into the result |
923 // register. If the parameter initial_capacity is larger than zero an elements | 919 // register. If the parameter initial_capacity is larger than zero an elements |
924 // backing store is allocated with this size and filled with the hole values. | 920 // backing store is allocated with this size and filled with the hole values. |
925 // Otherwise the elements backing store is set to the empty FixedArray. | 921 // Otherwise the elements backing store is set to the empty FixedArray. |
926 static void AllocateEmptyJSArray(MacroAssembler* masm, | 922 static void AllocateEmptyJSArray(MacroAssembler* masm, |
927 Register array_function, | 923 Register array_function, |
928 Register result, | 924 Register result, |
929 Register scratch1, | 925 Register scratch1, |
930 Register scratch2, | 926 Register scratch2, |
931 Register scratch3, | 927 Register scratch3, |
932 int initial_capacity, | |
933 Label* gc_required) { | 928 Label* gc_required) { |
| 929 int initial_capacity = JSArray::kPreallocatedArrayElements; |
934 ASSERT(initial_capacity >= 0); | 930 ASSERT(initial_capacity >= 0); |
935 | |
936 // Load the initial map from the array function. | 931 // Load the initial map from the array function. |
937 __ mov(scratch1, FieldOperand(array_function, | 932 __ mov(scratch1, FieldOperand(array_function, |
938 JSFunction::kPrototypeOrInitialMapOffset)); | 933 JSFunction::kPrototypeOrInitialMapOffset)); |
939 | 934 |
940 // Allocate the JSArray object together with space for a fixed array with the | 935 // Allocate the JSArray object together with space for a fixed array with the |
941 // requested elements. | 936 // requested elements. |
942 int size = JSArray::kSize; | 937 int size = JSArray::kSize; |
943 if (initial_capacity > 0) { | 938 if (initial_capacity > 0) { |
944 size += FixedArray::SizeFor(initial_capacity); | 939 size += FixedArray::SizeFor(initial_capacity); |
945 } | 940 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 // scratch1: elements array | 978 // scratch1: elements array |
984 // scratch2: start of next object | 979 // scratch2: start of next object |
985 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), | 980 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), |
986 factory->fixed_array_map()); | 981 factory->fixed_array_map()); |
987 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), | 982 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), |
988 Immediate(Smi::FromInt(initial_capacity))); | 983 Immediate(Smi::FromInt(initial_capacity))); |
989 | 984 |
990 // Fill the FixedArray with the hole value. Inline the code if short. | 985 // Fill the FixedArray with the hole value. Inline the code if short. |
991 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. | 986 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. |
992 static const int kLoopUnfoldLimit = 4; | 987 static const int kLoopUnfoldLimit = 4; |
993 STATIC_ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit); | |
994 if (initial_capacity <= kLoopUnfoldLimit) { | 988 if (initial_capacity <= kLoopUnfoldLimit) { |
995 // Use a scratch register here to have only one reloc info when unfolding | 989 // Use a scratch register here to have only one reloc info when unfolding |
996 // the loop. | 990 // the loop. |
997 __ mov(scratch3, factory->the_hole_value()); | 991 __ mov(scratch3, factory->the_hole_value()); |
998 for (int i = 0; i < initial_capacity; i++) { | 992 for (int i = 0; i < initial_capacity; i++) { |
999 __ mov(FieldOperand(scratch1, | 993 __ mov(FieldOperand(scratch1, |
1000 FixedArray::kHeaderSize + i * kPointerSize), | 994 FixedArray::kHeaderSize + i * kPointerSize), |
1001 scratch3); | 995 scratch3); |
1002 } | 996 } |
1003 } else { | 997 } else { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 __ j(not_zero, &argc_one_or_more); | 1140 __ j(not_zero, &argc_one_or_more); |
1147 | 1141 |
1148 __ bind(&empty_array); | 1142 __ bind(&empty_array); |
1149 // Handle construction of an empty array. | 1143 // Handle construction of an empty array. |
1150 AllocateEmptyJSArray(masm, | 1144 AllocateEmptyJSArray(masm, |
1151 edi, | 1145 edi, |
1152 eax, | 1146 eax, |
1153 ebx, | 1147 ebx, |
1154 ecx, | 1148 ecx, |
1155 edi, | 1149 edi, |
1156 kPreallocatedArrayElements, | |
1157 &prepare_generic_code_call); | 1150 &prepare_generic_code_call); |
1158 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); | 1151 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); |
1159 __ pop(ebx); | 1152 __ pop(ebx); |
1160 if (construct_call) { | 1153 if (construct_call) { |
1161 __ pop(edi); | 1154 __ pop(edi); |
1162 } | 1155 } |
1163 __ ret(kPointerSize); | 1156 __ ret(kPointerSize); |
1164 | 1157 |
1165 // Check for one argument. Bail out if argument is not smi or if it is | 1158 // Check for one argument. Bail out if argument is not smi or if it is |
1166 // negative. | 1159 // negative. |
1167 __ bind(&argc_one_or_more); | 1160 __ bind(&argc_one_or_more); |
1168 __ cmp(eax, 1); | 1161 __ cmp(eax, 1); |
1169 __ j(not_equal, &argc_two_or_more); | 1162 __ j(not_equal, &argc_two_or_more); |
1170 STATIC_ASSERT(kSmiTag == 0); | 1163 STATIC_ASSERT(kSmiTag == 0); |
1171 __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize)); | 1164 __ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize)); |
1172 __ test(ecx, ecx); | 1165 __ test(ecx, ecx); |
1173 __ j(not_zero, ¬_empty_array); | 1166 __ j(not_zero, ¬_empty_array); |
1174 | 1167 |
1175 // The single argument passed is zero, so we jump to the code above used to | 1168 // The single argument passed is zero, so we jump to the code above used to |
1176 // handle the case of no arguments passed. To adapt the stack for that we move | 1169 // handle the case of no arguments passed. To adapt the stack for that we move |
1177 // the return address and the pushed constructor (if pushed) one stack slot up | 1170 // the return address and the pushed constructor (if pushed) one stack slot up |
1178 // thereby removing the passed argument. Argc is also on the stack - at the | 1171 // thereby removing the passed argument. Argc is also on the stack - at the |
1179 // bottom - and it needs to be changed from 1 to 0 to have the call into the | 1172 // bottom - and it needs to be changed from 1 to 0 to have the call into the |
1180 // runtime system work in case a GC is required. | 1173 // runtime system work in case a GC is required. |
1181 for (int i = push_count; i > 0; i--) { | 1174 for (int i = push_count; i > 0; i--) { |
1182 __ mov(eax, Operand(esp, i * kPointerSize)); | 1175 __ mov(eax, Operand(esp, i * kPointerSize)); |
1183 __ mov(Operand(esp, (i + 1) * kPointerSize), eax); | 1176 __ mov(Operand(esp, (i + 1) * kPointerSize), eax); |
1184 } | 1177 } |
1185 __ add(esp, Immediate(2 * kPointerSize)); // Drop two stack slots. | 1178 __ Drop(2); // Drop two stack slots. |
1186 __ push(Immediate(0)); // Treat this as a call with argc of zero. | 1179 __ push(Immediate(0)); // Treat this as a call with argc of zero. |
1187 __ jmp(&empty_array); | 1180 __ jmp(&empty_array); |
1188 | 1181 |
1189 __ bind(¬_empty_array); | 1182 __ bind(¬_empty_array); |
1190 __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask)); | 1183 __ test(ecx, Immediate(kIntptrSignBit | kSmiTagMask)); |
1191 __ j(not_zero, &prepare_generic_code_call); | 1184 __ j(not_zero, &prepare_generic_code_call); |
1192 | 1185 |
1193 // Handle construction of an empty array of a certain size. Get the size from | 1186 // Handle construction of an empty array of a certain size. Get the size from |
1194 // the stack and bail out if size is to large to actually allocate an elements | 1187 // the stack and bail out if size is to large to actually allocate an elements |
1195 // array. | 1188 // array. |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1672 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1680 generator.Generate(); | 1673 generator.Generate(); |
1681 } | 1674 } |
1682 | 1675 |
1683 | 1676 |
1684 #undef __ | 1677 #undef __ |
1685 } | 1678 } |
1686 } // namespace v8::internal | 1679 } // namespace v8::internal |
1687 | 1680 |
1688 #endif // V8_TARGET_ARCH_IA32 | 1681 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |