| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 { | 132 { |
| 133 FrameScope scope(masm, StackFrame::CONSTRUCT); | 133 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 134 | 134 |
| 135 // Preserve the incoming parameters on the stack. | 135 // Preserve the incoming parameters on the stack. |
| 136 __ AssertUndefinedOrAllocationSite(rbx); | 136 __ AssertUndefinedOrAllocationSite(rbx); |
| 137 __ Push(rbx); | 137 __ Push(rbx); |
| 138 __ Integer32ToSmi(rcx, rax); | 138 __ Integer32ToSmi(rcx, rax); |
| 139 __ Push(rcx); | 139 __ Push(rcx); |
| 140 | 140 |
| 141 if (create_implicit_receiver) { | 141 if (create_implicit_receiver) { |
| 142 __ Push(rdi); | |
| 143 __ Push(rdx); | |
| 144 | |
| 145 // Try to allocate the object without transitioning into C code. If any of | 142 // Try to allocate the object without transitioning into C code. If any of |
| 146 // the preconditions is not met, the code bails out to the runtime call. | 143 // the preconditions is not met, the code bails out to the runtime call. |
| 147 Label rt_call, allocated; | 144 Label rt_call, allocated; |
| 148 if (FLAG_inline_new) { | 145 if (FLAG_inline_new) { |
| 149 // Verify that the new target is a JSFunction. | 146 // Verify that the new target is a JSFunction. |
| 150 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx); | 147 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx); |
| 151 __ j(not_equal, &rt_call); | 148 __ j(not_equal, &rt_call); |
| 152 | 149 |
| 153 // Load the initial map and verify that it is in fact a map. | 150 // Load the initial map and verify that it is in fact a map. |
| 154 // rdx: new target | 151 // rdx: new target |
| (...skipping 21 matching lines...) Expand all Loading... |
| 176 __ shrl(rsi, Immediate(Map::Counter::kShift)); | 173 __ shrl(rsi, Immediate(Map::Counter::kShift)); |
| 177 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | 174 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
| 178 __ j(less, &allocate); | 175 __ j(less, &allocate); |
| 179 // Decrease generous allocation count. | 176 // Decrease generous allocation count. |
| 180 __ subl(FieldOperand(rax, Map::kBitField3Offset), | 177 __ subl(FieldOperand(rax, Map::kBitField3Offset), |
| 181 Immediate(1 << Map::Counter::kShift)); | 178 Immediate(1 << Map::Counter::kShift)); |
| 182 | 179 |
| 183 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | 180 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
| 184 __ j(not_equal, &allocate); | 181 __ j(not_equal, &allocate); |
| 185 | 182 |
| 183 // Push the constructor, new_target and map to the stack, and |
| 184 // the map again as an argument to the runtime call. |
| 186 __ Push(rax); | 185 __ Push(rax); |
| 187 __ Push(rdx); | 186 __ Push(rdx); |
| 188 __ Push(rdi); | 187 __ Push(rdi); |
| 189 | 188 |
| 190 __ Push(rax); // initial map | 189 __ Push(rax); // initial map |
| 191 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 190 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 192 | 191 |
| 193 __ Pop(rdi); | 192 __ Pop(rdi); |
| 194 __ Pop(rdx); | 193 __ Pop(rdx); |
| 195 __ Pop(rax); | 194 __ Pop(rax); |
| 196 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); | 195 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); |
| 197 | 196 |
| 198 __ bind(&allocate); | 197 __ bind(&allocate); |
| 199 } | 198 } |
| 200 | 199 |
| 201 // Now allocate the JSObject on the heap. | 200 // Now allocate the JSObject on the heap. |
| 202 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); | 201 __ movzxbp(r9, FieldOperand(rax, Map::kInstanceSizeOffset)); |
| 203 __ shlp(rdi, Immediate(kPointerSizeLog2)); | 202 __ shlp(r9, Immediate(kPointerSizeLog2)); |
| 204 // rdi: size of new object | 203 // r9: size of new object |
| 205 __ Allocate(rdi, rbx, rdi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 204 __ Allocate(r9, rbx, r9, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
| 206 // Allocated the JSObject, now initialize the fields. | 205 // Allocated the JSObject, now initialize the fields. |
| 206 // rdi: constructor |
| 207 // rdx: new target |
| 207 // rax: initial map | 208 // rax: initial map |
| 208 // rbx: JSObject (not HeapObject tagged - the actual address). | 209 // rbx: JSObject (not HeapObject tagged - the actual address). |
| 209 // rdi: start of next object | 210 // r9: start of next object |
| 210 __ movp(Operand(rbx, JSObject::kMapOffset), rax); | 211 __ movp(Operand(rbx, JSObject::kMapOffset), rax); |
| 211 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | 212 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
| 212 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); | 213 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); |
| 213 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); | 214 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); |
| 214 // Set extra fields in the newly allocated object. | 215 // Set extra fields in the newly allocated object. |
| 215 // rax: initial map | 216 // rax: initial map |
| 217 // rdx: new target |
| 216 // rbx: JSObject | 218 // rbx: JSObject |
| 217 // rdi: start of next object | 219 // r9: start of next object |
| 218 // rsi: slack tracking counter (non-API function case) | 220 // rsi: slack tracking counter (non-API function case) |
| 219 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); | 221 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); |
| 220 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 222 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); |
| 221 if (!is_api_function) { | 223 if (!is_api_function) { |
| 222 Label no_inobject_slack_tracking; | 224 Label no_inobject_slack_tracking; |
| 223 | 225 |
| 224 // Check if slack tracking is enabled. | 226 // Check if slack tracking is enabled. |
| 225 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | 227 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
| 226 __ j(less, &no_inobject_slack_tracking); | 228 __ j(less, &no_inobject_slack_tracking); |
| 227 | 229 |
| 228 // Allocate object with a slack. | 230 // Allocate object with a slack. |
| 229 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); | 231 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); |
| 230 __ negp(rsi); | 232 __ negp(rsi); |
| 231 __ leap(rsi, Operand(rdi, rsi, times_pointer_size, 0)); | 233 __ leap(rsi, Operand(r9, rsi, times_pointer_size, 0)); |
| 232 // rsi: offset of first field after pre-allocated fields | 234 // rsi: offset of first field after pre-allocated fields |
| 233 if (FLAG_debug_code) { | 235 if (FLAG_debug_code) { |
| 234 __ cmpp(rcx, rsi); | 236 __ cmpp(rcx, rsi); |
| 235 __ Assert(less_equal, | 237 __ Assert(less_equal, |
| 236 kUnexpectedNumberOfPreAllocatedPropertyFields); | 238 kUnexpectedNumberOfPreAllocatedPropertyFields); |
| 237 } | 239 } |
| 238 __ InitializeFieldsWithFiller(rcx, rsi, rdx); | 240 __ InitializeFieldsWithFiller(rcx, rsi, r11); |
| 239 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); | 241 |
| 240 // Fill the remaining fields with one pointer filler map. | 242 // To allow truncation fill the remaining fields with one pointer |
| 243 // filler map. |
| 244 __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex); |
| 241 | 245 |
| 242 __ bind(&no_inobject_slack_tracking); | 246 __ bind(&no_inobject_slack_tracking); |
| 243 } | 247 } |
| 244 | 248 |
| 245 __ InitializeFieldsWithFiller(rcx, rdi, rdx); | 249 __ InitializeFieldsWithFiller(rcx, r9, r11); |
| 246 | 250 |
| 247 // Add the object tag to make the JSObject real, so that we can continue | 251 // Add the object tag to make the JSObject real, so that we can continue |
| 248 // and jump into the continuation code at any time from now on. | 252 // and jump into the continuation code at any time from now on. |
| 249 // rbx: JSObject (untagged) | 253 // rbx: JSObject (untagged) |
| 250 __ orp(rbx, Immediate(kHeapObjectTag)); | 254 __ orp(rbx, Immediate(kHeapObjectTag)); |
| 251 | 255 |
| 252 // Continue with JSObject being successfully allocated | 256 // Continue with JSObject being successfully allocated |
| 257 // rdi: constructor |
| 258 // rdx: new target |
| 253 // rbx: JSObject (tagged) | 259 // rbx: JSObject (tagged) |
| 254 __ jmp(&allocated); | 260 __ jmp(&allocated); |
| 255 } | 261 } |
| 256 | 262 |
| 257 // Allocate the new receiver object using the runtime call. | 263 // Allocate the new receiver object using the runtime call. |
| 264 // rdi: constructor |
| 258 // rdx: new target | 265 // rdx: new target |
| 259 __ bind(&rt_call); | 266 __ bind(&rt_call); |
| 260 int offset = kPointerSize; | |
| 261 | 267 |
| 262 // Must restore rsi (context) and rdi (constructor) before calling | 268 // Must restore rsi (context) before calling runtime. |
| 263 // runtime. | |
| 264 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 269 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 265 __ movp(rdi, Operand(rsp, offset)); | 270 |
| 271 // Push the constructor and new_target twice, second pair as arguments |
| 272 // to the runtime call. |
| 273 __ Push(rdi); |
| 274 __ Push(rdx); |
| 266 __ Push(rdi); // constructor function | 275 __ Push(rdi); // constructor function |
| 267 __ Push(rdx); // new target | 276 __ Push(rdx); // new target |
| 268 __ CallRuntime(Runtime::kNewObject, 2); | 277 __ CallRuntime(Runtime::kNewObject, 2); |
| 269 __ movp(rbx, rax); // store result in rbx | 278 __ movp(rbx, rax); // store result in rbx |
| 279 __ Pop(rdx); |
| 280 __ Pop(rdi); |
| 270 | 281 |
| 271 // New object allocated. | 282 // Receiver for constructor call allocated. |
| 283 // rdi: constructor |
| 284 // rdx: new target |
| 272 // rbx: newly allocated object | 285 // rbx: newly allocated object |
| 273 __ bind(&allocated); | 286 __ bind(&allocated); |
| 274 | 287 |
| 275 // Restore the parameters. | |
| 276 __ Pop(rdx); | |
| 277 __ Pop(rdi); | |
| 278 | |
| 279 // Retrieve smi-tagged arguments count from the stack. | 288 // Retrieve smi-tagged arguments count from the stack. |
| 280 __ movp(rax, Operand(rsp, 0)); | 289 __ movp(rax, Operand(rsp, 0)); |
| 281 __ SmiToInteger32(rax, rax); | 290 __ SmiToInteger32(rax, rax); |
| 282 } | 291 } |
| 283 | 292 |
| 284 // Push new.target onto the construct frame. This is stored just below the | 293 // Push new.target onto the construct frame. This is stored just below the |
| 285 // receiver on the stack. | 294 // receiver on the stack. |
| 286 __ Push(rdx); | 295 __ Push(rdx); |
| 287 | 296 |
| 288 if (create_implicit_receiver) { | 297 if (create_implicit_receiver) { |
| (...skipping 1621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 __ ret(0); | 1919 __ ret(0); |
| 1911 } | 1920 } |
| 1912 | 1921 |
| 1913 | 1922 |
| 1914 #undef __ | 1923 #undef __ |
| 1915 | 1924 |
| 1916 } // namespace internal | 1925 } // namespace internal |
| 1917 } // namespace v8 | 1926 } // namespace v8 |
| 1918 | 1927 |
| 1919 #endif // V8_TARGET_ARCH_X64 | 1928 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |