| 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 93 |
| 94 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 94 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
| 95 GenerateTailCallToReturnedCode(masm); | 95 GenerateTailCallToReturnedCode(masm); |
| 96 | 96 |
| 97 __ bind(&ok); | 97 __ bind(&ok); |
| 98 GenerateTailCallToSharedCode(masm); | 98 GenerateTailCallToSharedCode(masm); |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 102 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 103 bool is_api_function, | 103 bool is_api_function) { |
| 104 bool create_memento) { | |
| 105 // ----------- S t a t e ------------- | 104 // ----------- S t a t e ------------- |
| 106 // -- eax: number of arguments | 105 // -- eax: number of arguments |
| 107 // -- edi: constructor function | 106 // -- edi: constructor function |
| 108 // -- ebx: allocation site or undefined | 107 // -- ebx: allocation site or undefined |
| 109 // -- edx: original constructor | 108 // -- edx: original constructor |
| 110 // ----------------------------------- | 109 // ----------------------------------- |
| 111 | 110 |
| 112 // Should never create mementos for api functions. | |
| 113 DCHECK(!is_api_function || !create_memento); | |
| 114 | |
| 115 // Enter a construct frame. | 111 // Enter a construct frame. |
| 116 { | 112 { |
| 117 FrameScope scope(masm, StackFrame::CONSTRUCT); | 113 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 118 | 114 |
| 119 // Preserve the incoming parameters on the stack. | 115 // Preserve the incoming parameters on the stack. |
| 120 __ AssertUndefinedOrAllocationSite(ebx); | 116 __ AssertUndefinedOrAllocationSite(ebx); |
| 121 __ push(ebx); | 117 __ push(ebx); |
| 122 __ SmiTag(eax); | 118 __ SmiTag(eax); |
| 123 __ push(eax); | 119 __ push(eax); |
| 124 __ push(edi); | 120 __ push(edi); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 __ mov(esi, Map::kSlackTrackingCounterEnd - 1); | 181 __ mov(esi, Map::kSlackTrackingCounterEnd - 1); |
| 186 | 182 |
| 187 __ bind(&allocate); | 183 __ bind(&allocate); |
| 188 } | 184 } |
| 189 | 185 |
| 190 // Now allocate the JSObject on the heap. | 186 // Now allocate the JSObject on the heap. |
| 191 // edi: constructor | 187 // edi: constructor |
| 192 // eax: initial map | 188 // eax: initial map |
| 193 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); | 189 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); |
| 194 __ shl(edi, kPointerSizeLog2); | 190 __ shl(edi, kPointerSizeLog2); |
| 195 if (create_memento) { | |
| 196 __ add(edi, Immediate(AllocationMemento::kSize)); | |
| 197 } | |
| 198 | 191 |
| 199 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 192 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
| 200 | 193 |
| 201 Factory* factory = masm->isolate()->factory(); | 194 Factory* factory = masm->isolate()->factory(); |
| 202 | 195 |
| 203 // Allocated the JSObject, now initialize the fields. | 196 // Allocated the JSObject, now initialize the fields. |
| 204 // eax: initial map | 197 // eax: initial map |
| 205 // ebx: JSObject | 198 // ebx: JSObject |
| 206 // edi: start of next object (including memento if create_memento) | 199 // edi: start of next object |
| 207 __ mov(Operand(ebx, JSObject::kMapOffset), eax); | 200 __ mov(Operand(ebx, JSObject::kMapOffset), eax); |
| 208 __ mov(ecx, factory->empty_fixed_array()); | 201 __ mov(ecx, factory->empty_fixed_array()); |
| 209 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); | 202 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); |
| 210 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); | 203 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); |
| 211 // Set extra fields in the newly allocated object. | 204 // Set extra fields in the newly allocated object. |
| 212 // eax: initial map | 205 // eax: initial map |
| 213 // ebx: JSObject | 206 // ebx: JSObject |
| 214 // edi: start of next object (including memento if create_memento) | 207 // edi: start of next object |
| 215 // esi: slack tracking counter (non-API function case) | 208 // esi: slack tracking counter (non-API function case) |
| 216 __ mov(edx, factory->undefined_value()); | 209 __ mov(edx, factory->undefined_value()); |
| 217 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); | 210 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); |
| 218 if (!is_api_function) { | 211 if (!is_api_function) { |
| 219 Label no_inobject_slack_tracking; | 212 Label no_inobject_slack_tracking; |
| 220 | 213 |
| 221 // Check if slack tracking is enabled. | 214 // Check if slack tracking is enabled. |
| 222 __ cmp(esi, Map::kSlackTrackingCounterEnd); | 215 __ cmp(esi, Map::kSlackTrackingCounterEnd); |
| 223 __ j(less, &no_inobject_slack_tracking); | 216 __ j(less, &no_inobject_slack_tracking); |
| 224 | 217 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 237 __ Assert(less_equal, | 230 __ Assert(less_equal, |
| 238 kUnexpectedNumberOfPreAllocatedPropertyFields); | 231 kUnexpectedNumberOfPreAllocatedPropertyFields); |
| 239 } | 232 } |
| 240 __ InitializeFieldsWithFiller(ecx, esi, edx); | 233 __ InitializeFieldsWithFiller(ecx, esi, edx); |
| 241 __ mov(edx, factory->one_pointer_filler_map()); | 234 __ mov(edx, factory->one_pointer_filler_map()); |
| 242 // Fill the remaining fields with one pointer filler map. | 235 // Fill the remaining fields with one pointer filler map. |
| 243 | 236 |
| 244 __ bind(&no_inobject_slack_tracking); | 237 __ bind(&no_inobject_slack_tracking); |
| 245 } | 238 } |
| 246 | 239 |
| 247 if (create_memento) { | 240 __ InitializeFieldsWithFiller(ecx, edi, edx); |
| 248 __ lea(esi, Operand(edi, -AllocationMemento::kSize)); | |
| 249 __ InitializeFieldsWithFiller(ecx, esi, edx); | |
| 250 | |
| 251 // Fill in memento fields if necessary. | |
| 252 // esi: points to the allocated but uninitialized memento. | |
| 253 __ mov(Operand(esi, AllocationMemento::kMapOffset), | |
| 254 factory->allocation_memento_map()); | |
| 255 // Get the cell or undefined. | |
| 256 __ mov(edx, Operand(esp, 3 * kPointerSize)); | |
| 257 __ AssertUndefinedOrAllocationSite(edx); | |
| 258 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), | |
| 259 edx); | |
| 260 } else { | |
| 261 __ InitializeFieldsWithFiller(ecx, edi, edx); | |
| 262 } | |
| 263 | 241 |
| 264 // Add the object tag to make the JSObject real, so that we can continue | 242 // Add the object tag to make the JSObject real, so that we can continue |
| 265 // and jump into the continuation code at any time from now on. | 243 // and jump into the continuation code at any time from now on. |
| 266 // ebx: JSObject (untagged) | 244 // ebx: JSObject (untagged) |
| 267 __ or_(ebx, Immediate(kHeapObjectTag)); | 245 __ or_(ebx, Immediate(kHeapObjectTag)); |
| 268 | 246 |
| 269 // Continue with JSObject being successfully allocated | 247 // Continue with JSObject being successfully allocated |
| 270 // ebx: JSObject (tagged) | 248 // ebx: JSObject (tagged) |
| 271 __ jmp(&allocated); | 249 __ jmp(&allocated); |
| 272 } | 250 } |
| 273 | 251 |
| 274 // Allocate the new receiver object using the runtime call. | 252 // Allocate the new receiver object using the runtime call. |
| 275 // edx: original constructor | 253 // edx: original constructor |
| 276 __ bind(&rt_call); | 254 __ bind(&rt_call); |
| 277 int offset = kPointerSize; | 255 int offset = kPointerSize; |
| 278 if (create_memento) { | |
| 279 // Get the cell or allocation site. | |
| 280 __ mov(edi, Operand(esp, kPointerSize * 3)); | |
| 281 __ push(edi); // argument 1: allocation site | |
| 282 offset += kPointerSize; | |
| 283 } | |
| 284 | 256 |
| 285 // Must restore esi (context) and edi (constructor) before calling | 257 // Must restore esi (context) and edi (constructor) before calling |
| 286 // runtime. | 258 // runtime. |
| 287 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 259 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 288 __ mov(edi, Operand(esp, offset)); | 260 __ mov(edi, Operand(esp, offset)); |
| 289 __ push(edi); // argument 2/1: constructor function | 261 __ push(edi); // argument 2/1: constructor function |
| 290 __ push(edx); // argument 3/2: original constructor | 262 __ push(edx); // argument 3/2: original constructor |
| 291 if (create_memento) { | 263 __ CallRuntime(Runtime::kNewObject, 2); |
| 292 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | |
| 293 } else { | |
| 294 __ CallRuntime(Runtime::kNewObject, 2); | |
| 295 } | |
| 296 __ mov(ebx, eax); // store result in ebx | 264 __ mov(ebx, eax); // store result in ebx |
| 297 | 265 |
| 298 // Runtime_NewObjectWithAllocationSite increments allocation count. | |
| 299 // Skip the increment. | |
| 300 Label count_incremented; | |
| 301 if (create_memento) { | |
| 302 __ jmp(&count_incremented); | |
| 303 } | |
| 304 | |
| 305 // New object allocated. | 266 // New object allocated. |
| 306 // ebx: newly allocated object | 267 // ebx: newly allocated object |
| 307 __ bind(&allocated); | 268 __ bind(&allocated); |
| 308 | 269 |
| 309 if (create_memento) { | |
| 310 __ mov(ecx, Operand(esp, 3 * kPointerSize)); | |
| 311 __ cmp(ecx, masm->isolate()->factory()->undefined_value()); | |
| 312 __ j(equal, &count_incremented); | |
| 313 // ecx is an AllocationSite. We are creating a memento from it, so we | |
| 314 // need to increment the memento create count. | |
| 315 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), | |
| 316 Immediate(Smi::FromInt(1))); | |
| 317 __ bind(&count_incremented); | |
| 318 } | |
| 319 | |
| 320 // Restore the parameters. | 270 // Restore the parameters. |
| 321 __ pop(edx); // new.target | 271 __ pop(edx); // new.target |
| 322 __ pop(edi); // Constructor function. | 272 __ pop(edi); // Constructor function. |
| 323 | 273 |
| 324 // Retrieve smi-tagged arguments count from the stack. | 274 // Retrieve smi-tagged arguments count from the stack. |
| 325 __ mov(eax, Operand(esp, 0)); | 275 __ mov(eax, Operand(esp, 0)); |
| 326 __ SmiUntag(eax); | 276 __ SmiUntag(eax); |
| 327 | 277 |
| 328 // Push new.target onto the construct frame. This is stored just below the | 278 // Push new.target onto the construct frame. This is stored just below the |
| 329 // receiver on the stack. | 279 // receiver on the stack. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 348 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
| 399 __ pop(ecx); | 349 __ pop(ecx); |
| 400 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 350 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
| 401 __ push(ecx); | 351 __ push(ecx); |
| 402 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); | 352 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); |
| 403 __ ret(0); | 353 __ ret(0); |
| 404 } | 354 } |
| 405 | 355 |
| 406 | 356 |
| 407 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 357 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 408 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 358 Generate_JSConstructStubHelper(masm, false); |
| 409 } | 359 } |
| 410 | 360 |
| 411 | 361 |
| 412 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 362 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 413 Generate_JSConstructStubHelper(masm, true, false); | 363 Generate_JSConstructStubHelper(masm, true); |
| 414 } | 364 } |
| 415 | 365 |
| 416 | 366 |
| 417 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 367 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 418 // ----------- S t a t e ------------- | 368 // ----------- S t a t e ------------- |
| 419 // -- eax: number of arguments | 369 // -- eax: number of arguments |
| 420 // -- edi: constructor function | 370 // -- edi: constructor function |
| 421 // -- ebx: allocation site or undefined | 371 // -- ebx: allocation site or undefined |
| 422 // -- edx: original constructor | 372 // -- edx: original constructor |
| 423 // ----------------------------------- | 373 // ----------------------------------- |
| (...skipping 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 | 1770 |
| 1821 __ bind(&ok); | 1771 __ bind(&ok); |
| 1822 __ ret(0); | 1772 __ ret(0); |
| 1823 } | 1773 } |
| 1824 | 1774 |
| 1825 #undef __ | 1775 #undef __ |
| 1826 } // namespace internal | 1776 } // namespace internal |
| 1827 } // namespace v8 | 1777 } // namespace v8 |
| 1828 | 1778 |
| 1829 #endif // V8_TARGET_ARCH_IA32 | 1779 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |