| 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 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 // EDX: length of the array (was preserved by the stub). | 316 // EDX: length of the array (was preserved by the stub). |
| 317 __ pushl(EAX); // Array is in EAX and on top of stack. | 317 __ pushl(EAX); // Array is in EAX and on top of stack. |
| 318 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 318 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
| 319 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 319 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 320 // EBX: address of first argument on stack. | 320 // EBX: address of first argument on stack. |
| 321 // ECX: address of first argument in array. | 321 // ECX: address of first argument in array. |
| 322 Label loop, loop_condition; | 322 Label loop, loop_condition; |
| 323 __ jmp(&loop_condition, Assembler::kNearJump); | 323 __ jmp(&loop_condition, Assembler::kNearJump); |
| 324 __ Bind(&loop); | 324 __ Bind(&loop); |
| 325 __ movl(EDI, Address(EBX, 0)); | 325 __ movl(EDI, Address(EBX, 0)); |
| 326 // No generational barrier needed, since array is in new space. | 326 // Generational barrier is needed, array is not necessarily in new space. |
| 327 __ InitializeFieldNoBarrier(EAX, Address(ECX, 0), EDI); | 327 __ StoreIntoObject(EAX, Address(ECX, 0), EDI); |
| 328 __ AddImmediate(ECX, Immediate(kWordSize)); | 328 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 329 __ AddImmediate(EBX, Immediate(-kWordSize)); | 329 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 330 __ Bind(&loop_condition); | 330 __ Bind(&loop_condition); |
| 331 __ decl(EDX); | 331 __ decl(EDX); |
| 332 __ j(POSITIVE, &loop, Assembler::kNearJump); | 332 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 // Used by eager and lazy deoptimization. Preserve result in EAX if necessary. | 336 // Used by eager and lazy deoptimization. Preserve result in EAX if necessary. |
| 337 // This stub translates optimized frame into unoptimized frame. The optimized | 337 // This stub translates optimized frame into unoptimized frame. The optimized |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 | 617 |
| 618 // Get the class index and insert it into the tags. | 618 // Get the class index and insert it into the tags. |
| 619 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); | 619 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); |
| 620 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. | 620 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. |
| 621 } | 621 } |
| 622 // EAX: new object start as a tagged pointer. | 622 // EAX: new object start as a tagged pointer. |
| 623 // EBX: allocation size. | 623 // EBX: allocation size. |
| 624 // ECX: array element type. | 624 // ECX: array element type. |
| 625 // EDX: Array length as Smi (preserved). | 625 // EDX: Array length as Smi (preserved). |
| 626 // Store the type argument field. | 626 // Store the type argument field. |
| 627 __ InitializeFieldNoBarrier(EAX, | 627 // No generetional barrier needed, since we store into a new object. |
| 628 __ StoreIntoObjectNoBarrier(EAX, |
| 628 FieldAddress(EAX, Array::type_arguments_offset()), | 629 FieldAddress(EAX, Array::type_arguments_offset()), |
| 629 ECX); | 630 ECX); |
| 630 | 631 |
| 631 // Set the length field. | 632 // Set the length field. |
| 632 __ InitializeFieldNoBarrier(EAX, | 633 __ StoreIntoObjectNoBarrier(EAX, |
| 633 FieldAddress(EAX, Array::length_offset()), | 634 FieldAddress(EAX, Array::length_offset()), |
| 634 EDX); | 635 EDX); |
| 635 | 636 |
| 636 // Initialize all array elements to raw_null. | 637 // Initialize all array elements to raw_null. |
| 637 // EAX: new object start as a tagged pointer. | 638 // EAX: new object start as a tagged pointer. |
| 638 // EBX: allocation size. | 639 // EBX: allocation size. |
| 639 // EDI: iterator which initially points to the start of the variable | 640 // EDI: iterator which initially points to the start of the variable |
| 640 // data area to be initialized. | 641 // data area to be initialized. |
| 641 // ECX: array element type. | 642 // ECX: array element type. |
| 642 // EDX: array length as Smi. | 643 // EDX: array length as Smi. |
| 643 __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0)); | 644 __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0)); |
| 644 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 645 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
| 645 Label done; | 646 Label done; |
| 646 Label init_loop; | 647 Label init_loop; |
| 647 __ Bind(&init_loop); | 648 __ Bind(&init_loop); |
| 648 __ cmpl(EDI, EBX); | 649 __ cmpl(EDI, EBX); |
| 649 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 650 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 650 // No generational barrier needed, since we are storing null. | 651 // No generational barrier needed, since we are storing null. |
| 651 __ InitializeFieldNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | 652 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
| 652 __ addl(EDI, Immediate(kWordSize)); | 653 __ addl(EDI, Immediate(kWordSize)); |
| 653 __ jmp(&init_loop, Assembler::kNearJump); | 654 __ jmp(&init_loop, Assembler::kNearJump); |
| 654 __ Bind(&done); | 655 __ Bind(&done); |
| 655 __ ret(); // returns the newly allocated object in EAX. | 656 __ ret(); // returns the newly allocated object in EAX. |
| 656 | 657 |
| 657 // Unable to allocate the array using the fast inline code, just call | 658 // Unable to allocate the array using the fast inline code, just call |
| 658 // into the runtime. | 659 // into the runtime. |
| 659 __ Bind(&slow_case); | 660 __ Bind(&slow_case); |
| 660 // Create a stub frame as we are pushing some objects on the stack before | 661 // Create a stub frame as we are pushing some objects on the stack before |
| 661 // calling into the runtime. | 662 // calling into the runtime. |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 | 866 |
| 866 // Setup up number of context variables field. | 867 // Setup up number of context variables field. |
| 867 // EAX: new object. | 868 // EAX: new object. |
| 868 // EDX: number of context variables as integer value (not object). | 869 // EDX: number of context variables as integer value (not object). |
| 869 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 870 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
| 870 | 871 |
| 871 // Setup the parent field. | 872 // Setup the parent field. |
| 872 // EAX: new object. | 873 // EAX: new object. |
| 873 // EDX: number of context variables. | 874 // EDX: number of context variables. |
| 874 // No generational barrier needed, since we are storing null. | 875 // No generational barrier needed, since we are storing null. |
| 875 __ InitializeFieldNoBarrier(EAX, | 876 __ StoreIntoObjectNoBarrier(EAX, |
| 876 FieldAddress(EAX, Context::parent_offset()), | 877 FieldAddress(EAX, Context::parent_offset()), |
| 877 Object::null_object()); | 878 Object::null_object()); |
| 878 | 879 |
| 879 // Initialize the context variables. | 880 // Initialize the context variables. |
| 880 // EAX: new object. | 881 // EAX: new object. |
| 881 // EDX: number of context variables. | 882 // EDX: number of context variables. |
| 882 { | 883 { |
| 883 Label loop, entry; | 884 Label loop, entry; |
| 884 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); | 885 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); |
| 885 | 886 |
| 886 __ jmp(&entry, Assembler::kNearJump); | 887 __ jmp(&entry, Assembler::kNearJump); |
| 887 __ Bind(&loop); | 888 __ Bind(&loop); |
| 888 __ decl(EDX); | 889 __ decl(EDX); |
| 889 // No generational barrier needed, since we are storing null. | 890 // No generational barrier needed, since we are storing null. |
| 890 __ InitializeFieldNoBarrier(EAX, | 891 __ StoreIntoObjectNoBarrier(EAX, |
| 891 Address(EBX, EDX, TIMES_4, 0), | 892 Address(EBX, EDX, TIMES_4, 0), |
| 892 Object::null_object()); | 893 Object::null_object()); |
| 893 __ Bind(&entry); | 894 __ Bind(&entry); |
| 894 __ cmpl(EDX, Immediate(0)); | 895 __ cmpl(EDX, Immediate(0)); |
| 895 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 896 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 896 } | 897 } |
| 897 | 898 |
| 898 // Done allocating and initializing the context. | 899 // Done allocating and initializing the context. |
| 899 // EAX: new object. | 900 // EAX: new object. |
| 900 __ ret(); | 901 __ ret(); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 // EAX: new object (tagged). | 1052 // EAX: new object (tagged). |
| 1052 // EBX: next object start. | 1053 // EBX: next object start. |
| 1053 // EDX: new object type arguments (if is_cls_parameterized). | 1054 // EDX: new object type arguments (if is_cls_parameterized). |
| 1054 // First try inlining the initialization without a loop. | 1055 // First try inlining the initialization without a loop. |
| 1055 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1056 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1056 // Check if the object contains any non-header fields. | 1057 // Check if the object contains any non-header fields. |
| 1057 // Small objects are initialized using a consecutive set of writes. | 1058 // Small objects are initialized using a consecutive set of writes. |
| 1058 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1059 for (intptr_t current_offset = Instance::NextFieldOffset(); |
| 1059 current_offset < instance_size; | 1060 current_offset < instance_size; |
| 1060 current_offset += kWordSize) { | 1061 current_offset += kWordSize) { |
| 1061 __ InitializeFieldNoBarrier(EAX, | 1062 __ StoreIntoObjectNoBarrier(EAX, |
| 1062 FieldAddress(EAX, current_offset), | 1063 FieldAddress(EAX, current_offset), |
| 1063 Object::null_object()); | 1064 Object::null_object()); |
| 1064 } | 1065 } |
| 1065 } else { | 1066 } else { |
| 1066 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset())); | 1067 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset())); |
| 1067 // Loop until the whole object is initialized. | 1068 // Loop until the whole object is initialized. |
| 1068 // EAX: new object (tagged). | 1069 // EAX: new object (tagged). |
| 1069 // EBX: next object start. | 1070 // EBX: next object start. |
| 1070 // ECX: next word to be initialized. | 1071 // ECX: next word to be initialized. |
| 1071 // EDX: new object type arguments (if is_cls_parameterized). | 1072 // EDX: new object type arguments (if is_cls_parameterized). |
| 1072 Label init_loop; | 1073 Label init_loop; |
| 1073 Label done; | 1074 Label done; |
| 1074 __ Bind(&init_loop); | 1075 __ Bind(&init_loop); |
| 1075 __ cmpl(ECX, EBX); | 1076 __ cmpl(ECX, EBX); |
| 1076 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1077 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 1077 __ InitializeFieldNoBarrier(EAX, | 1078 __ StoreIntoObjectNoBarrier(EAX, |
| 1078 Address(ECX, 0), | 1079 Address(ECX, 0), |
| 1079 Object::null_object()); | 1080 Object::null_object()); |
| 1080 __ addl(ECX, Immediate(kWordSize)); | 1081 __ addl(ECX, Immediate(kWordSize)); |
| 1081 __ jmp(&init_loop, Assembler::kNearJump); | 1082 __ jmp(&init_loop, Assembler::kNearJump); |
| 1082 __ Bind(&done); | 1083 __ Bind(&done); |
| 1083 } | 1084 } |
| 1084 if (is_cls_parameterized) { | 1085 if (is_cls_parameterized) { |
| 1086 // EAX: new object (tagged). |
| 1085 // EDX: new object type arguments. | 1087 // EDX: new object type arguments. |
| 1086 // Set the type arguments in the new object. | 1088 // Set the type arguments in the new object. |
| 1087 intptr_t offset = cls.type_arguments_field_offset(); | 1089 intptr_t offset = cls.type_arguments_field_offset(); |
| 1088 // TODO(koda): Figure out why previous content is sometimes null here. | 1090 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX); |
| 1089 __ InitializeFieldNoBarrier(EAX, FieldAddress(EAX, offset), EDX); | |
| 1090 } | 1091 } |
| 1091 // Done allocating and initializing the instance. | 1092 // Done allocating and initializing the instance. |
| 1092 // EAX: new object (tagged). | 1093 // EAX: new object (tagged). |
| 1093 __ ret(); | 1094 __ ret(); |
| 1094 | 1095 |
| 1095 __ Bind(&slow_case); | 1096 __ Bind(&slow_case); |
| 1096 } | 1097 } |
| 1097 // If is_cls_parameterized: | 1098 // If is_cls_parameterized: |
| 1098 // EDX: new object type arguments. | 1099 // EDX: new object type arguments. |
| 1099 // 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 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2091 | 2092 |
| 2092 | 2093 |
| 2093 | 2094 |
| 2094 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2095 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
| 2095 __ int3(); | 2096 __ int3(); |
| 2096 } | 2097 } |
| 2097 | 2098 |
| 2098 } // namespace dart | 2099 } // namespace dart |
| 2099 | 2100 |
| 2100 #endif // defined TARGET_ARCH_IA32 | 2101 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |