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 |