OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 // Store a smi-tagged arguments count on the stack. | 496 // Store a smi-tagged arguments count on the stack. |
497 __ shl(rax, Immediate(kSmiTagSize)); | 497 __ shl(rax, Immediate(kSmiTagSize)); |
498 __ push(rax); | 498 __ push(rax); |
499 | 499 |
500 // Push the function to invoke on the stack. | 500 // Push the function to invoke on the stack. |
501 __ push(rdi); | 501 __ push(rdi); |
502 | 502 |
503 // Try to allocate the object without transitioning into C code. If any of the | 503 // Try to allocate the object without transitioning into C code. If any of the |
504 // preconditions is not met, the code bails out to the runtime call. | 504 // preconditions is not met, the code bails out to the runtime call. |
505 Label rt_call, allocated; | 505 Label rt_call, allocated; |
| 506 if (FLAG_inline_new) { |
| 507 Label undo_allocation; |
| 508 // TODO(X64): Enable debugger support, using debug_step_in_fp. |
506 | 509 |
507 // TODO(x64): Implement inlined allocation. | 510 // Verified that the constructor is a JSFunction. |
| 511 // Load the initial map and verify that it is in fact a map. |
| 512 // rdi: constructor |
| 513 __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
| 514 // Will both indicate a NULL and a Smi |
| 515 __ testl(rax, Immediate(kSmiTagMask)); |
| 516 __ j(zero, &rt_call); |
| 517 // rdi: constructor |
| 518 // rax: initial map (if proven valid below) |
| 519 __ CmpObjectType(rax, MAP_TYPE, rbx); |
| 520 __ j(not_equal, &rt_call); |
| 521 |
| 522 // Check that the constructor is not constructing a JSFunction (see comments |
| 523 // in Runtime_NewObject in runtime.cc). In which case the initial map's |
| 524 // instance type would be JS_FUNCTION_TYPE. |
| 525 // rdi: constructor |
| 526 // rax: initial map |
| 527 __ CmpInstanceType(rax, JS_FUNCTION_TYPE); |
| 528 __ j(equal, &rt_call); |
| 529 |
| 530 // Now allocate the JSObject on the heap. |
| 531 __ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); |
| 532 __ shl(rdi, Immediate(kPointerSizeLog2)); |
| 533 // rdi: size of new object |
| 534 // Make sure that the maximum heap object size will never cause us |
| 535 // problem here, because it is always greater than the maximum |
| 536 // instance size that can be represented in a byte. |
| 537 ASSERT(Heap::MaxObjectSizeInPagedSpace() >= (1 << kBitsPerByte)); |
| 538 ExternalReference new_space_allocation_top = |
| 539 ExternalReference::new_space_allocation_top_address(); |
| 540 __ movq(kScratchRegister, new_space_allocation_top); |
| 541 __ movq(rbx, Operand(kScratchRegister, 0)); |
| 542 __ addq(rdi, rbx); // Calculate new top |
| 543 ExternalReference new_space_allocation_limit = |
| 544 ExternalReference::new_space_allocation_limit_address(); |
| 545 __ movq(kScratchRegister, new_space_allocation_limit); |
| 546 __ cmpq(rdi, Operand(kScratchRegister, 0)); |
| 547 __ j(above_equal, &rt_call); |
| 548 // Allocated the JSObject, now initialize the fields. |
| 549 // rax: initial map |
| 550 // rbx: JSObject (not HeapObject tagged - the actual address). |
| 551 // rdi: start of next object |
| 552 __ movq(Operand(rbx, JSObject::kMapOffset), rax); |
| 553 __ Move(rcx, Factory::empty_fixed_array()); |
| 554 __ movq(Operand(rbx, JSObject::kPropertiesOffset), rcx); |
| 555 __ movq(Operand(rbx, JSObject::kElementsOffset), rcx); |
| 556 // Set extra fields in the newly allocated object. |
| 557 // rax: initial map |
| 558 // rbx: JSObject |
| 559 // rdi: start of next object |
| 560 { Label loop, entry; |
| 561 __ Move(rdx, Factory::undefined_value()); |
| 562 __ lea(rcx, Operand(rbx, JSObject::kHeaderSize)); |
| 563 __ jmp(&entry); |
| 564 __ bind(&loop); |
| 565 __ movq(Operand(rcx, 0), rdx); |
| 566 __ addq(rcx, Immediate(kPointerSize)); |
| 567 __ bind(&entry); |
| 568 __ cmpq(rcx, rdi); |
| 569 __ j(less, &loop); |
| 570 } |
| 571 |
| 572 // Mostly done with the JSObject. Add the heap tag and store the new top, so |
| 573 // that we can continue and jump into the continuation code at any time from |
| 574 // now on. Any failures need to undo the setting of the new top, so that the |
| 575 // heap is in a consistent state and verifiable. |
| 576 // rax: initial map |
| 577 // rbx: JSObject |
| 578 // rdi: start of next object |
| 579 __ or_(rbx, Immediate(kHeapObjectTag)); |
| 580 __ movq(kScratchRegister, new_space_allocation_top); |
| 581 __ movq(Operand(kScratchRegister, 0), rdi); |
| 582 |
| 583 // Check if a non-empty properties array is needed. |
| 584 // Allocate and initialize a FixedArray if it is. |
| 585 // rax: initial map |
| 586 // rbx: JSObject |
| 587 // rdi: start of next object |
| 588 __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); |
| 589 __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset)); |
| 590 // Calculate unused properties past the end of the in-object properties. |
| 591 __ subq(rdx, rcx); |
| 592 // Done if no extra properties are to be allocated. |
| 593 __ j(zero, &allocated); |
| 594 |
| 595 // Scale the number of elements by pointer size and add the header for |
| 596 // FixedArrays to the start of the next object calculation from above. |
| 597 // rbx: JSObject |
| 598 // rdi: start of next object (will be start of FixedArray) |
| 599 // rdx: number of elements in properties array |
| 600 ASSERT(Heap::MaxObjectSizeInPagedSpace() > |
| 601 (FixedArray::kHeaderSize + 255*kPointerSize)); |
| 602 __ lea(rax, Operand(rdi, rdx, times_pointer_size, FixedArray::kHeaderSize)); |
| 603 __ movq(kScratchRegister, new_space_allocation_limit); |
| 604 __ cmpq(rax, Operand(kScratchRegister, 0)); |
| 605 __ j(above_equal, &undo_allocation); |
| 606 __ store_rax(new_space_allocation_top); |
| 607 |
| 608 // Initialize the FixedArray. |
| 609 // rbx: JSObject |
| 610 // rdi: FixedArray |
| 611 // rdx: number of elements |
| 612 // rax: start of next object |
| 613 __ Move(rcx, Factory::fixed_array_map()); |
| 614 __ movq(Operand(rdi, JSObject::kMapOffset), rcx); // setup the map |
| 615 __ movl(Operand(rdi, FixedArray::kLengthOffset), rdx); // and length |
| 616 |
| 617 // Initialize the fields to undefined. |
| 618 // rbx: JSObject |
| 619 // rdi: FixedArray |
| 620 // rax: start of next object |
| 621 // rdx: number of elements |
| 622 { Label loop, entry; |
| 623 __ Move(rdx, Factory::undefined_value()); |
| 624 __ lea(rcx, Operand(rdi, FixedArray::kHeaderSize)); |
| 625 __ jmp(&entry); |
| 626 __ bind(&loop); |
| 627 __ movq(Operand(rcx, 0), rdx); |
| 628 __ addq(rcx, Immediate(kPointerSize)); |
| 629 __ bind(&entry); |
| 630 __ cmpq(rcx, rax); |
| 631 __ j(below, &loop); |
| 632 } |
| 633 |
| 634 // Store the initialized FixedArray into the properties field of |
| 635 // the JSObject |
| 636 // rbx: JSObject |
| 637 // rdi: FixedArray |
| 638 __ or_(rdi, Immediate(kHeapObjectTag)); // add the heap tag |
| 639 __ movq(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi); |
| 640 |
| 641 |
| 642 // Continue with JSObject being successfully allocated |
| 643 // rbx: JSObject |
| 644 __ jmp(&allocated); |
| 645 |
| 646 // Undo the setting of the new top so that the heap is verifiable. For |
| 647 // example, the map's unused properties potentially do not match the |
| 648 // allocated objects unused properties. |
| 649 // rbx: JSObject (previous new top) |
| 650 __ bind(&undo_allocation); |
| 651 __ xor_(rbx, Immediate(kHeapObjectTag)); // clear the heap tag |
| 652 __ movq(kScratchRegister, new_space_allocation_top); |
| 653 __ movq(Operand(kScratchRegister, 0), rbx); |
| 654 } |
508 | 655 |
509 // Allocate the new receiver object using the runtime call. | 656 // Allocate the new receiver object using the runtime call. |
510 // rdi: function (constructor) | 657 // rdi: function (constructor) |
511 __ bind(&rt_call); | 658 __ bind(&rt_call); |
512 // Must restore edi (constructor) before calling runtime. | 659 // Must restore rdi (constructor) before calling runtime. |
513 __ movq(rdi, Operand(rsp, 0)); | 660 __ movq(rdi, Operand(rsp, 0)); |
514 __ push(rdi); | 661 __ push(rdi); |
515 __ CallRuntime(Runtime::kNewObject, 1); | 662 __ CallRuntime(Runtime::kNewObject, 1); |
516 __ movq(rbx, rax); // store result in rbx | 663 __ movq(rbx, rax); // store result in rbx |
517 | 664 |
518 // New object allocated. | 665 // New object allocated. |
519 // rbx: newly allocated object | 666 // rbx: newly allocated object |
520 __ bind(&allocated); | 667 __ bind(&allocated); |
521 // Retrieve the function from the stack. | 668 // Retrieve the function from the stack. |
522 __ pop(rdi); | 669 __ pop(rdi); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 845 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
699 Generate_JSEntryTrampolineHelper(masm, false); | 846 Generate_JSEntryTrampolineHelper(masm, false); |
700 } | 847 } |
701 | 848 |
702 | 849 |
703 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 850 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
704 Generate_JSEntryTrampolineHelper(masm, true); | 851 Generate_JSEntryTrampolineHelper(masm, true); |
705 } | 852 } |
706 | 853 |
707 } } // namespace v8::internal | 854 } } // namespace v8::internal |
OLD | NEW |