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