| 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 { | 133 { |
| 134 FrameScope scope(masm, StackFrame::CONSTRUCT); | 134 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 135 | 135 |
| 136 // Preserve the incoming parameters on the stack. | 136 // Preserve the incoming parameters on the stack. |
| 137 __ AssertUndefinedOrAllocationSite(rbx); | 137 __ AssertUndefinedOrAllocationSite(rbx); |
| 138 __ Push(rbx); | 138 __ Push(rbx); |
| 139 __ Integer32ToSmi(rcx, rax); | 139 __ Integer32ToSmi(rcx, rax); |
| 140 __ Push(rcx); | 140 __ Push(rcx); |
| 141 | 141 |
| 142 if (create_implicit_receiver) { | 142 if (create_implicit_receiver) { |
| 143 // Try to allocate the object without transitioning into C code. If any of | 143 // Allocate the new receiver object. |
| 144 // the preconditions is not met, the code bails out to the runtime call. | |
| 145 Label rt_call, allocated; | |
| 146 if (FLAG_inline_new) { | |
| 147 // Verify that the new target is a JSFunction. | |
| 148 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx); | |
| 149 __ j(not_equal, &rt_call); | |
| 150 | |
| 151 // Load the initial map and verify that it is in fact a map. | |
| 152 // rdx: new target | |
| 153 __ movp(rax, | |
| 154 FieldOperand(rdx, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 155 // Will both indicate a NULL and a Smi | |
| 156 DCHECK(kSmiTag == 0); | |
| 157 __ JumpIfSmi(rax, &rt_call); | |
| 158 // rdi: constructor | |
| 159 // rax: initial map (if proven valid below) | |
| 160 __ CmpObjectType(rax, MAP_TYPE, rbx); | |
| 161 __ j(not_equal, &rt_call); | |
| 162 | |
| 163 // Fall back to runtime if the expected base constructor and base | |
| 164 // constructor differ. | |
| 165 __ cmpp(rdi, FieldOperand(rax, Map::kConstructorOrBackPointerOffset)); | |
| 166 __ j(not_equal, &rt_call); | |
| 167 | |
| 168 // Now allocate the JSObject on the heap. | |
| 169 __ movzxbp(r9, FieldOperand(rax, Map::kInstanceSizeOffset)); | |
| 170 __ shlp(r9, Immediate(kPointerSizeLog2)); | |
| 171 // r9: size of new object | |
| 172 __ Allocate(r9, rbx, r9, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | |
| 173 // Allocated the JSObject, now initialize the fields. | |
| 174 // rdi: constructor | |
| 175 // rdx: new target | |
| 176 // rax: initial map | |
| 177 // rbx: JSObject (not HeapObject tagged - the actual address). | |
| 178 // r9: start of next object | |
| 179 __ movp(Operand(rbx, JSObject::kMapOffset), rax); | |
| 180 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
| 181 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); | |
| 182 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); | |
| 183 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); | |
| 184 | |
| 185 // Add the object tag to make the JSObject real, so that we can continue | |
| 186 // and jump into the continuation code at any time from now on. | |
| 187 __ orp(rbx, Immediate(kHeapObjectTag)); | |
| 188 | |
| 189 // Fill all the in-object properties with the appropriate filler. | |
| 190 // rbx: JSObject (tagged) | |
| 191 // rcx: First in-object property of JSObject (not tagged) | |
| 192 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); | |
| 193 | |
| 194 if (!is_api_function) { | |
| 195 Label no_inobject_slack_tracking; | |
| 196 | |
| 197 // The code below relies on these assumptions. | |
| 198 STATIC_ASSERT(Map::kNoSlackTracking == 0); | |
| 199 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); | |
| 200 // Check if slack tracking is enabled. | |
| 201 __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset)); | |
| 202 __ shrl(rsi, Immediate(Map::ConstructionCounter::kShift)); | |
| 203 __ j(zero, &no_inobject_slack_tracking); // Map::kNoSlackTracking | |
| 204 __ Push(rsi); // Save allocation count value. | |
| 205 // Decrease generous allocation count. | |
| 206 __ subl(FieldOperand(rax, Map::kBitField3Offset), | |
| 207 Immediate(1 << Map::ConstructionCounter::kShift)); | |
| 208 | |
| 209 // Allocate object with a slack. | |
| 210 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); | |
| 211 __ negp(rsi); | |
| 212 __ leap(rsi, Operand(r9, rsi, times_pointer_size, 0)); | |
| 213 // rsi: offset of first field after pre-allocated fields | |
| 214 if (FLAG_debug_code) { | |
| 215 __ cmpp(rcx, rsi); | |
| 216 __ Assert(less_equal, | |
| 217 kUnexpectedNumberOfPreAllocatedPropertyFields); | |
| 218 } | |
| 219 __ InitializeFieldsWithFiller(rcx, rsi, r11); | |
| 220 | |
| 221 // To allow truncation fill the remaining fields with one pointer | |
| 222 // filler map. | |
| 223 __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex); | |
| 224 __ InitializeFieldsWithFiller(rcx, r9, r11); | |
| 225 | |
| 226 __ Pop(rsi); // Restore allocation count value before decreasing. | |
| 227 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | |
| 228 __ j(not_equal, &allocated); | |
| 229 | |
| 230 // Push the constructor, new_target and the object to the stack, | |
| 231 // and then the initial map as an argument to the runtime call. | |
| 232 __ Push(rdi); | |
| 233 __ Push(rdx); | |
| 234 __ Push(rbx); | |
| 235 | |
| 236 __ Push(rax); // initial map | |
| 237 __ CallRuntime(Runtime::kFinalizeInstanceSize); | |
| 238 | |
| 239 __ Pop(rbx); | |
| 240 __ Pop(rdx); | |
| 241 __ Pop(rdi); | |
| 242 | |
| 243 // Continue with JSObject being successfully allocated. | |
| 244 // rdi: constructor | |
| 245 // rdx: new target | |
| 246 // rbx: JSObject (tagged) | |
| 247 __ jmp(&allocated); | |
| 248 | |
| 249 __ bind(&no_inobject_slack_tracking); | |
| 250 } | |
| 251 | |
| 252 __ InitializeFieldsWithFiller(rcx, r9, r11); | |
| 253 | |
| 254 // Continue with JSObject being successfully allocated | |
| 255 // rdi: constructor | |
| 256 // rdx: new target | |
| 257 // rbx: JSObject (tagged) | |
| 258 __ jmp(&allocated); | |
| 259 } | |
| 260 | |
| 261 // Allocate the new receiver object using the runtime call. | |
| 262 // rdi: constructor | |
| 263 // rdx: new target | |
| 264 __ bind(&rt_call); | |
| 265 | |
| 266 // Must restore rsi (context) before calling runtime. | |
| 267 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 268 | |
| 269 // Push the constructor and new_target twice, second pair as arguments | |
| 270 // to the runtime call. | |
| 271 __ Push(rdi); | 144 __ Push(rdi); |
| 272 __ Push(rdx); | 145 __ Push(rdx); |
| 273 __ Push(rdi); // constructor function | 146 FastNewObjectStub stub(masm->isolate()); |
| 274 __ Push(rdx); // new target | 147 __ CallStub(&stub); |
| 275 __ CallRuntime(Runtime::kNewObject); | 148 __ movp(rbx, rax); |
| 276 __ movp(rbx, rax); // store result in rbx | |
| 277 __ Pop(rdx); | 149 __ Pop(rdx); |
| 278 __ Pop(rdi); | 150 __ Pop(rdi); |
| 279 | 151 |
| 280 // Receiver for constructor call allocated. | 152 // ----------- S t a t e ------------- |
| 281 // rdi: constructor | 153 // -- rdi: constructor function |
| 282 // rdx: new target | 154 // -- rbx: newly allocated object |
| 283 // rbx: newly allocated object | 155 // -- rdx: new target |
| 284 __ bind(&allocated); | 156 // ----------------------------------- |
| 285 | 157 |
| 286 // Retrieve smi-tagged arguments count from the stack. | 158 // Retrieve smi-tagged arguments count from the stack. |
| 287 __ movp(rax, Operand(rsp, 0)); | 159 __ SmiToInteger32(rax, Operand(rsp, 0 * kPointerSize)); |
| 288 __ SmiToInteger32(rax, rax); | |
| 289 } | 160 } |
| 290 | 161 |
| 291 if (create_implicit_receiver) { | 162 if (create_implicit_receiver) { |
| 292 // Push the allocated receiver to the stack. We need two copies | 163 // Push the allocated receiver to the stack. We need two copies |
| 293 // because we may have to return the original one and the calling | 164 // because we may have to return the original one and the calling |
| 294 // conventions dictate that the called function pops the receiver. | 165 // conventions dictate that the called function pops the receiver. |
| 295 __ Push(rbx); | 166 __ Push(rbx); |
| 296 __ Push(rbx); | 167 __ Push(rbx); |
| 297 } else { | 168 } else { |
| 298 __ PushRoot(Heap::kTheHoleValueRootIndex); | 169 __ PushRoot(Heap::kTheHoleValueRootIndex); |
| (...skipping 1374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 | 1544 |
| 1674 // 5. Allocate a JSValue wrapper for the number. | 1545 // 5. Allocate a JSValue wrapper for the number. |
| 1675 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); | 1546 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); |
| 1676 __ Ret(); | 1547 __ Ret(); |
| 1677 | 1548 |
| 1678 // 6. Fallback to the runtime to create new object. | 1549 // 6. Fallback to the runtime to create new object. |
| 1679 __ bind(&new_object); | 1550 __ bind(&new_object); |
| 1680 { | 1551 { |
| 1681 FrameScope scope(masm, StackFrame::INTERNAL); | 1552 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1682 __ Push(rbx); // the first argument | 1553 __ Push(rbx); // the first argument |
| 1683 __ Push(rdi); // constructor function | 1554 FastNewObjectStub stub(masm->isolate()); |
| 1684 __ Push(rdx); // new target | 1555 __ CallStub(&stub); |
| 1685 __ CallRuntime(Runtime::kNewObject); | |
| 1686 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); | 1556 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); |
| 1687 } | 1557 } |
| 1688 __ Ret(); | 1558 __ Ret(); |
| 1689 } | 1559 } |
| 1690 | 1560 |
| 1691 | 1561 |
| 1692 // static | 1562 // static |
| 1693 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 1563 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
| 1694 // ----------- S t a t e ------------- | 1564 // ----------- S t a t e ------------- |
| 1695 // -- rax : number of arguments | 1565 // -- rax : number of arguments |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 | 1679 |
| 1810 // 5. Allocate a JSValue wrapper for the string. | 1680 // 5. Allocate a JSValue wrapper for the string. |
| 1811 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); | 1681 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); |
| 1812 __ Ret(); | 1682 __ Ret(); |
| 1813 | 1683 |
| 1814 // 6. Fallback to the runtime to create new object. | 1684 // 6. Fallback to the runtime to create new object. |
| 1815 __ bind(&new_object); | 1685 __ bind(&new_object); |
| 1816 { | 1686 { |
| 1817 FrameScope scope(masm, StackFrame::INTERNAL); | 1687 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1818 __ Push(rbx); // the first argument | 1688 __ Push(rbx); // the first argument |
| 1819 __ Push(rdi); // constructor function | 1689 FastNewObjectStub stub(masm->isolate()); |
| 1820 __ Push(rdx); // new target | 1690 __ CallStub(&stub); |
| 1821 __ CallRuntime(Runtime::kNewObject); | |
| 1822 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); | 1691 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); |
| 1823 } | 1692 } |
| 1824 __ Ret(); | 1693 __ Ret(); |
| 1825 } | 1694 } |
| 1826 | 1695 |
| 1827 | 1696 |
| 1828 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 1697 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
| 1829 Label* stack_overflow) { | 1698 Label* stack_overflow) { |
| 1830 // ----------- S t a t e ------------- | 1699 // ----------- S t a t e ------------- |
| 1831 // -- rax : actual number of arguments | 1700 // -- rax : actual number of arguments |
| (...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2858 __ ret(0); | 2727 __ ret(0); |
| 2859 } | 2728 } |
| 2860 | 2729 |
| 2861 | 2730 |
| 2862 #undef __ | 2731 #undef __ |
| 2863 | 2732 |
| 2864 } // namespace internal | 2733 } // namespace internal |
| 2865 } // namespace v8 | 2734 } // namespace v8 |
| 2866 | 2735 |
| 2867 #endif // V8_TARGET_ARCH_X64 | 2736 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |