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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 379 |
380 // Jump to the dart function. | 380 // Jump to the dart function. |
381 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); | 381 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); |
382 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); | 382 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); |
383 | 383 |
384 // Remove the stub frame. | 384 // Remove the stub frame. |
385 __ LeaveStubFrameAndReturn(T0); | 385 __ LeaveStubFrameAndReturn(T0); |
386 } | 386 } |
387 | 387 |
388 | 388 |
389 // Called from array allocate instruction when the allocation stub has been | |
390 // disabled. | |
391 // A0: element type (preserved). | |
392 // A1: length (preserved). | |
393 void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) { | |
394 __ Comment("FixAllocationStubTarget"); | |
395 __ EnterStubFrame(); | |
396 // Setup space on stack for return value. | |
397 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | |
398 __ sw(A0, Address(SP, 2 * kWordSize)); | |
399 __ sw(A1, Address(SP, 1 * kWordSize)); | |
400 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); | |
401 __ sw(TMP, Address(SP, 0 * kWordSize)); | |
402 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | |
403 // Get Code object result. | |
404 __ lw(T0, Address(SP, 0 * kWordSize)); | |
405 __ lw(A1, Address(SP, 1 * kWordSize)); | |
406 __ lw(A0, Address(SP, 2 * kWordSize)); | |
407 __ addiu(SP, SP, Immediate(3 * kWordSize)); | |
408 | |
409 // Jump to the dart function. | |
410 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); | |
411 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); | |
412 | |
413 // Remove the stub frame. | |
414 __ LeaveStubFrameAndReturn(T0); | |
415 } | |
416 | |
417 | |
418 // Input parameters: | 389 // Input parameters: |
419 // A1: Smi-tagged argument count, may be zero. | 390 // A1: Smi-tagged argument count, may be zero. |
420 // FP[kParamEndSlotFromFp + 1]: Last argument. | 391 // FP[kParamEndSlotFromFp + 1]: Last argument. |
421 static void PushArgumentsArray(Assembler* assembler) { | 392 static void PushArgumentsArray(Assembler* assembler) { |
422 StubCode* stub_code = Isolate::Current()->stub_code(); | |
423 __ Comment("PushArgumentsArray"); | 393 __ Comment("PushArgumentsArray"); |
424 // Allocate array to store arguments of caller. | 394 // Allocate array to store arguments of caller. |
425 __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null())); | 395 __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null())); |
426 // A0: Null element type for raw Array. | 396 // A0: Null element type for raw Array. |
427 // A1: Smi-tagged argument count, may be zero. | 397 // A1: Smi-tagged argument count, may be zero. |
428 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); | 398 const ExternalLabel array_label(StubCode::AllocateArrayEntryPoint()); |
429 const ExternalLabel array_label(array_stub.EntryPoint()); | |
430 __ BranchLink(&array_label); | 399 __ BranchLink(&array_label); |
431 __ Comment("PushArgumentsArray return"); | 400 __ Comment("PushArgumentsArray return"); |
432 // V0: newly allocated array. | 401 // V0: newly allocated array. |
433 // A1: Smi-tagged argument count, may be zero (was preserved by the stub). | 402 // A1: Smi-tagged argument count, may be zero (was preserved by the stub). |
434 __ Push(V0); // Array is in V0 and on top of stack. | 403 __ Push(V0); // Array is in V0 and on top of stack. |
435 __ sll(T1, A1, 1); | 404 __ sll(T1, A1, 1); |
436 __ addu(T1, FP, T1); | 405 __ addu(T1, FP, T1); |
437 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize); | 406 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize); |
438 // T1: address of first argument on stack. | 407 // T1: address of first argument on stack. |
439 // T2: address of first argument in array. | 408 // T2: address of first argument in array. |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 } | 650 } |
682 | 651 |
683 | 652 |
684 // Called for inline allocation of arrays. | 653 // Called for inline allocation of arrays. |
685 // Input parameters: | 654 // Input parameters: |
686 // RA: return address. | 655 // RA: return address. |
687 // A1: Array length as Smi (must be preserved). | 656 // A1: Array length as Smi (must be preserved). |
688 // A0: array element type (either NULL or an instantiated type). | 657 // A0: array element type (either NULL or an instantiated type). |
689 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. | 658 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. |
690 // The newly allocated object is returned in V0. | 659 // The newly allocated object is returned in V0. |
691 void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler, | 660 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
692 uword* entry_patch_offset, uword* patch_code_pc_offset) { | |
693 __ Comment("AllocateArrayStub"); | 661 __ Comment("AllocateArrayStub"); |
694 *entry_patch_offset = assembler->CodeSize(); | |
695 Label slow_case; | 662 Label slow_case; |
696 Isolate* isolate = Isolate::Current(); | |
697 const Class& cls = Class::Handle(isolate->object_store()->array_class()); | |
698 ASSERT(!cls.IsNull()); | |
699 | |
700 // Compute the size to be allocated, it is based on the array length | 663 // Compute the size to be allocated, it is based on the array length |
701 // and is computed as: | 664 // and is computed as: |
702 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 665 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
703 __ mov(T3, A1); // Array length. | 666 __ mov(T3, A1); // Array length. |
704 | 667 |
705 // Check that length is a positive Smi. | 668 // Check that length is a positive Smi. |
706 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | 669 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
707 if (FLAG_use_slow_path || cls.trace_allocation()) { | 670 if (FLAG_use_slow_path) { |
708 __ b(&slow_case); | 671 __ b(&slow_case); |
709 } else { | 672 } else { |
710 __ bne(CMPRES1, ZR, &slow_case); | 673 __ bne(CMPRES1, ZR, &slow_case); |
711 } | 674 } |
712 __ bltz(T3, &slow_case); | 675 __ bltz(T3, &slow_case); |
713 | 676 |
714 // Check for maximum allowed length. | 677 // Check for maximum allowed length. |
715 const intptr_t max_len = | 678 const intptr_t max_len = |
716 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | 679 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |
717 __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case); | 680 __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case); |
718 | 681 |
| 682 const intptr_t cid = kArrayCid; |
| 683 __ MaybeTraceAllocation(kArrayCid, T4, &slow_case, |
| 684 /* inline_isolate = */ false); |
| 685 |
719 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 686 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
720 __ LoadImmediate(T2, fixed_size); | 687 __ LoadImmediate(T2, fixed_size); |
721 __ sll(T3, T3, 1); // T3 is a Smi. | 688 __ sll(T3, T3, 1); // T3 is a Smi. |
722 __ addu(T2, T2, T3); | 689 __ addu(T2, T2, T3); |
723 ASSERT(kSmiTagShift == 1); | 690 ASSERT(kSmiTagShift == 1); |
724 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); | 691 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); |
725 __ and_(T2, T2, T3); | 692 __ and_(T2, T2, T3); |
726 | 693 |
727 // T2: Allocation size. | 694 // T2: Allocation size. |
728 | 695 |
729 Heap* heap = isolate->heap(); | |
730 const intptr_t cid = kArrayCid; | |
731 Heap::Space space = Heap::SpaceForAllocation(cid); | 696 Heap::Space space = Heap::SpaceForAllocation(cid); |
732 __ LoadImmediate(T3, heap->TopAddress(space)); | 697 __ LoadIsolate(T3); |
733 __ lw(T0, Address(T3, 0)); // Potential new object start. | 698 __ lw(T3, Address(T3, Isolate::heap_offset())); |
| 699 // Potential new object start. |
| 700 __ lw(T0, Address(T3, Heap::TopOffset(space))); |
734 | 701 |
735 __ addu(T1, T0, T2); // Potential next object start. | 702 __ addu(T1, T0, T2); // Potential next object start. |
736 __ BranchUnsignedLess(T1, T0, &slow_case); // Branch on unsigned overflow. | 703 __ BranchUnsignedLess(T1, T0, &slow_case); // Branch on unsigned overflow. |
737 | 704 |
738 // Check if the allocation fits into the remaining space. | 705 // Check if the allocation fits into the remaining space. |
739 // T0: potential new object start. | 706 // T0: potential new object start. |
740 // T1: potential next object start. | 707 // T1: potential next object start. |
741 // T2: allocation size. | 708 // T2: allocation size. |
742 __ LoadImmediate(T4, heap->EndAddress(space)); | 709 // T3: heap. |
743 __ lw(T4, Address(T4, 0)); | 710 __ lw(T4, Address(T3, Heap::EndOffset(space))); |
744 __ BranchUnsignedGreaterEqual(T1, T4, &slow_case); | 711 __ BranchUnsignedGreaterEqual(T1, T4, &slow_case); |
745 | 712 |
746 // Successfully allocated the object(s), now update top to point to | 713 // Successfully allocated the object(s), now update top to point to |
747 // next object start and initialize the object. | 714 // next object start and initialize the object. |
748 __ sw(T1, Address(T3, 0)); | 715 // T3: heap. |
| 716 __ sw(T1, Address(T3, Heap::TopOffset(space))); |
749 __ addiu(T0, T0, Immediate(kHeapObjectTag)); | 717 __ addiu(T0, T0, Immediate(kHeapObjectTag)); |
750 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); | 718 __ UpdateAllocationStatsWithSize(cid, T2, T4, space, |
| 719 /* inline_isolate = */ false); |
751 | 720 |
752 // Initialize the tags. | 721 // Initialize the tags. |
753 // T0: new object start as a tagged pointer. | 722 // T0: new object start as a tagged pointer. |
754 // T1: new object end address. | 723 // T1: new object end address. |
755 // T2: allocation size. | 724 // T2: allocation size. |
756 { | 725 { |
757 Label overflow, done; | 726 Label overflow, done; |
758 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 727 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
759 | 728 |
760 __ BranchUnsignedGreater( | 729 __ BranchUnsignedGreater( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 __ sw(A0, Address(SP, 0 * kWordSize)); | 789 __ sw(A0, Address(SP, 0 * kWordSize)); |
821 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 790 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
822 __ Comment("AllocateArrayStub return"); | 791 __ Comment("AllocateArrayStub return"); |
823 // Pop arguments; result is popped in IP. | 792 // Pop arguments; result is popped in IP. |
824 __ lw(V0, Address(SP, 2 * kWordSize)); | 793 __ lw(V0, Address(SP, 2 * kWordSize)); |
825 __ lw(A1, Address(SP, 1 * kWordSize)); | 794 __ lw(A1, Address(SP, 1 * kWordSize)); |
826 __ lw(A0, Address(SP, 0 * kWordSize)); | 795 __ lw(A0, Address(SP, 0 * kWordSize)); |
827 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 796 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
828 | 797 |
829 __ LeaveStubFrameAndReturn(); | 798 __ LeaveStubFrameAndReturn(); |
830 *patch_code_pc_offset = assembler->CodeSize(); | |
831 StubCode* stub_code = Isolate::Current()->stub_code(); | |
832 __ BranchPatchable(&stub_code->FixAllocateArrayStubTargetLabel()); | |
833 } | 799 } |
834 | 800 |
835 | 801 |
836 // Called when invoking Dart code from C++ (VM code). | 802 // Called when invoking Dart code from C++ (VM code). |
837 // Input parameters: | 803 // Input parameters: |
838 // RA : points to return address. | 804 // RA : points to return address. |
839 // A0 : entrypoint of the Dart function to call. | 805 // A0 : entrypoint of the Dart function to call. |
840 // A1 : arguments descriptor array. | 806 // A1 : arguments descriptor array. |
841 // A2 : arguments array. | 807 // A2 : arguments array. |
842 // A3 : current thread. | 808 // A3 : current thread. |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 } | 1254 } |
1289 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1255 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
1290 __ Comment("AllocationStubForClass return"); | 1256 __ Comment("AllocationStubForClass return"); |
1291 // Pop result (newly allocated object). | 1257 // Pop result (newly allocated object). |
1292 __ lw(V0, Address(SP, 2 * kWordSize)); | 1258 __ lw(V0, Address(SP, 2 * kWordSize)); |
1293 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Pop arguments. | 1259 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Pop arguments. |
1294 // V0: new object | 1260 // V0: new object |
1295 // Restore the frame pointer and return. | 1261 // Restore the frame pointer and return. |
1296 __ LeaveStubFrameAndReturn(RA); | 1262 __ LeaveStubFrameAndReturn(RA); |
1297 *patch_code_pc_offset = assembler->CodeSize(); | 1263 *patch_code_pc_offset = assembler->CodeSize(); |
1298 StubCode* stub_code = Isolate::Current()->stub_code(); | 1264 __ BranchPatchable(&StubCode::FixAllocationStubTargetLabel()); |
1299 __ BranchPatchable(&stub_code->FixAllocationStubTargetLabel()); | |
1300 } | 1265 } |
1301 | 1266 |
1302 | 1267 |
1303 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1268 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1304 // from the entry code of a dart function after an error in passed argument | 1269 // from the entry code of a dart function after an error in passed argument |
1305 // name or number is detected. | 1270 // name or number is detected. |
1306 // Input parameters: | 1271 // Input parameters: |
1307 // RA : return address. | 1272 // RA : return address. |
1308 // SP : address of last argument. | 1273 // SP : address of last argument. |
1309 // S4: arguments descriptor array. | 1274 // S4: arguments descriptor array. |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2321 // Result: | 2286 // Result: |
2322 // T1: entry point. | 2287 // T1: entry point. |
2323 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2288 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2324 EmitMegamorphicLookup(assembler, T0, T1, T1); | 2289 EmitMegamorphicLookup(assembler, T0, T1, T1); |
2325 __ Ret(); | 2290 __ Ret(); |
2326 } | 2291 } |
2327 | 2292 |
2328 } // namespace dart | 2293 } // namespace dart |
2329 | 2294 |
2330 #endif // defined TARGET_ARCH_MIPS | 2295 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |