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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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(ebx); | 136 __ AssertUndefinedOrAllocationSite(ebx); |
137 __ push(ebx); | 137 __ push(ebx); |
138 __ SmiTag(eax); | 138 __ SmiTag(eax); |
139 __ push(eax); | 139 __ push(eax); |
140 | 140 |
141 if (create_implicit_receiver) { | 141 if (create_implicit_receiver) { |
142 __ push(edi); | 142 // Allocate the new receiver object. |
143 __ push(edx); | 143 __ Push(edi); |
| 144 __ Push(edx); |
| 145 FastNewObjectStub stub(masm->isolate()); |
| 146 __ CallStub(&stub); |
| 147 __ mov(ebx, eax); |
| 148 __ Pop(edx); |
| 149 __ Pop(edi); |
144 | 150 |
145 // Try to allocate the object without transitioning into C code. If any of | 151 // ----------- S t a t e ------------- |
146 // the preconditions is not met, the code bails out to the runtime call. | 152 // -- edi: constructor function |
147 Label rt_call, allocated; | 153 // -- ebx: newly allocated object |
148 if (FLAG_inline_new) { | 154 // -- edx: new target |
149 // Verify that the new target is a JSFunction. | 155 // ----------------------------------- |
150 __ CmpObjectType(edx, JS_FUNCTION_TYPE, ebx); | |
151 __ j(not_equal, &rt_call); | |
152 | |
153 // Load the initial map and verify that it is in fact a map. | |
154 // edx: new target | |
155 __ mov(eax, | |
156 FieldOperand(edx, JSFunction::kPrototypeOrInitialMapOffset)); | |
157 // Will both indicate a NULL and a Smi | |
158 __ JumpIfSmi(eax, &rt_call); | |
159 // edi: constructor | |
160 // eax: initial map (if proven valid below) | |
161 __ CmpObjectType(eax, MAP_TYPE, ebx); | |
162 __ j(not_equal, &rt_call); | |
163 | |
164 // Fall back to runtime if the expected base constructor and base | |
165 // constructor differ. | |
166 __ cmp(edi, FieldOperand(eax, Map::kConstructorOrBackPointerOffset)); | |
167 __ j(not_equal, &rt_call); | |
168 | |
169 // Check that the constructor is not constructing a JSFunction (see | |
170 // comments in Runtime_NewObject in runtime.cc). In which case the | |
171 // initial map's instance type would be JS_FUNCTION_TYPE. | |
172 // edi: constructor | |
173 // eax: initial map | |
174 __ CmpInstanceType(eax, JS_FUNCTION_TYPE); | |
175 __ j(equal, &rt_call); | |
176 | |
177 // Now allocate the JSObject on the heap. | |
178 // edi: constructor | |
179 // eax: initial map | |
180 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); | |
181 __ shl(edi, kPointerSizeLog2); | |
182 | |
183 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | |
184 | |
185 Factory* factory = masm->isolate()->factory(); | |
186 | |
187 // Allocated the JSObject, now initialize the fields. | |
188 // eax: initial map | |
189 // ebx: JSObject (not HeapObject tagged - the actual address). | |
190 // edi: start of next object | |
191 __ mov(Operand(ebx, JSObject::kMapOffset), eax); | |
192 __ mov(ecx, factory->empty_fixed_array()); | |
193 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); | |
194 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); | |
195 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); | |
196 | |
197 // Add the object tag to make the JSObject real, so that we can continue | |
198 // and jump into the continuation code at any time from now on. | |
199 __ or_(ebx, Immediate(kHeapObjectTag)); | |
200 | |
201 // Fill all the in-object properties with the appropriate filler. | |
202 // ebx: JSObject (tagged) | |
203 // ecx: First in-object property of JSObject (not tagged) | |
204 __ mov(edx, factory->undefined_value()); | |
205 | |
206 if (!is_api_function) { | |
207 Label no_inobject_slack_tracking; | |
208 | |
209 // The code below relies on these assumptions. | |
210 STATIC_ASSERT(Map::kNoSlackTracking == 0); | |
211 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); | |
212 // Check if slack tracking is enabled. | |
213 __ mov(esi, FieldOperand(eax, Map::kBitField3Offset)); | |
214 __ shr(esi, Map::ConstructionCounter::kShift); | |
215 __ j(zero, &no_inobject_slack_tracking); // Map::kNoSlackTracking | |
216 __ push(esi); // Save allocation count value. | |
217 // Decrease generous allocation count. | |
218 __ sub(FieldOperand(eax, Map::kBitField3Offset), | |
219 Immediate(1 << Map::ConstructionCounter::kShift)); | |
220 | |
221 // Allocate object with a slack. | |
222 __ movzx_b(esi, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); | |
223 __ neg(esi); | |
224 __ lea(esi, Operand(edi, esi, times_pointer_size, 0)); | |
225 // esi: offset of first field after pre-allocated fields | |
226 if (FLAG_debug_code) { | |
227 __ cmp(ecx, esi); | |
228 __ Assert(less_equal, | |
229 kUnexpectedNumberOfPreAllocatedPropertyFields); | |
230 } | |
231 __ InitializeFieldsWithFiller(ecx, esi, edx); | |
232 | |
233 // To allow truncation fill the remaining fields with one pointer | |
234 // filler map. | |
235 __ mov(edx, factory->one_pointer_filler_map()); | |
236 __ InitializeFieldsWithFiller(ecx, edi, edx); | |
237 | |
238 __ pop(esi); // Restore allocation count value before decreasing. | |
239 __ cmp(esi, Map::kSlackTrackingCounterEnd); | |
240 __ j(not_equal, &allocated); | |
241 | |
242 // Push the object to the stack, and then the initial map as | |
243 // an argument to the runtime call. | |
244 __ push(ebx); | |
245 __ push(eax); // initial map | |
246 __ CallRuntime(Runtime::kFinalizeInstanceSize); | |
247 __ pop(ebx); | |
248 | |
249 // Continue with JSObject being successfully allocated | |
250 // ebx: JSObject (tagged) | |
251 __ jmp(&allocated); | |
252 | |
253 __ bind(&no_inobject_slack_tracking); | |
254 } | |
255 | |
256 __ InitializeFieldsWithFiller(ecx, edi, edx); | |
257 | |
258 // Continue with JSObject being successfully allocated | |
259 // ebx: JSObject (tagged) | |
260 __ jmp(&allocated); | |
261 } | |
262 | |
263 // Allocate the new receiver object using the runtime call. | |
264 // edx: new target | |
265 __ bind(&rt_call); | |
266 int offset = kPointerSize; | |
267 | |
268 // Must restore esi (context) and edi (constructor) before calling | |
269 // runtime. | |
270 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
271 __ mov(edi, Operand(esp, offset)); | |
272 __ push(edi); // constructor function | |
273 __ push(edx); // new target | |
274 __ CallRuntime(Runtime::kNewObject); | |
275 __ mov(ebx, eax); // store result in ebx | |
276 | |
277 // New object allocated. | |
278 // ebx: newly allocated object | |
279 __ bind(&allocated); | |
280 | |
281 // Restore the parameters. | |
282 __ pop(edx); // new.target | |
283 __ pop(edi); // Constructor function. | |
284 | 156 |
285 // Retrieve smi-tagged arguments count from the stack. | 157 // Retrieve smi-tagged arguments count from the stack. |
286 __ mov(eax, Operand(esp, 0)); | 158 __ mov(eax, Operand(esp, 0)); |
287 } | 159 } |
288 | 160 |
289 __ SmiUntag(eax); | 161 __ SmiUntag(eax); |
290 | 162 |
291 if (create_implicit_receiver) { | 163 if (create_implicit_receiver) { |
292 // Push the allocated receiver to the stack. We need two copies | 164 // Push the allocated receiver to the stack. We need two copies |
293 // because we may have to return the original one and the calling | 165 // because we may have to return the original one and the calling |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 | 1477 |
1606 // 5. Allocate a JSValue wrapper for the number. | 1478 // 5. Allocate a JSValue wrapper for the number. |
1607 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); | 1479 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); |
1608 __ Ret(); | 1480 __ Ret(); |
1609 | 1481 |
1610 // 6. Fallback to the runtime to create new object. | 1482 // 6. Fallback to the runtime to create new object. |
1611 __ bind(&new_object); | 1483 __ bind(&new_object); |
1612 { | 1484 { |
1613 FrameScope scope(masm, StackFrame::INTERNAL); | 1485 FrameScope scope(masm, StackFrame::INTERNAL); |
1614 __ Push(ebx); // the first argument | 1486 __ Push(ebx); // the first argument |
1615 __ Push(edi); // constructor function | 1487 FastNewObjectStub stub(masm->isolate()); |
1616 __ Push(edx); // new target | 1488 __ CallStub(&stub); |
1617 __ CallRuntime(Runtime::kNewObject); | |
1618 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); | 1489 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); |
1619 } | 1490 } |
1620 __ Ret(); | 1491 __ Ret(); |
1621 } | 1492 } |
1622 | 1493 |
1623 | 1494 |
1624 // static | 1495 // static |
1625 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 1496 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
1626 // ----------- S t a t e ------------- | 1497 // ----------- S t a t e ------------- |
1627 // -- eax : number of arguments | 1498 // -- eax : number of arguments |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 | 1610 |
1740 // 5. Allocate a JSValue wrapper for the string. | 1611 // 5. Allocate a JSValue wrapper for the string. |
1741 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); | 1612 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); |
1742 __ Ret(); | 1613 __ Ret(); |
1743 | 1614 |
1744 // 6. Fallback to the runtime to create new object. | 1615 // 6. Fallback to the runtime to create new object. |
1745 __ bind(&new_object); | 1616 __ bind(&new_object); |
1746 { | 1617 { |
1747 FrameScope scope(masm, StackFrame::INTERNAL); | 1618 FrameScope scope(masm, StackFrame::INTERNAL); |
1748 __ Push(ebx); // the first argument | 1619 __ Push(ebx); // the first argument |
1749 __ Push(edi); // constructor function | 1620 FastNewObjectStub stub(masm->isolate()); |
1750 __ Push(edx); // new target | 1621 __ CallStub(&stub); |
1751 __ CallRuntime(Runtime::kNewObject); | |
1752 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); | 1622 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); |
1753 } | 1623 } |
1754 __ Ret(); | 1624 __ Ret(); |
1755 } | 1625 } |
1756 | 1626 |
1757 | 1627 |
1758 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 1628 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
1759 Label* stack_overflow) { | 1629 Label* stack_overflow) { |
1760 // ----------- S t a t e ------------- | 1630 // ----------- S t a t e ------------- |
1761 // -- eax : actual number of arguments | 1631 // -- eax : actual number of arguments |
(...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2780 | 2650 |
2781 __ bind(&ok); | 2651 __ bind(&ok); |
2782 __ ret(0); | 2652 __ ret(0); |
2783 } | 2653 } |
2784 | 2654 |
2785 #undef __ | 2655 #undef __ |
2786 } // namespace internal | 2656 } // namespace internal |
2787 } // namespace v8 | 2657 } // namespace v8 |
2788 | 2658 |
2789 #endif // V8_TARGET_ARCH_IA32 | 2659 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |