| 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/ic_data.h" | 10 #include "vm/ic_data.h" |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 // TOS + 2: Last argument of caller. | 413 // TOS + 2: Last argument of caller. |
| 414 // .... | 414 // .... |
| 415 // Total number of args is the first Smi in args descriptor array (EDX). | 415 // Total number of args is the first Smi in args descriptor array (EDX). |
| 416 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 416 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 417 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. | 417 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. |
| 418 __ pushl(EDX); // Preserve arguments descriptor array. | 418 __ pushl(EDX); // Preserve arguments descriptor array. |
| 419 __ pushl(EAX); // Preserve receiver. | 419 __ pushl(EAX); // Preserve receiver. |
| 420 __ pushl(ECX); // Preserve ic-data array. | 420 __ pushl(ECX); // Preserve ic-data array. |
| 421 // First resolve the function to get the function object. | 421 // First resolve the function to get the function object. |
| 422 | 422 |
| 423 // Setup space for return value on stack by pushing smi 0. | 423 __ pushl(raw_null); // Setup space on stack for return value. |
| 424 __ pushl(Immediate(0)); | |
| 425 __ pushl(EAX); // Push receiver. | 424 __ pushl(EAX); // Push receiver. |
| 426 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); | 425 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); |
| 427 __ popl(EAX); // Remove receiver pushed earlier. | 426 __ popl(EAX); // Remove receiver pushed earlier. |
| 428 __ popl(ECX); // Pop returned code object into ECX. | 427 __ popl(ECX); // Pop returned code object into ECX. |
| 429 // Pop preserved values | 428 // Pop preserved values |
| 430 __ popl(EDX); // Restore ic-data array. | 429 __ popl(EDX); // Restore ic-data array. |
| 431 __ popl(EAX); // Restore receiver. | 430 __ popl(EAX); // Restore receiver. |
| 432 __ popl(EDI); // Restore arguments descriptor array. | 431 __ popl(EDI); // Restore arguments descriptor array. |
| 433 | 432 |
| 434 __ cmpl(ECX, raw_null); | 433 __ cmpl(ECX, raw_null); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 449 // ECX: raw_null. | 448 // ECX: raw_null. |
| 450 // EDI: arguments descriptor array. | 449 // EDI: arguments descriptor array. |
| 451 // The target function was not found. | 450 // The target function was not found. |
| 452 // First check to see if this is a getter function and we are | 451 // First check to see if this is a getter function and we are |
| 453 // trying to create a closure of an instance function. | 452 // trying to create a closure of an instance function. |
| 454 // Push values that need to be preserved across runtime call. | 453 // Push values that need to be preserved across runtime call. |
| 455 __ pushl(EAX); // Preserve receiver. | 454 __ pushl(EAX); // Preserve receiver. |
| 456 __ pushl(EDX); // Preserve ic-data array. | 455 __ pushl(EDX); // Preserve ic-data array. |
| 457 __ pushl(EDI); // Preserve arguments descriptor array. | 456 __ pushl(EDI); // Preserve arguments descriptor array. |
| 458 | 457 |
| 459 __ pushl(Immediate(0)); | 458 __ pushl(raw_null); // Setup space on stack for return value. |
| 460 __ pushl(EAX); // Push receiver. | 459 __ pushl(EAX); // Push receiver. |
| 461 __ pushl(EDX); // Ic-data array. | 460 __ pushl(EDX); // Ic-data array. |
| 462 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); | 461 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); |
| 463 __ popl(EAX); | 462 __ popl(EAX); |
| 464 __ popl(EAX); | 463 __ popl(EAX); |
| 465 __ popl(ECX); // Get return value into ECX, might be Closure object. | 464 __ popl(ECX); // Get return value into ECX, might be Closure object. |
| 466 | 465 |
| 467 // Pop preserved values. | 466 // Pop preserved values. |
| 468 __ popl(EDI); // Restore arguments descriptor array. | 467 __ popl(EDI); // Restore arguments descriptor array. |
| 469 __ popl(EDX); // Restore ic-data array. | 468 __ popl(EDX); // Restore ic-data array. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 484 // ECX: raw_null. | 483 // ECX: raw_null. |
| 485 // EDI: arguments descriptor array. | 484 // EDI: arguments descriptor array. |
| 486 // This is not the case of an instance so invoke the getter of the | 485 // This is not the case of an instance so invoke the getter of the |
| 487 // same name and see if we get a closure back which we are then | 486 // same name and see if we get a closure back which we are then |
| 488 // supposed to invoke. | 487 // supposed to invoke. |
| 489 // Push values that need to be preserved across runtime call. | 488 // Push values that need to be preserved across runtime call. |
| 490 __ pushl(EAX); // Preserve receiver. | 489 __ pushl(EAX); // Preserve receiver. |
| 491 __ pushl(EDX); // Preserve ic-data array. | 490 __ pushl(EDX); // Preserve ic-data array. |
| 492 __ pushl(EDI); // Preserve arguments descriptor array. | 491 __ pushl(EDI); // Preserve arguments descriptor array. |
| 493 | 492 |
| 494 __ pushl(Immediate(0)); | 493 __ pushl(raw_null); // Setup space on stack for return value. |
| 495 __ pushl(EAX); // Push receiver. | 494 __ pushl(EAX); // Push receiver. |
| 496 __ pushl(EDX); // Ic-data array. | 495 __ pushl(EDX); // Ic-data array. |
| 497 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); | 496 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); |
| 498 __ popl(EDX); // Pop argument. | 497 __ popl(EDX); // Pop argument. |
| 499 __ popl(EAX); // Pop argument. | 498 __ popl(EAX); // Pop argument. |
| 500 __ popl(ECX); // get return value into ECX, might be Closure object. | 499 __ popl(ECX); // get return value into ECX, might be Closure object. |
| 501 | 500 |
| 502 // Pop preserved values. | 501 // Pop preserved values. |
| 503 __ popl(EDI); // Restore arguments descriptor array. | 502 __ popl(EDI); // Restore arguments descriptor array. |
| 504 __ popl(EDX); // Restore ic-data array. | 503 __ popl(EDX); // Restore ic-data array. |
| 505 __ popl(EAX); // Restore receiver. | 504 __ popl(EAX); // Restore receiver. |
| 506 | 505 |
| 507 __ cmpl(ECX, raw_null); | 506 __ cmpl(ECX, raw_null); |
| 508 Label function_not_found; | 507 Label function_not_found; |
| 509 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 508 __ j(EQUAL, &function_not_found, Assembler::kNearJump); |
| 510 | 509 |
| 511 // ECX: Closure object. | 510 // ECX: Closure object. |
| 512 // EDI: Arguments descriptor array. | 511 // EDI: Arguments descriptor array. |
| 513 __ pushl(Immediate(0)); // Result from invoking Closure. | 512 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. |
| 514 __ pushl(ECX); // Closure object. | 513 __ pushl(ECX); // Closure object. |
| 515 __ pushl(EDI); // Arguments descriptor. | 514 __ pushl(EDI); // Arguments descriptor. |
| 516 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 515 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 517 __ SmiUntag(EDI); | 516 __ SmiUntag(EDI); |
| 518 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 517 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 519 PushArgumentsArray(assembler, (kWordSize * 5)); | 518 PushArgumentsArray(assembler, (kWordSize * 5)); |
| 520 // Stack layout explaining "(kWordSize * 5)" offset. | 519 // Stack layout explaining "(kWordSize * 5)" offset. |
| 521 // TOS + 0: Argument array. | 520 // TOS + 0: Argument array. |
| 522 // TOS + 1: Arguments descriptor array. | 521 // TOS + 1: Arguments descriptor array. |
| 523 // TOS + 2: Closure object. | 522 // TOS + 2: Closure object. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 539 __ ret(); | 538 __ ret(); |
| 540 | 539 |
| 541 __ Bind(&function_not_found); | 540 __ Bind(&function_not_found); |
| 542 // The target function was not found, so invoke method | 541 // The target function was not found, so invoke method |
| 543 // "void noSuchMethod(function_name, args_array)". | 542 // "void noSuchMethod(function_name, args_array)". |
| 544 // EAX: receiver. | 543 // EAX: receiver. |
| 545 // EDX: ic-data array. | 544 // EDX: ic-data array. |
| 546 // ECX: raw_null. | 545 // ECX: raw_null. |
| 547 // EDI: argument descriptor array. | 546 // EDI: argument descriptor array. |
| 548 | 547 |
| 549 // Setup space for return value on stack by pushing smi 0. | 548 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 550 __ pushl(Immediate(0)); // Result from noSuchMethod. | |
| 551 __ pushl(EAX); // Receiver. | 549 __ pushl(EAX); // Receiver. |
| 552 __ pushl(EDX); // IC-data array. | 550 __ pushl(EDX); // IC-data array. |
| 553 __ pushl(EDI); // Argument descriptor array. | 551 __ pushl(EDI); // Argument descriptor array. |
| 554 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 552 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 555 __ SmiUntag(EDI); | 553 __ SmiUntag(EDI); |
| 556 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 554 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 557 // See stack layout below explaining "wordSize * 6" offset. | 555 // See stack layout below explaining "wordSize * 6" offset. |
| 558 PushArgumentsArray(assembler, (kWordSize * 6)); | 556 PushArgumentsArray(assembler, (kWordSize * 6)); |
| 559 | 557 |
| 560 // Stack: | 558 // Stack: |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 | 693 |
| 696 // Done allocating and initializing the array. | 694 // Done allocating and initializing the array. |
| 697 // EAX: new object. | 695 // EAX: new object. |
| 698 __ ret(); | 696 __ ret(); |
| 699 } | 697 } |
| 700 | 698 |
| 701 // Unable to allocate the array using the fast inline code, just call | 699 // Unable to allocate the array using the fast inline code, just call |
| 702 // into the runtime. | 700 // into the runtime. |
| 703 __ Bind(&slow_case); | 701 __ Bind(&slow_case); |
| 704 __ EnterFrame(0); | 702 __ EnterFrame(0); |
| 705 __ pushl(raw_null); // Push Null object for return value. | 703 __ pushl(raw_null); // Setup space on stack for return value. |
| 706 __ pushl(EDX); // Array length as Smi. | 704 __ pushl(EDX); // Array length as Smi. |
| 707 __ pushl(ECX); // Element type. | 705 __ pushl(ECX); // Element type. |
| 708 __ pushl(raw_null); // Null instantiator. | 706 __ pushl(raw_null); // Null instantiator. |
| 709 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); | 707 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); |
| 710 __ popl(EAX); // Pop instantiator. | 708 __ popl(EAX); // Pop instantiator. |
| 711 __ popl(EAX); // Pop element type argument. | 709 __ popl(EAX); // Pop element type argument. |
| 712 __ popl(EDX); // Pop array length argument. | 710 __ popl(EDX); // Pop array length argument. |
| 713 __ popl(EAX); // Pop return value from return slot. | 711 __ popl(EAX); // Pop return value from return slot. |
| 714 __ LeaveFrame(); | 712 __ LeaveFrame(); |
| 715 __ ret(); | 713 __ ret(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 // Call runtime to report that a closure call was attempted on a non-closure | 785 // Call runtime to report that a closure call was attempted on a non-closure |
| 788 // object, passing the non-closure object and its arguments array. | 786 // object, passing the non-closure object and its arguments array. |
| 789 // EDI: non-closure object. | 787 // EDI: non-closure object. |
| 790 // EDX: arguments descriptor array (num_args is first Smi element, closure | 788 // EDX: arguments descriptor array (num_args is first Smi element, closure |
| 791 // object is not included in num_args). | 789 // object is not included in num_args). |
| 792 | 790 |
| 793 // Create a stub frame as we are pushing some objects on the stack before | 791 // Create a stub frame as we are pushing some objects on the stack before |
| 794 // calling into the runtime. | 792 // calling into the runtime. |
| 795 __ EnterFrame(0); | 793 __ EnterFrame(0); |
| 796 | 794 |
| 797 // Setup space for return value on stack by pushing smi 0. | 795 __ pushl(raw_null); // Setup space on stack for result from error reporting. |
| 798 __ pushl(Immediate(0)); // Result from reporting the error. | |
| 799 __ pushl(EDI); // Non-closure object. | 796 __ pushl(EDI); // Non-closure object. |
| 800 // Total number of args is the first Smi in args descriptor array (EDX). | 797 // Total number of args is the first Smi in args descriptor array (EDX). |
| 801 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); // Load num_args. | 798 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); // Load num_args. |
| 802 __ SmiUntag(EDI); | 799 __ SmiUntag(EDI); |
| 803 // See stack layout below explaining "wordSize * 4" offset. | 800 // See stack layout below explaining "wordSize * 4" offset. |
| 804 PushArgumentsArray(assembler, (kWordSize * 4)); | 801 PushArgumentsArray(assembler, (kWordSize * 4)); |
| 805 | 802 |
| 806 // Stack: | 803 // Stack: |
| 807 // TOS + 0: Argument array. | 804 // TOS + 0: Argument array. |
| 808 // TOS + 1: Non-closure object. | 805 // TOS + 1: Non-closure object. |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 } | 928 } |
| 932 | 929 |
| 933 | 930 |
| 934 // Called for inline allocation of contexts. | 931 // Called for inline allocation of contexts. |
| 935 // Input: | 932 // Input: |
| 936 // EDX: number of context variables. | 933 // EDX: number of context variables. |
| 937 // Output: | 934 // Output: |
| 938 // EAX: new allocated RawContext object. | 935 // EAX: new allocated RawContext object. |
| 939 // EBX and EDX are destroyed. | 936 // EBX and EDX are destroyed. |
| 940 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 937 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 938 const Immediate raw_null = |
| 939 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 941 if (FLAG_inline_alloc) { | 940 if (FLAG_inline_alloc) { |
| 942 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 941 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 943 Label slow_case; | 942 Label slow_case; |
| 944 Heap* heap = Isolate::Current()->heap(); | 943 Heap* heap = Isolate::Current()->heap(); |
| 945 // First compute the rounded instance size. | 944 // First compute the rounded instance size. |
| 946 // EDX: number of context variables. | 945 // EDX: number of context variables. |
| 947 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 946 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 948 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); | 947 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); |
| 949 __ andl(EBX, Immediate(-kObjectAlignment)); | 948 __ andl(EBX, Immediate(-kObjectAlignment)); |
| 950 | 949 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 } | 1016 } |
| 1018 | 1017 |
| 1019 // Done allocating and initializing the context. | 1018 // Done allocating and initializing the context. |
| 1020 // EAX: new object. | 1019 // EAX: new object. |
| 1021 __ ret(); | 1020 __ ret(); |
| 1022 | 1021 |
| 1023 __ Bind(&slow_case); | 1022 __ Bind(&slow_case); |
| 1024 } | 1023 } |
| 1025 // Create a stub frame. | 1024 // Create a stub frame. |
| 1026 __ EnterFrame(0); | 1025 __ EnterFrame(0); |
| 1027 const Context& new_context = Context::ZoneHandle(); | 1026 __ pushl(raw_null); // Setup space on stack for return value. |
| 1028 __ PushObject(new_context); // Push Null context for return value. | |
| 1029 __ SmiTag(EDX); | 1027 __ SmiTag(EDX); |
| 1030 __ pushl(EDX); | 1028 __ pushl(EDX); |
| 1031 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. | 1029 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. |
| 1032 __ popl(EAX); // Pop number of context variables argument. | 1030 __ popl(EAX); // Pop number of context variables argument. |
| 1033 __ popl(EAX); // Pop the new context object. | 1031 __ popl(EAX); // Pop the new context object. |
| 1034 // EAX: new object | 1032 // EAX: new object |
| 1035 // Restore the frame pointer. | 1033 // Restore the frame pointer. |
| 1036 __ LeaveFrame(); | 1034 __ LeaveFrame(); |
| 1037 __ ret(); | 1035 __ ret(); |
| 1038 } | 1036 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 __ ret(); | 1196 __ ret(); |
| 1199 | 1197 |
| 1200 __ Bind(&slow_case); | 1198 __ Bind(&slow_case); |
| 1201 } | 1199 } |
| 1202 if (is_cls_parameterized) { | 1200 if (is_cls_parameterized) { |
| 1203 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); | 1201 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); |
| 1204 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); | 1202 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); |
| 1205 } | 1203 } |
| 1206 // Create a stub frame. | 1204 // Create a stub frame. |
| 1207 __ EnterFrame(0); | 1205 __ EnterFrame(0); |
| 1208 const Object& new_object = Object::ZoneHandle(); | 1206 __ pushl(raw_null); // Setup space on stack for return value. |
| 1209 __ PushObject(new_object); // Push Null object for return value. | |
| 1210 __ PushObject(cls); // Push class of object to be allocated. | 1207 __ PushObject(cls); // Push class of object to be allocated. |
| 1211 if (is_cls_parameterized) { | 1208 if (is_cls_parameterized) { |
| 1212 __ pushl(EAX); // Push type arguments of object to be allocated. | 1209 __ pushl(EAX); // Push type arguments of object to be allocated. |
| 1213 __ pushl(EDX); // Push type arguments of instantiator. | 1210 __ pushl(EDX); // Push type arguments of instantiator. |
| 1214 } else { | 1211 } else { |
| 1215 __ pushl(raw_null); // Push null type arguments. | 1212 __ pushl(raw_null); // Push null type arguments. |
| 1216 __ pushl(raw_null); // Push null instantiator. | 1213 __ pushl(raw_null); // Push null instantiator. |
| 1217 } | 1214 } |
| 1218 __ CallRuntimeFromStub(kAllocateObjectRuntimeEntry); // Allocate object. | 1215 __ CallRuntimeFromStub(kAllocateObjectRuntimeEntry); // Allocate object. |
| 1219 __ popl(EAX); // Pop argument (instantiator). | 1216 __ popl(EAX); // Pop argument (instantiator). |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 __ Bind(&slow_case); | 1344 __ Bind(&slow_case); |
| 1348 } | 1345 } |
| 1349 if (has_type_arguments) { | 1346 if (has_type_arguments) { |
| 1350 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); | 1347 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); |
| 1351 } | 1348 } |
| 1352 if (is_implicit_instance_closure) { | 1349 if (is_implicit_instance_closure) { |
| 1353 __ movl(EAX, Address(ESP, kReceiverOffset)); | 1350 __ movl(EAX, Address(ESP, kReceiverOffset)); |
| 1354 } | 1351 } |
| 1355 // Create a stub frame. | 1352 // Create a stub frame. |
| 1356 __ EnterFrame(0); | 1353 __ EnterFrame(0); |
| 1357 const Closure& new_closure = Closure::ZoneHandle(); | 1354 __ pushl(raw_null); // Setup space on stack for return value. |
| 1358 __ PushObject(new_closure); // Push Null closure for return value. | |
| 1359 __ PushObject(func); | 1355 __ PushObject(func); |
| 1360 if (is_implicit_static_closure) { | 1356 if (is_implicit_static_closure) { |
| 1361 __ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); | 1357 __ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); |
| 1362 } else { | 1358 } else { |
| 1363 if (is_implicit_instance_closure) { | 1359 if (is_implicit_instance_closure) { |
| 1364 __ pushl(EAX); // Receiver. | 1360 __ pushl(EAX); // Receiver. |
| 1365 } | 1361 } |
| 1366 if (has_type_arguments) { | 1362 if (has_type_arguments) { |
| 1367 __ pushl(ECX); // Push type arguments of closure to be allocated. | 1363 __ pushl(ECX); // Push type arguments of closure to be allocated. |
| 1368 } else { | 1364 } else { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 // The target function was not found, so invoke method | 1397 // The target function was not found, so invoke method |
| 1402 // "void noSuchMethod(function_name, Array arguments)". | 1398 // "void noSuchMethod(function_name, Array arguments)". |
| 1403 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1399 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1404 // and named, as the argument array. This is not correct if out-of-order | 1400 // and named, as the argument array. This is not correct if out-of-order |
| 1405 // named arguments were passed. | 1401 // named arguments were passed. |
| 1406 // The signature of the "noSuchMethod" method has to change from | 1402 // The signature of the "noSuchMethod" method has to change from |
| 1407 // noSuchMethod(String name, Array arguments) to something like | 1403 // noSuchMethod(String name, Array arguments) to something like |
| 1408 // noSuchMethod(InvocationMirror call). | 1404 // noSuchMethod(InvocationMirror call). |
| 1409 // Also, the class NoSuchMethodException has to be modified accordingly. | 1405 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1410 // Total number of args is the first Smi in args descriptor array (EDX). | 1406 // Total number of args is the first Smi in args descriptor array (EDX). |
| 1407 const Immediate raw_null = |
| 1408 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1411 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); | 1409 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); |
| 1412 __ SmiUntag(EDI); | 1410 __ SmiUntag(EDI); |
| 1413 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. | 1411 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. |
| 1414 | 1412 |
| 1415 __ EnterFrame(0); | 1413 __ EnterFrame(0); |
| 1416 // Setup space for return value on stack by pushing smi 0. | 1414 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1417 __ pushl(Immediate(0)); // Result from noSuchMethod. | |
| 1418 __ pushl(EAX); // Receiver. | 1415 __ pushl(EAX); // Receiver. |
| 1419 __ pushl(ECX); // IC data array. | 1416 __ pushl(ECX); // IC data array. |
| 1420 __ pushl(EDX); // Arguments descriptor array. | 1417 __ pushl(EDX); // Arguments descriptor array. |
| 1421 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 1418 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 1422 // See stack layout below explaining "wordSize * 8" offset. | 1419 // See stack layout below explaining "wordSize * 8" offset. |
| 1423 PushArgumentsArray(assembler, (kWordSize * 8)); | 1420 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1424 | 1421 |
| 1425 // Stack: | 1422 // Stack: |
| 1426 // TOS + 0: Argument array. | 1423 // TOS + 0: Argument array. |
| 1427 // TOS + 1: Arguments descriptor array. | 1424 // TOS + 1: Arguments descriptor array. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1522 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1526 __ cmpl(EDI, raw_null); // Done? | 1523 __ cmpl(EDI, raw_null); // Done? |
| 1527 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1524 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1528 } | 1525 } |
| 1529 | 1526 |
| 1530 __ Bind(&ic_miss); | 1527 __ Bind(&ic_miss); |
| 1531 // Get receiver, again. | 1528 // Get receiver, again. |
| 1532 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1529 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1533 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1530 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1534 __ EnterFrame(0); | 1531 __ EnterFrame(0); |
| 1535 // Setup space for return value on stack by pushing smi 0. | |
| 1536 __ pushl(EDX); // Preserve arguments array. | 1532 __ pushl(EDX); // Preserve arguments array. |
| 1537 __ pushl(ECX); // Preserve IC data array | 1533 __ pushl(ECX); // Preserve IC data array |
| 1538 __ pushl(Immediate(0)); // Space for result (target code object). | 1534 __ pushl(raw_null); // Setup space on stack for result (target code object). |
| 1539 __ movl(EDX, FieldAddress(EDX, Array::data_offset())); | 1535 __ movl(EDX, FieldAddress(EDX, Array::data_offset())); |
| 1540 // Push call arguments. | 1536 // Push call arguments. |
| 1541 for (intptr_t i = 0; i < num_args; i++) { | 1537 for (intptr_t i = 0; i < num_args; i++) { |
| 1542 __ movl(EDX, Address(EAX, -kWordSize * i)); | 1538 __ movl(EDX, Address(EAX, -kWordSize * i)); |
| 1543 __ pushl(EDX); | 1539 __ pushl(EDX); |
| 1544 } | 1540 } |
| 1545 if (num_args == 1) { | 1541 if (num_args == 1) { |
| 1546 __ CallRuntimeFromStub(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1542 __ CallRuntimeFromStub(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1547 } else if (num_args == 2) { | 1543 } else if (num_args == 2) { |
| 1548 __ CallRuntimeFromStub(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1544 __ CallRuntimeFromStub(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1642 __ popl(EDX); | 1638 __ popl(EDX); |
| 1643 __ popl(ECX); | 1639 __ popl(ECX); |
| 1644 __ LeaveFrame(); | 1640 __ LeaveFrame(); |
| 1645 // Now call the dynamic function. | 1641 // Now call the dynamic function. |
| 1646 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1642 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1647 } | 1643 } |
| 1648 | 1644 |
| 1649 } // namespace dart | 1645 } // namespace dart |
| 1650 | 1646 |
| 1651 #endif // defined TARGET_ARCH_IA32 | 1647 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |