Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 11442010: Introduce a class encapsulating arguments descriptor arrays. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporated review comments. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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, &not_closure, Assembler::kNearJump); 725 __ j(EQUAL, &not_closure, Assembler::kNearJump);
727 __ testl(EDI, Immediate(kSmiTagMask)); 726 __ testl(EDI, Immediate(kSmiTagMask));
728 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi. 727 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi.
(...skipping 28 matching lines...) Expand all
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(&not_closure); 772 __ Bind(&not_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
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
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
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
1705 __ Bind(&not_smi); 1702 __ Bind(&not_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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698