OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 } | 923 } |
924 | 924 |
925 | 925 |
926 // Allocate an empty JSArray. The allocated array is put into the result | 926 // Allocate an empty JSArray. The allocated array is put into the result |
927 // register. If the parameter initial_capacity is larger than zero an elements | 927 // register. If the parameter initial_capacity is larger than zero an elements |
928 // backing store is allocated with this size and filled with the hole values. | 928 // backing store is allocated with this size and filled with the hole values. |
929 // Otherwise the elements backing store is set to the empty FixedArray. | 929 // Otherwise the elements backing store is set to the empty FixedArray. |
930 static void AllocateEmptyJSArray(MacroAssembler* masm, | 930 static void AllocateEmptyJSArray(MacroAssembler* masm, |
931 Register array_function, | 931 Register array_function, |
932 Register result, | 932 Register result, |
933 Register scratch1, | 933 Register type_info_cell, |
934 Register scratch2, | 934 Register scratch2, |
935 Register scratch3, | 935 Register scratch3, |
936 Label* gc_required) { | 936 Label* gc_required) { |
937 const int initial_capacity = JSArray::kPreallocatedArrayElements; | 937 Label with_alloc_info, no_alloc_info, common_init, empty_double; |
938 STATIC_ASSERT(initial_capacity >= 0); | 938 Label no_known_elements_kind, init_js_array; |
| 939 Register scratch1 = type_info_cell; |
939 | 940 |
940 __ LoadInitialArrayMap(array_function, scratch2, scratch1, false); | 941 // If no type info cell is provided, then there's no point in tracking |
| 942 // site allocation info. |
| 943 Handle<Object> undefined_value(masm->isolate()->heap()->undefined_value()); |
| 944 __ cmp(type_info_cell, Immediate(undefined_value)); |
| 945 __ j(equal, &no_known_elements_kind); |
941 | 946 |
| 947 // If there is a type info cell provided, only track information about the |
| 948 // allocation site if the no ElementsKind transition has been detected. |
| 949 __ mov(scratch3, FieldOperand(type_info_cell, |
| 950 JSGlobalPropertyCell::kValueOffset)); |
| 951 __ JumpIfNotSmi(scratch3, &no_known_elements_kind); |
| 952 __ cmp(scratch3, Immediate(Smi::FromInt(GetInitialFastElementsKind()))); |
| 953 __ j(equal, &with_alloc_info); |
| 954 |
| 955 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
| 956 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 957 STATIC_ASSERT(FAST_ELEMENTS == 2); |
| 958 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 959 __ cmp(scratch3, Immediate(Smi::FromInt(FAST_HOLEY_ELEMENTS))); |
| 960 __ j(above, gc_required); |
| 961 |
| 962 __ LoadInitialArrayMap(array_function, scratch3, scratch2); |
| 963 __ jmp(&no_alloc_info); |
| 964 |
942 // Allocate the JSArray object together with space for a fixed array with the | 965 // Allocate the JSArray object together with space for a fixed array with the |
943 // requested elements. | 966 // requested elements and an AllocationSiteInfo object to later be able to |
| 967 // feed back array transition information to the allocation site. |
| 968 __ bind(&with_alloc_info); |
944 int size = JSArray::kSize; | 969 int size = JSArray::kSize; |
945 if (initial_capacity > 0) { | 970 int allocation_info_start = size; |
946 size += FixedArray::SizeFor(initial_capacity); | 971 int elements_offset = size; |
947 } | 972 size += AllocationSiteInfo::kSize; |
| 973 elements_offset = size; |
| 974 size += FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); |
948 __ AllocateInNewSpace(size, | 975 __ AllocateInNewSpace(size, |
949 result, | 976 result, |
950 scratch2, | 977 scratch2, |
951 scratch3, | 978 scratch3, |
952 gc_required, | 979 gc_required, |
953 TAG_OBJECT); | 980 TAG_OBJECT); |
954 | 981 |
955 // Allocated the JSArray. Now initialize the fields except for the elements | 982 // Track information about the allocation site |
956 // array. | 983 __ mov(FieldOperand(result, allocation_info_start), |
957 // result: JSObject | 984 Immediate(Handle<Map>(masm->isolate()->heap()-> |
958 // scratch1: initial map | 985 allocation_site_info_map()))); |
959 // scratch2: start of next object | 986 __ mov(FieldOperand(result, allocation_info_start + kPointerSize), |
960 __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1); | 987 type_info_cell); // No write barrier because it's a cell. |
961 Factory* factory = masm->isolate()->factory(); | |
962 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), | |
963 factory->empty_fixed_array()); | |
964 // Field JSArray::kElementsOffset is initialized later. | |
965 __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0)); | |
966 | |
967 // If no storage is requested for the elements array just set the empty | |
968 // fixed array. | |
969 if (initial_capacity == 0) { | |
970 __ mov(FieldOperand(result, JSArray::kElementsOffset), | |
971 factory->empty_fixed_array()); | |
972 return; | |
973 } | |
974 | 988 |
975 // Calculate the location of the elements array and set elements array member | 989 // Calculate the location of the elements array and set elements array member |
976 // of the JSArray. | 990 // of the JSArray. |
977 // result: JSObject | 991 // result: JSArray |
978 // scratch2: start of next object | 992 __ LoadInitialArrayMap(array_function, GetInitialFastElementsKind(), scratch2)
; |
979 __ lea(scratch1, Operand(result, JSArray::kSize)); | 993 __ lea(scratch1, Operand(result, elements_offset)); |
980 __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1); | 994 __ jmp(&common_init); |
981 | 995 |
| 996 __ bind(&no_known_elements_kind); |
| 997 __ LoadInitialArrayMap(array_function, GetInitialFastElementsKind(), scratch2)
; |
| 998 |
| 999 // Allocate the JSArray object together with space for a fixed array with the |
| 1000 // requested elements. |
| 1001 __ bind(&no_alloc_info); |
| 1002 size = JSArray::kSize; |
| 1003 elements_offset = size; |
| 1004 size += FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); |
| 1005 __ AllocateInNewSpace(size, |
| 1006 result, |
| 1007 scratch1, |
| 1008 scratch3, |
| 1009 gc_required, |
| 1010 TAG_OBJECT); |
| 1011 // Calculate the location of the elements array and set elements array member |
| 1012 // of the JSArray. |
| 1013 // result: JSArray |
| 1014 __ lea(scratch1, Operand(result, elements_offset)); |
| 1015 |
| 1016 __ bind(&common_init); |
982 // Initialize the FixedArray and fill it with holes. FixedArray length is | 1017 // Initialize the FixedArray and fill it with holes. FixedArray length is |
983 // stored as a smi. | 1018 // stored as a smi. |
984 // result: JSObject | 1019 // result: JSObject |
985 // scratch1: elements array | 1020 // scratch1: elements array |
986 // scratch2: start of next object | 1021 Factory* factory = masm->isolate()->factory(); |
987 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), | 1022 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), |
988 factory->fixed_array_map()); | 1023 factory->fixed_array_map()); |
989 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), | 1024 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), |
990 Immediate(Smi::FromInt(initial_capacity))); | 1025 Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements))); |
991 | 1026 |
992 // Fill the FixedArray with the hole value. Inline the code if short. | 1027 // Fill the FixedArray with the hole value. Inline the code if short. |
993 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. | 1028 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. |
994 static const int kLoopUnfoldLimit = 4; | 1029 static const int kLoopUnfoldLimit = 4; |
995 if (initial_capacity <= kLoopUnfoldLimit) { | 1030 if (JSArray::kPreallocatedArrayElements <= kLoopUnfoldLimit) { |
996 // Use a scratch register here to have only one reloc info when unfolding | 1031 // Use a scratch register here to have only one reloc info when unfolding |
997 // the loop. | 1032 // the loop. |
998 __ mov(scratch3, factory->the_hole_value()); | 1033 __ mov(scratch3, factory->the_hole_value()); |
999 for (int i = 0; i < initial_capacity; i++) { | 1034 for (int i = 0; i < JSArray::kPreallocatedArrayElements; i++) { |
1000 __ mov(FieldOperand(scratch1, | 1035 __ mov(FieldOperand(scratch1, |
1001 FixedArray::kHeaderSize + i * kPointerSize), | 1036 FixedArray::kHeaderSize + i * kPointerSize), |
1002 scratch3); | 1037 scratch3); |
1003 } | 1038 } |
1004 } else { | 1039 } else { |
1005 Label loop, entry; | 1040 Label loop, entry; |
1006 __ mov(scratch2, Immediate(initial_capacity)); | 1041 __ mov(scratch3, Immediate(JSArray::kPreallocatedArrayElements)); |
1007 __ jmp(&entry); | 1042 __ jmp(&entry); |
1008 __ bind(&loop); | 1043 __ bind(&loop); |
1009 __ mov(FieldOperand(scratch1, | 1044 __ mov(FieldOperand(scratch1, |
1010 scratch2, | 1045 scratch3, |
1011 times_pointer_size, | 1046 times_pointer_size, |
1012 FixedArray::kHeaderSize), | 1047 FixedArray::kHeaderSize), |
1013 factory->the_hole_value()); | 1048 factory->the_hole_value()); |
1014 __ bind(&entry); | 1049 __ bind(&entry); |
1015 __ dec(scratch2); | 1050 __ dec(scratch3); |
1016 __ j(not_sign, &loop); | 1051 __ j(not_sign, &loop); |
1017 } | 1052 } |
| 1053 |
| 1054 __ bind(&init_js_array); |
| 1055 // Initialize the fields of the JSArray |
| 1056 // result: JSArray |
| 1057 // scratch1: elements array |
| 1058 // scratch2: map for Array |
| 1059 __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1); |
| 1060 __ mov(FieldOperand(result, JSObject::kMapOffset), scratch2); |
| 1061 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), |
| 1062 factory->empty_fixed_array()); |
| 1063 __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0)); |
1018 } | 1064 } |
1019 | 1065 |
1020 | 1066 |
1021 // Allocate a JSArray with the number of elements stored in a register. The | 1067 // Allocate a JSArray with the number of elements stored in a register. The |
1022 // register array_function holds the built-in Array function and the register | 1068 // register array_function holds the built-in Array function and the register |
1023 // array_size holds the size of the array as a smi. The allocated array is put | 1069 // array_size holds the size of the array as a smi. The allocated array is put |
1024 // into the result register and beginning and end of the FixedArray elements | 1070 // into the result register and beginning and end of the FixedArray elements |
1025 // storage is put into registers elements_array and elements_array_end (see | 1071 // storage is put into registers elements_array and elements_array_end (see |
1026 // below for when that is not the case). If the parameter fill_with_holes is | 1072 // below for when that is not the case). If the parameter fill_with_holes is |
1027 // true the allocated elements backing store is filled with the hole values | 1073 // true the allocated elements backing store is filled with the hole values |
(...skipping 11 matching lines...) Expand all Loading... |
1039 ASSERT(scratch.is(edi)); // rep stos destination | 1085 ASSERT(scratch.is(edi)); // rep stos destination |
1040 ASSERT(!fill_with_hole || array_size.is(ecx)); // rep stos count | 1086 ASSERT(!fill_with_hole || array_size.is(ecx)); // rep stos count |
1041 ASSERT(!fill_with_hole || !result.is(eax)); // result is never eax | 1087 ASSERT(!fill_with_hole || !result.is(eax)); // result is never eax |
1042 | 1088 |
1043 __ LoadInitialArrayMap(array_function, scratch, | 1089 __ LoadInitialArrayMap(array_function, scratch, |
1044 elements_array, fill_with_hole); | 1090 elements_array, fill_with_hole); |
1045 | 1091 |
1046 // Allocate the JSArray object together with space for a FixedArray with the | 1092 // Allocate the JSArray object together with space for a FixedArray with the |
1047 // requested elements. | 1093 // requested elements. |
1048 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 1094 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
1049 __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize, | 1095 |
| 1096 int fixed_size = JSArray::kSize + FixedArray::kHeaderSize + |
| 1097 AllocationSiteInfo::kSize; |
| 1098 __ AllocateInNewSpace(fixed_size, |
1050 times_half_pointer_size, // array_size is a smi. | 1099 times_half_pointer_size, // array_size is a smi. |
1051 array_size, | 1100 array_size, |
1052 result, | 1101 result, |
1053 elements_array_end, | 1102 elements_array_end, |
1054 scratch, | 1103 scratch, |
1055 gc_required, | 1104 gc_required, |
1056 TAG_OBJECT); | 1105 TAG_OBJECT); |
| 1106 __ sub(elements_array_end, Immediate(AllocationSiteInfo::kSize)); |
1057 | 1107 |
1058 // Allocated the JSArray. Now initialize the fields except for the elements | 1108 // Allocated the JSArray. Now initialize the fields except for the elements |
1059 // array. | 1109 // array. |
1060 // result: JSObject | 1110 // result: JSObject |
1061 // elements_array: initial map | 1111 // elements_array: initial map |
1062 // elements_array_end: start of next object | 1112 // elements_array_end: start of next object |
1063 // array_size: size of array (smi) | 1113 // array_size: size of array (smi) |
1064 __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array); | 1114 __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array); |
1065 Factory* factory = masm->isolate()->factory(); | 1115 Factory* factory = masm->isolate()->factory(); |
1066 __ mov(elements_array, factory->empty_fixed_array()); | 1116 __ mov(elements_array, factory->empty_fixed_array()); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 __ j(below, &loop); // Note: ecx > 0. | 1154 __ j(below, &loop); // Note: ecx > 0. |
1105 __ rep_stos(); | 1155 __ rep_stos(); |
1106 __ jmp(&done); | 1156 __ jmp(&done); |
1107 __ bind(&loop); | 1157 __ bind(&loop); |
1108 __ stos(); | 1158 __ stos(); |
1109 __ bind(&entry); | 1159 __ bind(&entry); |
1110 __ cmp(edi, elements_array_end); | 1160 __ cmp(edi, elements_array_end); |
1111 __ j(below, &loop); | 1161 __ j(below, &loop); |
1112 __ bind(&done); | 1162 __ bind(&done); |
1113 } | 1163 } |
| 1164 |
| 1165 // Track information about the allocation site |
| 1166 __ mov(Operand(elements_array_end, 0), |
| 1167 Immediate(Handle<Map>(masm->isolate()->heap()-> |
| 1168 allocation_site_info_map()))); |
| 1169 __ mov(Operand(elements_array_end, kPointerSize), |
| 1170 Immediate(Handle<HeapObject>(masm->isolate()->heap()->null_value()))); |
1114 } | 1171 } |
1115 | 1172 |
1116 | 1173 |
1117 // Create a new array for the built-in Array function. This function allocates | 1174 // Create a new array for the built-in Array function. This function allocates |
1118 // the JSArray object and the FixedArray elements array and initializes these. | 1175 // the JSArray object and the FixedArray elements array and initializes these. |
1119 // If the Array cannot be constructed in native code the runtime is called. This | 1176 // If the Array cannot be constructed in native code the runtime is called. This |
1120 // function assumes the following state: | 1177 // function assumes the following state: |
1121 // edi: constructor (built-in Array function) | 1178 // edi: constructor (built-in Array function) |
1122 // eax: argc | 1179 // eax: argc |
| 1180 // ebx: cell containing type feedback cell for Array's ElementsKind |
1123 // esp[0]: return address | 1181 // esp[0]: return address |
1124 // esp[4]: last argument | 1182 // esp[4]: last argument |
1125 // This function is used for both construct and normal calls of Array. Whether | 1183 // This function is used for both construct and normal calls of Array. Whether |
1126 // it is a construct call or not is indicated by the construct_call parameter. | 1184 // it is a construct call or not is indicated by the construct_call parameter. |
1127 // The only difference between handling a construct call and a normal call is | 1185 // The only difference between handling a construct call and a normal call is |
1128 // that for a construct call the constructor function in edi needs to be | 1186 // that for a construct call the constructor function in edi needs to be |
1129 // preserved for entering the generic code. In both cases argc in eax needs to | 1187 // preserved for entering the generic code. In both cases argc in eax needs to |
1130 // be preserved. | 1188 // be preserved. |
1131 static void ArrayNativeCode(MacroAssembler* masm, | 1189 static void ArrayNativeCode(MacroAssembler* masm, |
1132 bool construct_call, | 1190 bool construct_call, |
(...skipping 15 matching lines...) Expand all Loading... |
1148 __ test(eax, eax); | 1206 __ test(eax, eax); |
1149 __ j(not_zero, &argc_one_or_more); | 1207 __ j(not_zero, &argc_one_or_more); |
1150 | 1208 |
1151 __ bind(&empty_array); | 1209 __ bind(&empty_array); |
1152 // Handle construction of an empty array. | 1210 // Handle construction of an empty array. |
1153 AllocateEmptyJSArray(masm, | 1211 AllocateEmptyJSArray(masm, |
1154 edi, | 1212 edi, |
1155 eax, | 1213 eax, |
1156 ebx, | 1214 ebx, |
1157 ecx, | 1215 ecx, |
1158 edi, | 1216 edx, |
1159 &prepare_generic_code_call); | 1217 &prepare_generic_code_call); |
1160 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); | 1218 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1); |
1161 __ pop(ebx); | 1219 __ pop(ebx); |
1162 if (construct_call) { | 1220 if (construct_call) { |
1163 __ pop(edi); | 1221 __ pop(edi); |
1164 } | 1222 } |
1165 __ ret(kPointerSize); | 1223 __ ret(kPointerSize); |
1166 | 1224 |
1167 // Check for one argument. Bail out if argument is not smi or if it is | 1225 // Check for one argument. Bail out if argument is not smi or if it is |
1168 // negative. | 1226 // negative. |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 // -- esp[0] : return address | 1412 // -- esp[0] : return address |
1355 // -- esp[4] : last argument | 1413 // -- esp[4] : last argument |
1356 // ----------------------------------- | 1414 // ----------------------------------- |
1357 Label generic_array_code; | 1415 Label generic_array_code; |
1358 | 1416 |
1359 // Get the InternalArray function. | 1417 // Get the InternalArray function. |
1360 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); | 1418 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); |
1361 | 1419 |
1362 if (FLAG_debug_code) { | 1420 if (FLAG_debug_code) { |
1363 // Initial map for the builtin InternalArray function should be a map. | 1421 // Initial map for the builtin InternalArray function should be a map. |
1364 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 1422 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
1365 // Will both indicate a NULL and a Smi. | 1423 // Will both indicate a NULL and a Smi. |
1366 __ test(ebx, Immediate(kSmiTagMask)); | 1424 __ test(ecx, Immediate(kSmiTagMask)); |
1367 __ Assert(not_zero, "Unexpected initial map for InternalArray function"); | 1425 __ Assert(not_zero, "Unexpected initial map for InternalArray function"); |
1368 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1426 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
1369 __ Assert(equal, "Unexpected initial map for InternalArray function"); | 1427 __ Assert(equal, "Unexpected initial map for InternalArray function"); |
1370 } | 1428 } |
1371 | 1429 |
| 1430 // No type feedback cell is available |
| 1431 Handle<Object> undefined_sentinel(masm->isolate()->heap()->undefined_value()); |
| 1432 __ mov(ebx, Immediate(undefined_sentinel)); |
| 1433 |
1372 // Run the native code for the InternalArray function called as a normal | 1434 // Run the native code for the InternalArray function called as a normal |
1373 // function. | 1435 // function. |
1374 ArrayNativeCode(masm, false, &generic_array_code); | 1436 ArrayNativeCode(masm, false, &generic_array_code); |
1375 | 1437 |
1376 // Jump to the generic internal array code in case the specialized code cannot | 1438 // Jump to the generic internal array code in case the specialized code cannot |
1377 // handle the construction. | 1439 // handle the construction. |
1378 __ bind(&generic_array_code); | 1440 __ bind(&generic_array_code); |
1379 Handle<Code> array_code = | 1441 Handle<Code> array_code = |
1380 masm->isolate()->builtins()->InternalArrayCodeGeneric(); | 1442 masm->isolate()->builtins()->InternalArrayCodeGeneric(); |
1381 __ jmp(array_code, RelocInfo::CODE_TARGET); | 1443 __ jmp(array_code, RelocInfo::CODE_TARGET); |
1382 } | 1444 } |
1383 | 1445 |
1384 | 1446 |
1385 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { | 1447 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { |
1386 // ----------- S t a t e ------------- | 1448 // ----------- S t a t e ------------- |
1387 // -- eax : argc | 1449 // -- eax : argc |
1388 // -- esp[0] : return address | 1450 // -- esp[0] : return address |
1389 // -- esp[4] : last argument | 1451 // -- esp[4] : last argument |
1390 // ----------------------------------- | 1452 // ----------------------------------- |
1391 Label generic_array_code; | 1453 Label generic_array_code; |
1392 | 1454 |
1393 // Get the Array function. | 1455 // Get the Array function. |
1394 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); | 1456 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); |
1395 | 1457 |
1396 if (FLAG_debug_code) { | 1458 if (FLAG_debug_code) { |
1397 // Initial map for the builtin Array function should be a map. | 1459 // Initial map for the builtin Array function should be a map. |
1398 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 1460 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
1399 // Will both indicate a NULL and a Smi. | 1461 // Will both indicate a NULL and a Smi. |
1400 __ test(ebx, Immediate(kSmiTagMask)); | 1462 __ test(ecx, Immediate(kSmiTagMask)); |
1401 __ Assert(not_zero, "Unexpected initial map for Array function"); | 1463 __ Assert(not_zero, "Unexpected initial map for Array function"); |
1402 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1464 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
1403 __ Assert(equal, "Unexpected initial map for Array function"); | 1465 __ Assert(equal, "Unexpected initial map for Array function"); |
1404 } | 1466 } |
1405 | 1467 |
| 1468 // No type feedback cell is available |
| 1469 Handle<Object> undefined_sentinel(masm->isolate()->heap()->undefined_value()); |
| 1470 __ mov(ebx, Immediate(undefined_sentinel)); |
| 1471 |
1406 // Run the native code for the Array function called as a normal function. | 1472 // Run the native code for the Array function called as a normal function. |
1407 ArrayNativeCode(masm, false, &generic_array_code); | 1473 ArrayNativeCode(masm, false, &generic_array_code); |
1408 | 1474 |
1409 // Jump to the generic array code in case the specialized code cannot handle | 1475 // Jump to the generic array code in case the specialized code cannot handle |
1410 // the construction. | 1476 // the construction. |
1411 __ bind(&generic_array_code); | 1477 __ bind(&generic_array_code); |
1412 Handle<Code> array_code = | 1478 Handle<Code> array_code = |
1413 masm->isolate()->builtins()->ArrayCodeGeneric(); | 1479 masm->isolate()->builtins()->ArrayCodeGeneric(); |
1414 __ jmp(array_code, RelocInfo::CODE_TARGET); | 1480 __ jmp(array_code, RelocInfo::CODE_TARGET); |
1415 } | 1481 } |
1416 | 1482 |
1417 | 1483 |
1418 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { | 1484 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { |
1419 // ----------- S t a t e ------------- | 1485 // ----------- S t a t e ------------- |
1420 // -- eax : argc | 1486 // -- eax : argc |
1421 // -- edi : constructor | 1487 // -- edi : constructor |
1422 // -- esp[0] : return address | 1488 // -- esp[0] : return address |
1423 // -- esp[4] : last argument | 1489 // -- esp[4] : last argument |
1424 // ----------------------------------- | 1490 // ----------------------------------- |
1425 Label generic_constructor; | 1491 Label generic_constructor; |
1426 | 1492 |
1427 if (FLAG_debug_code) { | 1493 if (FLAG_debug_code) { |
1428 // The array construct code is only set for the global and natives | 1494 // The array construct code is only set for the global and natives |
1429 // builtin Array functions which always have maps. | 1495 // builtin Array functions which always have maps. |
1430 | 1496 |
1431 // Initial map for the builtin Array function should be a map. | 1497 // Initial map for the builtin Array function should be a map. |
1432 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 1498 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
1433 // Will both indicate a NULL and a Smi. | 1499 // Will both indicate a NULL and a Smi. |
1434 __ test(ebx, Immediate(kSmiTagMask)); | 1500 __ test(ecx, Immediate(kSmiTagMask)); |
1435 __ Assert(not_zero, "Unexpected initial map for Array function"); | 1501 __ Assert(not_zero, "Unexpected initial map for Array function"); |
1436 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1502 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
1437 __ Assert(equal, "Unexpected initial map for Array function"); | 1503 __ Assert(equal, "Unexpected initial map for Array function"); |
1438 } | 1504 } |
1439 | 1505 |
1440 // Run the native code for the Array function called as constructor. | 1506 // Run the native code for the Array function called as constructor. |
1441 ArrayNativeCode(masm, true, &generic_constructor); | 1507 ArrayNativeCode(masm, true, &generic_constructor); |
1442 | 1508 |
1443 // Jump to the generic construct code in case the specialized code cannot | 1509 // Jump to the generic construct code in case the specialized code cannot |
1444 // handle the construction. | 1510 // handle the construction. |
1445 __ bind(&generic_constructor); | 1511 __ bind(&generic_constructor); |
1446 Handle<Code> generic_construct_stub = | 1512 Handle<Code> generic_construct_stub = |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1833 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1768 generator.Generate(); | 1834 generator.Generate(); |
1769 } | 1835 } |
1770 | 1836 |
1771 | 1837 |
1772 #undef __ | 1838 #undef __ |
1773 } | 1839 } |
1774 } // namespace v8::internal | 1840 } // namespace v8::internal |
1775 | 1841 |
1776 #endif // V8_TARGET_ARCH_IA32 | 1842 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |