| 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" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/instructions.h" | 12 #include "vm/instructions.h" |
| 13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
| 16 #include "vm/scavenger.h" | 16 #include "vm/scavenger.h" |
| 17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 18 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 19 #include "vm/tags.h" | 19 #include "vm/tags.h" |
| 20 | 20 |
| 21 | 21 |
| 22 #define __ assembler-> | 22 #define __ assembler-> |
| 23 | 23 |
| 24 namespace dart { | 24 namespace dart { |
| 25 | 25 |
| 26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
| 27 DEFINE_FLAG(bool, use_slow_path, false, | 27 DEFINE_FLAG(bool, use_slow_path, false, |
| 28 "Set to true for debugging & verifying the slow paths."); | 28 "Set to true for debugging & verifying the slow paths."); |
| 29 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 29 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
| 30 DEFINE_FLAG(bool, verify_incoming_contexts, false, ""); | 30 DECLARE_FLAG(int, optimization_counter_threshold); |
| 31 | 31 |
| 32 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x)) | 32 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x)) |
| 33 | 33 |
| 34 // Input parameters: | 34 // Input parameters: |
| 35 // ESP : points to return address. | 35 // ESP : points to return address. |
| 36 // ESP + 4 : address of last argument in argument array. | 36 // ESP + 4 : address of last argument in argument array. |
| 37 // ESP + 4*EDX : address of first argument in argument array. | 37 // ESP + 4*EDX : address of first argument in argument array. |
| 38 // ESP + 4*EDX + 4 : address of return value. | 38 // ESP + 4*EDX + 4 : address of return value. |
| 39 // ECX : address of the runtime function to call. | 39 // ECX : address of the runtime function to call. |
| 40 // EDX : number of arguments to the call. | 40 // EDX : number of arguments to the call. |
| (...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1178 __ popl(func_reg); // Restore. | 1178 __ popl(func_reg); // Restore. |
| 1179 __ LeaveFrame(); | 1179 __ LeaveFrame(); |
| 1180 } | 1180 } |
| 1181 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1181 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1182 } | 1182 } |
| 1183 | 1183 |
| 1184 | 1184 |
| 1185 // Loads function into 'temp_reg'. | 1185 // Loads function into 'temp_reg'. |
| 1186 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1186 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
| 1187 Register temp_reg) { | 1187 Register temp_reg) { |
| 1188 Register ic_reg = ECX; | 1188 if (FLAG_optimization_counter_threshold >= 0) { |
| 1189 Register func_reg = temp_reg; | 1189 Register ic_reg = ECX; |
| 1190 ASSERT(ic_reg != func_reg); | 1190 Register func_reg = temp_reg; |
| 1191 __ Comment("Increment function counter"); | 1191 ASSERT(ic_reg != func_reg); |
| 1192 __ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); | 1192 __ Comment("Increment function counter"); |
| 1193 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1193 __ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); |
| 1194 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1195 } |
| 1194 } | 1196 } |
| 1195 | 1197 |
| 1196 | 1198 |
| 1197 // Note: ECX must be preserved. | 1199 // Note: ECX must be preserved. |
| 1198 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1200 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1199 // must have been primed with a Smi/Smi check that will be used for counting | 1201 // must have been primed with a Smi/Smi check that will be used for counting |
| 1200 // the invocations. | 1202 // the invocations. |
| 1201 static void EmitFastSmiOp(Assembler* assembler, | 1203 static void EmitFastSmiOp(Assembler* assembler, |
| 1202 Token::Kind kind, | 1204 Token::Kind kind, |
| 1203 intptr_t num_args, | 1205 intptr_t num_args, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 const Immediate& imm_smi_cid = | 1253 const Immediate& imm_smi_cid = |
| 1252 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid))); | 1254 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid))); |
| 1253 __ cmpl(Address(EBX, 0 * kWordSize), imm_smi_cid); | 1255 __ cmpl(Address(EBX, 0 * kWordSize), imm_smi_cid); |
| 1254 __ j(NOT_EQUAL, &error, Assembler::kNearJump); | 1256 __ j(NOT_EQUAL, &error, Assembler::kNearJump); |
| 1255 __ cmpl(Address(EBX, 1 * kWordSize), imm_smi_cid); | 1257 __ cmpl(Address(EBX, 1 * kWordSize), imm_smi_cid); |
| 1256 __ j(EQUAL, &ok, Assembler::kNearJump); | 1258 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1257 __ Bind(&error); | 1259 __ Bind(&error); |
| 1258 __ Stop("Incorrect IC data"); | 1260 __ Stop("Incorrect IC data"); |
| 1259 __ Bind(&ok); | 1261 __ Bind(&ok); |
| 1260 #endif | 1262 #endif |
| 1261 // Update counter. | 1263 if (FLAG_optimization_counter_threshold >= 0) { |
| 1262 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1264 // Update counter. |
| 1263 __ movl(ECX, Address(EBX, count_offset)); | 1265 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1264 __ addl(ECX, Immediate(Smi::RawValue(1))); | 1266 __ movl(ECX, Address(EBX, count_offset)); |
| 1265 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1267 __ addl(ECX, Immediate(Smi::RawValue(1))); |
| 1266 __ cmovno(EDI, ECX); | 1268 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1267 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1269 __ cmovno(EDI, ECX); |
| 1268 | 1270 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1271 } |
| 1269 __ ret(); | 1272 __ ret(); |
| 1270 } | 1273 } |
| 1271 | 1274 |
| 1272 | 1275 |
| 1273 // Generate inline cache check for 'num_args'. | 1276 // Generate inline cache check for 'num_args'. |
| 1274 // ECX: Inline cache data object. | 1277 // ECX: Inline cache data object. |
| 1275 // TOS(0): return address | 1278 // TOS(0): return address |
| 1276 // Control flow: | 1279 // Control flow: |
| 1277 // - If receiver is null -> jump to IC miss. | 1280 // - If receiver is null -> jump to IC miss. |
| 1278 // - If receiver is Smi -> load Smi class. | 1281 // - If receiver is Smi -> load Smi class. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 __ popl(EDX); // Restore arguments descriptor array. | 1418 __ popl(EDX); // Restore arguments descriptor array. |
| 1416 __ LeaveFrame(); | 1419 __ LeaveFrame(); |
| 1417 Label call_target_function; | 1420 Label call_target_function; |
| 1418 __ jmp(&call_target_function); | 1421 __ jmp(&call_target_function); |
| 1419 | 1422 |
| 1420 __ Bind(&found); | 1423 __ Bind(&found); |
| 1421 | 1424 |
| 1422 // EBX: Pointer to an IC data check group. | 1425 // EBX: Pointer to an IC data check group. |
| 1423 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1426 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1424 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1427 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1425 | 1428 if (FLAG_optimization_counter_threshold >= 0) { |
| 1426 __ Comment("Update caller's counter"); | 1429 __ Comment("Update caller's counter"); |
| 1427 __ movl(EAX, Address(EBX, count_offset)); | 1430 __ movl(EAX, Address(EBX, count_offset)); |
| 1428 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1431 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1429 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1432 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1430 __ cmovno(EDI, EAX); | 1433 __ cmovno(EDI, EAX); |
| 1431 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1434 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1435 } |
| 1432 | 1436 |
| 1433 __ movl(EAX, Address(EBX, target_offset)); | 1437 __ movl(EAX, Address(EBX, target_offset)); |
| 1434 __ Bind(&call_target_function); | 1438 __ Bind(&call_target_function); |
| 1435 __ Comment("Call target"); | 1439 __ Comment("Call target"); |
| 1436 // EAX: Target function. | 1440 // EAX: Target function. |
| 1437 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1441 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
| 1438 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1442 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1439 if (range_collection_mode == kCollectRanges) { | 1443 if (range_collection_mode == kCollectRanges) { |
| 1440 __ movl(EDI, Address(ESP, + 1 * kWordSize)); | 1444 __ movl(EDI, Address(ESP, + 1 * kWordSize)); |
| 1441 if (num_args == 2) { | 1445 if (num_args == 2) { |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 __ Bind(&done_stepping); | 1626 __ Bind(&done_stepping); |
| 1623 | 1627 |
| 1624 // ECX: IC data object (preserved). | 1628 // ECX: IC data object (preserved). |
| 1625 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1629 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1626 // EBX: ic_data_array with entries: target functions and count. | 1630 // EBX: ic_data_array with entries: target functions and count. |
| 1627 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1631 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1628 // EBX: points directly to the first ic data array element. | 1632 // EBX: points directly to the first ic data array element. |
| 1629 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1633 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1630 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1634 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1631 | 1635 |
| 1632 // Increment count for this call. | 1636 if (FLAG_optimization_counter_threshold >= 0) { |
| 1633 __ movl(EAX, Address(EBX, count_offset)); | 1637 // Increment count for this call. |
| 1634 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1638 __ movl(EAX, Address(EBX, count_offset)); |
| 1635 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1639 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1636 __ cmovno(EDI, EAX); | 1640 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1637 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1641 __ cmovno(EDI, EAX); |
| 1642 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1643 } |
| 1638 | 1644 |
| 1639 // Load arguments descriptor into EDX. | 1645 // Load arguments descriptor into EDX. |
| 1640 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1646 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1641 | 1647 |
| 1642 // Get function and call it, if possible. | 1648 // Get function and call it, if possible. |
| 1643 __ movl(EAX, Address(EBX, target_offset)); | 1649 __ movl(EAX, Address(EBX, target_offset)); |
| 1644 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1650 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
| 1645 | 1651 |
| 1646 // EBX: Target instructions. | 1652 // EBX: Target instructions. |
| 1647 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1653 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2050 const Register temp = ECX; | 2056 const Register temp = ECX; |
| 2051 __ movl(left, Address(ESP, 2 * kWordSize)); | 2057 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2052 __ movl(right, Address(ESP, 1 * kWordSize)); | 2058 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2053 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2059 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2054 __ ret(); | 2060 __ ret(); |
| 2055 } | 2061 } |
| 2056 | 2062 |
| 2057 } // namespace dart | 2063 } // namespace dart |
| 2058 | 2064 |
| 2059 #endif // defined TARGET_ARCH_IA32 | 2065 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |