| 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 |