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

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

Issue 8359034: Refactor and clean up array allocation across platforms. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 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
« src/arm/builtins-arm.cc ('K') | « src/ia32/builtins-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 986 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
987 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 987 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
988 RelocInfo::CODE_TARGET); 988 RelocInfo::CODE_TARGET);
989 989
990 // Leave internal frame. 990 // Leave internal frame.
991 } 991 }
992 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 992 __ ret(3 * kPointerSize); // remove this, receiver, and arguments
993 } 993 }
994 994
995 995
996 // Number of empty elements to allocate for an empty array.
997 static const int kPreallocatedArrayElements = 4;
998
999
1000 // Allocate an empty JSArray. The allocated array is put into the result 996 // Allocate an empty JSArray. The allocated array is put into the result
1001 // register. If the parameter initial_capacity is larger than zero an elements 997 // register. If the parameter initial_capacity is larger than zero an elements
1002 // backing store is allocated with this size and filled with the hole values. 998 // backing store is allocated with this size and filled with the hole values.
1003 // Otherwise the elements backing store is set to the empty FixedArray. 999 // Otherwise the elements backing store is set to the empty FixedArray.
1004 static void AllocateEmptyJSArray(MacroAssembler* masm, 1000 static void AllocateEmptyJSArray(MacroAssembler* masm,
1005 Register array_function, 1001 Register array_function,
1006 Register result, 1002 Register result,
1007 Register scratch1, 1003 Register scratch1,
1008 Register scratch2, 1004 Register scratch2,
1009 Register scratch3, 1005 Register scratch3,
1010 int initial_capacity,
1011 Label* gc_required) { 1006 Label* gc_required) {
1007 int initial_capacity = JSArray::kPreallocatedArrayElements;
1012 ASSERT(initial_capacity >= 0); 1008 ASSERT(initial_capacity >= 0);
1013 1009
1014 // Load the initial map from the array function. 1010 // Load the initial map from the array function.
1015 __ movq(scratch1, FieldOperand(array_function, 1011 __ movq(scratch1, FieldOperand(array_function,
1016 JSFunction::kPrototypeOrInitialMapOffset)); 1012 JSFunction::kPrototypeOrInitialMapOffset));
1017 1013
1018 // Allocate the JSArray object together with space for a fixed array with the 1014 // Allocate the JSArray object together with space for a fixed array with the
1019 // requested elements. 1015 // requested elements.
1020 int size = JSArray::kSize; 1016 int size = JSArray::kSize;
1021 if (initial_capacity > 0) { 1017 if (initial_capacity > 0) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 // scratch1: elements array 1056 // scratch1: elements array
1061 // scratch2: start of next object 1057 // scratch2: start of next object
1062 __ Move(FieldOperand(scratch1, HeapObject::kMapOffset), 1058 __ Move(FieldOperand(scratch1, HeapObject::kMapOffset),
1063 FACTORY->fixed_array_map()); 1059 FACTORY->fixed_array_map());
1064 __ Move(FieldOperand(scratch1, FixedArray::kLengthOffset), 1060 __ Move(FieldOperand(scratch1, FixedArray::kLengthOffset),
1065 Smi::FromInt(initial_capacity)); 1061 Smi::FromInt(initial_capacity));
1066 1062
1067 // Fill the FixedArray with the hole value. Inline the code if short. 1063 // Fill the FixedArray with the hole value. Inline the code if short.
1068 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. 1064 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed.
1069 static const int kLoopUnfoldLimit = 4; 1065 static const int kLoopUnfoldLimit = 4;
1070 ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
1071 __ Move(scratch3, FACTORY->the_hole_value()); 1066 __ Move(scratch3, FACTORY->the_hole_value());
1072 if (initial_capacity <= kLoopUnfoldLimit) { 1067 if (initial_capacity <= kLoopUnfoldLimit) {
1073 // Use a scratch register here to have only one reloc info when unfolding 1068 // Use a scratch register here to have only one reloc info when unfolding
1074 // the loop. 1069 // the loop.
1075 for (int i = 0; i < initial_capacity; i++) { 1070 for (int i = 0; i < initial_capacity; i++) {
1076 __ movq(FieldOperand(scratch1, 1071 __ movq(FieldOperand(scratch1,
1077 FixedArray::kHeaderSize + i * kPointerSize), 1072 FixedArray::kHeaderSize + i * kPointerSize),
1078 scratch3); 1073 scratch3);
1079 } 1074 }
1080 } else { 1075 } else {
(...skipping 13 matching lines...) Expand all
1094 // register array_function holds the built-in Array function and the register 1089 // register array_function holds the built-in Array function and the register
1095 // array_size holds the size of the array as a smi. The allocated array is put 1090 // array_size holds the size of the array as a smi. The allocated array is put
1096 // into the result register and beginning and end of the FixedArray elements 1091 // into the result register and beginning and end of the FixedArray elements
1097 // storage is put into registers elements_array and elements_array_end (see 1092 // storage is put into registers elements_array and elements_array_end (see
1098 // below for when that is not the case). If the parameter fill_with_holes is 1093 // below for when that is not the case). If the parameter fill_with_holes is
1099 // true the allocated elements backing store is filled with the hole values 1094 // true the allocated elements backing store is filled with the hole values
1100 // otherwise it is left uninitialized. When the backing store is filled the 1095 // otherwise it is left uninitialized. When the backing store is filled the
1101 // register elements_array is scratched. 1096 // register elements_array is scratched.
1102 static void AllocateJSArray(MacroAssembler* masm, 1097 static void AllocateJSArray(MacroAssembler* masm,
1103 Register array_function, // Array function. 1098 Register array_function, // Array function.
1104 Register array_size, // As a smi. 1099 Register array_size, // As a smi, cannot be 0.
1105 Register result, 1100 Register result,
1106 Register elements_array, 1101 Register elements_array,
1107 Register elements_array_end, 1102 Register elements_array_end,
1108 Register scratch, 1103 Register scratch,
1109 bool fill_with_hole, 1104 bool fill_with_hole,
1110 Label* gc_required) { 1105 Label* gc_required) {
1111 Label not_empty, allocated;
1112
1113 // Load the initial map from the array function. 1106 // Load the initial map from the array function.
1114 __ movq(elements_array, 1107 __ movq(elements_array,
1115 FieldOperand(array_function, 1108 FieldOperand(array_function,
1116 JSFunction::kPrototypeOrInitialMapOffset)); 1109 JSFunction::kPrototypeOrInitialMapOffset));
1117 1110
1118 // Check whether an empty sized array is requested. 1111 if (FLAG_debug_code) { // Assert that array size is not zero.
1119 __ testq(array_size, array_size); 1112 Label not_empty;
1120 __ j(not_zero, &not_empty); 1113 __ testq(array_size, array_size);
1121 1114 __ j(not_zero, &not_empty);
1122 // If an empty array is requested allocate a small elements array anyway. This 1115 __ int3();
1123 // keeps the code below free of special casing for the empty array. 1116 __ bind(&not_empty);
1124 int size = JSArray::kSize + FixedArray::SizeFor(kPreallocatedArrayElements); 1117 }
1125 __ AllocateInNewSpace(size,
1126 result,
1127 elements_array_end,
1128 scratch,
1129 gc_required,
1130 TAG_OBJECT);
1131 __ jmp(&allocated);
1132 1118
1133 // Allocate the JSArray object together with space for a FixedArray with the 1119 // Allocate the JSArray object together with space for a FixedArray with the
1134 // requested elements. 1120 // requested elements.
1135 __ bind(&not_empty);
1136 SmiIndex index = 1121 SmiIndex index =
1137 masm->SmiToIndex(kScratchRegister, array_size, kPointerSizeLog2); 1122 masm->SmiToIndex(kScratchRegister, array_size, kPointerSizeLog2);
1138 __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize, 1123 __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
1139 index.scale, 1124 index.scale,
1140 index.reg, 1125 index.reg,
1141 result, 1126 result,
1142 elements_array_end, 1127 elements_array_end,
1143 scratch, 1128 scratch,
1144 gc_required, 1129 gc_required,
1145 TAG_OBJECT); 1130 TAG_OBJECT);
1146 1131
1147 // Allocated the JSArray. Now initialize the fields except for the elements 1132 // Allocated the JSArray. Now initialize the fields except for the elements
1148 // array. 1133 // array.
1149 // result: JSObject 1134 // result: JSObject
1150 // elements_array: initial map 1135 // elements_array: initial map
1151 // elements_array_end: start of next object 1136 // elements_array_end: start of next object
1152 // array_size: size of array (smi) 1137 // array_size: size of array (smi)
1153 __ bind(&allocated);
1154 __ movq(FieldOperand(result, JSObject::kMapOffset), elements_array); 1138 __ movq(FieldOperand(result, JSObject::kMapOffset), elements_array);
1155 __ Move(elements_array, FACTORY->empty_fixed_array()); 1139 __ Move(elements_array, FACTORY->empty_fixed_array());
1156 __ movq(FieldOperand(result, JSArray::kPropertiesOffset), elements_array); 1140 __ movq(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
1157 // Field JSArray::kElementsOffset is initialized later. 1141 // Field JSArray::kElementsOffset is initialized later.
1158 __ movq(FieldOperand(result, JSArray::kLengthOffset), array_size); 1142 __ movq(FieldOperand(result, JSArray::kLengthOffset), array_size);
1159 1143
1160 // Calculate the location of the elements array and set elements array member 1144 // Calculate the location of the elements array and set elements array member
1161 // of the JSArray. 1145 // of the JSArray.
1162 // result: JSObject 1146 // result: JSObject
1163 // elements_array_end: start of next object 1147 // elements_array_end: start of next object
1164 // array_size: size of array (smi) 1148 // array_size: size of array (smi)
1165 __ lea(elements_array, Operand(result, JSArray::kSize)); 1149 __ lea(elements_array, Operand(result, JSArray::kSize));
1166 __ movq(FieldOperand(result, JSArray::kElementsOffset), elements_array); 1150 __ movq(FieldOperand(result, JSArray::kElementsOffset), elements_array);
1167 1151
1168 // Initialize the fixed array. FixedArray length is stored as a smi. 1152 // Initialize the fixed array. FixedArray length is stored as a smi.
1169 // result: JSObject 1153 // result: JSObject
1170 // elements_array: elements array 1154 // elements_array: elements array
1171 // elements_array_end: start of next object 1155 // elements_array_end: start of next object
1172 // array_size: size of array (smi) 1156 // array_size: size of array (smi)
1173 __ Move(FieldOperand(elements_array, JSObject::kMapOffset), 1157 __ Move(FieldOperand(elements_array, JSObject::kMapOffset),
1174 FACTORY->fixed_array_map()); 1158 FACTORY->fixed_array_map());
1175 Label not_empty_2, fill_array;
1176 __ SmiTest(array_size);
1177 __ j(not_zero, &not_empty_2);
1178 // Length of the FixedArray is the number of pre-allocated elements even
1179 // though the actual JSArray has length 0.
1180 __ Move(FieldOperand(elements_array, FixedArray::kLengthOffset),
1181 Smi::FromInt(kPreallocatedArrayElements));
1182 __ jmp(&fill_array);
1183 __ bind(&not_empty_2);
1184 // For non-empty JSArrays the length of the FixedArray and the JSArray is the 1159 // For non-empty JSArrays the length of the FixedArray and the JSArray is the
1185 // same. 1160 // same.
1186 __ movq(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size); 1161 __ movq(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size);
1187 1162
1188 // Fill the allocated FixedArray with the hole value if requested. 1163 // Fill the allocated FixedArray with the hole value if requested.
1189 // result: JSObject 1164 // result: JSObject
1190 // elements_array: elements array 1165 // elements_array: elements array
1191 // elements_array_end: start of next object 1166 // elements_array_end: start of next object
1192 __ bind(&fill_array);
1193 if (fill_with_hole) { 1167 if (fill_with_hole) {
1194 Label loop, entry; 1168 Label loop, entry;
1195 __ Move(scratch, FACTORY->the_hole_value()); 1169 __ Move(scratch, FACTORY->the_hole_value());
1196 __ lea(elements_array, Operand(elements_array, 1170 __ lea(elements_array, Operand(elements_array,
1197 FixedArray::kHeaderSize - kHeapObjectTag)); 1171 FixedArray::kHeaderSize - kHeapObjectTag));
1198 __ jmp(&entry); 1172 __ jmp(&entry);
1199 __ bind(&loop); 1173 __ bind(&loop);
1200 __ movq(Operand(elements_array, 0), scratch); 1174 __ movq(Operand(elements_array, 0), scratch);
1201 __ addq(elements_array, Immediate(kPointerSize)); 1175 __ addq(elements_array, Immediate(kPointerSize));
1202 __ bind(&entry); 1176 __ bind(&entry);
(...skipping 12 matching lines...) Expand all
1215 // rsp[0]: return address 1189 // rsp[0]: return address
1216 // rsp[8]: last argument 1190 // rsp[8]: last argument
1217 // This function is used for both construct and normal calls of Array. The only 1191 // This function is used for both construct and normal calls of Array. The only
1218 // difference between handling a construct call and a normal call is that for a 1192 // difference between handling a construct call and a normal call is that for a
1219 // construct call the constructor function in rdi needs to be preserved for 1193 // construct call the constructor function in rdi needs to be preserved for
1220 // entering the generic code. In both cases argc in rax needs to be preserved. 1194 // entering the generic code. In both cases argc in rax needs to be preserved.
1221 // Both registers are preserved by this code so no need to differentiate between 1195 // Both registers are preserved by this code so no need to differentiate between
1222 // a construct call and a normal call. 1196 // a construct call and a normal call.
1223 static void ArrayNativeCode(MacroAssembler* masm, 1197 static void ArrayNativeCode(MacroAssembler* masm,
1224 Label *call_generic_code) { 1198 Label *call_generic_code) {
1225 Label argc_one_or_more, argc_two_or_more; 1199 Label argc_one_or_more, argc_two_or_more, empty_array, not_empty_array;
1226 1200
1227 // Check for array construction with zero arguments. 1201 // Check for array construction with zero arguments.
1228 __ testq(rax, rax); 1202 __ testq(rax, rax);
1229 __ j(not_zero, &argc_one_or_more); 1203 __ j(not_zero, &argc_one_or_more);
1230 1204
1205 __ bind(&empty_array);
1231 // Handle construction of an empty array. 1206 // Handle construction of an empty array.
1232 AllocateEmptyJSArray(masm, 1207 AllocateEmptyJSArray(masm,
1233 rdi, 1208 rdi,
1234 rbx, 1209 rbx,
1235 rcx, 1210 rcx,
1236 rdx, 1211 rdx,
1237 r8, 1212 r8,
1238 kPreallocatedArrayElements,
1239 call_generic_code); 1213 call_generic_code);
1240 Counters* counters = masm->isolate()->counters(); 1214 Counters* counters = masm->isolate()->counters();
1241 __ IncrementCounter(counters->array_function_native(), 1); 1215 __ IncrementCounter(counters->array_function_native(), 1);
1242 __ movq(rax, rbx); 1216 __ movq(rax, rbx);
1243 __ ret(kPointerSize); 1217 __ ret(kPointerSize);
1244 1218
1245 // Check for one argument. Bail out if argument is not smi or if it is 1219 // Check for one argument. Bail out if argument is not smi or if it is
1246 // negative. 1220 // negative.
1247 __ bind(&argc_one_or_more); 1221 __ bind(&argc_one_or_more);
1248 __ cmpq(rax, Immediate(1)); 1222 __ cmpq(rax, Immediate(1));
1249 __ j(not_equal, &argc_two_or_more); 1223 __ j(not_equal, &argc_two_or_more);
1250 __ movq(rdx, Operand(rsp, kPointerSize)); // Get the argument from the stack. 1224 __ movq(rdx, Operand(rsp, kPointerSize)); // Get the argument from the stack.
1225
1226 __ SmiTest(rdx);
1227 __ j(not_zero, &not_empty_array);
1228 __ pop(r8); // Adjust stack.
1229 __ Drop(1);
1230 __ push(r8);
1231 __ movq(rax, Immediate(0)); // Treat this as a call with argc of zero.
1232 __ jmp(&empty_array);
1233
1234 __ bind(&not_empty_array);
1251 __ JumpUnlessNonNegativeSmi(rdx, call_generic_code); 1235 __ JumpUnlessNonNegativeSmi(rdx, call_generic_code);
1252 1236
1253 // Handle construction of an empty array of a certain size. Bail out if size 1237 // Handle construction of an empty array of a certain size. Bail out if size
1254 // is to large to actually allocate an elements array. 1238 // is to large to actually allocate an elements array.
1255 __ SmiCompare(rdx, Smi::FromInt(JSObject::kInitialMaxFastElementArray)); 1239 __ SmiCompare(rdx, Smi::FromInt(JSObject::kInitialMaxFastElementArray));
1256 __ j(greater_equal, call_generic_code); 1240 __ j(greater_equal, call_generic_code);
1257 1241
1258 // rax: argc 1242 // rax: argc
1259 // rdx: array_size (smi) 1243 // rdx: array_size (smi)
1260 // rdi: constructor 1244 // rdi: constructor
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); 1570 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1587 generator.Generate(); 1571 generator.Generate();
1588 } 1572 }
1589 1573
1590 1574
1591 #undef __ 1575 #undef __
1592 1576
1593 } } // namespace v8::internal 1577 } } // namespace v8::internal
1594 1578
1595 #endif // V8_TARGET_ARCH_X64 1579 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/arm/builtins-arm.cc ('K') | « src/ia32/builtins-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698