| 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 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 // The new Context structure contains a pointer to the current Isolate | 766 // The new Context structure contains a pointer to the current Isolate |
| 767 // structure. Cache the Context pointer in the CTX register so that it is | 767 // structure. Cache the Context pointer in the CTX register so that it is |
| 768 // available in generated code and calls to Isolate::Current() need not be | 768 // available in generated code and calls to Isolate::Current() need not be |
| 769 // done. The assumption is that this register will never be clobbered by | 769 // done. The assumption is that this register will never be clobbered by |
| 770 // compiled or runtime stub code. | 770 // compiled or runtime stub code. |
| 771 | 771 |
| 772 // Cache the new Context pointer into CTX while executing dart code. | 772 // Cache the new Context pointer into CTX while executing dart code. |
| 773 __ movl(CTX, Address(EBP, kNewContextOffset)); | 773 __ movl(CTX, Address(EBP, kNewContextOffset)); |
| 774 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); | 774 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 775 | 775 |
| 776 // Load Isolate pointer from Context structure into EDI. | 776 __ movl(EDI, Immediate(Isolate::CurrentAddress())); |
| 777 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); | |
| 778 | 777 |
| 779 // Save the current VMTag on the stack. | 778 // Save the current VMTag on the stack. |
| 780 ASSERT(kSavedVMTagSlotFromEntryFp == -4); | 779 ASSERT(kSavedVMTagSlotFromEntryFp == -4); |
| 781 __ movl(ECX, Address(EDI, Isolate::vm_tag_offset())); | 780 __ movl(ECX, Address(EDI, Isolate::vm_tag_offset())); |
| 782 __ pushl(ECX); | 781 __ pushl(ECX); |
| 783 | 782 |
| 784 // Mark that the isolate is executing Dart code. | 783 // Mark that the isolate is executing Dart code. |
| 785 __ movl(Address(EDI, Isolate::vm_tag_offset()), | 784 __ movl(Address(EDI, Isolate::vm_tag_offset()), |
| 786 Immediate(VMTag::kDartTagId)); | 785 Immediate(VMTag::kDartTagId)); |
| 787 | 786 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); | 852 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 854 | 853 |
| 855 // Reread the arguments descriptor array to obtain the number of passed | 854 // Reread the arguments descriptor array to obtain the number of passed |
| 856 // arguments. | 855 // arguments. |
| 857 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); | 856 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); |
| 858 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); | 857 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 859 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 858 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 860 // Get rid of arguments pushed on the stack. | 859 // Get rid of arguments pushed on the stack. |
| 861 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. | 860 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. |
| 862 | 861 |
| 863 // Load Isolate pointer from Context structure into CTX. Drop Context. | 862 // Load Isolate pointer into CTX. Drop Context. |
| 864 __ movl(CTX, FieldAddress(CTX, Context::isolate_offset())); | 863 __ movl(CTX, Immediate(Isolate::CurrentAddress())); |
| 865 | 864 |
| 866 // Restore the saved Context pointer into the Isolate structure. | 865 // Restore the saved Context pointer into the Isolate structure. |
| 867 // Uses ECX as a temporary register for this. | 866 __ popl(Address(CTX, Isolate::top_context_offset())); |
| 868 __ popl(ECX); | |
| 869 __ movl(Address(CTX, Isolate::top_context_offset()), ECX); | |
| 870 | 867 |
| 871 // Restore the saved top exit frame info back into the Isolate structure. | 868 // Restore the saved top exit frame info back into the Isolate structure. |
| 872 // Uses EDX as a temporary register for this. | 869 __ popl(Address(CTX, Isolate::top_exit_frame_info_offset())); |
| 873 __ popl(EDX); | |
| 874 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), EDX); | |
| 875 | 870 |
| 876 // Restore the current VMTag from the stack. | 871 // Restore the current VMTag from the stack. |
| 877 __ popl(ECX); | 872 __ popl(Address(CTX, Isolate::vm_tag_offset())); |
| 878 __ movl(Address(CTX, Isolate::vm_tag_offset()), ECX); | |
| 879 | 873 |
| 880 // Restore C++ ABI callee-saved registers. | 874 // Restore C++ ABI callee-saved registers. |
| 881 __ popl(EDI); | 875 __ popl(EDI); |
| 882 __ popl(ESI); | 876 __ popl(ESI); |
| 883 __ popl(EBX); | 877 __ popl(EBX); |
| 884 | 878 |
| 885 // Restore the frame pointer. | 879 // Restore the frame pointer. |
| 886 __ LeaveFrame(); | 880 __ LeaveFrame(); |
| 887 | 881 |
| 888 __ ret(); | 882 __ ret(); |
| 889 } | 883 } |
| 890 | 884 |
| 891 | 885 |
| 892 // Called for inline allocation of contexts. | 886 // Called for inline allocation of contexts. |
| 893 // Input: | 887 // Input: |
| 894 // EDX: number of context variables. | 888 // EDX: number of context variables. |
| 895 // Output: | 889 // Output: |
| 896 // EAX: new allocated RawContext object. | 890 // EAX: new allocated RawContext object. |
| 897 // EBX and EDX are destroyed. | 891 // EBX and EDX are destroyed. |
| 898 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 892 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 899 const Immediate& raw_null = | 893 const Immediate& raw_null = |
| 900 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 894 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 901 if (FLAG_inline_alloc) { | 895 if (FLAG_inline_alloc) { |
| 902 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 896 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 903 Label slow_case; | 897 Label slow_case; |
| 904 Heap* heap = Isolate::Current()->heap(); | 898 Isolate* isolate = Isolate::Current(); |
| 899 Heap* heap = isolate->heap(); |
| 905 // First compute the rounded instance size. | 900 // First compute the rounded instance size. |
| 906 // EDX: number of context variables. | 901 // EDX: number of context variables. |
| 907 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 902 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 908 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); | 903 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); |
| 909 __ andl(EBX, Immediate(-kObjectAlignment)); | 904 __ andl(EBX, Immediate(-kObjectAlignment)); |
| 910 | 905 |
| 911 // Now allocate the object. | 906 // Now allocate the object. |
| 912 // EDX: number of context variables. | 907 // EDX: number of context variables. |
| 913 __ movl(EAX, Address::Absolute(heap->TopAddress())); | 908 __ movl(EAX, Address::Absolute(heap->TopAddress())); |
| 914 __ addl(EBX, EAX); | 909 __ addl(EBX, EAX); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 | 956 |
| 962 // Setup up number of context variables field. | 957 // Setup up number of context variables field. |
| 963 // EAX: new object. | 958 // EAX: new object. |
| 964 // EDX: number of context variables as integer value (not object). | 959 // EDX: number of context variables as integer value (not object). |
| 965 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 960 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
| 966 | 961 |
| 967 // Setup isolate field. | 962 // Setup isolate field. |
| 968 // Load Isolate pointer from Context structure into EBX. | 963 // Load Isolate pointer from Context structure into EBX. |
| 969 // EAX: new object. | 964 // EAX: new object. |
| 970 // EDX: number of context variables. | 965 // EDX: number of context variables. |
| 971 __ movl(EBX, FieldAddress(CTX, Context::isolate_offset())); | 966 __ movl(FieldAddress(EAX, Context::isolate_offset()), |
| 972 // EBX: Isolate, not an object. | 967 Immediate(reinterpret_cast<int32_t>(isolate))); |
| 973 __ movl(FieldAddress(EAX, Context::isolate_offset()), EBX); | |
| 974 | 968 |
| 975 const Immediate& raw_null = | 969 const Immediate& raw_null = |
| 976 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 970 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 977 // Setup the parent field. | 971 // Setup the parent field. |
| 978 // EAX: new object. | 972 // EAX: new object. |
| 979 // EDX: number of context variables. | 973 // EDX: number of context variables. |
| 980 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); | 974 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); |
| 981 | 975 |
| 982 // Initialize the context variables. | 976 // Initialize the context variables. |
| 983 // EAX: new object. | 977 // EAX: new object. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 __ popl(EDX); | 1032 __ popl(EDX); |
| 1039 __ ret(); | 1033 __ ret(); |
| 1040 | 1034 |
| 1041 // Update the tags that this object has been remembered. | 1035 // Update the tags that this object has been remembered. |
| 1042 // EAX: Address being stored | 1036 // EAX: Address being stored |
| 1043 // ECX: Current tag value | 1037 // ECX: Current tag value |
| 1044 __ Bind(&add_to_buffer); | 1038 __ Bind(&add_to_buffer); |
| 1045 __ orl(ECX, Immediate(1 << RawObject::kRememberedBit)); | 1039 __ orl(ECX, Immediate(1 << RawObject::kRememberedBit)); |
| 1046 __ movl(FieldAddress(EAX, Object::tags_offset()), ECX); | 1040 __ movl(FieldAddress(EAX, Object::tags_offset()), ECX); |
| 1047 | 1041 |
| 1048 // Load the isolate out of the context. | 1042 // Load the isolate. |
| 1049 // Spilled: EDX, ECX | 1043 // Spilled: EDX, ECX |
| 1050 // EAX: Address being stored | 1044 // EAX: Address being stored |
| 1051 __ movl(EDX, FieldAddress(CTX, Context::isolate_offset())); | 1045 __ movl(EDX, Immediate(Isolate::CurrentAddress())); |
| 1052 | 1046 |
| 1053 // Load the StoreBuffer block out of the isolate. Then load top_ out of the | 1047 // Load the StoreBuffer block out of the isolate. Then load top_ out of the |
| 1054 // StoreBufferBlock and add the address to the pointers_. | 1048 // StoreBufferBlock and add the address to the pointers_. |
| 1055 // Spilled: EDX, ECX | 1049 // Spilled: EDX, ECX |
| 1056 // EAX: Address being stored | 1050 // EAX: Address being stored |
| 1057 // EDX: Isolate | 1051 // EDX: Isolate |
| 1058 __ movl(EDX, Address(EDX, Isolate::store_buffer_offset())); | 1052 __ movl(EDX, Address(EDX, Isolate::store_buffer_offset())); |
| 1059 __ movl(ECX, Address(EDX, StoreBufferBlock::top_offset())); | 1053 __ movl(ECX, Address(EDX, StoreBufferBlock::top_offset())); |
| 1060 __ movl(Address(EDX, ECX, TIMES_4, StoreBufferBlock::pointers_offset()), EAX); | 1054 __ movl(Address(EDX, ECX, TIMES_4, StoreBufferBlock::pointers_offset()), EAX); |
| 1061 | 1055 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1072 __ popl(ECX); | 1066 __ popl(ECX); |
| 1073 __ popl(EDX); | 1067 __ popl(EDX); |
| 1074 __ j(EQUAL, &L, Assembler::kNearJump); | 1068 __ j(EQUAL, &L, Assembler::kNearJump); |
| 1075 __ ret(); | 1069 __ ret(); |
| 1076 | 1070 |
| 1077 // Handle overflow: Call the runtime leaf function. | 1071 // Handle overflow: Call the runtime leaf function. |
| 1078 __ Bind(&L); | 1072 __ Bind(&L); |
| 1079 // Setup frame, push callee-saved registers. | 1073 // Setup frame, push callee-saved registers. |
| 1080 | 1074 |
| 1081 __ EnterCallRuntimeFrame(1 * kWordSize); | 1075 __ EnterCallRuntimeFrame(1 * kWordSize); |
| 1082 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1076 __ movl(EAX, Immediate(Isolate::CurrentAddress())); |
| 1083 __ movl(Address(ESP, 0), EAX); // Push the isolate as the only argument. | 1077 __ movl(Address(ESP, 0), EAX); // Push the isolate as the only argument. |
| 1084 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); | 1078 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); |
| 1085 // Restore callee-saved registers, tear down frame. | 1079 // Restore callee-saved registers, tear down frame. |
| 1086 __ LeaveCallRuntimeFrame(); | 1080 __ LeaveCallRuntimeFrame(); |
| 1087 __ ret(); | 1081 __ ret(); |
| 1088 } | 1082 } |
| 1089 | 1083 |
| 1090 | 1084 |
| 1091 // Called for inline allocation of objects. | 1085 // Called for inline allocation of objects. |
| 1092 // Input parameters: | 1086 // Input parameters: |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1370 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
| 1377 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1371 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1378 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1372 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
| 1379 __ cmpl(EBX, Immediate(num_args)); | 1373 __ cmpl(EBX, Immediate(num_args)); |
| 1380 __ j(EQUAL, &ok, Assembler::kNearJump); | 1374 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1381 __ Stop("Incorrect stub for IC data"); | 1375 __ Stop("Incorrect stub for IC data"); |
| 1382 __ Bind(&ok); | 1376 __ Bind(&ok); |
| 1383 } | 1377 } |
| 1384 #endif // DEBUG | 1378 #endif // DEBUG |
| 1385 | 1379 |
| 1380 // Check single stepping. |
| 1386 Label stepping, done_stepping; | 1381 Label stepping, done_stepping; |
| 1387 // Check single stepping. | 1382 uword single_step_address = |
| 1388 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1383 Isolate::CurrentAddress() + Isolate::single_step_offset(); |
| 1389 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); | 1384 __ cmpb(Address::Absolute(single_step_address), Immediate(0)); |
| 1390 __ j(NOT_EQUAL, &stepping); | 1385 __ j(NOT_EQUAL, &stepping); |
| 1391 __ Bind(&done_stepping); | 1386 __ Bind(&done_stepping); |
| 1392 | 1387 |
| 1393 if (kind != Token::kILLEGAL) { | 1388 if (kind != Token::kILLEGAL) { |
| 1394 Label not_smi_or_overflow; | 1389 Label not_smi_or_overflow; |
| 1395 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1390 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1396 __ Bind(¬_smi_or_overflow); | 1391 __ Bind(¬_smi_or_overflow); |
| 1397 } | 1392 } |
| 1398 | 1393 |
| 1399 // ECX: IC data object (preserved). | 1394 // ECX: IC data object (preserved). |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1610 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1616 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1611 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
| 1617 __ cmpl(EBX, Immediate(0)); | 1612 __ cmpl(EBX, Immediate(0)); |
| 1618 __ j(EQUAL, &ok, Assembler::kNearJump); | 1613 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1619 __ Stop("Incorrect IC data for unoptimized static call"); | 1614 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1620 __ Bind(&ok); | 1615 __ Bind(&ok); |
| 1621 } | 1616 } |
| 1622 #endif // DEBUG | 1617 #endif // DEBUG |
| 1623 // Check single stepping. | 1618 // Check single stepping. |
| 1624 Label stepping, done_stepping; | 1619 Label stepping, done_stepping; |
| 1625 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1620 uword single_step_address = |
| 1626 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1621 Isolate::CurrentAddress() + Isolate::single_step_offset(); |
| 1627 __ cmpl(EAX, Immediate(0)); | 1622 __ cmpb(Address::Absolute(single_step_address), Immediate(0)); |
| 1628 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); | 1623 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
| 1629 __ Bind(&done_stepping); | 1624 __ Bind(&done_stepping); |
| 1630 | 1625 |
| 1631 // ECX: IC data object (preserved). | 1626 // ECX: IC data object (preserved). |
| 1632 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1627 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1633 // EBX: ic_data_array with entries: target functions and count. | 1628 // EBX: ic_data_array with entries: target functions and count. |
| 1634 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1629 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1635 // EBX: points directly to the first ic data array element. | 1630 // EBX: points directly to the first ic data array element. |
| 1636 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1631 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1637 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1632 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 const Register temp = ECX; | 2048 const Register temp = ECX; |
| 2054 __ movl(left, Address(ESP, 2 * kWordSize)); | 2049 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2055 __ movl(right, Address(ESP, 1 * kWordSize)); | 2050 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2056 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2051 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2057 __ ret(); | 2052 __ ret(); |
| 2058 } | 2053 } |
| 2059 | 2054 |
| 2060 } // namespace dart | 2055 } // namespace dart |
| 2061 | 2056 |
| 2062 #endif // defined TARGET_ARCH_IA32 | 2057 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |