| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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" |
| 9 #include "vm/assembler_macros.h" |
| 8 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| 9 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
| 10 #include "vm/object_store.h" | 12 #include "vm/object_store.h" |
| 11 #include "vm/pages.h" | 13 #include "vm/pages.h" |
| 12 #include "vm/resolver.h" | 14 #include "vm/resolver.h" |
| 13 #include "vm/scavenger.h" | 15 #include "vm/scavenger.h" |
| 14 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
| 15 | 17 |
| 16 | 18 |
| 17 #define __ assembler-> | 19 #define __ assembler-> |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 | 96 |
| 95 // Input parameters: | 97 // Input parameters: |
| 96 // ESP : points to return address. | 98 // ESP : points to return address. |
| 97 // EAX : stop message (const char*). | 99 // EAX : stop message (const char*). |
| 98 // Must preserve all registers, except EAX. | 100 // Must preserve all registers, except EAX. |
| 99 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { | 101 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { |
| 100 // Preserve caller-saved registers. | 102 // Preserve caller-saved registers. |
| 101 __ pushl(ECX); | 103 __ pushl(ECX); |
| 102 __ pushl(EDX); | 104 __ pushl(EDX); |
| 103 | 105 |
| 104 __ EnterFrame(0); | 106 // Create a stub frame as we are pushing some objects on the stack before |
| 107 // calling into the runtime. |
| 108 AssemblerMacros::EnterStubFrame(assembler); |
| 105 | 109 |
| 106 // Reserve space for the native argument and align frame before entering | 110 // Reserve space for the native argument and align frame before entering |
| 107 // the C++ world. | 111 // the C++ world. |
| 108 __ AddImmediate(ESP, Immediate(-sizeof(kWordSize))); | 112 __ AddImmediate(ESP, Immediate(-sizeof(kWordSize))); |
| 109 if (OS::ActivationFrameAlignment() > 0) { | 113 if (OS::ActivationFrameAlignment() > 0) { |
| 110 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 114 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 111 } | 115 } |
| 112 | 116 |
| 113 // Pass argument and call native function. | 117 // Pass argument and call native function. |
| 114 __ movl(Address(ESP, 0), EAX); | 118 __ movl(Address(ESP, 0), EAX); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 const Immediate raw_null = | 208 const Immediate raw_null = |
| 205 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 209 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 206 | 210 |
| 207 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 211 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 208 __ cmpl(EAX, raw_null); | 212 __ cmpl(EAX, raw_null); |
| 209 Label function_compiled; | 213 Label function_compiled; |
| 210 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); | 214 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| 211 | 215 |
| 212 // Create a stub frame as we are pushing some objects on the stack before | 216 // Create a stub frame as we are pushing some objects on the stack before |
| 213 // calling into the runtime. | 217 // calling into the runtime. |
| 214 __ EnterFrame(0); | 218 AssemblerMacros::EnterStubFrame(assembler); |
| 215 | 219 |
| 216 __ pushl(EDX); // Preserve arguments descriptor array. | 220 __ pushl(EDX); // Preserve arguments descriptor array. |
| 217 __ pushl(ECX); | 221 __ pushl(ECX); |
| 218 __ CallRuntime(kCompileFunctionRuntimeEntry); | 222 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| 219 __ popl(ECX); // Restore read-only function object argument in ECX. | 223 __ popl(ECX); // Restore read-only function object argument in ECX. |
| 220 __ popl(EDX); // Restore arguments descriptor array. | 224 __ popl(EDX); // Restore arguments descriptor array. |
| 221 // Restore EAX. | 225 // Restore EAX. |
| 222 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 226 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 223 | 227 |
| 224 // Remove the stub frame as we are about to jump to the dart function. | 228 // Remove the stub frame as we are about to jump to the dart function. |
| 225 __ LeaveFrame(); | 229 __ LeaveFrame(); |
| 226 | 230 |
| 227 __ Bind(&function_compiled); | 231 __ Bind(&function_compiled); |
| 228 // Patch caller. | 232 // Patch caller. |
| 229 __ EnterFrame(0); | 233 |
| 234 // Create a stub frame as we are pushing some objects on the stack before |
| 235 // calling into the runtime. |
| 236 AssemblerMacros::EnterStubFrame(assembler); |
| 230 | 237 |
| 231 __ pushl(EDX); // Preserve arguments descriptor array. | 238 __ pushl(EDX); // Preserve arguments descriptor array. |
| 232 __ pushl(ECX); // Preserve function object. | 239 __ pushl(ECX); // Preserve function object. |
| 233 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 240 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
| 234 __ popl(ECX); // Restore function object argument in ECX. | 241 __ popl(ECX); // Restore function object argument in ECX. |
| 235 __ popl(EDX); // Restore arguments descriptor array. | 242 __ popl(EDX); // Restore arguments descriptor array. |
| 236 // Remove the stub frame as we are about to jump to the dart function. | 243 // Remove the stub frame as we are about to jump to the dart function. |
| 237 __ LeaveFrame(); | 244 __ LeaveFrame(); |
| 245 |
| 238 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 246 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 239 | |
| 240 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 247 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 241 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 248 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 242 __ jmp(ECX); | 249 __ jmp(ECX); |
| 243 } | 250 } |
| 244 | 251 |
| 245 | 252 |
| 246 // Called from a static call only when an invalid code has been entered | 253 // Called from a static call only when an invalid code has been entered |
| 247 // (invalid because its function was optimized or deoptimized). | 254 // (invalid because its function was optimized or deoptimized). |
| 248 // ECX: function object. | 255 // ECX: function object. |
| 249 // EDX: arguments descriptor array (num_args is first Smi element). | 256 // EDX: arguments descriptor array (num_args is first Smi element). |
| 250 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 257 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 251 __ EnterFrame(0); | 258 // Create a stub frame as we are pushing some objects on the stack before |
| 259 // calling into the runtime. |
| 260 AssemblerMacros::EnterStubFrame(assembler); |
| 252 __ pushl(EDX); // Preserve arguments descriptor array. | 261 __ pushl(EDX); // Preserve arguments descriptor array. |
| 253 __ pushl(ECX); // Preserve target function. | 262 __ pushl(ECX); // Preserve target function. |
| 254 __ pushl(ECX); // Target function. | 263 __ pushl(ECX); // Target function. |
| 255 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 264 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
| 256 __ popl(EAX); // discard argument. | 265 __ popl(EAX); // discard argument. |
| 257 __ popl(EAX); // Restore function. | 266 __ popl(EAX); // Restore function. |
| 258 __ popl(EDX); // Restore arguments descriptor array. | 267 __ popl(EDX); // Restore arguments descriptor array. |
| 259 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 268 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 260 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 269 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 261 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 270 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 397 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 389 const Immediate raw_null = | 398 const Immediate raw_null = |
| 390 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 399 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 391 | 400 |
| 392 MegamorphicLookup(assembler); | 401 MegamorphicLookup(assembler); |
| 393 // Lookup in function_table_ failed, resolve, compile and enter function | 402 // Lookup in function_table_ failed, resolve, compile and enter function |
| 394 // into function_table_. | 403 // into function_table_. |
| 395 | 404 |
| 396 // Create a stub frame as we are pushing some objects on the stack before | 405 // Create a stub frame as we are pushing some objects on the stack before |
| 397 // calling into the runtime. | 406 // calling into the runtime. |
| 398 __ EnterFrame(0); | 407 AssemblerMacros::EnterStubFrame(assembler); |
| 399 | 408 |
| 400 // Preserve values across call to resolving. | 409 // Preserve values across call to resolving. |
| 401 // Stack at this point: | 410 // Stack at this point: |
| 402 // TOS + 0: Saved EBP of previous frame. <== EBP | 411 // TOS + 0: PC marker => RawInstruction object. |
| 403 // TOS + 1: Dart code return address | 412 // TOS + 1: Saved EBP of previous frame. <== EBP |
| 404 // TOS + 2: Last argument of caller. | 413 // TOS + 2: Dart code return address |
| 414 // TOS + 3: Last argument of caller. |
| 405 // .... | 415 // .... |
| 406 // Total number of args is the first Smi in args descriptor array (EDX). | 416 // Total number of args is the first Smi in args descriptor array (EDX). |
| 407 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 417 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 408 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. | 418 __ movl(EAX, Address(EBP, EAX, TIMES_2, kWordSize)); // Get receiver. |
| 409 __ pushl(EDX); // Preserve arguments descriptor array. | 419 __ pushl(EDX); // Preserve arguments descriptor array. |
| 410 __ pushl(EAX); // Preserve receiver. | 420 __ pushl(EAX); // Preserve receiver. |
| 411 __ pushl(ECX); // Preserve ic-data. | 421 __ pushl(ECX); // Preserve ic-data. |
| 412 // First resolve the function to get the function object. | 422 // First resolve the function to get the function object. |
| 413 | 423 |
| 414 __ pushl(raw_null); // Setup space on stack for return value. | 424 __ pushl(raw_null); // Setup space on stack for return value. |
| 415 __ pushl(EAX); // Push receiver. | 425 __ pushl(EAX); // Push receiver. |
| 416 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry); | 426 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry); |
| 417 __ popl(EAX); // Remove receiver pushed earlier. | 427 __ popl(EAX); // Remove receiver pushed earlier. |
| 418 __ popl(ECX); // Pop returned code object into ECX. | 428 __ popl(ECX); // Pop returned code object into ECX. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 509 __ j(EQUAL, &function_not_found, Assembler::kNearJump); |
| 500 | 510 |
| 501 // ECX: Closure object. | 511 // ECX: Closure object. |
| 502 // EDI: Arguments descriptor array. | 512 // EDI: Arguments descriptor array. |
| 503 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. | 513 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. |
| 504 __ pushl(ECX); // Closure object. | 514 __ pushl(ECX); // Closure object. |
| 505 __ pushl(EDI); // Arguments descriptor. | 515 __ pushl(EDI); // Arguments descriptor. |
| 506 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 516 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 507 __ SmiUntag(EDI); | 517 __ SmiUntag(EDI); |
| 508 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 518 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 509 PushArgumentsArray(assembler, (kWordSize * 5)); | 519 PushArgumentsArray(assembler, (kWordSize * 6)); |
| 510 // Stack layout explaining "(kWordSize * 5)" offset. | 520 // Stack layout explaining "(kWordSize * 6)" offset. |
| 511 // TOS + 0: Argument array. | 521 // TOS + 0: Argument array. |
| 512 // TOS + 1: Arguments descriptor array. | 522 // TOS + 1: Arguments descriptor array. |
| 513 // TOS + 2: Closure object. | 523 // TOS + 2: Closure object. |
| 514 // TOS + 3: Place for result from closure function. | 524 // TOS + 3: Place for result from closure function. |
| 515 // TOS + 4: Saved EBP of previous frame. <== EBP | 525 // TOS + 4: PC marker => RawInstruction object. |
| 516 // TOS + 5: Dart code return address | 526 // TOS + 5: Saved EBP of previous frame. <== EBP |
| 517 // TOS + 6: Last argument of caller. | 527 // TOS + 6: Dart code return address |
| 528 // TOS + 7: Last argument of caller. |
| 518 // .... | 529 // .... |
| 519 | 530 |
| 520 __ CallRuntime(kInvokeImplicitClosureFunctionRuntimeEntry); | 531 __ CallRuntime(kInvokeImplicitClosureFunctionRuntimeEntry); |
| 521 // Remove arguments. | 532 // Remove arguments. |
| 522 __ popl(EAX); | 533 __ popl(EAX); |
| 523 __ popl(EAX); | 534 __ popl(EAX); |
| 524 __ popl(EAX); | 535 __ popl(EAX); |
| 525 __ popl(EAX); // Get result into EAX. | 536 __ popl(EAX); // Get result into EAX. |
| 526 | 537 |
| 527 // Remove the stub frame as we are about to return. | 538 // Remove the stub frame as we are about to return. |
| 528 __ LeaveFrame(); | 539 __ LeaveFrame(); |
| 529 __ ret(); | 540 __ ret(); |
| 530 | 541 |
| 531 __ Bind(&function_not_found); | 542 __ Bind(&function_not_found); |
| 532 // The target function was not found, so invoke method | 543 // The target function was not found, so invoke method |
| 533 // "void noSuchMethod(function_name, args_array)". | 544 // "void noSuchMethod(function_name, args_array)". |
| 534 // EAX: receiver. | 545 // EAX: receiver. |
| 535 // EDX: ic-data. | 546 // EDX: ic-data. |
| 536 // ECX: raw_null. | 547 // ECX: raw_null. |
| 537 // EDI: argument descriptor array. | 548 // EDI: argument descriptor array. |
| 538 | 549 |
| 539 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 550 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 540 __ pushl(EAX); // Receiver. | 551 __ pushl(EAX); // Receiver. |
| 541 __ pushl(EDX); // IC-data. | 552 __ pushl(EDX); // IC-data. |
| 542 __ pushl(EDI); // Argument descriptor array. | 553 __ pushl(EDI); // Argument descriptor array. |
| 543 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 554 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 544 __ SmiUntag(EDI); | 555 __ SmiUntag(EDI); |
| 545 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 556 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 546 // See stack layout below explaining "wordSize * 6" offset. | 557 // See stack layout below explaining "wordSize * 7" offset. |
| 547 PushArgumentsArray(assembler, (kWordSize * 6)); | 558 PushArgumentsArray(assembler, (kWordSize * 7)); |
| 548 | 559 |
| 549 // Stack: | 560 // Stack: |
| 550 // TOS + 0: Argument array. | 561 // TOS + 0: Argument array. |
| 551 // TOS + 1: Argument descriptor array. | 562 // TOS + 1: Argument descriptor array. |
| 552 // TOS + 2: IC-data. | 563 // TOS + 2: IC-data. |
| 553 // TOS + 3: Receiver. | 564 // TOS + 3: Receiver |
| 554 // TOS + 4: Place for result from noSuchMethod. | 565 // TOS + 4: Place for result from noSuchMethod. |
| 555 // TOS + 5: Saved EBP of previous frame. <== EBP | 566 // TOS + 5: PC marker => RawInstruction object. |
| 556 // TOS + 6: Dart code return address | 567 // TOS + 6: Saved EBP of previous frame. <== EBP |
| 557 // TOS + 7: Last argument of caller. | 568 // TOS + 7: Dart code return address |
| 569 // TOS + 8: Last argument of caller. |
| 558 // .... | 570 // .... |
| 559 | 571 |
| 560 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); | 572 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 561 // Remove arguments. | 573 // Remove arguments. |
| 562 __ popl(EAX); | 574 __ popl(EAX); |
| 563 __ popl(EAX); | 575 __ popl(EAX); |
| 564 __ popl(EAX); | 576 __ popl(EAX); |
| 565 __ popl(EAX); | 577 __ popl(EAX); |
| 566 __ popl(EAX); // Get result into EAX. | 578 __ popl(EAX); // Get result into EAX. |
| 567 | 579 |
| 568 // Remove the stub frame as we are about to return. | 580 // Remove the stub frame as we are about to return. |
| 569 __ LeaveFrame(); | 581 __ LeaveFrame(); |
| 570 __ ret(); | 582 __ ret(); |
| 571 } | 583 } |
| 572 | 584 |
| 573 | 585 |
| 574 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 586 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 575 __ EnterFrame(0); | 587 // Create a stub frame as we are pushing some objects on the stack before |
| 588 // calling into the runtime. |
| 589 AssemblerMacros::EnterStubFrame(assembler); |
| 576 // EAX: deoptimization reason id. | 590 // EAX: deoptimization reason id. |
| 577 // Stack at this point: | 591 // Stack at this point: |
| 578 // TOS + 0: Saved EBP of function frame that will be deoptimized. <== EBP | 592 // TOS + 0: PC marker => RawInstruction object. |
| 579 // TOS + 1: Deoptimization point (return address), will be patched. | 593 // TOS + 1: Saved EBP of function frame that will be deoptimized. <== EBP |
| 580 // TOS + 2: top-of-stack at deoptimization point (all arguments on stack). | 594 // TOS + 2: Deoptimization point (return address), will be patched. |
| 595 // TOS + 3: top-of-stack at deoptimization point (all arguments on stack). |
| 581 __ pushl(EAX); | 596 __ pushl(EAX); |
| 582 __ CallRuntime(kDeoptimizeRuntimeEntry); | 597 __ CallRuntime(kDeoptimizeRuntimeEntry); |
| 583 __ popl(EAX); | 598 __ popl(EAX); |
| 584 __ LeaveFrame(); | 599 __ LeaveFrame(); |
| 585 __ ret(); | 600 __ ret(); |
| 586 } | 601 } |
| 587 | 602 |
| 588 | 603 |
| 589 // Called for inline allocation of arrays. | 604 // Called for inline allocation of arrays. |
| 590 // Input parameters: | 605 // Input parameters: |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 | 725 |
| 711 // Done allocating and initializing the array. | 726 // Done allocating and initializing the array. |
| 712 // EAX: new object. | 727 // EAX: new object. |
| 713 // EDX: Array length as Smi (preserved for the caller.) | 728 // EDX: Array length as Smi (preserved for the caller.) |
| 714 __ ret(); | 729 __ ret(); |
| 715 } | 730 } |
| 716 | 731 |
| 717 // Unable to allocate the array using the fast inline code, just call | 732 // Unable to allocate the array using the fast inline code, just call |
| 718 // into the runtime. | 733 // into the runtime. |
| 719 __ Bind(&slow_case); | 734 __ Bind(&slow_case); |
| 720 __ EnterFrame(0); | 735 // Create a stub frame as we are pushing some objects on the stack before |
| 736 // calling into the runtime. |
| 737 AssemblerMacros::EnterStubFrame(assembler); |
| 721 __ pushl(raw_null); // Setup space on stack for return value. | 738 __ pushl(raw_null); // Setup space on stack for return value. |
| 722 __ pushl(EDX); // Array length as Smi. | 739 __ pushl(EDX); // Array length as Smi. |
| 723 __ pushl(ECX); // Element type. | 740 __ pushl(ECX); // Element type. |
| 724 __ CallRuntime(kAllocateArrayRuntimeEntry); | 741 __ CallRuntime(kAllocateArrayRuntimeEntry); |
| 725 __ popl(EAX); // Pop element type argument. | 742 __ popl(EAX); // Pop element type argument. |
| 726 __ popl(EDX); // Pop array length argument. | 743 __ popl(EDX); // Pop array length argument. |
| 727 __ popl(EAX); // Pop return value from return slot. | 744 __ popl(EAX); // Pop return value from return slot. |
| 728 __ LeaveFrame(); | 745 __ LeaveFrame(); |
| 729 __ ret(); | 746 __ ret(); |
| 730 } | 747 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); | 785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); |
| 769 | 786 |
| 770 // Load closure function code in EAX. | 787 // Load closure function code in EAX. |
| 771 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 788 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 772 __ cmpl(EAX, raw_null); | 789 __ cmpl(EAX, raw_null); |
| 773 Label function_compiled; | 790 Label function_compiled; |
| 774 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); | 791 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| 775 | 792 |
| 776 // Create a stub frame as we are pushing some objects on the stack before | 793 // Create a stub frame as we are pushing some objects on the stack before |
| 777 // calling into the runtime. | 794 // calling into the runtime. |
| 778 __ EnterFrame(0); | 795 AssemblerMacros::EnterStubFrame(assembler); |
| 779 | 796 |
| 780 __ pushl(EDX); // Preserve arguments descriptor array. | 797 __ pushl(EDX); // Preserve arguments descriptor array. |
| 781 __ pushl(ECX); | 798 __ pushl(ECX); |
| 782 __ CallRuntime(kCompileFunctionRuntimeEntry); | 799 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| 783 __ popl(ECX); // Restore read-only function object argument in ECX. | 800 __ popl(ECX); // Restore read-only function object argument in ECX. |
| 784 __ popl(EDX); // Restore arguments descriptor array. | 801 __ popl(EDX); // Restore arguments descriptor array. |
| 785 // Restore EAX. | 802 // Restore EAX. |
| 786 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 803 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 787 | 804 |
| 788 // Remove the stub frame as we are about to jump to the closure function. | 805 // Remove the stub frame as we are about to jump to the closure function. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 799 | 816 |
| 800 __ Bind(¬_closure); | 817 __ Bind(¬_closure); |
| 801 // Call runtime to report that a closure call was attempted on a non-closure | 818 // Call runtime to report that a closure call was attempted on a non-closure |
| 802 // object, passing the non-closure object and its arguments array. | 819 // object, passing the non-closure object and its arguments array. |
| 803 // EDI: non-closure object. | 820 // EDI: non-closure object. |
| 804 // EDX: arguments descriptor array (num_args is first Smi element, closure | 821 // EDX: arguments descriptor array (num_args is first Smi element, closure |
| 805 // object is not included in num_args). | 822 // object is not included in num_args). |
| 806 | 823 |
| 807 // Create a stub frame as we are pushing some objects on the stack before | 824 // Create a stub frame as we are pushing some objects on the stack before |
| 808 // calling into the runtime. | 825 // calling into the runtime. |
| 809 __ EnterFrame(0); | 826 AssemblerMacros::EnterStubFrame(assembler); |
| 810 | 827 |
| 811 __ pushl(raw_null); // Setup space on stack for result from error reporting. | 828 __ pushl(raw_null); // Setup space on stack for result from error reporting. |
| 812 __ pushl(EDI); // Non-closure object. | 829 __ pushl(EDI); // Non-closure object. |
| 813 // Total number of args is the first Smi in args descriptor array (EDX). | 830 // Total number of args is the first Smi in args descriptor array (EDX). |
| 814 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); // Load num_args. | 831 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); // Load num_args. |
| 815 __ SmiUntag(EDI); | 832 __ SmiUntag(EDI); |
| 816 // See stack layout below explaining "wordSize * 4" offset. | 833 // See stack layout below explaining "wordSize * 5" offset. |
| 817 PushArgumentsArray(assembler, (kWordSize * 4)); | 834 PushArgumentsArray(assembler, (kWordSize * 5)); |
| 818 | 835 |
| 819 // Stack: | 836 // Stack: |
| 820 // TOS + 0: Argument array. | 837 // TOS + 0: Argument array. |
| 821 // TOS + 1: Non-closure object. | 838 // TOS + 1: Non-closure object. |
| 822 // TOS + 2: Place for result from reporting the error. | 839 // TOS + 2: Place for result from reporting the error. |
| 823 // TOS + 3: Saved EBP of previous frame. <== EBP | 840 // TOS + 3: PC marker => RawInstruction object. |
| 824 // TOS + 4: Dart code return address | 841 // TOS + 4: Saved EBP of previous frame. <== EBP |
| 825 // TOS + 5: Last argument of caller. | 842 // TOS + 5: Dart code return address |
| 843 // TOS + 6: Last argument of caller. |
| 826 // .... | 844 // .... |
| 827 __ CallRuntime(kReportObjectNotClosureRuntimeEntry); | 845 __ CallRuntime(kReportObjectNotClosureRuntimeEntry); |
| 828 __ Stop("runtime call throws an exception"); | 846 __ Stop("runtime call throws an exception"); |
| 829 } | 847 } |
| 830 | 848 |
| 831 | 849 |
| 832 // Called when invoking dart code from C++ (VM code). | 850 // Called when invoking dart code from C++ (VM code). |
| 833 // Input parameters: | 851 // Input parameters: |
| 834 // ESP : points to return address. | 852 // ESP : points to return address. |
| 835 // ESP + 4 : entrypoint of the dart function to call. | 853 // ESP + 4 : entrypoint of the dart function to call. |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 __ cmpl(EDX, Immediate(0)); | 1071 __ cmpl(EDX, Immediate(0)); |
| 1054 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1072 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1055 } | 1073 } |
| 1056 | 1074 |
| 1057 // Done allocating and initializing the context. | 1075 // Done allocating and initializing the context. |
| 1058 // EAX: new object. | 1076 // EAX: new object. |
| 1059 __ ret(); | 1077 __ ret(); |
| 1060 | 1078 |
| 1061 __ Bind(&slow_case); | 1079 __ Bind(&slow_case); |
| 1062 } | 1080 } |
| 1063 // Create a stub frame. | 1081 // Create a stub frame as we are pushing some objects on the stack before |
| 1064 __ EnterFrame(0); | 1082 // calling into the runtime. |
| 1083 AssemblerMacros::EnterStubFrame(assembler); |
| 1065 __ pushl(raw_null); // Setup space on stack for return value. | 1084 __ pushl(raw_null); // Setup space on stack for return value. |
| 1066 __ SmiTag(EDX); | 1085 __ SmiTag(EDX); |
| 1067 __ pushl(EDX); | 1086 __ pushl(EDX); |
| 1068 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. | 1087 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. |
| 1069 __ popl(EAX); // Pop number of context variables argument. | 1088 __ popl(EAX); // Pop number of context variables argument. |
| 1070 __ popl(EAX); // Pop the new context object. | 1089 __ popl(EAX); // Pop the new context object. |
| 1071 // EAX: new object | 1090 // EAX: new object |
| 1072 // Restore the frame pointer. | 1091 // Restore the frame pointer. |
| 1073 __ LeaveFrame(); | 1092 __ LeaveFrame(); |
| 1074 __ ret(); | 1093 __ ret(); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 // EAX: new object. | 1263 // EAX: new object. |
| 1245 __ addl(EAX, Immediate(kHeapObjectTag)); | 1264 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 1246 __ ret(); | 1265 __ ret(); |
| 1247 | 1266 |
| 1248 __ Bind(&slow_case); | 1267 __ Bind(&slow_case); |
| 1249 } | 1268 } |
| 1250 if (is_cls_parameterized) { | 1269 if (is_cls_parameterized) { |
| 1251 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); | 1270 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); |
| 1252 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); | 1271 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); |
| 1253 } | 1272 } |
| 1254 // Create a stub frame. | 1273 // Create a stub frame as we are pushing some objects on the stack before |
| 1255 __ EnterFrame(0); | 1274 // calling into the runtime. |
| 1275 AssemblerMacros::EnterStubFrame(assembler); |
| 1256 __ pushl(raw_null); // Setup space on stack for return value. | 1276 __ pushl(raw_null); // Setup space on stack for return value. |
| 1257 __ PushObject(cls); // Push class of object to be allocated. | 1277 __ PushObject(cls); // Push class of object to be allocated. |
| 1258 if (is_cls_parameterized) { | 1278 if (is_cls_parameterized) { |
| 1259 __ pushl(EAX); // Push type arguments of object to be allocated. | 1279 __ pushl(EAX); // Push type arguments of object to be allocated. |
| 1260 __ pushl(EDX); // Push type arguments of instantiator. | 1280 __ pushl(EDX); // Push type arguments of instantiator. |
| 1261 } else { | 1281 } else { |
| 1262 __ pushl(raw_null); // Push null type arguments. | 1282 __ pushl(raw_null); // Push null type arguments. |
| 1263 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1283 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1264 } | 1284 } |
| 1265 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. | 1285 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 __ ret(); | 1421 __ ret(); |
| 1402 | 1422 |
| 1403 __ Bind(&slow_case); | 1423 __ Bind(&slow_case); |
| 1404 } | 1424 } |
| 1405 if (has_type_arguments) { | 1425 if (has_type_arguments) { |
| 1406 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); | 1426 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); |
| 1407 } | 1427 } |
| 1408 if (is_implicit_instance_closure) { | 1428 if (is_implicit_instance_closure) { |
| 1409 __ movl(EAX, Address(ESP, kReceiverOffset)); | 1429 __ movl(EAX, Address(ESP, kReceiverOffset)); |
| 1410 } | 1430 } |
| 1411 // Create a stub frame. | 1431 // Create a stub frame as we are pushing some objects on the stack before |
| 1412 __ EnterFrame(0); | 1432 // calling into the runtime. |
| 1433 AssemblerMacros::EnterStubFrame(assembler); |
| 1413 __ pushl(raw_null); // Setup space on stack for return value. | 1434 __ pushl(raw_null); // Setup space on stack for return value. |
| 1414 __ PushObject(func); | 1435 __ PushObject(func); |
| 1415 if (is_implicit_static_closure) { | 1436 if (is_implicit_static_closure) { |
| 1416 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); | 1437 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); |
| 1417 } else { | 1438 } else { |
| 1418 if (is_implicit_instance_closure) { | 1439 if (is_implicit_instance_closure) { |
| 1419 __ pushl(EAX); // Receiver. | 1440 __ pushl(EAX); // Receiver. |
| 1420 } | 1441 } |
| 1421 if (has_type_arguments) { | 1442 if (has_type_arguments) { |
| 1422 __ pushl(ECX); // Push type arguments of closure to be allocated. | 1443 __ pushl(ECX); // Push type arguments of closure to be allocated. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1438 // EAX: new object | 1459 // EAX: new object |
| 1439 // Restore the frame pointer. | 1460 // Restore the frame pointer. |
| 1440 __ LeaveFrame(); | 1461 __ LeaveFrame(); |
| 1441 __ ret(); | 1462 __ ret(); |
| 1442 } | 1463 } |
| 1443 | 1464 |
| 1444 | 1465 |
| 1445 // Called for invoking noSuchMethod function from the entry code of a dart | 1466 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1446 // function after an error in passed named arguments is detected. | 1467 // function after an error in passed named arguments is detected. |
| 1447 // Input parameters: | 1468 // Input parameters: |
| 1469 // EBP - 4 : PC marker => RawInstruction object. |
| 1448 // EBP : points to previous frame pointer. | 1470 // EBP : points to previous frame pointer. |
| 1449 // EBP + 4 : points to return address. | 1471 // EBP + 4 : points to return address. |
| 1450 // EBP + 8 : address of last argument (arg n-1). | 1472 // EBP + 8 : address of last argument (arg n-1). |
| 1451 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). | 1473 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). |
| 1452 // ECX : ic-data. | 1474 // ECX : ic-data. |
| 1453 // EDX : arguments descriptor array. | 1475 // EDX : arguments descriptor array. |
| 1454 // Uses EAX, EBX, EDI as temporary registers. | 1476 // Uses EAX, EBX, EDI as temporary registers. |
| 1455 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1477 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1456 // The target function was not found, so invoke method | 1478 // The target function was not found, so invoke method |
| 1457 // "void noSuchMethod(function_name, Array arguments)". | 1479 // "void noSuchMethod(function_name, Array arguments)". |
| 1458 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1480 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1459 // and named, as the argument array. This is not correct if out-of-order | 1481 // and named, as the argument array. This is not correct if out-of-order |
| 1460 // named arguments were passed. | 1482 // named arguments were passed. |
| 1461 // The signature of the "noSuchMethod" method has to change from | 1483 // The signature of the "noSuchMethod" method has to change from |
| 1462 // noSuchMethod(String name, Array arguments) to something like | 1484 // noSuchMethod(String name, Array arguments) to something like |
| 1463 // noSuchMethod(InvocationMirror call). | 1485 // noSuchMethod(InvocationMirror call). |
| 1464 // Also, the class NoSuchMethodException has to be modified accordingly. | 1486 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1465 // Total number of args is the first Smi in args descriptor array (EDX). | 1487 // Total number of args is the first Smi in args descriptor array (EDX). |
| 1466 const Immediate raw_null = | 1488 const Immediate raw_null = |
| 1467 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1489 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1468 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); | 1490 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); |
| 1469 __ SmiUntag(EDI); | 1491 __ SmiUntag(EDI); |
| 1470 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. | 1492 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. |
| 1471 | 1493 |
| 1472 __ EnterFrame(0); | 1494 // Create a stub frame as we are pushing some objects on the stack before |
| 1495 // calling into the runtime. |
| 1496 AssemblerMacros::EnterStubFrame(assembler); |
| 1497 |
| 1473 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 1498 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1474 __ pushl(EAX); // Receiver. | 1499 __ pushl(EAX); // Receiver. |
| 1475 __ pushl(ECX); // IC data array. | 1500 __ pushl(ECX); // IC data array. |
| 1476 __ pushl(EDX); // Arguments descriptor array. | 1501 __ pushl(EDX); // Arguments descriptor array. |
| 1477 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 1502 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 1478 // See stack layout below explaining "wordSize * 8" offset. | 1503 // See stack layout below explaining "wordSize * 10" offset. |
| 1479 PushArgumentsArray(assembler, (kWordSize * 8)); | 1504 PushArgumentsArray(assembler, (kWordSize * 10)); |
| 1480 | 1505 |
| 1481 // Stack: | 1506 // Stack: |
| 1482 // TOS + 0: Argument array. | 1507 // TOS + 0: Argument array. |
| 1483 // TOS + 1: Arguments descriptor array. | 1508 // TOS + 1: Arguments descriptor array. |
| 1484 // TOS + 2: Ic-data. | 1509 // TOS + 2: Ic-data. |
| 1485 // TOS + 3: Receiver. | 1510 // TOS + 3: Receiver. |
| 1486 // TOS + 4: Place for result from noSuchMethod. | 1511 // TOS + 4: Place for result from noSuchMethod. |
| 1487 // TOS + 5: Saved EBP of previous frame. <== EBP | 1512 // TOS + 5: PC marker => RawInstruction object. |
| 1488 // TOS + 6: Dart callee (or stub) code return address | 1513 // TOS + 6: Saved EBP of previous frame. <== EBP |
| 1489 // TOS + 7: Saved EBP of dart caller frame. | 1514 // TOS + 7: Dart callee (or stub) code return address |
| 1490 // TOS + 8: Dart caller code return address | 1515 // TOS + 8: PC marker => RawInstruction object of dart caller frame. |
| 1491 // TOS + 9: Last argument of caller. | 1516 // TOS + 9: Saved EBP of dart caller frame. |
| 1517 // TOS + 10: Dart caller code return address |
| 1518 // TOS + 11: Last argument of caller. |
| 1492 // .... | 1519 // .... |
| 1493 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); | 1520 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1494 // Remove arguments. | 1521 // Remove arguments. |
| 1495 __ popl(EAX); | 1522 __ popl(EAX); |
| 1496 __ popl(EAX); | 1523 __ popl(EAX); |
| 1497 __ popl(EAX); | 1524 __ popl(EAX); |
| 1498 __ popl(EAX); | 1525 __ popl(EAX); |
| 1499 __ popl(EAX); // Get result into EAX. | 1526 __ popl(EAX); // Get result into EAX. |
| 1500 | 1527 |
| 1501 // Remove the stub frame as we are about to return. | 1528 // Remove the stub frame as we are about to return. |
| 1502 __ LeaveFrame(); | 1529 __ LeaveFrame(); |
| 1503 __ ret(); | 1530 __ ret(); |
| 1504 } | 1531 } |
| 1505 | 1532 |
| 1506 | 1533 |
| 1507 | 1534 |
| 1508 // Generate inline cache check for 'num_args'. | 1535 // Generate inline cache check for 'num_args'. |
| 1509 // ECX: Inline cache data object. | 1536 // ECX: Inline cache data object. |
| 1510 // EDX: Arguments descriptor array. | 1537 // EDX: Arguments descriptor array. |
| 1511 // TOS(0): return address | 1538 // TOS(0): return address |
| 1512 // Control flow: | 1539 // Control flow: |
| 1513 // - If receiver is null -> jump to IC miss. | 1540 // - If receiver is null -> jump to IC miss. |
| 1514 // - If receiver is Smi -> load Smi class. | 1541 // - If receiver is Smi -> load Smi class. |
| 1515 // - If receiver is not-Smi -> load receiver's class. | 1542 // - If receiver is not-Smi -> load receiver's class. |
| 1516 // - Check if 'num_args' (including receiver) match any IC data group. | 1543 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1517 // - Match found -> jump to target. | 1544 // - Match found -> jump to target. |
| 1518 // - Match not found -> jump to IC miss. | 1545 // - Match not found -> jump to IC miss. |
| 1519 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1546 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1520 intptr_t num_args) { | 1547 intptr_t num_args) { |
| 1548 const Immediate raw_null = |
| 1549 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1550 |
| 1521 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); | 1551 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); |
| 1522 __ incl(FieldAddress(EBX, Function::usage_counter_offset())); | 1552 __ incl(FieldAddress(EBX, Function::usage_counter_offset())); |
| 1523 if (CodeGenerator::CanOptimize()) { | 1553 if (CodeGenerator::CanOptimize()) { |
| 1524 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()), | 1554 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()), |
| 1525 Immediate(FLAG_optimization_counter_threshold)); | 1555 Immediate(FLAG_optimization_counter_threshold)); |
| 1526 Label not_yet_hot; | 1556 Label not_yet_hot; |
| 1527 __ j(LESS_EQUAL, ¬_yet_hot, Assembler::kNearJump); | 1557 __ j(LESS_EQUAL, ¬_yet_hot, Assembler::kNearJump); |
| 1528 __ EnterFrame(0); | 1558 // Create a stub frame as we are pushing some objects on the stack before |
| 1559 // calling into the runtime. |
| 1560 AssemblerMacros::EnterStubFrame(assembler); |
| 1529 __ pushl(ECX); // Preserve inline cache data object. | 1561 __ pushl(ECX); // Preserve inline cache data object. |
| 1530 __ pushl(EDX); // Preserve arguments array. | 1562 __ pushl(EDX); // Preserve arguments array. |
| 1531 __ pushl(EBX); // Argument for runtime: function object. | 1563 __ pushl(EBX); // Argument for runtime: function object. |
| 1532 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 1564 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 1533 __ popl(EBX); // Remove argument. | 1565 __ popl(EBX); // Remove argument. |
| 1534 __ popl(EDX); // Restore arguments array. | 1566 __ popl(EDX); // Restore arguments array. |
| 1535 __ popl(ECX); // Restore inline cache data object. | 1567 __ popl(ECX); // Restore inline cache data object. |
| 1536 __ LeaveFrame(); | 1568 __ LeaveFrame(); |
| 1537 __ Bind(¬_yet_hot); | 1569 __ Bind(¬_yet_hot); |
| 1538 } | 1570 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1560 } | 1592 } |
| 1561 #endif // DEBUG | 1593 #endif // DEBUG |
| 1562 | 1594 |
| 1563 // Loop that checks if there is an IC data match. | 1595 // Loop that checks if there is an IC data match. |
| 1564 // EAX: receiver's class. | 1596 // EAX: receiver's class. |
| 1565 // ECX: IC data object (preserved). | 1597 // ECX: IC data object (preserved). |
| 1566 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1598 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1567 // EBX: ic_data_array with check entries: classes and target functions. | 1599 // EBX: ic_data_array with check entries: classes and target functions. |
| 1568 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1600 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1569 // EBX: points directly to the first ic data array element. | 1601 // EBX: points directly to the first ic data array element. |
| 1570 const Immediate raw_null = | |
| 1571 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1572 Label loop, found; | 1602 Label loop, found; |
| 1573 if (num_args == 1) { | 1603 if (num_args == 1) { |
| 1574 __ Bind(&loop); | 1604 __ Bind(&loop); |
| 1575 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1605 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1576 __ cmpl(EAX, EDI); // Match? | 1606 __ cmpl(EAX, EDI); // Match? |
| 1577 __ j(EQUAL, &found, Assembler::kNearJump); | 1607 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1578 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1579 __ cmpl(EDI, raw_null); // Done? | 1609 __ cmpl(EDI, raw_null); // Done? |
| 1580 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1581 } else if (num_args == 2) { | 1611 } else if (num_args == 2) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1605 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1635 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1606 __ cmpl(EDI, raw_null); // Done? | 1636 __ cmpl(EDI, raw_null); // Done? |
| 1607 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1637 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1608 } | 1638 } |
| 1609 | 1639 |
| 1610 __ Bind(&ic_miss); | 1640 __ Bind(&ic_miss); |
| 1611 // Compute address of arguments (first read number of arguments from argument | 1641 // Compute address of arguments (first read number of arguments from argument |
| 1612 // descriptor array and then compute address on the stack). | 1642 // descriptor array and then compute address on the stack). |
| 1613 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1643 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1614 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1644 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1615 __ EnterFrame(0); | 1645 // Create a stub frame as we are pushing some objects on the stack before |
| 1646 // calling into the runtime. |
| 1647 AssemblerMacros::EnterStubFrame(assembler); |
| 1616 __ pushl(EDX); // Preserve arguments array. | 1648 __ pushl(EDX); // Preserve arguments array. |
| 1617 __ pushl(ECX); // Preserve IC data array | 1649 __ pushl(ECX); // Preserve IC data array |
| 1618 __ pushl(raw_null); // Setup space on stack for result (target code object). | 1650 __ pushl(raw_null); // Setup space on stack for result (target code object). |
| 1619 // Push call arguments. | 1651 // Push call arguments. |
| 1620 for (intptr_t i = 0; i < num_args; i++) { | 1652 for (intptr_t i = 0; i < num_args; i++) { |
| 1621 __ movl(EDX, Address(EAX, -kWordSize * i)); | 1653 __ movl(EDX, Address(EAX, -kWordSize * i)); |
| 1622 __ pushl(EDX); | 1654 __ pushl(EDX); |
| 1623 } | 1655 } |
| 1624 if (num_args == 1) { | 1656 if (num_args == 1) { |
| 1625 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1657 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1686 | 1718 |
| 1687 | 1719 |
| 1688 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1720 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1689 return GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1721 return GenerateNArgsCheckInlineCacheStub(assembler, 2); |
| 1690 } | 1722 } |
| 1691 | 1723 |
| 1692 // ECX: Function object. | 1724 // ECX: Function object. |
| 1693 // EDX: Arguments array. | 1725 // EDX: Arguments array. |
| 1694 // TOS(0): return address (Dart code). | 1726 // TOS(0): return address (Dart code). |
| 1695 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1727 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1696 __ EnterFrame(0); | 1728 // Create a stub frame as we are pushing some objects on the stack before |
| 1729 // calling into the runtime. |
| 1730 AssemblerMacros::EnterStubFrame(assembler); |
| 1697 __ pushl(EDX); | 1731 __ pushl(EDX); |
| 1698 __ pushl(ECX); | 1732 __ pushl(ECX); |
| 1699 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1733 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| 1700 __ popl(ECX); | 1734 __ popl(ECX); |
| 1701 __ popl(EDX); | 1735 __ popl(EDX); |
| 1702 __ LeaveFrame(); | 1736 __ LeaveFrame(); |
| 1703 | 1737 |
| 1704 // Now call the static function. The breakpoint handler function | 1738 // Now call the static function. The breakpoint handler function |
| 1705 // ensures that the call target is compiled. | 1739 // ensures that the call target is compiled. |
| 1706 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 1740 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 1707 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 1741 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 1708 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1742 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1709 __ jmp(ECX); | 1743 __ jmp(ECX); |
| 1710 } | 1744 } |
| 1711 | 1745 |
| 1712 | 1746 |
| 1713 // TOS(0): return address (Dart code). | 1747 // TOS(0): return address (Dart code). |
| 1714 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { | 1748 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { |
| 1715 __ EnterFrame(0); | 1749 // Create a stub frame as we are pushing some objects on the stack before |
| 1750 // calling into the runtime. |
| 1751 AssemblerMacros::EnterStubFrame(assembler); |
| 1716 __ pushl(EAX); | 1752 __ pushl(EAX); |
| 1717 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); | 1753 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); |
| 1718 __ popl(EAX); | 1754 __ popl(EAX); |
| 1719 __ LeaveFrame(); | 1755 __ LeaveFrame(); |
| 1720 | 1756 |
| 1721 // Instead of returning to the patched Dart function, emulate the | 1757 // Instead of returning to the patched Dart function, emulate the |
| 1722 // smashed return code pattern and return to the function's caller. | 1758 // smashed return code pattern and return to the function's caller. |
| 1723 __ popl(ECX); // Discard return address to patched dart code. | 1759 __ popl(ECX); // Discard return address to patched dart code. |
| 1724 // Execute function epilog code that was smashed in the Dart code. | 1760 // Execute function epilog code that was smashed in the Dart code. |
| 1725 __ LeaveFrame(); | 1761 __ LeaveFrame(); |
| 1726 __ ret(); | 1762 __ ret(); |
| 1727 } | 1763 } |
| 1728 | 1764 |
| 1729 | 1765 |
| 1730 // ECX: Inline cache data array. | 1766 // ECX: Inline cache data array. |
| 1731 // EDX: Arguments array. | 1767 // EDX: Arguments array. |
| 1732 // TOS(0): return address (Dart code). | 1768 // TOS(0): return address (Dart code). |
| 1733 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1769 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1734 __ EnterFrame(0); | 1770 // Create a stub frame as we are pushing some objects on the stack before |
| 1771 // calling into the runtime. |
| 1772 AssemblerMacros::EnterStubFrame(assembler); |
| 1735 __ pushl(ECX); | 1773 __ pushl(ECX); |
| 1736 __ pushl(EDX); | 1774 __ pushl(EDX); |
| 1737 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1775 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| 1738 __ popl(EDX); | 1776 __ popl(EDX); |
| 1739 __ popl(ECX); | 1777 __ popl(ECX); |
| 1740 __ LeaveFrame(); | 1778 __ LeaveFrame(); |
| 1741 | 1779 |
| 1742 // Find out which dispatch stub to call. | 1780 // Find out which dispatch stub to call. |
| 1743 Label ic_cache_one_arg; | 1781 Label ic_cache_one_arg; |
| 1744 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1782 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 // TOS + 2: instance. | 1892 // TOS + 2: instance. |
| 1855 // TOS + 3: cache array. | 1893 // TOS + 3: cache array. |
| 1856 // Result in ECX: null -> not found, otherwise result (true or false). | 1894 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1857 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1895 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1858 GenerateSubtypeNTestCacheStub(assembler, 3); | 1896 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1859 } | 1897 } |
| 1860 | 1898 |
| 1861 } // namespace dart | 1899 } // namespace dart |
| 1862 | 1900 |
| 1863 #endif // defined TARGET_ARCH_IA32 | 1901 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |