OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 | 978 |
979 // Check that the elements are in fast mode (not dictionary). | 979 // Check that the elements are in fast mode (not dictionary). |
980 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 980 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
981 Factory::fixed_array_map()); | 981 Factory::fixed_array_map()); |
982 __ j(not_equal, &miss); | 982 __ j(not_equal, &miss); |
983 | 983 |
984 if (argc == 1) { // Otherwise fall through to call builtin. | 984 if (argc == 1) { // Otherwise fall through to call builtin. |
985 Label call_builtin, exit, with_write_barrier, attempt_to_grow_elements; | 985 Label call_builtin, exit, with_write_barrier, attempt_to_grow_elements; |
986 | 986 |
987 // Get the array's length into rax and calculate new length. | 987 // Get the array's length into rax and calculate new length. |
988 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 988 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
989 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); | 989 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |
990 __ SmiAddConstant(rax, rax, Smi::FromInt(argc)); | 990 __ addl(rax, Immediate(argc)); |
991 | 991 |
992 // Get the element's length into rcx. | 992 // Get the element's length into rcx. |
993 __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); | 993 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); |
994 | 994 |
995 // Check if we could survive without allocation. | 995 // Check if we could survive without allocation. |
996 __ SmiCompare(rax, rcx); | 996 __ cmpl(rax, rcx); |
997 __ j(greater, &attempt_to_grow_elements); | 997 __ j(greater, &attempt_to_grow_elements); |
998 | 998 |
999 // Save new length. | 999 // Save new length. |
1000 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1000 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1001 | 1001 |
1002 // Push the element. | 1002 // Push the element. |
1003 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1003 __ movq(rcx, Operand(rsp, argc * kPointerSize)); |
1004 SmiIndex index = | |
1005 masm()->SmiToIndex(kScratchRegister, rax, times_pointer_size); | |
1006 __ lea(rdx, FieldOperand(rbx, | 1004 __ lea(rdx, FieldOperand(rbx, |
1007 index.reg, index.scale, | 1005 rax, times_pointer_size, |
1008 FixedArray::kHeaderSize - argc * kPointerSize)); | 1006 FixedArray::kHeaderSize - argc * kPointerSize)); |
1009 __ movq(Operand(rdx, 0), rcx); | 1007 __ movq(Operand(rdx, 0), rcx); |
1010 | 1008 |
1011 // Check if value is a smi. | 1009 // Check if value is a smi. |
| 1010 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 1011 |
1012 __ JumpIfNotSmi(rcx, &with_write_barrier); | 1012 __ JumpIfNotSmi(rcx, &with_write_barrier); |
1013 | 1013 |
1014 __ bind(&exit); | 1014 __ bind(&exit); |
1015 __ ret((argc + 1) * kPointerSize); | 1015 __ ret((argc + 1) * kPointerSize); |
1016 | 1016 |
1017 __ bind(&with_write_barrier); | 1017 __ bind(&with_write_barrier); |
1018 | 1018 |
1019 __ InNewSpace(rbx, rcx, equal, &exit); | 1019 __ InNewSpace(rbx, rcx, equal, &exit); |
1020 | 1020 |
1021 RecordWriteStub stub(rbx, rdx, rcx); | 1021 RecordWriteStub stub(rbx, rdx, rcx); |
1022 __ CallStub(&stub); | 1022 __ CallStub(&stub); |
| 1023 |
1023 __ ret((argc + 1) * kPointerSize); | 1024 __ ret((argc + 1) * kPointerSize); |
1024 | 1025 |
1025 __ bind(&attempt_to_grow_elements); | 1026 __ bind(&attempt_to_grow_elements); |
1026 ExternalReference new_space_allocation_top = | 1027 ExternalReference new_space_allocation_top = |
1027 ExternalReference::new_space_allocation_top_address(); | 1028 ExternalReference::new_space_allocation_top_address(); |
1028 ExternalReference new_space_allocation_limit = | 1029 ExternalReference new_space_allocation_limit = |
1029 ExternalReference::new_space_allocation_limit_address(); | 1030 ExternalReference::new_space_allocation_limit_address(); |
1030 | 1031 |
1031 const int kAllocationDelta = 4; | 1032 const int kAllocationDelta = 4; |
1032 // Load top. | 1033 // Load top. |
1033 __ movq(rcx, new_space_allocation_top); | 1034 __ movq(rcx, new_space_allocation_top); |
1034 __ movq(rcx, Operand(rcx, 0)); | 1035 __ movq(rcx, Operand(rcx, 0)); |
1035 | 1036 |
1036 // Check if it's the end of elements. | 1037 // Check if it's the end of elements. |
1037 index = masm()->SmiToIndex(kScratchRegister, rax, times_pointer_size); | |
1038 __ lea(rdx, FieldOperand(rbx, | 1038 __ lea(rdx, FieldOperand(rbx, |
1039 index.reg, index.scale, | 1039 rax, times_pointer_size, |
1040 FixedArray::kHeaderSize - argc * kPointerSize)); | 1040 FixedArray::kHeaderSize - argc * kPointerSize)); |
1041 __ cmpq(rdx, rcx); | 1041 __ cmpq(rdx, rcx); |
1042 __ j(not_equal, &call_builtin); | 1042 __ j(not_equal, &call_builtin); |
1043 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); | 1043 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); |
1044 __ movq(kScratchRegister, new_space_allocation_limit); | 1044 __ movq(kScratchRegister, new_space_allocation_limit); |
1045 __ cmpq(rcx, Operand(kScratchRegister, 0)); | 1045 __ cmpq(rcx, Operand(kScratchRegister, 0)); |
1046 __ j(above, &call_builtin); | 1046 __ j(above, &call_builtin); |
1047 | 1047 |
1048 // We fit and could grow elements. | 1048 // We fit and could grow elements. |
1049 __ movq(kScratchRegister, new_space_allocation_top); | 1049 __ movq(kScratchRegister, new_space_allocation_top); |
1050 __ movq(Operand(kScratchRegister, 0), rcx); | 1050 __ movq(Operand(kScratchRegister, 0), rcx); |
1051 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1051 __ movq(rcx, Operand(rsp, argc * kPointerSize)); |
1052 | 1052 |
1053 // Push the argument... | 1053 // Push the argument... |
1054 __ movq(Operand(rdx, 0), rcx); | 1054 __ movq(Operand(rdx, 0), rcx); |
1055 // ... and fill the rest with holes. | 1055 // ... and fill the rest with holes. |
1056 __ Move(kScratchRegister, Factory::the_hole_value()); | 1056 __ Move(kScratchRegister, Factory::the_hole_value()); |
1057 for (int i = 1; i < kAllocationDelta; i++) { | 1057 for (int i = 1; i < kAllocationDelta; i++) { |
1058 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); | 1058 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); |
1059 } | 1059 } |
1060 | 1060 |
1061 // Restore receiver to rdx as finish sequence assumes it's here. | 1061 // Restore receiver to rdx as finish sequence assumes it's here. |
1062 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1062 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
1063 | 1063 |
1064 // Increment element's and array's sizes. | 1064 // Increment element's and array's sizes. |
1065 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), | 1065 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), |
1066 Smi::FromInt(kAllocationDelta)); | 1066 Smi::FromInt(kAllocationDelta)); |
| 1067 // Make new length a smi before returning it. |
| 1068 __ Integer32ToSmi(rax, rax); |
1067 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1069 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1068 | |
1069 // Elements are in new space, so write barrier is not required. | 1070 // Elements are in new space, so write barrier is not required. |
1070 __ ret((argc + 1) * kPointerSize); | 1071 __ ret((argc + 1) * kPointerSize); |
1071 | 1072 |
1072 __ bind(&call_builtin); | 1073 __ bind(&call_builtin); |
1073 } | 1074 } |
1074 | 1075 |
1075 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), | 1076 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), |
1076 argc + 1, | 1077 argc + 1, |
1077 1); | 1078 1); |
1078 } | 1079 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 rax, name, &miss); | 1122 rax, name, &miss); |
1122 | 1123 |
1123 // Get the elements array of the object. | 1124 // Get the elements array of the object. |
1124 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1125 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
1125 | 1126 |
1126 // Check that the elements are in fast mode (not dictionary). | 1127 // Check that the elements are in fast mode (not dictionary). |
1127 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::fixed_array_map()); | 1128 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::fixed_array_map()); |
1128 __ j(not_equal, &miss); | 1129 __ j(not_equal, &miss); |
1129 | 1130 |
1130 // Get the array's length into rcx and calculate new length. | 1131 // Get the array's length into rcx and calculate new length. |
1131 __ movq(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); | 1132 __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); |
1132 __ SmiSubConstant(rcx, rcx, Smi::FromInt(1)); | 1133 __ subl(rcx, Immediate(1)); |
1133 __ SmiTest(rcx); | |
1134 __ j(negative, &return_undefined); | 1134 __ j(negative, &return_undefined); |
1135 | 1135 |
1136 // Get the last element. | 1136 // Get the last element. |
1137 __ Move(r9, Factory::the_hole_value()); | 1137 __ Move(r9, Factory::the_hole_value()); |
1138 SmiIndex index = | |
1139 masm()->SmiToIndex(r8, rcx, times_pointer_size); | |
1140 __ movq(rax, FieldOperand(rbx, | 1138 __ movq(rax, FieldOperand(rbx, |
1141 index.reg, index.scale, | 1139 rcx, times_pointer_size, |
1142 FixedArray::kHeaderSize)); | 1140 FixedArray::kHeaderSize)); |
1143 // Check if element is already the hole. | 1141 // Check if element is already the hole. |
1144 __ cmpq(rax, r9); | 1142 __ cmpq(rax, r9); |
| 1143 // If so, call slow-case to also check prototypes for value. |
1145 __ j(equal, &call_builtin); | 1144 __ j(equal, &call_builtin); |
1146 | 1145 |
1147 // Set the array's length. | 1146 // Set the array's length. |
1148 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 1147 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
1149 | 1148 |
1150 // Fill with the hole and return original value.. | 1149 // Fill with the hole and return original value. |
1151 __ movq(FieldOperand(rbx, | 1150 __ movq(FieldOperand(rbx, |
1152 index.reg, index.scale, | 1151 rcx, times_pointer_size, |
1153 FixedArray::kHeaderSize), | 1152 FixedArray::kHeaderSize), |
1154 r9); | 1153 r9); |
1155 __ ret((argc + 1) * kPointerSize); | 1154 __ ret((argc + 1) * kPointerSize); |
1156 | 1155 |
1157 __ bind(&return_undefined); | 1156 __ bind(&return_undefined); |
1158 | 1157 |
1159 __ Move(rax, Factory::undefined_value()); | 1158 __ Move(rax, Factory::undefined_value()); |
1160 __ ret((argc + 1) * kPointerSize); | 1159 __ ret((argc + 1) * kPointerSize); |
1161 | 1160 |
1162 __ bind(&call_builtin); | 1161 __ bind(&call_builtin); |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2332 // Return the generated code. | 2331 // Return the generated code. |
2333 return GetCode(); | 2332 return GetCode(); |
2334 } | 2333 } |
2335 | 2334 |
2336 | 2335 |
2337 #undef __ | 2336 #undef __ |
2338 | 2337 |
2339 } } // namespace v8::internal | 2338 } } // namespace v8::internal |
2340 | 2339 |
2341 #endif // V8_TARGET_ARCH_X64 | 2340 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |