| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| 11 #include "vm/dart_entry.h" |
| 11 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/instructions.h" | 13 #include "vm/instructions.h" |
| 13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 14 #include "vm/pages.h" | 15 #include "vm/pages.h" |
| 15 #include "vm/resolver.h" | 16 #include "vm/resolver.h" |
| 16 #include "vm/scavenger.h" | 17 #include "vm/scavenger.h" |
| 17 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 18 | 19 |
| 19 | 20 |
| 20 #define __ assembler-> | 21 #define __ assembler-> |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 | 177 |
| 177 // Cache Context pointer into CTX while executing Dart code. | 178 // Cache Context pointer into CTX while executing Dart code. |
| 178 __ movl(CTX, EDI); | 179 __ movl(CTX, EDI); |
| 179 | 180 |
| 180 __ LeaveFrame(); | 181 __ LeaveFrame(); |
| 181 __ ret(); | 182 __ ret(); |
| 182 } | 183 } |
| 183 | 184 |
| 184 | 185 |
| 185 // Input parameters: | 186 // Input parameters: |
| 186 // EDX: arguments descriptor array (num_args is first Smi element). | 187 // EDX: arguments descriptor array. |
| 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 188 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| 188 const Immediate raw_null = | 189 const Immediate raw_null = |
| 189 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 190 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 190 AssemblerMacros::EnterStubFrame(assembler); | 191 AssemblerMacros::EnterStubFrame(assembler); |
| 191 __ pushl(EDX); // Preserve arguments descriptor array. | 192 __ pushl(EDX); // Preserve arguments descriptor array. |
| 192 __ pushl(raw_null); // Setup space on stack for return value. | 193 __ pushl(raw_null); // Setup space on stack for return value. |
| 193 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 194 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
| 194 __ popl(EAX); // Get Code object result. | 195 __ popl(EAX); // Get Code object result. |
| 195 __ popl(EDX); // Restore arguments descriptor array. | 196 __ popl(EDX); // Restore arguments descriptor array. |
| 196 // Remove the stub frame as we are about to jump to the dart function. | 197 // Remove the stub frame as we are about to jump to the dart function. |
| 197 __ LeaveFrame(); | 198 __ LeaveFrame(); |
| 198 | 199 |
| 199 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 200 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 200 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 201 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 201 __ jmp(ECX); | 202 __ jmp(ECX); |
| 202 } | 203 } |
| 203 | 204 |
| 204 | 205 |
| 205 // Called from a static call only when an invalid code has been entered | 206 // Called from a static call only when an invalid code has been entered |
| 206 // (invalid because its function was optimized or deoptimized). | 207 // (invalid because its function was optimized or deoptimized). |
| 207 // EDX: arguments descriptor array (num_args is first Smi element). | 208 // EDX: arguments descriptor array. |
| 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 209 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 209 const Immediate raw_null = | 210 const Immediate raw_null = |
| 210 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 211 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 211 // Create a stub frame as we are pushing some objects on the stack before | 212 // Create a stub frame as we are pushing some objects on the stack before |
| 212 // calling into the runtime. | 213 // calling into the runtime. |
| 213 AssemblerMacros::EnterStubFrame(assembler); | 214 AssemblerMacros::EnterStubFrame(assembler); |
| 214 __ pushl(EDX); // Preserve arguments descriptor array. | 215 __ pushl(EDX); // Preserve arguments descriptor array. |
| 215 __ pushl(raw_null); // Setup space on stack for return value. | 216 __ pushl(raw_null); // Setup space on stack for return value. |
| 216 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 217 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
| 217 __ popl(EAX); // Get Code object. | 218 __ popl(EAX); // Get Code object. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 __ AddImmediate(ECX, Immediate(kWordSize)); | 251 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 251 __ AddImmediate(EBX, Immediate(-kWordSize)); | 252 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 252 __ Bind(&loop_condition); | 253 __ Bind(&loop_condition); |
| 253 __ decl(EDX); | 254 __ decl(EDX); |
| 254 __ j(POSITIVE, &loop, Assembler::kNearJump); | 255 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 255 } | 256 } |
| 256 | 257 |
| 257 | 258 |
| 258 // Input parameters: | 259 // Input parameters: |
| 259 // ECX: ic-data. | 260 // ECX: ic-data. |
| 260 // EDX: arguments descriptor array (num_args is first Smi element). | 261 // EDX: arguments descriptor array. |
| 261 // Note: The receiver object is the first argument to the function being | 262 // Note: The receiver object is the first argument to the function being |
| 262 // called, the stub accesses the receiver from this location directly | 263 // called, the stub accesses the receiver from this location directly |
| 263 // when trying to resolve the call. | 264 // when trying to resolve the call. |
| 264 // Uses EDI. | 265 // Uses EDI. |
| 265 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 266 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| 266 const Immediate raw_null = | 267 const Immediate raw_null = |
| 267 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 268 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 268 | 269 |
| 269 // Create a stub frame as we are pushing some objects on the stack before | 270 // Create a stub frame as we are pushing some objects on the stack before |
| 270 // calling into the runtime. | 271 // calling into the runtime. |
| 271 AssemblerMacros::EnterStubFrame(assembler); | 272 AssemblerMacros::EnterStubFrame(assembler); |
| 272 | 273 |
| 273 // Preserve values across call to resolving. | 274 // Preserve values across call to resolving. |
| 274 // Stack at this point: | 275 // Stack at this point: |
| 275 // TOS + 0: PC marker => RawInstruction object. | 276 // TOS + 0: PC marker => RawInstruction object. |
| 276 // TOS + 1: Saved EBP of previous frame. <== EBP | 277 // TOS + 1: Saved EBP of previous frame. <== EBP |
| 277 // TOS + 2: Dart code return address | 278 // TOS + 2: Dart code return address |
| 278 // TOS + 3: Last argument of caller. | 279 // TOS + 3: Last argument of caller. |
| 279 // .... | 280 // .... |
| 280 // Total number of args is the first Smi in args descriptor array (EDX). | 281 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 281 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | |
| 282 __ movl(EAX, Address(EBP, EAX, TIMES_2, kWordSize)); // Get receiver. | 282 __ movl(EAX, Address(EBP, EAX, TIMES_2, kWordSize)); // Get receiver. |
| 283 __ pushl(EDX); // Preserve arguments descriptor array. | 283 __ pushl(EDX); // Preserve arguments descriptor array. |
| 284 __ pushl(EAX); // Preserve receiver. | 284 __ pushl(EAX); // Preserve receiver. |
| 285 __ pushl(ECX); // Preserve ic-data. | 285 __ pushl(ECX); // Preserve ic-data. |
| 286 // First resolve the function to get the function object. | 286 // First resolve the function to get the function object. |
| 287 | 287 |
| 288 __ pushl(raw_null); // Setup space on stack for return value. | 288 __ pushl(raw_null); // Setup space on stack for return value. |
| 289 __ pushl(EAX); // Push receiver. | 289 __ pushl(EAX); // Push receiver. |
| 290 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry); | 290 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry); |
| 291 __ popl(EAX); // Remove receiver pushed earlier. | 291 __ popl(EAX); // Remove receiver pushed earlier. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 | 370 |
| 371 __ cmpl(ECX, raw_null); | 371 __ cmpl(ECX, raw_null); |
| 372 Label function_not_found; | 372 Label function_not_found; |
| 373 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 373 __ j(EQUAL, &function_not_found, Assembler::kNearJump); |
| 374 | 374 |
| 375 // ECX: Closure object. | 375 // ECX: Closure object. |
| 376 // EDI: Arguments descriptor array. | 376 // EDI: Arguments descriptor array. |
| 377 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. | 377 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. |
| 378 __ pushl(ECX); // Closure object. | 378 __ pushl(ECX); // Closure object. |
| 379 __ pushl(EDI); // Arguments descriptor. | 379 __ pushl(EDI); // Arguments descriptor. |
| 380 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 380 __ movl(EDI, FieldAddress(EDI, ArgumentsDescriptor::count_offset())); |
| 381 __ SmiUntag(EDI); | 381 __ SmiUntag(EDI); |
| 382 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 382 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 383 PushArgumentsArray(assembler, (kWordSize * 6)); | 383 PushArgumentsArray(assembler, (kWordSize * 6)); |
| 384 // Stack layout explaining "(kWordSize * 6)" offset. | 384 // Stack layout explaining "(kWordSize * 6)" offset. |
| 385 // TOS + 0: Argument array. | 385 // TOS + 0: Argument array. |
| 386 // TOS + 1: Arguments descriptor array. | 386 // TOS + 1: Arguments descriptor array. |
| 387 // TOS + 2: Closure object. | 387 // TOS + 2: Closure object. |
| 388 // TOS + 3: Place for result from closure function. | 388 // TOS + 3: Place for result from closure function. |
| 389 // TOS + 4: PC marker => RawInstruction object. | 389 // TOS + 4: PC marker => RawInstruction object. |
| 390 // TOS + 5: Saved EBP of previous frame. <== EBP | 390 // TOS + 5: Saved EBP of previous frame. <== EBP |
| (...skipping 11 matching lines...) Expand all Loading... |
| 402 // Remove the stub frame as we are about to return. | 402 // Remove the stub frame as we are about to return. |
| 403 __ LeaveFrame(); | 403 __ LeaveFrame(); |
| 404 __ ret(); | 404 __ ret(); |
| 405 | 405 |
| 406 __ Bind(&function_not_found); | 406 __ Bind(&function_not_found); |
| 407 // The target function was not found, so invoke method | 407 // The target function was not found, so invoke method |
| 408 // "void noSuchMethod(function_name, args_array)". | 408 // "void noSuchMethod(function_name, args_array)". |
| 409 // EAX: receiver. | 409 // EAX: receiver. |
| 410 // EDX: ic-data. | 410 // EDX: ic-data. |
| 411 // ECX: raw_null. | 411 // ECX: raw_null. |
| 412 // EDI: argument descriptor array. | 412 // EDI: arguments descriptor array. |
| 413 | 413 |
| 414 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 414 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 415 __ pushl(EAX); // Receiver. | 415 __ pushl(EAX); // Receiver. |
| 416 __ pushl(EDX); // IC-data. | 416 __ pushl(EDX); // IC-data. |
| 417 __ pushl(EDI); // Argument descriptor array. | 417 __ pushl(EDI); // Arguments descriptor array. |
| 418 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 418 __ movl(EDI, FieldAddress(EDI, ArgumentsDescriptor::count_offset())); |
| 419 __ SmiUntag(EDI); | 419 __ SmiUntag(EDI); |
| 420 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 420 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 421 // See stack layout below explaining "wordSize * 7" offset. | 421 // See stack layout below explaining "wordSize * 7" offset. |
| 422 PushArgumentsArray(assembler, (kWordSize * 7)); | 422 PushArgumentsArray(assembler, (kWordSize * 7)); |
| 423 | 423 |
| 424 // Stack: | 424 // Stack: |
| 425 // TOS + 0: Argument array. | 425 // TOS + 0: Arguments array. |
| 426 // TOS + 1: Argument descriptor array. | 426 // TOS + 1: Arguments descriptor array. |
| 427 // TOS + 2: IC-data. | 427 // TOS + 2: IC-data. |
| 428 // TOS + 3: Receiver | 428 // TOS + 3: Receiver |
| 429 // TOS + 4: Place for result from noSuchMethod. | 429 // TOS + 4: Place for result from noSuchMethod. |
| 430 // TOS + 5: PC marker => RawInstruction object. | 430 // TOS + 5: PC marker => RawInstruction object. |
| 431 // TOS + 6: Saved EBP of previous frame. <== EBP | 431 // TOS + 6: Saved EBP of previous frame. <== EBP |
| 432 // TOS + 7: Dart code return address | 432 // TOS + 7: Dart code return address |
| 433 // TOS + 8: Last argument of caller. | 433 // TOS + 8: Last argument of caller. |
| 434 // .... | 434 // .... |
| 435 | 435 |
| 436 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); | 436 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 __ CallRuntime(kAllocateArrayRuntimeEntry); | 697 __ CallRuntime(kAllocateArrayRuntimeEntry); |
| 698 __ popl(EAX); // Pop element type argument. | 698 __ popl(EAX); // Pop element type argument. |
| 699 __ popl(EDX); // Pop array length argument. | 699 __ popl(EDX); // Pop array length argument. |
| 700 __ popl(EAX); // Pop return value from return slot. | 700 __ popl(EAX); // Pop return value from return slot. |
| 701 __ LeaveFrame(); | 701 __ LeaveFrame(); |
| 702 __ ret(); | 702 __ ret(); |
| 703 } | 703 } |
| 704 | 704 |
| 705 | 705 |
| 706 // Input parameters: | 706 // Input parameters: |
| 707 // EDX: Arguments descriptor array (num_args is first Smi element, closure | 707 // EDX: Arguments descriptor array. |
| 708 // object is included in num_args and is first argument). | |
| 709 // Note: The closure object is the first argument to the function being | 708 // Note: The closure object is the first argument to the function being |
| 710 // called, the stub accesses the closure from this location directly | 709 // called, the stub accesses the closure from this location directly |
| 711 // when trying to resolve the call. | 710 // when trying to resolve the call. |
| 712 // Uses EDI. | 711 // Uses EDI. |
| 713 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 712 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
| 714 const Immediate raw_null = | 713 const Immediate raw_null = |
| 715 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 714 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 716 | 715 |
| 717 // Total number of args is the first Smi in args descriptor array (EDX). | 716 // Load num_args. |
| 718 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); // Load num_args. | 717 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 719 // Load closure object in EDI. | 718 // Load closure object in EDI. |
| 720 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX is a Smi. | 719 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX is a Smi. |
| 721 | 720 |
| 722 // Verify that EDI is a closure by checking its class. | 721 // Verify that EDI is a closure by checking its class. |
| 723 Label not_closure; | 722 Label not_closure; |
| 724 __ cmpl(EDI, raw_null); | 723 __ cmpl(EDI, raw_null); |
| 725 // Not a closure, but null object. | 724 // Not a closure, but null object. |
| 726 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 725 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 727 __ testl(EDI, Immediate(kSmiTagMask)); | 726 __ testl(EDI, Immediate(kSmiTagMask)); |
| 728 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. | 727 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 757 __ popl(EDX); // Restore arguments descriptor array. | 756 __ popl(EDX); // Restore arguments descriptor array. |
| 758 // Restore EAX. | 757 // Restore EAX. |
| 759 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 758 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 760 | 759 |
| 761 // Remove the stub frame as we are about to jump to the closure function. | 760 // Remove the stub frame as we are about to jump to the closure function. |
| 762 __ LeaveFrame(); | 761 __ LeaveFrame(); |
| 763 | 762 |
| 764 __ Bind(&function_compiled); | 763 __ Bind(&function_compiled); |
| 765 // EAX: Code. | 764 // EAX: Code. |
| 766 // ECX: Function. | 765 // ECX: Function. |
| 767 // EDX: Arguments descriptor array (num_args is first Smi element). | 766 // EDX: Arguments descriptor array. |
| 768 | 767 |
| 769 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 768 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 770 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 769 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 771 __ jmp(ECX); | 770 __ jmp(ECX); |
| 772 | 771 |
| 773 __ Bind(¬_closure); | 772 __ Bind(¬_closure); |
| 774 // Call runtime to report that a closure call was attempted on a non-closure | 773 // Call runtime to report that a closure call was attempted on a non-closure |
| 775 // object, passing the non-closure object and its arguments array. | 774 // object, passing the non-closure object and its arguments array. |
| 776 // EDI: non-closure object. | 775 // EDI: non-closure object. |
| 777 // EDX: arguments descriptor array (num_args is first Smi element, closure | 776 // EDX: arguments descriptor array. |
| 778 // object is included in num_args). | |
| 779 | 777 |
| 780 // Create a stub frame as we are pushing some objects on the stack before | 778 // Create a stub frame as we are pushing some objects on the stack before |
| 781 // calling into the runtime. | 779 // calling into the runtime. |
| 782 AssemblerMacros::EnterStubFrame(assembler); | 780 AssemblerMacros::EnterStubFrame(assembler); |
| 783 | 781 |
| 784 __ pushl(raw_null); // Setup space on stack for result from error reporting. | 782 __ pushl(raw_null); // Setup space on stack for result from error reporting. |
| 785 __ pushl(EDI); // Non-closure object. | 783 __ pushl(EDI); // Non-closure object. |
| 786 // Total number of args is the first Smi in args descriptor array (EDX). | 784 // Load num_args. |
| 787 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); // Load num_args. | 785 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 788 __ SmiUntag(EDI); | 786 __ SmiUntag(EDI); |
| 789 __ subl(EDI, Immediate(1)); // Arguments array length, minus the closure. | 787 __ subl(EDI, Immediate(1)); // Arguments array length, minus the closure. |
| 790 // See stack layout below explaining "wordSize * 5" offset. | 788 // See stack layout below explaining "wordSize * 5" offset. |
| 791 PushArgumentsArray(assembler, (kWordSize * 5)); | 789 PushArgumentsArray(assembler, (kWordSize * 5)); |
| 792 | 790 |
| 793 // Stack: | 791 // Stack: |
| 794 // TOS + 0: Argument array. | 792 // TOS + 0: Argument array. |
| 795 // TOS + 1: Non-closure object. | 793 // TOS + 1: Non-closure object. |
| 796 // TOS + 2: Place for result from reporting the error. | 794 // TOS + 2: Place for result from reporting the error. |
| 797 // TOS + 3: PC marker => RawInstruction object. | 795 // TOS + 3: PC marker => RawInstruction object. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 // GC marking, since it traverses any information between SP and | 851 // GC marking, since it traverses any information between SP and |
| 854 // FP - kExitLinkOffsetInEntryFrame. | 852 // FP - kExitLinkOffsetInEntryFrame. |
| 855 __ movl(ECX, Address(EDI, Isolate::top_context_offset())); | 853 __ movl(ECX, Address(EDI, Isolate::top_context_offset())); |
| 856 __ pushl(ECX); | 854 __ pushl(ECX); |
| 857 | 855 |
| 858 // Load arguments descriptor array into EDX. | 856 // Load arguments descriptor array into EDX. |
| 859 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); | 857 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); |
| 860 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); | 858 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 861 | 859 |
| 862 // Load number of arguments into EBX. | 860 // Load number of arguments into EBX. |
| 863 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 861 __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 864 __ SmiUntag(EBX); | 862 __ SmiUntag(EBX); |
| 865 | 863 |
| 866 // Set up arguments for the dart call. | 864 // Set up arguments for the dart call. |
| 867 Label push_arguments; | 865 Label push_arguments; |
| 868 Label done_push_arguments; | 866 Label done_push_arguments; |
| 869 __ testl(EBX, EBX); // check if there are arguments. | 867 __ testl(EBX, EBX); // check if there are arguments. |
| 870 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); | 868 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); |
| 871 __ movl(EAX, Immediate(0)); | 869 __ movl(EAX, Immediate(0)); |
| 872 __ movl(EDI, Address(EBP, kArgumentsOffset)); // start of arguments. | 870 __ movl(EDI, Address(EBP, kArgumentsOffset)); // start of arguments. |
| 873 __ Bind(&push_arguments); | 871 __ Bind(&push_arguments); |
| 874 __ movl(ECX, Address(EDI, EAX, TIMES_4, 0)); | 872 __ movl(ECX, Address(EDI, EAX, TIMES_4, 0)); |
| 875 __ movl(ECX, Address(ECX, VMHandles::kOffsetOfRawPtrInHandle)); | 873 __ movl(ECX, Address(ECX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 876 __ pushl(ECX); | 874 __ pushl(ECX); |
| 877 __ incl(EAX); | 875 __ incl(EAX); |
| 878 __ cmpl(EAX, EBX); | 876 __ cmpl(EAX, EBX); |
| 879 __ j(LESS, &push_arguments, Assembler::kNearJump); | 877 __ j(LESS, &push_arguments, Assembler::kNearJump); |
| 880 __ Bind(&done_push_arguments); | 878 __ Bind(&done_push_arguments); |
| 881 | 879 |
| 882 // Call the dart code entrypoint. | 880 // Call the dart code entrypoint. |
| 883 __ call(Address(EBP, kEntryPointOffset)); | 881 __ call(Address(EBP, kEntryPointOffset)); |
| 884 | 882 |
| 885 // Reread the Context pointer. | 883 // Reread the Context pointer. |
| 886 __ movl(CTX, Address(EBP, kNewContextOffset)); | 884 __ movl(CTX, Address(EBP, kNewContextOffset)); |
| 887 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); | 885 __ movl(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 888 | 886 |
| 889 // Reread the arguments descriptor array to obtain the number of passed | 887 // Reread the arguments descriptor array to obtain the number of passed |
| 890 // arguments, which is the first element of the array, a Smi. | 888 // arguments. |
| 891 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); | 889 __ movl(EDX, Address(EBP, kArgumentsDescOffset)); |
| 892 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); | 890 __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 893 __ movl(EDX, FieldAddress(EDX, Array::data_offset())); | 891 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 894 // Get rid of arguments pushed on the stack. | 892 // Get rid of arguments pushed on the stack. |
| 895 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. | 893 __ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi. |
| 896 | 894 |
| 897 // Load Isolate pointer from Context structure into CTX. Drop Context. | 895 // Load Isolate pointer from Context structure into CTX. Drop Context. |
| 898 __ movl(CTX, FieldAddress(CTX, Context::isolate_offset())); | 896 __ movl(CTX, FieldAddress(CTX, Context::isolate_offset())); |
| 899 | 897 |
| 900 // Restore the saved Context pointer into the Isolate structure. | 898 // Restore the saved Context pointer into the Isolate structure. |
| 901 // Uses ECX as a temporary register for this. | 899 // Uses ECX as a temporary register for this. |
| 902 __ popl(ECX); | 900 __ popl(ECX); |
| 903 __ movl(Address(CTX, Isolate::top_context_offset()), ECX); | 901 __ movl(Address(CTX, Isolate::top_context_offset()), ECX); |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1441 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1439 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1442 // The target function was not found, so invoke method | 1440 // The target function was not found, so invoke method |
| 1443 // "void noSuchMethod(function_name, Array arguments)". | 1441 // "void noSuchMethod(function_name, Array arguments)". |
| 1444 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1442 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1445 // and named, as the argument array. This is not correct if out-of-order | 1443 // and named, as the argument array. This is not correct if out-of-order |
| 1446 // named arguments were passed. | 1444 // named arguments were passed. |
| 1447 // The signature of the "noSuchMethod" method has to change from | 1445 // The signature of the "noSuchMethod" method has to change from |
| 1448 // noSuchMethod(String name, Array arguments) to something like | 1446 // noSuchMethod(String name, Array arguments) to something like |
| 1449 // noSuchMethod(InvocationMirror call). | 1447 // noSuchMethod(InvocationMirror call). |
| 1450 // Also, the class NoSuchMethodError has to be modified accordingly. | 1448 // Also, the class NoSuchMethodError has to be modified accordingly. |
| 1451 // Total number of args is the first Smi in args descriptor array (EDX). | |
| 1452 const Immediate raw_null = | 1449 const Immediate raw_null = |
| 1453 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1450 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1454 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); | 1451 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1455 __ SmiUntag(EDI); | 1452 __ SmiUntag(EDI); |
| 1456 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. | 1453 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. |
| 1457 | 1454 |
| 1458 // Create a stub frame as we are pushing some objects on the stack before | 1455 // Create a stub frame as we are pushing some objects on the stack before |
| 1459 // calling into the runtime. | 1456 // calling into the runtime. |
| 1460 AssemblerMacros::EnterStubFrame(assembler); | 1457 AssemblerMacros::EnterStubFrame(assembler); |
| 1461 | 1458 |
| 1462 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 1459 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1463 __ pushl(EAX); // Receiver. | 1460 __ pushl(EAX); // Receiver. |
| 1464 __ pushl(ECX); // IC data array. | 1461 __ pushl(ECX); // IC data array. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 | 1579 |
| 1583 // Loop that checks if there is an IC data match. | 1580 // Loop that checks if there is an IC data match. |
| 1584 Label loop, update, test, found, get_class_id_as_smi; | 1581 Label loop, update, test, found, get_class_id_as_smi; |
| 1585 // ECX: IC data object (preserved). | 1582 // ECX: IC data object (preserved). |
| 1586 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1583 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1587 // EBX: ic_data_array with check entries: classes and target functions. | 1584 // EBX: ic_data_array with check entries: classes and target functions. |
| 1588 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1585 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1589 // EBX: points directly to the first ic data array element. | 1586 // EBX: points directly to the first ic data array element. |
| 1590 | 1587 |
| 1591 // Get the receiver's class ID (first read number of arguments from | 1588 // Get the receiver's class ID (first read number of arguments from |
| 1592 // argument descriptor array and then access the receiver from the stack). | 1589 // arguments descriptor array and then access the receiver from the stack). |
| 1593 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1590 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1594 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi. | 1591 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi. |
| 1595 __ call(&get_class_id_as_smi); | 1592 __ call(&get_class_id_as_smi); |
| 1596 // EAX: receiver's class ID (smi). | 1593 // EAX: receiver's class ID (smi). |
| 1597 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check. | 1594 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check. |
| 1598 __ jmp(&test); | 1595 __ jmp(&test); |
| 1599 | 1596 |
| 1600 __ Bind(&loop); | 1597 __ Bind(&loop); |
| 1601 for (int i = 0; i < num_args; i++) { | 1598 for (int i = 0; i < num_args; i++) { |
| 1602 if (i > 0) { | 1599 if (i > 0) { |
| 1603 // If not the first, load the next argument's class ID. | 1600 // If not the first, load the next argument's class ID. |
| 1604 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1601 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1605 __ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize)); | 1602 __ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize)); |
| 1606 __ call(&get_class_id_as_smi); | 1603 __ call(&get_class_id_as_smi); |
| 1607 // EAX: next argument class ID (smi). | 1604 // EAX: next argument class ID (smi). |
| 1608 __ movl(EDI, Address(EBX, i * kWordSize)); | 1605 __ movl(EDI, Address(EBX, i * kWordSize)); |
| 1609 // EDI: next class ID to check (smi). | 1606 // EDI: next class ID to check (smi). |
| 1610 } | 1607 } |
| 1611 __ cmpl(EAX, EDI); // Class id match? | 1608 __ cmpl(EAX, EDI); // Class id match? |
| 1612 if (i < (num_args - 1)) { | 1609 if (i < (num_args - 1)) { |
| 1613 __ j(NOT_EQUAL, &update); // Continue. | 1610 __ j(NOT_EQUAL, &update); // Continue. |
| 1614 } else { | 1611 } else { |
| 1615 // Last check, all checks before matched. | 1612 // Last check, all checks before matched. |
| 1616 __ j(EQUAL, &found, Assembler::kNearJump); // Break. | 1613 __ j(EQUAL, &found, Assembler::kNearJump); // Break. |
| 1617 } | 1614 } |
| 1618 } | 1615 } |
| 1619 __ Bind(&update); | 1616 __ Bind(&update); |
| 1620 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1617 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
| 1621 if (num_args > 1) { | 1618 if (num_args > 1) { |
| 1622 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1619 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1623 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); | 1620 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
| 1624 __ call(&get_class_id_as_smi); | 1621 __ call(&get_class_id_as_smi); |
| 1625 } | 1622 } |
| 1626 | 1623 |
| 1627 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1624 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1628 __ addl(EBX, Immediate(entry_size)); // Next entry. | 1625 __ addl(EBX, Immediate(entry_size)); // Next entry. |
| 1629 __ movl(EDI, Address(EBX, 0)); // Next class ID. | 1626 __ movl(EDI, Address(EBX, 0)); // Next class ID. |
| 1630 | 1627 |
| 1631 __ Bind(&test); | 1628 __ Bind(&test); |
| 1632 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1629 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1633 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1630 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1634 | 1631 |
| 1635 // IC miss. | 1632 // IC miss. |
| 1636 const Immediate raw_null = | 1633 const Immediate raw_null = |
| 1637 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1634 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1638 // Compute address of arguments (first read number of arguments from | 1635 // Compute address of arguments (first read number of arguments from |
| 1639 // argument descriptor array and then compute address on the stack). | 1636 // arguments descriptor array and then compute address on the stack). |
| 1640 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1637 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1641 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1638 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1642 // Create a stub frame as we are pushing some objects on the stack before | 1639 // Create a stub frame as we are pushing some objects on the stack before |
| 1643 // calling into the runtime. | 1640 // calling into the runtime. |
| 1644 AssemblerMacros::EnterStubFrame(assembler); | 1641 AssemblerMacros::EnterStubFrame(assembler); |
| 1645 __ pushl(EDX); // Preserve arguments array. | 1642 __ pushl(EDX); // Preserve arguments descriptor array. |
| 1646 __ pushl(ECX); // Preserve IC data array | 1643 __ pushl(ECX); // Preserve IC data array |
| 1647 __ pushl(raw_null); // Setup space on stack for result (target code object). | 1644 __ pushl(raw_null); // Setup space on stack for result (target code object). |
| 1648 // Push call arguments. | 1645 // Push call arguments. |
| 1649 for (intptr_t i = 0; i < num_args; i++) { | 1646 for (intptr_t i = 0; i < num_args; i++) { |
| 1650 __ movl(EDX, Address(EAX, -kWordSize * i)); | 1647 __ movl(EDX, Address(EAX, -kWordSize * i)); |
| 1651 __ pushl(EDX); | 1648 __ pushl(EDX); |
| 1652 } | 1649 } |
| 1653 if (num_args == 1) { | 1650 if (num_args == 1) { |
| 1654 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1651 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1655 } else if (num_args == 2) { | 1652 } else if (num_args == 2) { |
| 1656 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1653 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1657 } else if (num_args == 3) { | 1654 } else if (num_args == 3) { |
| 1658 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); | 1655 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1659 } else { | 1656 } else { |
| 1660 UNIMPLEMENTED(); | 1657 UNIMPLEMENTED(); |
| 1661 } | 1658 } |
| 1662 // Remove call arguments pushed earlier. | 1659 // Remove call arguments pushed earlier. |
| 1663 for (intptr_t i = 0; i < num_args; i++) { | 1660 for (intptr_t i = 0; i < num_args; i++) { |
| 1664 __ popl(EAX); | 1661 __ popl(EAX); |
| 1665 } | 1662 } |
| 1666 __ popl(EAX); // Pop returned code object into EAX (null if not found). | 1663 __ popl(EAX); // Pop returned code object into EAX (null if not found). |
| 1667 __ popl(ECX); // Restore IC data array. | 1664 __ popl(ECX); // Restore IC data array. |
| 1668 __ popl(EDX); // Restore arguments array. | 1665 __ popl(EDX); // Restore arguments descriptor array. |
| 1669 __ LeaveFrame(); | 1666 __ LeaveFrame(); |
| 1670 Label call_target_function; | 1667 Label call_target_function; |
| 1671 __ cmpl(EAX, raw_null); | 1668 __ cmpl(EAX, raw_null); |
| 1672 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1669 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
| 1673 // NoSuchMethod or closure. | 1670 // NoSuchMethod or closure. |
| 1674 // Mark IC call that it may be a closure call that does not collect | 1671 // Mark IC call that it may be a closure call that does not collect |
| 1675 // type feedback. | 1672 // type feedback. |
| 1676 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); | 1673 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); |
| 1677 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 1674 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 1678 | 1675 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1705 __ Bind(¬_smi); | 1702 __ Bind(¬_smi); |
| 1706 __ LoadClassId(EAX, EAX); | 1703 __ LoadClassId(EAX, EAX); |
| 1707 __ SmiTag(EAX); | 1704 __ SmiTag(EAX); |
| 1708 __ ret(); | 1705 __ ret(); |
| 1709 } | 1706 } |
| 1710 | 1707 |
| 1711 | 1708 |
| 1712 // Use inline cache data array to invoke the target or continue in inline | 1709 // Use inline cache data array to invoke the target or continue in inline |
| 1713 // cache miss handler. Stub for 1-argument check (receiver class). | 1710 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1714 // ECX: Inline cache data object. | 1711 // ECX: Inline cache data object. |
| 1715 // EDX: Arguments array. | 1712 // EDX: Arguments descriptor array. |
| 1716 // TOS(0): Return address. | 1713 // TOS(0): Return address. |
| 1717 // Inline cache data object structure: | 1714 // Inline cache data object structure: |
| 1718 // 0: function-name | 1715 // 0: function-name |
| 1719 // 1: N, number of arguments checked. | 1716 // 1: N, number of arguments checked. |
| 1720 // 2 .. (length - 1): group of checks, each check containing: | 1717 // 2 .. (length - 1): group of checks, each check containing: |
| 1721 // - N classes. | 1718 // - N classes. |
| 1722 // - 1 target function. | 1719 // - 1 target function. |
| 1723 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1720 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1724 GenerateUsageCounterIncrement(assembler, EBX); | 1721 GenerateUsageCounterIncrement(assembler, EBX); |
| 1725 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1722 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1736 GenerateUsageCounterIncrement(assembler, EBX); | 1733 GenerateUsageCounterIncrement(assembler, EBX); |
| 1737 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1734 GenerateNArgsCheckInlineCacheStub(assembler, 3); |
| 1738 } | 1735 } |
| 1739 | 1736 |
| 1740 | 1737 |
| 1741 | 1738 |
| 1742 // Use inline cache data array to invoke the target or continue in inline | 1739 // Use inline cache data array to invoke the target or continue in inline |
| 1743 // cache miss handler. Stub for 1-argument check (receiver class). | 1740 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1744 // EDI: function which counter needs to be incremented. | 1741 // EDI: function which counter needs to be incremented. |
| 1745 // ECX: Inline cache data object. | 1742 // ECX: Inline cache data object. |
| 1746 // EDX: Arguments array. | 1743 // EDX: Arguments descriptor array. |
| 1747 // TOS(0): Return address. | 1744 // TOS(0): Return address. |
| 1748 // Inline cache data object structure: | 1745 // Inline cache data object structure: |
| 1749 // 0: function-name | 1746 // 0: function-name |
| 1750 // 1: N, number of arguments checked. | 1747 // 1: N, number of arguments checked. |
| 1751 // 2 .. (length - 1): group of checks, each check containing: | 1748 // 2 .. (length - 1): group of checks, each check containing: |
| 1752 // - N classes. | 1749 // - N classes. |
| 1753 // - 1 target function. | 1750 // - 1 target function. |
| 1754 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1751 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
| 1755 Assembler* assembler) { | 1752 Assembler* assembler) { |
| 1756 GenerateOptimizedUsageCounterIncrement(assembler); | 1753 GenerateOptimizedUsageCounterIncrement(assembler); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1778 } | 1775 } |
| 1779 | 1776 |
| 1780 | 1777 |
| 1781 // Megamorphic call is currently implemented as IC call but through a stub | 1778 // Megamorphic call is currently implemented as IC call but through a stub |
| 1782 // that does not check/count function invocations. | 1779 // that does not check/count function invocations. |
| 1783 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1780 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1784 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1781 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1785 } | 1782 } |
| 1786 | 1783 |
| 1787 | 1784 |
| 1788 // EDX: Arguments array. | 1785 // EDX: Arguments descriptor array. |
| 1789 // TOS(0): return address (Dart code). | 1786 // TOS(0): return address (Dart code). |
| 1790 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1787 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1791 // Create a stub frame as we are pushing some objects on the stack before | 1788 // Create a stub frame as we are pushing some objects on the stack before |
| 1792 // calling into the runtime. | 1789 // calling into the runtime. |
| 1793 AssemblerMacros::EnterStubFrame(assembler); | 1790 AssemblerMacros::EnterStubFrame(assembler); |
| 1794 __ pushl(EDX); // Preserve arguments descriptor. | 1791 __ pushl(EDX); // Preserve arguments descriptor. |
| 1795 const Immediate raw_null = | 1792 const Immediate raw_null = |
| 1796 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1793 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1797 __ pushl(raw_null); // Room for result. | 1794 __ pushl(raw_null); // Room for result. |
| 1798 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1795 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1821 // Instead of returning to the patched Dart function, emulate the | 1818 // Instead of returning to the patched Dart function, emulate the |
| 1822 // smashed return code pattern and return to the function's caller. | 1819 // smashed return code pattern and return to the function's caller. |
| 1823 __ popl(ECX); // Discard return address to patched dart code. | 1820 __ popl(ECX); // Discard return address to patched dart code. |
| 1824 // Execute function epilog code that was smashed in the Dart code. | 1821 // Execute function epilog code that was smashed in the Dart code. |
| 1825 __ LeaveFrame(); | 1822 __ LeaveFrame(); |
| 1826 __ ret(); | 1823 __ ret(); |
| 1827 } | 1824 } |
| 1828 | 1825 |
| 1829 | 1826 |
| 1830 // ECX: Inline cache data array. | 1827 // ECX: Inline cache data array. |
| 1831 // EDX: Arguments array. | 1828 // EDX: Arguments descriptor array. |
| 1832 // TOS(0): return address (Dart code). | 1829 // TOS(0): return address (Dart code). |
| 1833 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1830 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1834 // Create a stub frame as we are pushing some objects on the stack before | 1831 // Create a stub frame as we are pushing some objects on the stack before |
| 1835 // calling into the runtime. | 1832 // calling into the runtime. |
| 1836 AssemblerMacros::EnterStubFrame(assembler); | 1833 AssemblerMacros::EnterStubFrame(assembler); |
| 1837 __ pushl(ECX); | 1834 __ pushl(ECX); |
| 1838 __ pushl(EDX); | 1835 __ pushl(EDX); |
| 1839 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1836 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| 1840 __ popl(EDX); | 1837 __ popl(EDX); |
| 1841 __ popl(ECX); | 1838 __ popl(ECX); |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2212 __ Bind(&done); | 2209 __ Bind(&done); |
| 2213 __ popl(temp); | 2210 __ popl(temp); |
| 2214 __ popl(right); | 2211 __ popl(right); |
| 2215 __ popl(left); | 2212 __ popl(left); |
| 2216 __ ret(); | 2213 __ ret(); |
| 2217 } | 2214 } |
| 2218 | 2215 |
| 2219 } // namespace dart | 2216 } // namespace dart |
| 2220 | 2217 |
| 2221 #endif // defined TARGET_ARCH_IA32 | 2218 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |