Chromium Code Reviews| 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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 430 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 431 __ LeaveFrame(); | 431 __ LeaveFrame(); |
| 432 __ jmp(EAX); | 432 __ jmp(EAX); |
| 433 __ int3(); | 433 __ int3(); |
| 434 } | 434 } |
| 435 | 435 |
| 436 | 436 |
| 437 // Input parameters: | 437 // Input parameters: |
| 438 // EDX: smi-tagged argument count, may be zero. | 438 // EDX: smi-tagged argument count, may be zero. |
| 439 // EBP[kParamEndSlotFromFp + 1]: last argument. | 439 // EBP[kParamEndSlotFromFp + 1]: last argument. |
| 440 // Uses EAX, EBX, ECX, EDX. | 440 // Uses EAX, EBX, ECX, EDX, EDI. |
| 441 static void PushArgumentsArray(Assembler* assembler) { | 441 static void PushArgumentsArray(Assembler* assembler) { |
| 442 const Immediate& raw_null = | 442 const Immediate& raw_null = |
| 443 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 443 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 444 StubCode* stub_code = Isolate::Current()->stub_code(); | 444 StubCode* stub_code = Isolate::Current()->stub_code(); |
| 445 | 445 |
| 446 // Allocate array to store arguments of caller. | 446 // Allocate array to store arguments of caller. |
| 447 __ movl(ECX, raw_null); // Null element type for raw Array. | 447 __ movl(ECX, raw_null); // Null element type for raw Array. |
| 448 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); | 448 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); |
| 449 const ExternalLabel array_label(array_stub.EntryPoint()); | 449 const ExternalLabel array_label(array_stub.EntryPoint()); |
| 450 __ call(&array_label); | 450 __ call(&array_label); |
| 451 __ SmiUntag(EDX); | 451 __ SmiUntag(EDX); |
| 452 // EAX: newly allocated array. | 452 // EAX: newly allocated array. |
| 453 // EDX: length of the array (was preserved by the stub). | 453 // EDX: length of the array (was preserved by the stub). |
| 454 __ pushl(EAX); // Array is in EAX and on top of stack. | 454 __ pushl(EAX); // Array is in EAX and on top of stack. |
| 455 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 455 __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
| 456 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 456 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 457 // EBX: address of first argument on stack. | 457 // EBX: address of first argument on stack. |
| 458 // ECX: address of first argument in array. | 458 // ECX: address of first argument in array. |
| 459 Label loop, loop_condition; | 459 Label loop, loop_condition; |
| 460 __ jmp(&loop_condition, Assembler::kNearJump); | 460 __ jmp(&loop_condition, Assembler::kNearJump); |
| 461 __ Bind(&loop); | 461 __ Bind(&loop); |
| 462 __ movl(EAX, Address(EBX, 0)); | 462 __ movl(EDI, Address(EBX, 0)); |
| 463 __ movl(Address(ECX, 0), EAX); | 463 // No generational barrier needed, since array is in new space. |
| 464 __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), EDI); | |
| 464 __ AddImmediate(ECX, Immediate(kWordSize)); | 465 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 465 __ AddImmediate(EBX, Immediate(-kWordSize)); | 466 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 466 __ Bind(&loop_condition); | 467 __ Bind(&loop_condition); |
| 467 __ decl(EDX); | 468 __ decl(EDX); |
| 468 __ j(POSITIVE, &loop, Assembler::kNearJump); | 469 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 469 } | 470 } |
| 470 | 471 |
| 471 | 472 |
| 472 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 473 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 473 intptr_t deopt_reason, | 474 intptr_t deopt_reason, |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 737 // EDI: iterator which initially points to the start of the variable | 738 // EDI: iterator which initially points to the start of the variable |
| 738 // data area to be initialized. | 739 // data area to be initialized. |
| 739 // ECX: array element type. | 740 // ECX: array element type. |
| 740 // EDX: array length as Smi. | 741 // EDX: array length as Smi. |
| 741 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 742 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
| 742 Label done; | 743 Label done; |
| 743 Label init_loop; | 744 Label init_loop; |
| 744 __ Bind(&init_loop); | 745 __ Bind(&init_loop); |
| 745 __ cmpl(EDI, EBX); | 746 __ cmpl(EDI, EBX); |
| 746 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 747 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 747 __ movl(Address(EDI, 0), raw_null); | 748 // No generational barrier needed, since we are storing null. |
| 749 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | |
| 748 __ addl(EDI, Immediate(kWordSize)); | 750 __ addl(EDI, Immediate(kWordSize)); |
| 749 __ jmp(&init_loop, Assembler::kNearJump); | 751 __ jmp(&init_loop, Assembler::kNearJump); |
| 750 __ Bind(&done); | 752 __ Bind(&done); |
| 751 __ ret(); // returns the newly allocated object in EAX. | 753 __ ret(); // returns the newly allocated object in EAX. |
| 752 | 754 |
| 753 // Unable to allocate the array using the fast inline code, just call | 755 // Unable to allocate the array using the fast inline code, just call |
| 754 // into the runtime. | 756 // into the runtime. |
| 755 __ Bind(&slow_case); | 757 __ Bind(&slow_case); |
| 756 // Create a stub frame as we are pushing some objects on the stack before | 758 // Create a stub frame as we are pushing some objects on the stack before |
| 757 // calling into the runtime. | 759 // calling into the runtime. |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 981 __ orl(EBX, | 983 __ orl(EBX, |
| 982 Immediate(RawObject::ClassIdTag::encode(cid))); | 984 Immediate(RawObject::ClassIdTag::encode(cid))); |
| 983 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags. | 985 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags. |
| 984 } | 986 } |
| 985 | 987 |
| 986 // Setup up number of context variables field. | 988 // Setup up number of context variables field. |
| 987 // EAX: new object. | 989 // EAX: new object. |
| 988 // EDX: number of context variables as integer value (not object). | 990 // EDX: number of context variables as integer value (not object). |
| 989 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 991 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
| 990 | 992 |
| 991 const Immediate& raw_null = | |
| 992 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 993 // Setup the parent field. | 993 // Setup the parent field. |
| 994 // EAX: new object. | 994 // EAX: new object. |
| 995 // EDX: number of context variables. | 995 // EDX: number of context variables. |
| 996 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); | 996 // No generational barrier needed, since we are storing null. |
| 997 __ StoreIntoObjectNoBarrier(EAX, | |
|
Ivan Posva
2014/10/29 07:58:41
Here and other places: In the long run we will nee
koda
2014/10/29 18:29:21
Yes, I was aware of that, and that also applies to
| |
| 998 FieldAddress(EAX, Context::parent_offset()), | |
| 999 Object::null_object()); | |
| 997 | 1000 |
| 998 // Initialize the context variables. | 1001 // Initialize the context variables. |
| 999 // EAX: new object. | 1002 // EAX: new object. |
| 1000 // EDX: number of context variables. | 1003 // EDX: number of context variables. |
| 1001 { | 1004 { |
| 1002 Label loop, entry; | 1005 Label loop, entry; |
| 1003 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); | 1006 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); |
| 1004 | 1007 |
| 1005 __ jmp(&entry, Assembler::kNearJump); | 1008 __ jmp(&entry, Assembler::kNearJump); |
| 1006 __ Bind(&loop); | 1009 __ Bind(&loop); |
| 1007 __ decl(EDX); | 1010 __ decl(EDX); |
| 1008 __ movl(Address(EBX, EDX, TIMES_4, 0), raw_null); | 1011 // No generational barrier needed, since we are storing null. |
| 1012 __ StoreIntoObjectNoBarrier(EAX, | |
| 1013 Address(EBX, EDX, TIMES_4, 0), | |
| 1014 Object::null_object()); | |
| 1009 __ Bind(&entry); | 1015 __ Bind(&entry); |
| 1010 __ cmpl(EDX, Immediate(0)); | 1016 __ cmpl(EDX, Immediate(0)); |
| 1011 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1017 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1012 } | 1018 } |
| 1013 | 1019 |
| 1014 // Done allocating and initializing the context. | 1020 // Done allocating and initializing the context. |
| 1015 // EAX: new object. | 1021 // EAX: new object. |
| 1016 __ ret(); | 1022 __ ret(); |
| 1017 | 1023 |
| 1018 __ Bind(&slow_case); | 1024 __ Bind(&slow_case); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1151 // EBX: potential next object start. | 1157 // EBX: potential next object start. |
| 1152 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); | 1158 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); |
| 1153 if (FLAG_use_slow_path) { | 1159 if (FLAG_use_slow_path) { |
| 1154 __ jmp(&slow_case); | 1160 __ jmp(&slow_case); |
| 1155 } else { | 1161 } else { |
| 1156 __ j(ABOVE_EQUAL, &slow_case); | 1162 __ j(ABOVE_EQUAL, &slow_case); |
| 1157 } | 1163 } |
| 1158 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); | 1164 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); |
| 1159 __ UpdateAllocationStats(cls.id(), ECX, space); | 1165 __ UpdateAllocationStats(cls.id(), ECX, space); |
| 1160 | 1166 |
| 1161 // EAX: new object start. | 1167 // EAX: new object start (untagged). |
| 1162 // EBX: next object start. | 1168 // EBX: next object start. |
| 1163 // EDX: new object type arguments (if is_cls_parameterized). | 1169 // EDX: new object type arguments (if is_cls_parameterized). |
| 1164 // Set the tags. | 1170 // Set the tags. |
| 1165 uword tags = 0; | 1171 uword tags = 0; |
| 1166 tags = RawObject::SizeTag::update(instance_size, tags); | 1172 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1167 ASSERT(cls.id() != kIllegalCid); | 1173 ASSERT(cls.id() != kIllegalCid); |
| 1168 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1174 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1169 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); | 1175 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); |
| 1176 __ addl(EAX, Immediate(kHeapObjectTag)); | |
| 1170 | 1177 |
| 1171 // Initialize the remaining words of the object. | 1178 // Initialize the remaining words of the object. |
| 1172 const Immediate& raw_null = | |
| 1173 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1174 | 1179 |
| 1175 // EAX: new object start. | 1180 // EAX: new object (tagged). |
| 1176 // EBX: next object start. | 1181 // EBX: next object start. |
| 1177 // EDX: new object type arguments (if is_cls_parameterized). | 1182 // EDX: new object type arguments (if is_cls_parameterized). |
| 1178 // First try inlining the initialization without a loop. | 1183 // First try inlining the initialization without a loop. |
| 1179 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1184 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1180 // Check if the object contains any non-header fields. | 1185 // Check if the object contains any non-header fields. |
| 1181 // Small objects are initialized using a consecutive set of writes. | 1186 // Small objects are initialized using a consecutive set of writes. |
| 1182 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1187 for (intptr_t current_offset = Instance::NextFieldOffset(); |
| 1183 current_offset < instance_size; | 1188 current_offset < instance_size; |
| 1184 current_offset += kWordSize) { | 1189 current_offset += kWordSize) { |
| 1185 __ movl(Address(EAX, current_offset), raw_null); | 1190 __ StoreIntoObjectNoBarrier(EAX, |
|
Ivan Posva
2014/10/29 07:58:41
ditto here and other places
| |
| 1191 FieldAddress(EAX, current_offset), | |
| 1192 Object::null_object()); | |
| 1186 } | 1193 } |
| 1187 } else { | 1194 } else { |
| 1188 __ leal(ECX, Address(EAX, Instance::NextFieldOffset())); | 1195 __ leal(ECX, Address(EAX, Instance::NextFieldOffset())); |
| 1189 // Loop until the whole object is initialized. | 1196 // Loop until the whole object is initialized. |
| 1190 // EAX: new object. | 1197 // EAX: new object (tagged). |
| 1191 // EBX: next object start. | 1198 // EBX: next object start. |
| 1192 // ECX: next word to be initialized. | 1199 // ECX: next word to be initialized. |
| 1193 // EDX: new object type arguments (if is_cls_parameterized). | 1200 // EDX: new object type arguments (if is_cls_parameterized). |
| 1194 Label init_loop; | 1201 Label init_loop; |
| 1195 Label done; | 1202 Label done; |
| 1196 __ Bind(&init_loop); | 1203 __ Bind(&init_loop); |
| 1197 __ cmpl(ECX, EBX); | 1204 __ cmpl(ECX, EBX); |
| 1198 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1205 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 1199 __ movl(Address(ECX, 0), raw_null); | 1206 __ StoreIntoObjectNoBarrier(EAX, |
| 1207 Address(ECX, 0), | |
| 1208 Object::null_object()); | |
| 1200 __ addl(ECX, Immediate(kWordSize)); | 1209 __ addl(ECX, Immediate(kWordSize)); |
| 1201 __ jmp(&init_loop, Assembler::kNearJump); | 1210 __ jmp(&init_loop, Assembler::kNearJump); |
| 1202 __ Bind(&done); | 1211 __ Bind(&done); |
| 1203 } | 1212 } |
| 1204 if (is_cls_parameterized) { | 1213 if (is_cls_parameterized) { |
| 1205 // EDX: new object type arguments. | 1214 // EDX: new object type arguments. |
| 1206 // Set the type arguments in the new object. | 1215 // Set the type arguments in the new object. |
| 1207 __ movl(Address(EAX, cls.type_arguments_field_offset()), EDX); | 1216 intptr_t offset = cls.type_arguments_field_offset(); |
| 1217 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX); | |
| 1208 } | 1218 } |
| 1209 // Done allocating and initializing the instance. | 1219 // Done allocating and initializing the instance. |
| 1210 // EAX: new object. | 1220 // EAX: new object (tagged). |
| 1211 __ addl(EAX, Immediate(kHeapObjectTag)); | |
| 1212 __ ret(); | 1221 __ ret(); |
| 1213 | 1222 |
| 1214 __ Bind(&slow_case); | 1223 __ Bind(&slow_case); |
| 1215 } | 1224 } |
| 1216 // If is_cls_parameterized: | 1225 // If is_cls_parameterized: |
| 1217 // EDX: new object type arguments. | 1226 // EDX: new object type arguments. |
| 1218 // Create a stub frame as we are pushing some objects on the stack before | 1227 // Create a stub frame as we are pushing some objects on the stack before |
| 1219 // calling into the runtime. | 1228 // calling into the runtime. |
| 1220 __ EnterStubFrame(); | 1229 __ EnterStubFrame(); |
| 1221 __ pushl(raw_null); // Setup space on stack for return value. | 1230 __ pushl(raw_null); // Setup space on stack for return value. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1362 __ Bind(&error); | 1371 __ Bind(&error); |
| 1363 __ Stop("Incorrect IC data"); | 1372 __ Stop("Incorrect IC data"); |
| 1364 __ Bind(&ok); | 1373 __ Bind(&ok); |
| 1365 #endif | 1374 #endif |
| 1366 // Update counter. | 1375 // Update counter. |
| 1367 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1376 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1368 __ movl(ECX, Address(EBX, count_offset)); | 1377 __ movl(ECX, Address(EBX, count_offset)); |
| 1369 __ addl(ECX, Immediate(Smi::RawValue(1))); | 1378 __ addl(ECX, Immediate(Smi::RawValue(1))); |
| 1370 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1379 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1371 __ cmovno(EDI, ECX); | 1380 __ cmovno(EDI, ECX); |
| 1372 __ movl(Address(EBX, count_offset), EDI); | 1381 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1373 | 1382 |
| 1374 __ ret(); | 1383 __ ret(); |
| 1375 } | 1384 } |
| 1376 | 1385 |
| 1377 | 1386 |
| 1378 // Generate inline cache check for 'num_args'. | 1387 // Generate inline cache check for 'num_args'. |
| 1379 // ECX: Inline cache data object. | 1388 // ECX: Inline cache data object. |
| 1380 // TOS(0): return address | 1389 // TOS(0): return address |
| 1381 // Control flow: | 1390 // Control flow: |
| 1382 // - If receiver is null -> jump to IC miss. | 1391 // - If receiver is null -> jump to IC miss. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1510 __ Bind(&found); | 1519 __ Bind(&found); |
| 1511 // EBX: Pointer to an IC data check group. | 1520 // EBX: Pointer to an IC data check group. |
| 1512 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1521 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1513 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1522 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1514 | 1523 |
| 1515 // Update counter. | 1524 // Update counter. |
| 1516 __ movl(EAX, Address(EBX, count_offset)); | 1525 __ movl(EAX, Address(EBX, count_offset)); |
| 1517 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1526 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1518 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1527 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1519 __ cmovno(EDI, EAX); | 1528 __ cmovno(EDI, EAX); |
| 1520 __ movl(Address(EBX, count_offset), EDI); | 1529 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1521 | 1530 |
| 1522 __ movl(EAX, Address(EBX, target_offset)); | 1531 __ movl(EAX, Address(EBX, target_offset)); |
| 1523 __ Bind(&call_target_function); | 1532 __ Bind(&call_target_function); |
| 1524 // EAX: Target function. | 1533 // EAX: Target function. |
| 1525 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1534 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
| 1526 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1535 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1527 __ jmp(EBX); | 1536 __ jmp(EBX); |
| 1528 __ int3(); | 1537 __ int3(); |
| 1529 | 1538 |
| 1530 __ Bind(&stepping); | 1539 __ Bind(&stepping); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2076 const Register temp = ECX; | 2085 const Register temp = ECX; |
| 2077 __ movl(left, Address(ESP, 2 * kWordSize)); | 2086 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2078 __ movl(right, Address(ESP, 1 * kWordSize)); | 2087 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2079 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2088 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2080 __ ret(); | 2089 __ ret(); |
| 2081 } | 2090 } |
| 2082 | 2091 |
| 2083 } // namespace dart | 2092 } // namespace dart |
| 2084 | 2093 |
| 2085 #endif // defined TARGET_ARCH_IA32 | 2094 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |