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 11 matching lines...) Expand all Loading... | |
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 DECLARE_FLAG(int, optimization_counter_threshold); | 30 DECLARE_FLAG(int, optimization_counter_threshold); |
31 DECLARE_FLAG(bool, support_debugger); | 31 DECLARE_FLAG(bool, support_debugger); |
32 DECLARE_FLAG(bool, lazy_dispatchers); | |
32 | 33 |
33 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x)) | 34 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x)) |
34 | 35 |
35 // Input parameters: | 36 // Input parameters: |
36 // ESP : points to return address. | 37 // ESP : points to return address. |
37 // ESP + 4 : address of last argument in argument array. | 38 // ESP + 4 : address of last argument in argument array. |
38 // ESP + 4*EDX : address of first argument in argument array. | 39 // ESP + 4*EDX : address of first argument in argument array. |
39 // ESP + 4*EDX + 4 : address of return value. | 40 // ESP + 4*EDX + 4 : address of return value. |
40 // ECX : address of the runtime function to call. | 41 // ECX : address of the runtime function to call. |
41 // EDX : number of arguments to the call. | 42 // EDX : number of arguments to the call. |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 __ pushl(EBX); | 499 __ pushl(EBX); |
499 GenerateDeoptimizationSequence(assembler, true); // Preserve EAX. | 500 GenerateDeoptimizationSequence(assembler, true); // Preserve EAX. |
500 } | 501 } |
501 | 502 |
502 | 503 |
503 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 504 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
504 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. | 505 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. |
505 } | 506 } |
506 | 507 |
507 | 508 |
509 static void GenerateDispatcherCode(Assembler* assembler, | |
510 Label* call_target_function) { | |
511 __ Comment("NoSuchMethodDispatch"); | |
512 // When lazily generated invocation dispatchers are disabled, the | |
513 // miss-handler may return null. | |
514 const Immediate& raw_null = | |
515 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
516 __ cmpl(EAX, raw_null); | |
517 __ j(NOT_EQUAL, call_target_function); | |
518 __ EnterStubFrame(); | |
519 // Load the receiver. | |
520 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | |
521 __ movl(EAX, Address( | |
522 EBP, EDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize)); | |
523 __ pushl(raw_null); // Setup space on stack for result. | |
524 __ pushl(EAX); // Receiver. | |
525 __ pushl(ECX); | |
526 __ pushl(EDX); // Arguments descriptor array. | |
527 __ movl(EDX, EDI); | |
528 // EDX: Smi-tagged arguments array length. | |
529 PushArgumentsArray(assembler); | |
530 const intptr_t kNumArgs = 4; | |
531 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | |
532 __ popl(EAX); | |
Florian Schneider
2015/06/17 08:01:34
__ Drop(4);
__ popl(EAX);
rmacnak
2015/06/17 17:42:20
Done.
| |
533 __ popl(EAX); | |
534 __ popl(EAX); | |
535 __ popl(EAX); | |
536 __ popl(EAX); // Return value. | |
537 __ LeaveFrame(); | |
538 __ ret(); | |
539 } | |
540 | |
541 | |
508 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 542 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
509 __ EnterStubFrame(); | 543 __ EnterStubFrame(); |
510 // Load the receiver into EAX. The argument count in the arguments | 544 // Load the receiver into EAX. The argument count in the arguments |
511 // descriptor in EDX is a smi. | 545 // descriptor in EDX is a smi. |
512 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 546 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
513 // Two words (saved fp, stub's pc marker) in the stack above the return | 547 // Two words (saved fp, stub's pc marker) in the stack above the return |
514 // address. | 548 // address. |
515 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); | 549 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); |
516 // Preserve IC data and arguments descriptor. | 550 // Preserve IC data and arguments descriptor. |
517 __ pushl(ECX); | 551 __ pushl(ECX); |
518 __ pushl(EDX); | 552 __ pushl(EDX); |
519 | 553 |
520 const Immediate& raw_null = | 554 const Immediate& raw_null = |
521 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 555 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
522 __ pushl(raw_null); // Space for the result of the runtime call. | 556 __ pushl(raw_null); // Space for the result of the runtime call. |
523 __ pushl(EAX); // Pass receiver. | 557 __ pushl(EAX); // Pass receiver. |
524 __ pushl(ECX); // Pass IC data. | 558 __ pushl(ECX); // Pass IC data. |
525 __ pushl(EDX); // Pass arguments descriptor. | 559 __ pushl(EDX); // Pass arguments descriptor. |
526 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); | 560 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); |
527 // Discard arguments. | 561 // Discard arguments. |
528 __ popl(EAX); | 562 __ popl(EAX); |
529 __ popl(EAX); | 563 __ popl(EAX); |
530 __ popl(EAX); | 564 __ popl(EAX); |
531 __ popl(EAX); // Return value from the runtime call (function). | 565 __ popl(EAX); // Return value from the runtime call (function). |
532 __ popl(EDX); // Restore arguments descriptor. | 566 __ popl(EDX); // Restore arguments descriptor. |
533 __ popl(ECX); // Restore IC data. | 567 __ popl(ECX); // Restore IC data. |
534 __ LeaveFrame(); | 568 __ LeaveFrame(); |
535 | 569 |
570 if (!FLAG_lazy_dispatchers) { | |
571 Label call_target_function; | |
572 GenerateDispatcherCode(assembler, &call_target_function); | |
573 __ Bind(&call_target_function); | |
574 } | |
575 | |
536 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 576 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
537 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 577 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
538 __ jmp(EBX); | 578 __ jmp(EBX); |
539 } | 579 } |
540 | 580 |
541 | 581 |
542 // Called for inline allocation of arrays. | 582 // Called for inline allocation of arrays. |
543 // Input parameters: | 583 // Input parameters: |
544 // EDX : Array length as Smi (must be preserved). | 584 // EDX : Array length as Smi (must be preserved). |
545 // ECX : array element type (either NULL or an instantiated type). | 585 // ECX : array element type (either NULL or an instantiated type). |
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1363 | 1403 |
1364 // EAX: next argument class ID (smi). | 1404 // EAX: next argument class ID (smi). |
1365 __ movl(EDI, Address(EBX, i * kWordSize)); | 1405 __ movl(EDI, Address(EBX, i * kWordSize)); |
1366 // EDI: next class ID to check (smi). | 1406 // EDI: next class ID to check (smi). |
1367 } | 1407 } |
1368 __ cmpl(EAX, EDI); // Class id match? | 1408 __ cmpl(EAX, EDI); // Class id match? |
1369 if (i < (num_args - 1)) { | 1409 if (i < (num_args - 1)) { |
1370 __ j(NOT_EQUAL, &update); // Continue. | 1410 __ j(NOT_EQUAL, &update); // Continue. |
1371 } else { | 1411 } else { |
1372 // Last check, all checks before matched. | 1412 // Last check, all checks before matched. |
1373 __ j(EQUAL, &found, Assembler::kNearJump); // Break. | 1413 __ j(EQUAL, &found); // Break. |
1374 } | 1414 } |
1375 } | 1415 } |
1376 __ Bind(&update); | 1416 __ Bind(&update); |
1377 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1417 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
1378 if (num_args > 1) { | 1418 if (num_args > 1) { |
1379 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1419 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
1380 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); | 1420 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); |
1381 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); | 1421 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); |
1382 } | 1422 } |
1383 | 1423 |
(...skipping 27 matching lines...) Expand all Loading... | |
1411 __ CallRuntime(handle_ic_miss, num_args + 1); | 1451 __ CallRuntime(handle_ic_miss, num_args + 1); |
1412 // Remove the call arguments pushed earlier, including the IC data object. | 1452 // Remove the call arguments pushed earlier, including the IC data object. |
1413 for (intptr_t i = 0; i < num_args + 1; i++) { | 1453 for (intptr_t i = 0; i < num_args + 1; i++) { |
1414 __ popl(EAX); | 1454 __ popl(EAX); |
1415 } | 1455 } |
1416 __ popl(EAX); // Pop returned function object into EAX. | 1456 __ popl(EAX); // Pop returned function object into EAX. |
1417 __ popl(ECX); // Restore IC data array. | 1457 __ popl(ECX); // Restore IC data array. |
1418 __ popl(EDX); // Restore arguments descriptor array. | 1458 __ popl(EDX); // Restore arguments descriptor array. |
1419 __ LeaveFrame(); | 1459 __ LeaveFrame(); |
1420 Label call_target_function; | 1460 Label call_target_function; |
1421 __ jmp(&call_target_function); | 1461 if (!FLAG_lazy_dispatchers) { |
1462 GenerateDispatcherCode(assembler, &call_target_function); | |
1463 } else { | |
1464 __ jmp(&call_target_function); | |
1465 } | |
1422 | 1466 |
1423 __ Bind(&found); | 1467 __ Bind(&found); |
1424 | 1468 |
1425 // EBX: Pointer to an IC data check group. | 1469 // EBX: Pointer to an IC data check group. |
1426 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1470 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
1427 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1471 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1428 if (FLAG_optimization_counter_threshold >= 0) { | 1472 if (FLAG_optimization_counter_threshold >= 0) { |
1429 __ Comment("Update caller's counter"); | 1473 __ Comment("Update caller's counter"); |
1430 __ movl(EAX, Address(EBX, count_offset)); | 1474 __ movl(EAX, Address(EBX, count_offset)); |
1431 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1475 __ addl(EAX, Immediate(Smi::RawValue(1))); |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2082 // EBX: entry point. | 2126 // EBX: entry point. |
2083 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2127 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2084 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); | 2128 EmitMegamorphicLookup(assembler, EDI, EBX, EBX); |
2085 __ ret(); | 2129 __ ret(); |
2086 } | 2130 } |
2087 | 2131 |
2088 | 2132 |
2089 } // namespace dart | 2133 } // namespace dart |
2090 | 2134 |
2091 #endif // defined TARGET_ARCH_IA32 | 2135 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |