Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 1247783002: Make array allocation stub shared between isolates. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698