| 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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 338 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 339 __ LeaveFrame(); | 339 __ LeaveFrame(); |
| 340 __ jmp(EAX); | 340 __ jmp(EAX); |
| 341 __ int3(); | 341 __ int3(); |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 // Input parameters: | 345 // Input parameters: |
| 346 // EDX: smi-tagged argument count, may be zero. | 346 // EDX: smi-tagged argument count, may be zero. |
| 347 // EBP[kParamEndSlotFromFp + 1]: last argument. | 347 // EBP[kParamEndSlotFromFp + 1]: last argument. |
| 348 // Uses EAX, EBX, ECX, EDX. | 348 // Uses EAX, EBX, ECX, EDX, EDI. |
| 349 static void PushArgumentsArray(Assembler* assembler) { | 349 static void PushArgumentsArray(Assembler* assembler) { |
| 350 const Immediate& raw_null = | 350 const Immediate& raw_null = |
| 351 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 351 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 352 StubCode* stub_code = Isolate::Current()->stub_code(); | 352 StubCode* stub_code = Isolate::Current()->stub_code(); |
| 353 | 353 |
| 354 // Allocate array to store arguments of caller. | 354 // Allocate array to store arguments of caller. |
| 355 __ movl(ECX, raw_null); // Null element type for raw Array. | 355 __ movl(ECX, raw_null); // Null element type for raw Array. |
| 356 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); | 356 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); |
| 357 const ExternalLabel array_label(array_stub.EntryPoint()); | 357 const ExternalLabel array_label(array_stub.EntryPoint()); |
| 358 __ call(&array_label); | 358 __ call(&array_label); |
| 359 __ SmiUntag(EDX); | 359 __ SmiUntag(EDX); |
| 360 // EAX: newly allocated array. | 360 // EAX: newly allocated array. |
| 361 // EDX: length of the array (was preserved by the stub). | 361 // EDX: length of the array (was preserved by the stub). |
| 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(EAX, Address(EBX, 0)); | 370 __ movl(EDI, Address(EBX, 0)); |
| 371 __ movl(Address(ECX, 0), EAX); | 371 // No generational barrier needed, since array is in new space. |
| 372 __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), EDI); |
| 372 __ AddImmediate(ECX, Immediate(kWordSize)); | 373 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 373 __ AddImmediate(EBX, Immediate(-kWordSize)); | 374 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 374 __ Bind(&loop_condition); | 375 __ Bind(&loop_condition); |
| 375 __ decl(EDX); | 376 __ decl(EDX); |
| 376 __ j(POSITIVE, &loop, Assembler::kNearJump); | 377 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 377 } | 378 } |
| 378 | 379 |
| 379 | 380 |
| 380 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 381 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 381 intptr_t deopt_reason, | 382 intptr_t deopt_reason, |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 // EDI: iterator which initially points to the start of the variable | 646 // EDI: iterator which initially points to the start of the variable |
| 646 // data area to be initialized. | 647 // data area to be initialized. |
| 647 // ECX: array element type. | 648 // ECX: array element type. |
| 648 // EDX: array length as Smi. | 649 // EDX: array length as Smi. |
| 649 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 650 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
| 650 Label done; | 651 Label done; |
| 651 Label init_loop; | 652 Label init_loop; |
| 652 __ Bind(&init_loop); | 653 __ Bind(&init_loop); |
| 653 __ cmpl(EDI, EBX); | 654 __ cmpl(EDI, EBX); |
| 654 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 655 __ movl(Address(EDI, 0), raw_null); | 656 // No generational barrier needed, since we are storing null. |
| 657 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
| 656 __ addl(EDI, Immediate(kWordSize)); | 658 __ addl(EDI, Immediate(kWordSize)); |
| 657 __ jmp(&init_loop, Assembler::kNearJump); | 659 __ jmp(&init_loop, Assembler::kNearJump); |
| 658 __ Bind(&done); | 660 __ Bind(&done); |
| 659 __ ret(); // returns the newly allocated object in EAX. | 661 __ ret(); // returns the newly allocated object in EAX. |
| 660 | 662 |
| 661 // 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 |
| 662 // into the runtime. | 664 // into the runtime. |
| 663 __ Bind(&slow_case); | 665 __ Bind(&slow_case); |
| 664 // 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 |
| 665 // calling into the runtime. | 667 // calling into the runtime. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 __ orl(EBX, | 850 __ orl(EBX, |
| 849 Immediate(RawObject::ClassIdTag::encode(cid))); | 851 Immediate(RawObject::ClassIdTag::encode(cid))); |
| 850 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags. | 852 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags. |
| 851 } | 853 } |
| 852 | 854 |
| 853 // Setup up number of context variables field. | 855 // Setup up number of context variables field. |
| 854 // EAX: new object. | 856 // EAX: new object. |
| 855 // EDX: number of context variables as integer value (not object). | 857 // EDX: number of context variables as integer value (not object). |
| 856 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 858 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
| 857 | 859 |
| 858 const Immediate& raw_null = | |
| 859 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 860 // Setup the parent field. | 860 // Setup the parent field. |
| 861 // EAX: new object. | 861 // EAX: new object. |
| 862 // EDX: number of context variables. | 862 // EDX: number of context variables. |
| 863 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); | 863 // No generational barrier needed, since we are storing null. |
| 864 __ StoreIntoObjectNoBarrier(EAX, |
| 865 FieldAddress(EAX, Context::parent_offset()), |
| 866 Object::null_object()); |
| 864 | 867 |
| 865 // Initialize the context variables. | 868 // Initialize the context variables. |
| 866 // EAX: new object. | 869 // EAX: new object. |
| 867 // EDX: number of context variables. | 870 // EDX: number of context variables. |
| 868 { | 871 { |
| 869 Label loop, entry; | 872 Label loop, entry; |
| 870 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); | 873 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); |
| 871 | 874 |
| 872 __ jmp(&entry, Assembler::kNearJump); | 875 __ jmp(&entry, Assembler::kNearJump); |
| 873 __ Bind(&loop); | 876 __ Bind(&loop); |
| 874 __ decl(EDX); | 877 __ decl(EDX); |
| 875 __ movl(Address(EBX, EDX, TIMES_4, 0), raw_null); | 878 // No generational barrier needed, since we are storing null. |
| 879 __ StoreIntoObjectNoBarrier(EAX, |
| 880 Address(EBX, EDX, TIMES_4, 0), |
| 881 Object::null_object()); |
| 876 __ Bind(&entry); | 882 __ Bind(&entry); |
| 877 __ cmpl(EDX, Immediate(0)); | 883 __ cmpl(EDX, Immediate(0)); |
| 878 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 884 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 879 } | 885 } |
| 880 | 886 |
| 881 // Done allocating and initializing the context. | 887 // Done allocating and initializing the context. |
| 882 // EAX: new object. | 888 // EAX: new object. |
| 883 __ ret(); | 889 __ ret(); |
| 884 | 890 |
| 885 __ Bind(&slow_case); | 891 __ Bind(&slow_case); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 // EBX: potential next object start. | 1024 // EBX: potential next object start. |
| 1019 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); | 1025 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); |
| 1020 if (FLAG_use_slow_path) { | 1026 if (FLAG_use_slow_path) { |
| 1021 __ jmp(&slow_case); | 1027 __ jmp(&slow_case); |
| 1022 } else { | 1028 } else { |
| 1023 __ j(ABOVE_EQUAL, &slow_case); | 1029 __ j(ABOVE_EQUAL, &slow_case); |
| 1024 } | 1030 } |
| 1025 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); | 1031 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); |
| 1026 __ UpdateAllocationStats(cls.id(), ECX, space); | 1032 __ UpdateAllocationStats(cls.id(), ECX, space); |
| 1027 | 1033 |
| 1028 // EAX: new object start. | 1034 // EAX: new object start (untagged). |
| 1029 // EBX: next object start. | 1035 // EBX: next object start. |
| 1030 // EDX: new object type arguments (if is_cls_parameterized). | 1036 // EDX: new object type arguments (if is_cls_parameterized). |
| 1031 // Set the tags. | 1037 // Set the tags. |
| 1032 uword tags = 0; | 1038 uword tags = 0; |
| 1033 tags = RawObject::SizeTag::update(instance_size, tags); | 1039 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1034 ASSERT(cls.id() != kIllegalCid); | 1040 ASSERT(cls.id() != kIllegalCid); |
| 1035 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1041 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1036 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); | 1042 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); |
| 1043 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 1037 | 1044 |
| 1038 // Initialize the remaining words of the object. | 1045 // Initialize the remaining words of the object. |
| 1039 const Immediate& raw_null = | |
| 1040 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1041 | 1046 |
| 1042 // EAX: new object start. | 1047 // EAX: new object (tagged). |
| 1043 // EBX: next object start. | 1048 // EBX: next object start. |
| 1044 // EDX: new object type arguments (if is_cls_parameterized). | 1049 // EDX: new object type arguments (if is_cls_parameterized). |
| 1045 // First try inlining the initialization without a loop. | 1050 // First try inlining the initialization without a loop. |
| 1046 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1051 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1047 // Check if the object contains any non-header fields. | 1052 // Check if the object contains any non-header fields. |
| 1048 // Small objects are initialized using a consecutive set of writes. | 1053 // Small objects are initialized using a consecutive set of writes. |
| 1049 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1054 for (intptr_t current_offset = Instance::NextFieldOffset(); |
| 1050 current_offset < instance_size; | 1055 current_offset < instance_size; |
| 1051 current_offset += kWordSize) { | 1056 current_offset += kWordSize) { |
| 1052 __ movl(Address(EAX, current_offset), raw_null); | 1057 __ StoreIntoObjectNoBarrier(EAX, |
| 1058 FieldAddress(EAX, current_offset), |
| 1059 Object::null_object()); |
| 1053 } | 1060 } |
| 1054 } else { | 1061 } else { |
| 1055 __ leal(ECX, Address(EAX, Instance::NextFieldOffset())); | 1062 __ leal(ECX, Address(EAX, Instance::NextFieldOffset())); |
| 1056 // Loop until the whole object is initialized. | 1063 // Loop until the whole object is initialized. |
| 1057 // EAX: new object. | 1064 // EAX: new object (tagged). |
| 1058 // EBX: next object start. | 1065 // EBX: next object start. |
| 1059 // ECX: next word to be initialized. | 1066 // ECX: next word to be initialized. |
| 1060 // EDX: new object type arguments (if is_cls_parameterized). | 1067 // EDX: new object type arguments (if is_cls_parameterized). |
| 1061 Label init_loop; | 1068 Label init_loop; |
| 1062 Label done; | 1069 Label done; |
| 1063 __ Bind(&init_loop); | 1070 __ Bind(&init_loop); |
| 1064 __ cmpl(ECX, EBX); | 1071 __ cmpl(ECX, EBX); |
| 1065 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1072 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 1066 __ movl(Address(ECX, 0), raw_null); | 1073 __ StoreIntoObjectNoBarrier(EAX, |
| 1074 Address(ECX, 0), |
| 1075 Object::null_object()); |
| 1067 __ addl(ECX, Immediate(kWordSize)); | 1076 __ addl(ECX, Immediate(kWordSize)); |
| 1068 __ jmp(&init_loop, Assembler::kNearJump); | 1077 __ jmp(&init_loop, Assembler::kNearJump); |
| 1069 __ Bind(&done); | 1078 __ Bind(&done); |
| 1070 } | 1079 } |
| 1071 if (is_cls_parameterized) { | 1080 if (is_cls_parameterized) { |
| 1072 // EDX: new object type arguments. | 1081 // EDX: new object type arguments. |
| 1073 // Set the type arguments in the new object. | 1082 // Set the type arguments in the new object. |
| 1074 __ movl(Address(EAX, cls.type_arguments_field_offset()), EDX); | 1083 intptr_t offset = cls.type_arguments_field_offset(); |
| 1084 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX); |
| 1075 } | 1085 } |
| 1076 // Done allocating and initializing the instance. | 1086 // Done allocating and initializing the instance. |
| 1077 // EAX: new object. | 1087 // EAX: new object (tagged). |
| 1078 __ addl(EAX, Immediate(kHeapObjectTag)); | |
| 1079 __ ret(); | 1088 __ ret(); |
| 1080 | 1089 |
| 1081 __ Bind(&slow_case); | 1090 __ Bind(&slow_case); |
| 1082 } | 1091 } |
| 1083 // If is_cls_parameterized: | 1092 // If is_cls_parameterized: |
| 1084 // EDX: new object type arguments. | 1093 // EDX: new object type arguments. |
| 1085 // Create a stub frame as we are pushing some objects on the stack before | 1094 // Create a stub frame as we are pushing some objects on the stack before |
| 1086 // calling into the runtime. | 1095 // calling into the runtime. |
| 1087 __ EnterStubFrame(); | 1096 __ EnterStubFrame(); |
| 1088 __ pushl(raw_null); // Setup space on stack for return value. | 1097 __ pushl(raw_null); // Setup space on stack for return value. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 __ Bind(&error); | 1238 __ Bind(&error); |
| 1230 __ Stop("Incorrect IC data"); | 1239 __ Stop("Incorrect IC data"); |
| 1231 __ Bind(&ok); | 1240 __ Bind(&ok); |
| 1232 #endif | 1241 #endif |
| 1233 // Update counter. | 1242 // Update counter. |
| 1234 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1243 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1235 __ movl(ECX, Address(EBX, count_offset)); | 1244 __ movl(ECX, Address(EBX, count_offset)); |
| 1236 __ addl(ECX, Immediate(Smi::RawValue(1))); | 1245 __ addl(ECX, Immediate(Smi::RawValue(1))); |
| 1237 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1246 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1238 __ cmovno(EDI, ECX); | 1247 __ cmovno(EDI, ECX); |
| 1239 __ movl(Address(EBX, count_offset), EDI); | 1248 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1240 | 1249 |
| 1241 __ ret(); | 1250 __ ret(); |
| 1242 } | 1251 } |
| 1243 | 1252 |
| 1244 | 1253 |
| 1245 // Generate inline cache check for 'num_args'. | 1254 // Generate inline cache check for 'num_args'. |
| 1246 // ECX: Inline cache data object. | 1255 // ECX: Inline cache data object. |
| 1247 // TOS(0): return address | 1256 // TOS(0): return address |
| 1248 // Control flow: | 1257 // Control flow: |
| 1249 // - If receiver is null -> jump to IC miss. | 1258 // - If receiver is null -> jump to IC miss. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1377 __ Bind(&found); | 1386 __ Bind(&found); |
| 1378 // EBX: Pointer to an IC data check group. | 1387 // EBX: Pointer to an IC data check group. |
| 1379 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1388 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1380 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1389 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1381 | 1390 |
| 1382 // Update counter. | 1391 // Update counter. |
| 1383 __ movl(EAX, Address(EBX, count_offset)); | 1392 __ movl(EAX, Address(EBX, count_offset)); |
| 1384 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1393 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1385 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1394 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1386 __ cmovno(EDI, EAX); | 1395 __ cmovno(EDI, EAX); |
| 1387 __ movl(Address(EBX, count_offset), EDI); | 1396 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1388 | 1397 |
| 1389 __ movl(EAX, Address(EBX, target_offset)); | 1398 __ movl(EAX, Address(EBX, target_offset)); |
| 1390 __ Bind(&call_target_function); | 1399 __ Bind(&call_target_function); |
| 1391 // EAX: Target function. | 1400 // EAX: Target function. |
| 1392 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1401 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
| 1393 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1402 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1394 __ jmp(EBX); | 1403 __ jmp(EBX); |
| 1395 __ int3(); | 1404 __ int3(); |
| 1396 | 1405 |
| 1397 __ Bind(&stepping); | 1406 __ Bind(&stepping); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 const Register temp = ECX; | 1952 const Register temp = ECX; |
| 1944 __ movl(left, Address(ESP, 2 * kWordSize)); | 1953 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 1945 __ movl(right, Address(ESP, 1 * kWordSize)); | 1954 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 1946 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1955 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1947 __ ret(); | 1956 __ ret(); |
| 1948 } | 1957 } |
| 1949 | 1958 |
| 1950 } // namespace dart | 1959 } // namespace dart |
| 1951 | 1960 |
| 1952 #endif // defined TARGET_ARCH_IA32 | 1961 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |