| 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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 __ pushl(EAX); // Array is in EAX and on top of stack. | 362 __ pushl(EAX); // Array is in EAX and on top of stack. |
| 363 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 363 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
| 364 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 364 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 365 // EBX: address of first argument on stack. | 365 // EBX: address of first argument on stack. |
| 366 // ECX: address of first argument in array. | 366 // ECX: address of first argument in array. |
| 367 Label loop, loop_condition; | 367 Label loop, loop_condition; |
| 368 __ jmp(&loop_condition, Assembler::kNearJump); | 368 __ jmp(&loop_condition, Assembler::kNearJump); |
| 369 __ Bind(&loop); | 369 __ Bind(&loop); |
| 370 __ movl(EDI, Address(EBX, 0)); | 370 __ movl(EDI, Address(EBX, 0)); |
| 371 // No generational barrier needed, since array is in new space. | 371 // No generational barrier needed, since array is in new space. |
| 372 __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), EDI); | 372 __ InitializeFieldNoBarrier(EAX, Address(ECX, 0), EDI); |
| 373 __ AddImmediate(ECX, Immediate(kWordSize)); | 373 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 374 __ AddImmediate(EBX, Immediate(-kWordSize)); | 374 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 375 __ Bind(&loop_condition); | 375 __ Bind(&loop_condition); |
| 376 __ decl(EDX); | 376 __ decl(EDX); |
| 377 __ j(POSITIVE, &loop, Assembler::kNearJump); | 377 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 378 } | 378 } |
| 379 | 379 |
| 380 | 380 |
| 381 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 381 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 382 intptr_t deopt_reason, | 382 intptr_t deopt_reason, |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 | 624 |
| 625 // Get the class index and insert it into the tags. | 625 // Get the class index and insert it into the tags. |
| 626 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); | 626 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); |
| 627 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. | 627 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. |
| 628 } | 628 } |
| 629 // EAX: new object start as a tagged pointer. | 629 // EAX: new object start as a tagged pointer. |
| 630 // EBX: new object end address. | 630 // EBX: new object end address. |
| 631 // ECX: array element type. | 631 // ECX: array element type. |
| 632 // EDX: Array length as Smi (preserved). | 632 // EDX: Array length as Smi (preserved). |
| 633 // Store the type argument field. | 633 // Store the type argument field. |
| 634 __ StoreIntoObjectNoBarrier(EAX, | 634 __ InitializeFieldNoBarrier(EAX, |
| 635 FieldAddress(EAX, Array::type_arguments_offset()), | 635 FieldAddress(EAX, Array::type_arguments_offset()), |
| 636 ECX); | 636 ECX); |
| 637 | 637 |
| 638 // Set the length field. | 638 // Set the length field. |
| 639 __ StoreIntoObjectNoBarrier(EAX, | 639 __ InitializeFieldNoBarrier(EAX, |
| 640 FieldAddress(EAX, Array::length_offset()), | 640 FieldAddress(EAX, Array::length_offset()), |
| 641 EDX); | 641 EDX); |
| 642 | 642 |
| 643 // Initialize all array elements to raw_null. | 643 // Initialize all array elements to raw_null. |
| 644 // EAX: new object start as a tagged pointer. | 644 // EAX: new object start as a tagged pointer. |
| 645 // EBX: new object end address. | 645 // EBX: new object end address. |
| 646 // EDI: iterator which initially points to the start of the variable | 646 // EDI: iterator which initially points to the start of the variable |
| 647 // data area to be initialized. | 647 // data area to be initialized. |
| 648 // ECX: array element type. | 648 // ECX: array element type. |
| 649 // EDX: array length as Smi. | 649 // EDX: array length as Smi. |
| 650 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 650 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
| 651 Label done; | 651 Label done; |
| 652 Label init_loop; | 652 Label init_loop; |
| 653 __ Bind(&init_loop); | 653 __ Bind(&init_loop); |
| 654 __ cmpl(EDI, EBX); | 654 __ cmpl(EDI, EBX); |
| 655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 656 // No generational barrier needed, since we are storing null. | 656 // No generational barrier needed, since we are storing null. |
| 657 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | 657 __ InitializeFieldNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
| 658 __ addl(EDI, Immediate(kWordSize)); | 658 __ addl(EDI, Immediate(kWordSize)); |
| 659 __ jmp(&init_loop, Assembler::kNearJump); | 659 __ jmp(&init_loop, Assembler::kNearJump); |
| 660 __ Bind(&done); | 660 __ Bind(&done); |
| 661 __ ret(); // returns the newly allocated object in EAX. | 661 __ ret(); // returns the newly allocated object in EAX. |
| 662 | 662 |
| 663 // Unable to allocate the array using the fast inline code, just call | 663 // Unable to allocate the array using the fast inline code, just call |
| 664 // into the runtime. | 664 // into the runtime. |
| 665 __ Bind(&slow_case); | 665 __ Bind(&slow_case); |
| 666 // Create a stub frame as we are pushing some objects on the stack before | 666 // Create a stub frame as we are pushing some objects on the stack before |
| 667 // calling into the runtime. | 667 // calling into the runtime. |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 __ movl(EAX, Address::Absolute(heap->TopAddress(space))); | 806 __ movl(EAX, Address::Absolute(heap->TopAddress(space))); |
| 807 __ addl(EBX, EAX); | 807 __ addl(EBX, EAX); |
| 808 // Check if the allocation fits into the remaining space. | 808 // Check if the allocation fits into the remaining space. |
| 809 // EAX: potential new object. | 809 // EAX: potential new object. |
| 810 // EBX: potential next object start. | 810 // EBX: potential next object start. |
| 811 // EDX: number of context variables. | 811 // EDX: number of context variables. |
| 812 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); | 812 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); |
| 813 if (FLAG_use_slow_path) { | 813 if (FLAG_use_slow_path) { |
| 814 __ jmp(&slow_case); | 814 __ jmp(&slow_case); |
| 815 } else { | 815 } else { |
| 816 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); | 816 #if defined(DEBUG) |
| 817 static const bool kJumpLength = Assembler::kFarJump; |
| 818 #else |
| 819 static const bool kJumpLength = Assembler::kNearJump; |
| 820 #endif // DEBUG |
| 821 __ j(ABOVE_EQUAL, &slow_case, kJumpLength); |
| 817 } | 822 } |
| 818 | 823 |
| 819 // Successfully allocated the object, now update top to point to | 824 // Successfully allocated the object, now update top to point to |
| 820 // next object start and initialize the object. | 825 // next object start and initialize the object. |
| 821 // EAX: new object. | 826 // EAX: new object. |
| 822 // EBX: next object start. | 827 // EBX: next object start. |
| 823 // EDX: number of context variables. | 828 // EDX: number of context variables. |
| 824 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); | 829 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); |
| 825 __ addl(EAX, Immediate(kHeapObjectTag)); | 830 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 826 // EBX: Size of allocation in bytes. | 831 // EBX: Size of allocation in bytes. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 854 | 859 |
| 855 // Setup up number of context variables field. | 860 // Setup up number of context variables field. |
| 856 // EAX: new object. | 861 // EAX: new object. |
| 857 // EDX: number of context variables as integer value (not object). | 862 // EDX: number of context variables as integer value (not object). |
| 858 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 863 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
| 859 | 864 |
| 860 // Setup the parent field. | 865 // Setup the parent field. |
| 861 // EAX: new object. | 866 // EAX: new object. |
| 862 // EDX: number of context variables. | 867 // EDX: number of context variables. |
| 863 // No generational barrier needed, since we are storing null. | 868 // No generational barrier needed, since we are storing null. |
| 864 __ StoreIntoObjectNoBarrier(EAX, | 869 __ InitializeFieldNoBarrier(EAX, |
| 865 FieldAddress(EAX, Context::parent_offset()), | 870 FieldAddress(EAX, Context::parent_offset()), |
| 866 Object::null_object()); | 871 Object::null_object()); |
| 867 | 872 |
| 868 // Initialize the context variables. | 873 // Initialize the context variables. |
| 869 // EAX: new object. | 874 // EAX: new object. |
| 870 // EDX: number of context variables. | 875 // EDX: number of context variables. |
| 871 { | 876 { |
| 872 Label loop, entry; | 877 Label loop, entry; |
| 873 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); | 878 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); |
| 874 | 879 |
| 875 __ jmp(&entry, Assembler::kNearJump); | 880 __ jmp(&entry, Assembler::kNearJump); |
| 876 __ Bind(&loop); | 881 __ Bind(&loop); |
| 877 __ decl(EDX); | 882 __ decl(EDX); |
| 878 // No generational barrier needed, since we are storing null. | 883 // No generational barrier needed, since we are storing null. |
| 879 __ StoreIntoObjectNoBarrier(EAX, | 884 __ InitializeFieldNoBarrier(EAX, |
| 880 Address(EBX, EDX, TIMES_4, 0), | 885 Address(EBX, EDX, TIMES_4, 0), |
| 881 Object::null_object()); | 886 Object::null_object()); |
| 882 __ Bind(&entry); | 887 __ Bind(&entry); |
| 883 __ cmpl(EDX, Immediate(0)); | 888 __ cmpl(EDX, Immediate(0)); |
| 884 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 889 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 885 } | 890 } |
| 886 | 891 |
| 887 // Done allocating and initializing the context. | 892 // Done allocating and initializing the context. |
| 888 // EAX: new object. | 893 // EAX: new object. |
| 889 __ ret(); | 894 __ ret(); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 // EAX: new object (tagged). | 1052 // EAX: new object (tagged). |
| 1048 // EBX: next object start. | 1053 // EBX: next object start. |
| 1049 // EDX: new object type arguments (if is_cls_parameterized). | 1054 // EDX: new object type arguments (if is_cls_parameterized). |
| 1050 // First try inlining the initialization without a loop. | 1055 // First try inlining the initialization without a loop. |
| 1051 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1056 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1052 // Check if the object contains any non-header fields. | 1057 // Check if the object contains any non-header fields. |
| 1053 // Small objects are initialized using a consecutive set of writes. | 1058 // Small objects are initialized using a consecutive set of writes. |
| 1054 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1059 for (intptr_t current_offset = Instance::NextFieldOffset(); |
| 1055 current_offset < instance_size; | 1060 current_offset < instance_size; |
| 1056 current_offset += kWordSize) { | 1061 current_offset += kWordSize) { |
| 1057 __ StoreIntoObjectNoBarrier(EAX, | 1062 __ InitializeFieldNoBarrier(EAX, |
| 1058 FieldAddress(EAX, current_offset), | 1063 FieldAddress(EAX, current_offset), |
| 1059 Object::null_object()); | 1064 Object::null_object()); |
| 1060 } | 1065 } |
| 1061 } else { | 1066 } else { |
| 1062 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset())); | 1067 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset())); |
| 1063 // Loop until the whole object is initialized. | 1068 // Loop until the whole object is initialized. |
| 1064 // EAX: new object (tagged). | 1069 // EAX: new object (tagged). |
| 1065 // EBX: next object start. | 1070 // EBX: next object start. |
| 1066 // ECX: next word to be initialized. | 1071 // ECX: next word to be initialized. |
| 1067 // EDX: new object type arguments (if is_cls_parameterized). | 1072 // EDX: new object type arguments (if is_cls_parameterized). |
| 1068 Label init_loop; | 1073 Label init_loop; |
| 1069 Label done; | 1074 Label done; |
| 1070 __ Bind(&init_loop); | 1075 __ Bind(&init_loop); |
| 1071 __ cmpl(ECX, EBX); | 1076 __ cmpl(ECX, EBX); |
| 1072 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1077 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 1073 __ StoreIntoObjectNoBarrier(EAX, | 1078 __ InitializeFieldNoBarrier(EAX, |
| 1074 Address(ECX, 0), | 1079 Address(ECX, 0), |
| 1075 Object::null_object()); | 1080 Object::null_object()); |
| 1076 __ addl(ECX, Immediate(kWordSize)); | 1081 __ addl(ECX, Immediate(kWordSize)); |
| 1077 __ jmp(&init_loop, Assembler::kNearJump); | 1082 __ jmp(&init_loop, Assembler::kNearJump); |
| 1078 __ Bind(&done); | 1083 __ Bind(&done); |
| 1079 } | 1084 } |
| 1080 if (is_cls_parameterized) { | 1085 if (is_cls_parameterized) { |
| 1081 // EDX: new object type arguments. | 1086 // EDX: new object type arguments. |
| 1082 // Set the type arguments in the new object. | 1087 // Set the type arguments in the new object. |
| 1083 intptr_t offset = cls.type_arguments_field_offset(); | 1088 intptr_t offset = cls.type_arguments_field_offset(); |
| 1084 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX); | 1089 // TODO(koda): Figure out why previous content is sometimes null here. |
| 1090 __ InitializeFieldNoBarrier(EAX, FieldAddress(EAX, offset), EDX); |
| 1085 } | 1091 } |
| 1086 // Done allocating and initializing the instance. | 1092 // Done allocating and initializing the instance. |
| 1087 // EAX: new object (tagged). | 1093 // EAX: new object (tagged). |
| 1088 __ ret(); | 1094 __ ret(); |
| 1089 | 1095 |
| 1090 __ Bind(&slow_case); | 1096 __ Bind(&slow_case); |
| 1091 } | 1097 } |
| 1092 // If is_cls_parameterized: | 1098 // If is_cls_parameterized: |
| 1093 // EDX: new object type arguments. | 1099 // EDX: new object type arguments. |
| 1094 // Create a stub frame as we are pushing some objects on the stack before | 1100 // Create a stub frame as we are pushing some objects on the stack before |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 const Register temp = ECX; | 2045 const Register temp = ECX; |
| 2040 __ movl(left, Address(ESP, 2 * kWordSize)); | 2046 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2041 __ movl(right, Address(ESP, 1 * kWordSize)); | 2047 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2042 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2048 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2043 __ ret(); | 2049 __ ret(); |
| 2044 } | 2050 } |
| 2045 | 2051 |
| 2046 } // namespace dart | 2052 } // namespace dart |
| 2047 | 2053 |
| 2048 #endif // defined TARGET_ARCH_IA32 | 2054 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |