OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 __ B(hs, &ok); | 295 __ B(hs, &ok); |
296 | 296 |
297 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 297 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
298 GenerateTailCallToReturnedCode(masm); | 298 GenerateTailCallToReturnedCode(masm); |
299 | 299 |
300 __ Bind(&ok); | 300 __ Bind(&ok); |
301 GenerateTailCallToSharedCode(masm); | 301 GenerateTailCallToSharedCode(masm); |
302 } | 302 } |
303 | 303 |
304 | 304 |
305 static void Generate_Runtime_NewObject(MacroAssembler* masm, | |
306 bool create_memento, | |
307 Register original_constructor, | |
308 Label* count_incremented, | |
309 Label* allocated) { | |
310 if (create_memento) { | |
311 // Get the cell or allocation site. | |
312 __ Peek(x4, 3 * kXRegSize); | |
313 __ Push(x4); | |
314 __ Push(x1); // Argument for Runtime_NewObject. | |
315 __ Push(original_constructor); | |
316 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | |
317 __ Mov(x4, x0); | |
318 // If we ended up using the runtime, and we want a memento, then the | |
319 // runtime call made it for us, and we shouldn't do create count | |
320 // increment. | |
321 __ jmp(count_incremented); | |
322 } else { | |
323 __ Push(x1); // Argument for Runtime_NewObject. | |
324 __ Push(original_constructor); | |
325 __ CallRuntime(Runtime::kNewObject, 2); | |
326 __ Mov(x4, x0); | |
327 __ jmp(allocated); | |
328 } | |
329 } | |
330 | |
331 | |
332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 305 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
333 bool is_api_function, | 306 bool is_api_function, |
334 bool create_memento) { | 307 bool create_memento) { |
335 // ----------- S t a t e ------------- | 308 // ----------- S t a t e ------------- |
336 // -- x0 : number of arguments | 309 // -- x0 : number of arguments |
337 // -- x1 : constructor function | 310 // -- x1 : constructor function |
338 // -- x2 : allocation site or undefined | 311 // -- x2 : allocation site or undefined |
339 // -- x3 : original constructor | 312 // -- x3 : original constructor |
340 // -- lr : return address | 313 // -- lr : return address |
341 // -- sp[...]: constructor arguments | 314 // -- sp[...]: constructor arguments |
(...skipping 19 matching lines...) Expand all Loading... |
361 Register constructor = x1; | 334 Register constructor = x1; |
362 Register original_constructor = x3; | 335 Register original_constructor = x3; |
363 | 336 |
364 // Preserve the incoming parameters on the stack. | 337 // Preserve the incoming parameters on the stack. |
365 __ SmiTag(argc); | 338 __ SmiTag(argc); |
366 __ Push(argc, constructor, original_constructor); | 339 __ Push(argc, constructor, original_constructor); |
367 // sp[0]: new.target | 340 // sp[0]: new.target |
368 // sp[1]: Constructor function. | 341 // sp[1]: Constructor function. |
369 // sp[2]: number of arguments (smi-tagged) | 342 // sp[2]: number of arguments (smi-tagged) |
370 | 343 |
371 Label rt_call, count_incremented, allocated, normal_new; | |
372 __ Cmp(constructor, original_constructor); | |
373 __ B(eq, &normal_new); | |
374 Generate_Runtime_NewObject(masm, create_memento, original_constructor, | |
375 &count_incremented, &allocated); | |
376 | |
377 __ Bind(&normal_new); | |
378 | |
379 // Try to allocate the object without transitioning into C code. If any of | 344 // Try to allocate the object without transitioning into C code. If any of |
380 // the preconditions is not met, the code bails out to the runtime call. | 345 // the preconditions is not met, the code bails out to the runtime call. |
| 346 Label rt_call, allocated; |
381 if (FLAG_inline_new) { | 347 if (FLAG_inline_new) { |
382 ExternalReference debug_step_in_fp = | 348 ExternalReference debug_step_in_fp = |
383 ExternalReference::debug_step_in_fp_address(isolate); | 349 ExternalReference::debug_step_in_fp_address(isolate); |
384 __ Mov(x2, Operand(debug_step_in_fp)); | 350 __ Mov(x2, Operand(debug_step_in_fp)); |
385 __ Ldr(x2, MemOperand(x2)); | 351 __ Ldr(x2, MemOperand(x2)); |
386 __ Cbnz(x2, &rt_call); | 352 __ Cbnz(x2, &rt_call); |
| 353 |
| 354 // Fall back to runtime if the original constructor and function differ. |
| 355 __ Cmp(constructor, original_constructor); |
| 356 __ B(ne, &rt_call); |
| 357 |
387 // Load the initial map and verify that it is in fact a map. | 358 // Load the initial map and verify that it is in fact a map. |
388 Register init_map = x2; | 359 Register init_map = x2; |
389 __ Ldr(init_map, | 360 __ Ldr(init_map, |
390 FieldMemOperand(constructor, | 361 FieldMemOperand(constructor, |
391 JSFunction::kPrototypeOrInitialMapOffset)); | 362 JSFunction::kPrototypeOrInitialMapOffset)); |
392 __ JumpIfSmi(init_map, &rt_call); | 363 __ JumpIfSmi(init_map, &rt_call); |
393 __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call); | 364 __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call); |
394 | 365 |
395 // Check that the constructor is not constructing a JSFunction (see | 366 // Check that the constructor is not constructing a JSFunction (see |
396 // comments in Runtime_NewObject in runtime.cc). In which case the initial | 367 // comments in Runtime_NewObject in runtime.cc). In which case the initial |
(...skipping 20 matching lines...) Expand all Loading... |
417 // Push the constructor and map to the stack, and the constructor again | 388 // Push the constructor and map to the stack, and the constructor again |
418 // as argument to the runtime call. | 389 // as argument to the runtime call. |
419 __ Push(constructor, init_map, constructor); | 390 __ Push(constructor, init_map, constructor); |
420 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 391 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
421 __ Pop(init_map, constructor); | 392 __ Pop(init_map, constructor); |
422 __ Mov(constructon_count, Operand(Map::kSlackTrackingCounterEnd - 1)); | 393 __ Mov(constructon_count, Operand(Map::kSlackTrackingCounterEnd - 1)); |
423 __ Bind(&allocate); | 394 __ Bind(&allocate); |
424 } | 395 } |
425 | 396 |
426 // Now allocate the JSObject on the heap. | 397 // Now allocate the JSObject on the heap. |
| 398 Label rt_call_reload_new_target; |
427 Register obj_size = x3; | 399 Register obj_size = x3; |
428 Register new_obj = x4; | 400 Register new_obj = x4; |
429 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); | 401 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); |
430 if (create_memento) { | 402 if (create_memento) { |
431 __ Add(x7, obj_size, | 403 __ Add(x7, obj_size, |
432 Operand(AllocationMemento::kSize / kPointerSize)); | 404 Operand(AllocationMemento::kSize / kPointerSize)); |
433 __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); | 405 __ Allocate(x7, new_obj, x10, x11, &rt_call_reload_new_target, |
| 406 SIZE_IN_WORDS); |
434 } else { | 407 } else { |
435 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); | 408 __ Allocate(obj_size, new_obj, x10, x11, &rt_call_reload_new_target, |
| 409 SIZE_IN_WORDS); |
436 } | 410 } |
437 | 411 |
438 // Allocated the JSObject, now initialize the fields. Map is set to | 412 // Allocated the JSObject, now initialize the fields. Map is set to |
439 // initial map and properties and elements are set to empty fixed array. | 413 // initial map and properties and elements are set to empty fixed array. |
440 // NB. the object pointer is not tagged, so MemOperand is used. | 414 // NB. the object pointer is not tagged, so MemOperand is used. |
441 Register empty = x5; | 415 Register empty = x5; |
442 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); | 416 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); |
443 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); | 417 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); |
444 STATIC_ASSERT(JSObject::kElementsOffset == | 418 STATIC_ASSERT(JSObject::kElementsOffset == |
445 (JSObject::kPropertiesOffset + kPointerSize)); | 419 (JSObject::kPropertiesOffset + kPointerSize)); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 first_prop = NoReg; | 493 first_prop = NoReg; |
520 prop_fields = NoReg; | 494 prop_fields = NoReg; |
521 } | 495 } |
522 | 496 |
523 // Add the object tag to make the JSObject real, so that we can continue | 497 // Add the object tag to make the JSObject real, so that we can continue |
524 // and jump into the continuation code at any time from now on. | 498 // and jump into the continuation code at any time from now on. |
525 __ Add(new_obj, new_obj, kHeapObjectTag); | 499 __ Add(new_obj, new_obj, kHeapObjectTag); |
526 | 500 |
527 // Continue with JSObject being successfully allocated. | 501 // Continue with JSObject being successfully allocated. |
528 __ B(&allocated); | 502 __ B(&allocated); |
| 503 |
| 504 // Reload the original constructor and fall-through. |
| 505 __ Bind(&rt_call_reload_new_target); |
| 506 __ Peek(x3, 0 * kXRegSize); |
529 } | 507 } |
530 | 508 |
531 // Allocate the new receiver object using the runtime call. | 509 // Allocate the new receiver object using the runtime call. |
| 510 // x1: constructor function |
| 511 // x3: original constructor |
532 __ Bind(&rt_call); | 512 __ Bind(&rt_call); |
533 Generate_Runtime_NewObject(masm, create_memento, constructor, | 513 Label count_incremented; |
534 &count_incremented, &allocated); | 514 if (create_memento) { |
| 515 // Get the cell or allocation site. |
| 516 __ Peek(x4, 3 * kXRegSize); |
| 517 __ Push(x4, constructor, original_constructor); // arguments 1-3 |
| 518 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); |
| 519 __ Mov(x4, x0); |
| 520 // If we ended up using the runtime, and we want a memento, then the |
| 521 // runtime call made it for us, and we shouldn't do create count |
| 522 // increment. |
| 523 __ B(&count_incremented); |
| 524 } else { |
| 525 __ Push(constructor, original_constructor); // arguments 1-2 |
| 526 __ CallRuntime(Runtime::kNewObject, 2); |
| 527 __ Mov(x4, x0); |
| 528 } |
535 | 529 |
536 // Receiver for constructor call allocated. | 530 // Receiver for constructor call allocated. |
537 // x4: JSObject | 531 // x4: JSObject |
538 __ Bind(&allocated); | 532 __ Bind(&allocated); |
539 | 533 |
540 if (create_memento) { | 534 if (create_memento) { |
541 __ Peek(x10, 3 * kXRegSize); | 535 __ Peek(x10, 3 * kXRegSize); |
542 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); | 536 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
543 // r2 is an AllocationSite. We are creating a memento from it, so we | 537 // r2 is an AllocationSite. We are creating a memento from it, so we |
544 // need to increment the memento create count. | 538 // need to increment the memento create count. |
(...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1795 } | 1789 } |
1796 } | 1790 } |
1797 | 1791 |
1798 | 1792 |
1799 #undef __ | 1793 #undef __ |
1800 | 1794 |
1801 } // namespace internal | 1795 } // namespace internal |
1802 } // namespace v8 | 1796 } // namespace v8 |
1803 | 1797 |
1804 #endif // V8_TARGET_ARCH_ARM | 1798 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |