OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 314 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
315 __ popl(EAX); // Get Code object. | 315 __ popl(EAX); // Get Code object. |
316 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 316 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
317 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 317 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
318 __ LeaveFrame(); | 318 __ LeaveFrame(); |
319 __ jmp(EAX); | 319 __ jmp(EAX); |
320 __ int3(); | 320 __ int3(); |
321 } | 321 } |
322 | 322 |
323 | 323 |
324 // Called from array allocate instruction when the allocation stub has been | |
325 // disabled. | |
326 // EDX: length (preserved). | |
327 // ECX: element type (preserved). | |
328 void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) { | |
329 const Immediate& raw_null = | |
330 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
331 __ EnterStubFrame(); | |
332 __ pushl(EDX); // Preserve length. | |
333 __ pushl(ECX); // Preserve element type. | |
334 __ pushl(raw_null); // Setup space on stack for return value. | |
335 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | |
336 __ popl(EAX); // Get Code object. | |
337 __ popl(ECX); // Restore element type. | |
338 __ popl(EDX); // Restore length. | |
339 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | |
340 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
341 __ LeaveFrame(); | |
342 __ jmp(EAX); | |
343 __ int3(); | |
344 } | |
345 | |
346 | |
347 // Input parameters: | 324 // Input parameters: |
348 // EDX: smi-tagged argument count, may be zero. | 325 // EDX: smi-tagged argument count, may be zero. |
349 // EBP[kParamEndSlotFromFp + 1]: last argument. | 326 // EBP[kParamEndSlotFromFp + 1]: last argument. |
350 // Uses EAX, EBX, ECX, EDX, EDI. | 327 // Uses EAX, EBX, ECX, EDX, EDI. |
351 static void PushArgumentsArray(Assembler* assembler) { | 328 static void PushArgumentsArray(Assembler* assembler) { |
| 329 // Allocate array to store arguments of caller. |
352 const Immediate& raw_null = | 330 const Immediate& raw_null = |
353 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 331 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
354 StubCode* stub_code = Isolate::Current()->stub_code(); | |
355 | |
356 // Allocate array to store arguments of caller. | |
357 __ movl(ECX, raw_null); // Null element type for raw Array. | 332 __ movl(ECX, raw_null); // Null element type for raw Array. |
358 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); | 333 const ExternalLabel array_label(StubCode::AllocateArrayEntryPoint()); |
359 const ExternalLabel array_label(array_stub.EntryPoint()); | |
360 __ call(&array_label); | 334 __ call(&array_label); |
361 __ SmiUntag(EDX); | 335 __ SmiUntag(EDX); |
362 // EAX: newly allocated array. | 336 // EAX: newly allocated array. |
363 // EDX: length of the array (was preserved by the stub). | 337 // EDX: length of the array (was preserved by the stub). |
364 __ pushl(EAX); // Array is in EAX and on top of stack. | 338 __ pushl(EAX); // Array is in EAX and on top of stack. |
365 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 339 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
366 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 340 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
367 // EBX: address of first argument on stack. | 341 // EBX: address of first argument on stack. |
368 // ECX: address of first argument in array. | 342 // ECX: address of first argument in array. |
369 Label loop, loop_condition; | 343 Label loop, loop_condition; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 __ jmp(EBX); | 549 __ jmp(EBX); |
576 } | 550 } |
577 | 551 |
578 | 552 |
579 // Called for inline allocation of arrays. | 553 // Called for inline allocation of arrays. |
580 // Input parameters: | 554 // Input parameters: |
581 // EDX : Array length as Smi (must be preserved). | 555 // EDX : Array length as Smi (must be preserved). |
582 // ECX : array element type (either NULL or an instantiated type). | 556 // ECX : array element type (either NULL or an instantiated type). |
583 // Uses EAX, EBX, ECX, EDI as temporary registers. | 557 // Uses EAX, EBX, ECX, EDI as temporary registers. |
584 // The newly allocated object is returned in EAX. | 558 // The newly allocated object is returned in EAX. |
585 void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler, | 559 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
586 uword* entry_patch_offset, uword* patch_code_pc_offset) { | |
587 *entry_patch_offset = assembler->CodeSize(); | |
588 Label slow_case; | 560 Label slow_case; |
589 const Immediate& raw_null = | 561 const Immediate& raw_null = |
590 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 562 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
591 | |
592 Isolate* isolate = Isolate::Current(); | |
593 const Class& cls = Class::Handle(isolate->object_store()->array_class()); | |
594 ASSERT(!cls.IsNull()); | |
595 // Compute the size to be allocated, it is based on the array length | 563 // Compute the size to be allocated, it is based on the array length |
596 // and is computed as: | 564 // and is computed as: |
597 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 565 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
598 // Assert that length is a Smi. | 566 // Assert that length is a Smi. |
599 __ testl(EDX, Immediate(kSmiTagMask)); | 567 __ testl(EDX, Immediate(kSmiTagMask)); |
600 | 568 |
601 if (FLAG_use_slow_path || cls.trace_allocation()) { | 569 if (FLAG_use_slow_path) { |
602 __ jmp(&slow_case); | 570 __ jmp(&slow_case); |
603 } else { | 571 } else { |
604 __ j(NOT_ZERO, &slow_case); | 572 __ j(NOT_ZERO, &slow_case); |
605 } | 573 } |
606 __ cmpl(EDX, Immediate(0)); | 574 __ cmpl(EDX, Immediate(0)); |
607 __ j(LESS, &slow_case); | 575 __ j(LESS, &slow_case); |
608 | 576 |
609 // Check for maximum allowed length. | 577 // Check for maximum allowed length. |
610 const Immediate& max_len = | 578 const Immediate& max_len = |
611 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); | 579 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); |
612 __ cmpl(EDX, max_len); | 580 __ cmpl(EDX, max_len); |
613 __ j(GREATER, &slow_case); | 581 __ j(GREATER, &slow_case); |
614 | 582 |
| 583 __ MaybeTraceAllocation(kArrayCid, |
| 584 EAX, |
| 585 &slow_case, |
| 586 /* near_jump = */ false, |
| 587 /* inline_isolate = */ false); |
| 588 |
615 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 589 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
616 __ leal(EDI, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. | 590 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. |
617 ASSERT(kSmiTagShift == 1); | 591 ASSERT(kSmiTagShift == 1); |
618 __ andl(EDI, Immediate(-kObjectAlignment)); | 592 __ andl(EBX, Immediate(-kObjectAlignment)); |
619 | 593 |
620 // ECX: array element type. | 594 // ECX: array element type. |
621 // EDX: array length as Smi. | 595 // EDX: array length as Smi. |
622 // EDI: allocation size. | 596 // EBX: allocation size. |
623 | 597 |
624 Heap* heap = isolate->heap(); | |
625 const intptr_t cid = kArrayCid; | 598 const intptr_t cid = kArrayCid; |
626 Heap::Space space = Heap::SpaceForAllocation(cid); | 599 Heap::Space space = Heap::SpaceForAllocation(cid); |
627 __ movl(EAX, Address::Absolute(heap->TopAddress(space))); | 600 __ LoadIsolate(EDI); |
628 __ movl(EBX, EAX); | 601 __ movl(EDI, Address(EDI, Isolate::heap_offset())); |
629 | 602 __ movl(EAX, Address(EDI, Heap::TopOffset(space))); |
630 // EDI: allocation size. | 603 __ addl(EBX, EAX); |
631 __ addl(EBX, EDI); | |
632 __ j(CARRY, &slow_case); | 604 __ j(CARRY, &slow_case); |
633 | 605 |
634 // Check if the allocation fits into the remaining space. | 606 // Check if the allocation fits into the remaining space. |
635 // EAX: potential new object start. | 607 // EAX: potential new object start. |
636 // EBX: potential next object start. | 608 // EBX: potential next object start. |
637 // EDI: allocation size. | 609 // EDI: heap. |
638 // ECX: array element type. | 610 // ECX: array element type. |
639 // EDX: array length as Smi). | 611 // EDX: array length as Smi). |
640 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); | 612 __ cmpl(EBX, Address(EDI, Heap::EndOffset(space))); |
641 __ j(ABOVE_EQUAL, &slow_case); | 613 __ j(ABOVE_EQUAL, &slow_case); |
642 | 614 |
643 // Successfully allocated the object(s), now update top to point to | 615 // Successfully allocated the object(s), now update top to point to |
644 // next object start and initialize the object. | 616 // next object start and initialize the object. |
645 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); | 617 __ movl(Address(EDI, Heap::TopOffset(space)), EBX); |
| 618 __ subl(EBX, EAX); |
646 __ addl(EAX, Immediate(kHeapObjectTag)); | 619 __ addl(EAX, Immediate(kHeapObjectTag)); |
647 __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space); | 620 __ UpdateAllocationStatsWithSize(cid, EBX, EDI, space, |
| 621 /* inline_isolate = */ false); |
648 | 622 |
649 // Initialize the tags. | 623 // Initialize the tags. |
650 // EAX: new object start as a tagged pointer. | 624 // EAX: new object start as a tagged pointer. |
651 // EBX: new object end address. | 625 // EBX: allocation size. |
652 // EDI: allocation size. | |
653 // ECX: array element type. | 626 // ECX: array element type. |
654 // EDX: array length as Smi. | 627 // EDX: array length as Smi. |
655 { | 628 { |
656 Label size_tag_overflow, done; | 629 Label size_tag_overflow, done; |
| 630 __ movl(EDI, EBX); |
657 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 631 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
658 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 632 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
659 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); | 633 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); |
660 __ jmp(&done, Assembler::kNearJump); | 634 __ jmp(&done, Assembler::kNearJump); |
661 | 635 |
662 __ Bind(&size_tag_overflow); | 636 __ Bind(&size_tag_overflow); |
663 __ movl(EDI, Immediate(0)); | 637 __ movl(EDI, Immediate(0)); |
664 __ Bind(&done); | 638 __ Bind(&done); |
665 | 639 |
666 // Get the class index and insert it into the tags. | 640 // Get the class index and insert it into the tags. |
667 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); | 641 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); |
668 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. | 642 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. |
669 } | 643 } |
670 // EAX: new object start as a tagged pointer. | 644 // EAX: new object start as a tagged pointer. |
671 // EBX: new object end address. | 645 // EBX: allocation size. |
672 // ECX: array element type. | 646 // ECX: array element type. |
673 // EDX: Array length as Smi (preserved). | 647 // EDX: Array length as Smi (preserved). |
674 // Store the type argument field. | 648 // Store the type argument field. |
675 __ InitializeFieldNoBarrier(EAX, | 649 __ InitializeFieldNoBarrier(EAX, |
676 FieldAddress(EAX, Array::type_arguments_offset()), | 650 FieldAddress(EAX, Array::type_arguments_offset()), |
677 ECX); | 651 ECX); |
678 | 652 |
679 // Set the length field. | 653 // Set the length field. |
680 __ InitializeFieldNoBarrier(EAX, | 654 __ InitializeFieldNoBarrier(EAX, |
681 FieldAddress(EAX, Array::length_offset()), | 655 FieldAddress(EAX, Array::length_offset()), |
682 EDX); | 656 EDX); |
683 | 657 |
684 // Initialize all array elements to raw_null. | 658 // Initialize all array elements to raw_null. |
685 // EAX: new object start as a tagged pointer. | 659 // EAX: new object start as a tagged pointer. |
686 // EBX: new object end address. | 660 // EBX: allocation size. |
687 // EDI: iterator which initially points to the start of the variable | 661 // EDI: iterator which initially points to the start of the variable |
688 // data area to be initialized. | 662 // data area to be initialized. |
689 // ECX: array element type. | 663 // ECX: array element type. |
690 // EDX: array length as Smi. | 664 // EDX: array length as Smi. |
| 665 __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0)); |
691 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 666 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
692 Label done; | 667 Label done; |
693 Label init_loop; | 668 Label init_loop; |
694 __ Bind(&init_loop); | 669 __ Bind(&init_loop); |
695 __ cmpl(EDI, EBX); | 670 __ cmpl(EDI, EBX); |
696 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 671 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
697 // No generational barrier needed, since we are storing null. | 672 // No generational barrier needed, since we are storing null. |
698 __ InitializeFieldNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | 673 __ InitializeFieldNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
699 __ addl(EDI, Immediate(kWordSize)); | 674 __ addl(EDI, Immediate(kWordSize)); |
700 __ jmp(&init_loop, Assembler::kNearJump); | 675 __ jmp(&init_loop, Assembler::kNearJump); |
701 __ Bind(&done); | 676 __ Bind(&done); |
702 __ ret(); // returns the newly allocated object in EAX. | 677 __ ret(); // returns the newly allocated object in EAX. |
703 | 678 |
704 // Unable to allocate the array using the fast inline code, just call | 679 // Unable to allocate the array using the fast inline code, just call |
705 // into the runtime. | 680 // into the runtime. |
706 __ Bind(&slow_case); | 681 __ Bind(&slow_case); |
707 // Create a stub frame as we are pushing some objects on the stack before | 682 // Create a stub frame as we are pushing some objects on the stack before |
708 // calling into the runtime. | 683 // calling into the runtime. |
709 __ EnterStubFrame(); | 684 __ EnterStubFrame(); |
710 __ pushl(raw_null); // Setup space on stack for return value. | 685 __ pushl(raw_null); // Setup space on stack for return value. |
711 __ pushl(EDX); // Array length as Smi. | 686 __ pushl(EDX); // Array length as Smi. |
712 __ pushl(ECX); // Element type. | 687 __ pushl(ECX); // Element type. |
713 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 688 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
714 __ popl(EAX); // Pop element type argument. | 689 __ popl(EAX); // Pop element type argument. |
715 __ popl(EDX); // Pop array length argument (preserved). | 690 __ popl(EDX); // Pop array length argument (preserved). |
716 __ popl(EAX); // Pop return value from return slot. | 691 __ popl(EAX); // Pop return value from return slot. |
717 __ LeaveFrame(); | 692 __ LeaveFrame(); |
718 __ ret(); | 693 __ ret(); |
719 // Emit function patching code. This will be swapped with the first 5 bytes | |
720 // at entry point. | |
721 *patch_code_pc_offset = assembler->CodeSize(); | |
722 StubCode* stub_code = Isolate::Current()->stub_code(); | |
723 __ jmp(&stub_code->FixAllocateArrayStubTargetLabel()); | |
724 } | 694 } |
725 | 695 |
726 | 696 |
727 // Called when invoking dart code from C++ (VM code). | 697 // Called when invoking dart code from C++ (VM code). |
728 // Input parameters: | 698 // Input parameters: |
729 // ESP : points to return address. | 699 // ESP : points to return address. |
730 // ESP + 4 : entrypoint of the dart function to call. | 700 // ESP + 4 : entrypoint of the dart function to call. |
731 // ESP + 8 : arguments descriptor array. | 701 // ESP + 8 : arguments descriptor array. |
732 // ESP + 12 : arguments array. | 702 // ESP + 12 : arguments array. |
733 // ESP + 16 : current thread. | 703 // ESP + 16 : current thread. |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 __ popl(EAX); // Pop argument (type arguments of object). | 1127 __ popl(EAX); // Pop argument (type arguments of object). |
1158 __ popl(EAX); // Pop argument (class of object). | 1128 __ popl(EAX); // Pop argument (class of object). |
1159 __ popl(EAX); // Pop result (newly allocated object). | 1129 __ popl(EAX); // Pop result (newly allocated object). |
1160 // EAX: new object | 1130 // EAX: new object |
1161 // Restore the frame pointer. | 1131 // Restore the frame pointer. |
1162 __ LeaveFrame(); | 1132 __ LeaveFrame(); |
1163 __ ret(); | 1133 __ ret(); |
1164 // Emit function patching code. This will be swapped with the first 5 bytes | 1134 // Emit function patching code. This will be swapped with the first 5 bytes |
1165 // at entry point. | 1135 // at entry point. |
1166 *patch_code_pc_offset = assembler->CodeSize(); | 1136 *patch_code_pc_offset = assembler->CodeSize(); |
1167 StubCode* stub_code = Isolate::Current()->stub_code(); | 1137 __ jmp(&StubCode::FixAllocationStubTargetLabel()); |
1168 __ jmp(&stub_code->FixAllocationStubTargetLabel()); | |
1169 } | 1138 } |
1170 | 1139 |
1171 | 1140 |
1172 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1141 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1173 // from the entry code of a dart function after an error in passed argument | 1142 // from the entry code of a dart function after an error in passed argument |
1174 // name or number is detected. | 1143 // name or number is detected. |
1175 // Input parameters: | 1144 // Input parameters: |
1176 // ESP : points to return address. | 1145 // ESP : points to return address. |
1177 // ESP + 4 : address of last argument. | 1146 // ESP + 4 : address of last argument. |
1178 // EDX : arguments descriptor array. | 1147 // EDX : arguments descriptor array. |
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2127 // EBX: entry point. | 2096 // EBX: entry point. |
2128 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2097 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2129 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); | 2098 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); |
2130 __ ret(); | 2099 __ ret(); |
2131 } | 2100 } |
2132 | 2101 |
2133 | 2102 |
2134 } // namespace dart | 2103 } // namespace dart |
2135 | 2104 |
2136 #endif // defined TARGET_ARCH_IA32 | 2105 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |