OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/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/dart_entry.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. | 74 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. |
75 __ call(ECX); | 75 __ call(ECX); |
76 | 76 |
77 // Reset exit frame information in Isolate structure. | 77 // Reset exit frame information in Isolate structure. |
78 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 78 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
79 | 79 |
80 // Load Context pointer from Isolate structure into ECX. | 80 // Load Context pointer from Isolate structure into ECX. |
81 __ movl(ECX, Address(CTX, Isolate::top_context_offset())); | 81 __ movl(ECX, Address(CTX, Isolate::top_context_offset())); |
82 | 82 |
83 // Reset Context pointer in Isolate structure. | 83 // Reset Context pointer in Isolate structure. |
84 const Immediate raw_null = | 84 const Immediate& raw_null = |
85 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 85 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
86 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); | 86 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); |
87 | 87 |
88 // Cache Context pointer into CTX while executing Dart code. | 88 // Cache Context pointer into CTX while executing Dart code. |
89 __ movl(CTX, ECX); | 89 __ movl(CTX, ECX); |
90 | 90 |
91 __ LeaveFrame(); | 91 __ LeaveFrame(); |
92 __ ret(); | 92 __ ret(); |
93 } | 93 } |
94 | 94 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. | 164 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. |
165 __ call(ECX); | 165 __ call(ECX); |
166 | 166 |
167 // Reset exit frame information in Isolate structure. | 167 // Reset exit frame information in Isolate structure. |
168 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 168 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
169 | 169 |
170 // Load Context pointer from Isolate structure into EDI. | 170 // Load Context pointer from Isolate structure into EDI. |
171 __ movl(EDI, Address(CTX, Isolate::top_context_offset())); | 171 __ movl(EDI, Address(CTX, Isolate::top_context_offset())); |
172 | 172 |
173 // Reset Context pointer in Isolate structure. | 173 // Reset Context pointer in Isolate structure. |
174 const Immediate raw_null = | 174 const Immediate& raw_null = |
175 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 175 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
176 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); | 176 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); |
177 | 177 |
178 // Cache Context pointer into CTX while executing Dart code. | 178 // Cache Context pointer into CTX while executing Dart code. |
179 __ movl(CTX, EDI); | 179 __ movl(CTX, EDI); |
180 | 180 |
181 __ LeaveFrame(); | 181 __ LeaveFrame(); |
182 __ ret(); | 182 __ ret(); |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 // Input parameters: | 186 // Input parameters: |
187 // EDX: arguments descriptor array. | 187 // EDX: arguments descriptor array. |
188 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 188 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
189 const Immediate raw_null = | 189 const Immediate& raw_null = |
190 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 190 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
191 AssemblerMacros::EnterStubFrame(assembler); | 191 AssemblerMacros::EnterStubFrame(assembler); |
192 __ pushl(EDX); // Preserve arguments descriptor array. | 192 __ pushl(EDX); // Preserve arguments descriptor array. |
193 __ pushl(raw_null); // Setup space on stack for return value. | 193 __ pushl(raw_null); // Setup space on stack for return value. |
194 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 194 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
195 __ popl(EAX); // Get Code object result. | 195 __ popl(EAX); // Get Code object result. |
196 __ popl(EDX); // Restore arguments descriptor array. | 196 __ popl(EDX); // Restore arguments descriptor array. |
197 // 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. |
198 __ LeaveFrame(); | 198 __ LeaveFrame(); |
199 | 199 |
200 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 200 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
201 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 201 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
202 __ jmp(ECX); | 202 __ jmp(ECX); |
203 } | 203 } |
204 | 204 |
205 | 205 |
206 // 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 |
207 // (invalid because its function was optimized or deoptimized). | 207 // (invalid because its function was optimized or deoptimized). |
208 // EDX: arguments descriptor array. | 208 // EDX: arguments descriptor array. |
209 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 209 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
210 const Immediate raw_null = | 210 const Immediate& raw_null = |
211 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 211 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
212 // 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 |
213 // calling into the runtime. | 213 // calling into the runtime. |
214 AssemblerMacros::EnterStubFrame(assembler); | 214 AssemblerMacros::EnterStubFrame(assembler); |
215 __ pushl(EDX); // Preserve arguments descriptor array. | 215 __ pushl(EDX); // Preserve arguments descriptor array. |
216 __ pushl(raw_null); // Setup space on stack for return value. | 216 __ pushl(raw_null); // Setup space on stack for return value. |
217 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 217 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
218 __ popl(EAX); // Get Code object. | 218 __ popl(EAX); // Get Code object. |
219 __ popl(EDX); // Restore arguments descriptor array. | 219 __ popl(EDX); // Restore arguments descriptor array. |
220 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 220 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
221 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 221 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
222 __ LeaveFrame(); | 222 __ LeaveFrame(); |
223 __ jmp(EAX); | 223 __ jmp(EAX); |
224 __ int3(); | 224 __ int3(); |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 // Input parameters: | 228 // Input parameters: |
229 // EDX: smi-tagged argument count, may be zero. | 229 // EDX: smi-tagged argument count, may be zero. |
230 // Uses EAX, EBX, ECX, EDX. | 230 // Uses EAX, EBX, ECX, EDX. |
231 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 231 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
232 const Immediate raw_null = | 232 const Immediate& raw_null = |
233 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 233 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
234 | 234 |
235 // Allocate array to store arguments of caller. | 235 // Allocate array to store arguments of caller. |
236 __ movl(ECX, raw_null); // Null element type for raw Array. | 236 __ movl(ECX, raw_null); // Null element type for raw Array. |
237 __ call(&StubCode::AllocateArrayLabel()); | 237 __ call(&StubCode::AllocateArrayLabel()); |
238 __ SmiUntag(EDX); | 238 __ SmiUntag(EDX); |
239 // EAX: newly allocated array. | 239 // EAX: newly allocated array. |
240 // EDX: length of the array (was preserved by the stub). | 240 // EDX: length of the array (was preserved by the stub). |
241 __ pushl(EAX); // Array is in EAX and on top of stack. | 241 __ pushl(EAX); // Array is in EAX and on top of stack. |
242 __ leal(EBX, Address(ESP, EDX, TIMES_4, arg_offset)); // Addr of first arg. | 242 __ leal(EBX, Address(ESP, EDX, TIMES_4, arg_offset)); // Addr of first arg. |
(...skipping 14 matching lines...) Expand all Loading... |
257 // Input parameters: | 257 // Input parameters: |
258 // ECX: ic-data. | 258 // ECX: ic-data. |
259 // EDX: arguments descriptor array. | 259 // EDX: arguments descriptor array. |
260 // Note: The receiver object is the first argument to the function being | 260 // Note: The receiver object is the first argument to the function being |
261 // called, the stub accesses the receiver from this location directly | 261 // called, the stub accesses the receiver from this location directly |
262 // when trying to resolve the call. | 262 // when trying to resolve the call. |
263 // Uses EDI. | 263 // Uses EDI. |
264 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 264 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
265 AssemblerMacros::EnterStubFrame(assembler); | 265 AssemblerMacros::EnterStubFrame(assembler); |
266 | 266 |
267 const Immediate raw_null = | 267 const Immediate& raw_null = |
268 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 268 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
269 __ pushl(raw_null); // Space for the return value. | 269 __ pushl(raw_null); // Space for the return value. |
270 | 270 |
271 // Push the receiver as an argument. Load the smi-tagged argument | 271 // Push the receiver as an argument. Load the smi-tagged argument |
272 // count into EDI to index the receiver in the stack. There are | 272 // count into EDI to index the receiver in the stack. There are |
273 // three words (null, stub's pc marker, saved fp) above the return | 273 // three words (null, stub's pc marker, saved fp) above the return |
274 // address. | 274 // address. |
275 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 275 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
276 __ pushl(Address(ESP, EDI, TIMES_2, (3 * kWordSize))); | 276 __ pushl(Address(ESP, EDI, TIMES_2, (3 * kWordSize))); |
277 | 277 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 // Load the receiver into EAX. The argument count in the arguments | 427 // Load the receiver into EAX. The argument count in the arguments |
428 // descriptor in EDX is a smi. | 428 // descriptor in EDX is a smi. |
429 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 429 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
430 // Two words (saved fp, stub's pc marker) in the stack above the return | 430 // Two words (saved fp, stub's pc marker) in the stack above the return |
431 // address. | 431 // address. |
432 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); | 432 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); |
433 // Preserve IC data and arguments descriptor. | 433 // Preserve IC data and arguments descriptor. |
434 __ pushl(ECX); | 434 __ pushl(ECX); |
435 __ pushl(EDX); | 435 __ pushl(EDX); |
436 | 436 |
437 const Immediate raw_null = | 437 const Immediate& raw_null = |
438 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 438 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
439 __ pushl(raw_null); // Space for the result of the runtime call. | 439 __ pushl(raw_null); // Space for the result of the runtime call. |
440 __ pushl(EAX); // Pass receiver. | 440 __ pushl(EAX); // Pass receiver. |
441 __ pushl(ECX); // Pass IC data. | 441 __ pushl(ECX); // Pass IC data. |
442 __ pushl(EDX); // Pass rguments descriptor. | 442 __ pushl(EDX); // Pass rguments descriptor. |
443 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); | 443 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); |
444 // Discard arguments. | 444 // Discard arguments. |
445 __ popl(EAX); | 445 __ popl(EAX); |
446 __ popl(EAX); | 446 __ popl(EAX); |
447 __ popl(EAX); | 447 __ popl(EAX); |
(...skipping 15 matching lines...) Expand all Loading... |
463 | 463 |
464 // Called for inline allocation of arrays. | 464 // Called for inline allocation of arrays. |
465 // Input parameters: | 465 // Input parameters: |
466 // EDX : Array length as Smi. | 466 // EDX : Array length as Smi. |
467 // ECX : array element type (either NULL or an instantiated type). | 467 // ECX : array element type (either NULL or an instantiated type). |
468 // Uses EAX, EBX, ECX, EDI as temporary registers. | 468 // Uses EAX, EBX, ECX, EDI as temporary registers. |
469 // NOTE: EDX cannot be clobbered here as the caller relies on it being saved. | 469 // NOTE: EDX cannot be clobbered here as the caller relies on it being saved. |
470 // The newly allocated object is returned in EAX. | 470 // The newly allocated object is returned in EAX. |
471 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 471 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
472 Label slow_case; | 472 Label slow_case; |
473 const Immediate raw_null = | 473 const Immediate& raw_null = |
474 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 474 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
475 | 475 |
476 if (FLAG_inline_alloc) { | 476 if (FLAG_inline_alloc) { |
477 // Compute the size to be allocated, it is based on the array length | 477 // Compute the size to be allocated, it is based on the array length |
478 // and is computed as: | 478 // and is computed as: |
479 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 479 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
480 // Assert that length is a Smi. | 480 // Assert that length is a Smi. |
481 __ testl(EDX, Immediate(kSmiTagSize)); | 481 __ testl(EDX, Immediate(kSmiTagSize)); |
482 if (FLAG_use_slow_path) { | 482 if (FLAG_use_slow_path) { |
483 __ jmp(&slow_case); | 483 __ jmp(&slow_case); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 } | 600 } |
601 | 601 |
602 | 602 |
603 // Input parameters: | 603 // Input parameters: |
604 // EDX: Arguments descriptor array. | 604 // EDX: Arguments descriptor array. |
605 // Note: The closure object is the first argument to the function being | 605 // Note: The closure object is the first argument to the function being |
606 // called, the stub accesses the closure from this location directly | 606 // called, the stub accesses the closure from this location directly |
607 // when trying to resolve the call. | 607 // when trying to resolve the call. |
608 // Uses EDI. | 608 // Uses EDI. |
609 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 609 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
610 const Immediate raw_null = | 610 const Immediate& raw_null = |
611 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 611 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
612 | 612 |
613 // Load num_args. | 613 // Load num_args. |
614 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 614 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
615 // Load closure object in EDI. | 615 // Load closure object in EDI. |
616 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX is a Smi. | 616 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX is a Smi. |
617 | 617 |
618 // Verify that EDI is a closure by checking its class. | 618 // Verify that EDI is a closure by checking its class. |
619 Label not_closure; | 619 Label not_closure; |
620 __ cmpl(EDI, raw_null); | 620 __ cmpl(EDI, raw_null); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 } | 828 } |
829 | 829 |
830 | 830 |
831 // Called for inline allocation of contexts. | 831 // Called for inline allocation of contexts. |
832 // Input: | 832 // Input: |
833 // EDX: number of context variables. | 833 // EDX: number of context variables. |
834 // Output: | 834 // Output: |
835 // EAX: new allocated RawContext object. | 835 // EAX: new allocated RawContext object. |
836 // EBX and EDX are destroyed. | 836 // EBX and EDX are destroyed. |
837 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 837 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
838 const Immediate raw_null = | 838 const Immediate& raw_null = |
839 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 839 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
840 if (FLAG_inline_alloc) { | 840 if (FLAG_inline_alloc) { |
841 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 841 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
842 Label slow_case; | 842 Label slow_case; |
843 Heap* heap = Isolate::Current()->heap(); | 843 Heap* heap = Isolate::Current()->heap(); |
844 // First compute the rounded instance size. | 844 // First compute the rounded instance size. |
845 // EDX: number of context variables. | 845 // EDX: number of context variables. |
846 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 846 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
847 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); | 847 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); |
848 __ andl(EBX, Immediate(-kObjectAlignment)); | 848 __ andl(EBX, Immediate(-kObjectAlignment)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); | 901 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); |
902 | 902 |
903 // Setup isolate field. | 903 // Setup isolate field. |
904 // Load Isolate pointer from Context structure into EBX. | 904 // Load Isolate pointer from Context structure into EBX. |
905 // EAX: new object. | 905 // EAX: new object. |
906 // EDX: number of context variables. | 906 // EDX: number of context variables. |
907 __ movl(EBX, FieldAddress(CTX, Context::isolate_offset())); | 907 __ movl(EBX, FieldAddress(CTX, Context::isolate_offset())); |
908 // EBX: Isolate, not an object. | 908 // EBX: Isolate, not an object. |
909 __ movl(FieldAddress(EAX, Context::isolate_offset()), EBX); | 909 __ movl(FieldAddress(EAX, Context::isolate_offset()), EBX); |
910 | 910 |
911 const Immediate raw_null = | 911 const Immediate& raw_null = |
912 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 912 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
913 // Setup the parent field. | 913 // Setup the parent field. |
914 // EAX: new object. | 914 // EAX: new object. |
915 // EDX: number of context variables. | 915 // EDX: number of context variables. |
916 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); | 916 __ movl(FieldAddress(EAX, Context::parent_offset()), raw_null); |
917 | 917 |
918 // Initialize the context variables. | 918 // Initialize the context variables. |
919 // EAX: new object. | 919 // EAX: new object. |
920 // EDX: number of context variables. | 920 // EDX: number of context variables. |
921 { | 921 { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 // Called for inline allocation of objects. | 1012 // Called for inline allocation of objects. |
1013 // Input parameters: | 1013 // Input parameters: |
1014 // ESP + 8 : type arguments object (only if class is parameterized). | 1014 // ESP + 8 : type arguments object (only if class is parameterized). |
1015 // ESP + 4 : type arguments of instantiator (only if class is parameterized). | 1015 // ESP + 4 : type arguments of instantiator (only if class is parameterized). |
1016 // ESP : points to return address. | 1016 // ESP : points to return address. |
1017 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. | 1017 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. |
1018 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1018 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
1019 const Class& cls) { | 1019 const Class& cls) { |
1020 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1020 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
1021 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1021 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
1022 const Immediate raw_null = | 1022 const Immediate& raw_null = |
1023 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1023 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1024 // The generated code is different if the class is parameterized. | 1024 // The generated code is different if the class is parameterized. |
1025 const bool is_cls_parameterized = | 1025 const bool is_cls_parameterized = |
1026 cls.type_arguments_field_offset() != Class::kNoTypeArguments; | 1026 cls.type_arguments_field_offset() != Class::kNoTypeArguments; |
1027 // kInlineInstanceSize is a constant used as a threshold for determining | 1027 // kInlineInstanceSize is a constant used as a threshold for determining |
1028 // when the object initialization should be done as a loop or as | 1028 // when the object initialization should be done as a loop or as |
1029 // straight line code. | 1029 // straight line code. |
1030 const int kInlineInstanceSize = 12; | 1030 const int kInlineInstanceSize = 12; |
1031 const intptr_t instance_size = cls.instance_size(); | 1031 const intptr_t instance_size = cls.instance_size(); |
1032 ASSERT(instance_size > 0); | 1032 ASSERT(instance_size > 0); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 // EDI: new object type arguments (if is_cls_parameterized). | 1105 // EDI: new object type arguments (if is_cls_parameterized). |
1106 __ LoadObject(EDX, cls); // Load class of object to be allocated. | 1106 __ LoadObject(EDX, cls); // Load class of object to be allocated. |
1107 // Set the tags. | 1107 // Set the tags. |
1108 uword tags = 0; | 1108 uword tags = 0; |
1109 tags = RawObject::SizeTag::update(instance_size, tags); | 1109 tags = RawObject::SizeTag::update(instance_size, tags); |
1110 ASSERT(cls.id() != kIllegalCid); | 1110 ASSERT(cls.id() != kIllegalCid); |
1111 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1111 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1112 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); | 1112 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); |
1113 | 1113 |
1114 // Initialize the remaining words of the object. | 1114 // Initialize the remaining words of the object. |
1115 const Immediate raw_null = | 1115 const Immediate& raw_null = |
1116 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1116 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1117 | 1117 |
1118 // EAX: new object start. | 1118 // EAX: new object start. |
1119 // EBX: next object start. | 1119 // EBX: next object start. |
1120 // EDX: class of the object to be allocated. | 1120 // EDX: class of the object to be allocated. |
1121 // EDI: new object type arguments (if is_cls_parameterized). | 1121 // EDI: new object type arguments (if is_cls_parameterized). |
1122 // First try inlining the initialization without a loop. | 1122 // First try inlining the initialization without a loop. |
1123 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1123 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1124 // Check if the object contains any non-header fields. | 1124 // Check if the object contains any non-header fields. |
1125 // Small objects are initialized using a consecutive set of writes. | 1125 // Small objects are initialized using a consecutive set of writes. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 | 1186 |
1187 | 1187 |
1188 // Called for inline allocation of closures. | 1188 // Called for inline allocation of closures. |
1189 // Input parameters: | 1189 // Input parameters: |
1190 // ESP + 8 : receiver (null if not an implicit instance closure). | 1190 // ESP + 8 : receiver (null if not an implicit instance closure). |
1191 // ESP + 4 : type arguments object (null if class is no parameterized). | 1191 // ESP + 4 : type arguments object (null if class is no parameterized). |
1192 // ESP : points to return address. | 1192 // ESP : points to return address. |
1193 // Uses EAX, EBX, ECX, EDX as temporary registers. | 1193 // Uses EAX, EBX, ECX, EDX as temporary registers. |
1194 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1194 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
1195 const Function& func) { | 1195 const Function& func) { |
1196 const Immediate raw_null = | 1196 const Immediate& raw_null = |
1197 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1197 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1198 ASSERT(func.IsClosureFunction()); | 1198 ASSERT(func.IsClosureFunction()); |
1199 const bool is_implicit_static_closure = | 1199 const bool is_implicit_static_closure = |
1200 func.IsImplicitStaticClosureFunction(); | 1200 func.IsImplicitStaticClosureFunction(); |
1201 const bool is_implicit_instance_closure = | 1201 const bool is_implicit_instance_closure = |
1202 func.IsImplicitInstanceClosureFunction(); | 1202 func.IsImplicitInstanceClosureFunction(); |
1203 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1203 const Class& cls = Class::ZoneHandle(func.signature_class()); |
1204 const bool has_type_arguments = cls.HasTypeArguments(); | 1204 const bool has_type_arguments = cls.HasTypeArguments(); |
1205 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1205 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
1206 const intptr_t kReceiverOffset = 2 * kWordSize; | 1206 const intptr_t kReceiverOffset = 2 * kWordSize; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1343 // EBP : points to previous frame pointer. | 1343 // EBP : points to previous frame pointer. |
1344 // EBP + 4 : points to return address. | 1344 // EBP + 4 : points to return address. |
1345 // EBP + 8 : address of last argument (arg n-1). | 1345 // EBP + 8 : address of last argument (arg n-1). |
1346 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). | 1346 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). |
1347 // ECX : ic-data. | 1347 // ECX : ic-data. |
1348 // EDX : arguments descriptor array. | 1348 // EDX : arguments descriptor array. |
1349 // Uses EAX, EBX, EDI as temporary registers. | 1349 // Uses EAX, EBX, EDI as temporary registers. |
1350 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1350 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1351 // The target function was not found, so invoke method | 1351 // The target function was not found, so invoke method |
1352 // "dynamic noSuchMethod(InvocationMirror invocation)". | 1352 // "dynamic noSuchMethod(InvocationMirror invocation)". |
1353 const Immediate raw_null = | 1353 const Immediate& raw_null = |
1354 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1354 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1355 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1355 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
1356 __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize)); // Get receiver. | 1356 __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize)); // Get receiver. |
1357 | 1357 |
1358 // Create a stub frame as we are pushing some objects on the stack before | 1358 // Create a stub frame as we are pushing some objects on the stack before |
1359 // calling into the runtime. | 1359 // calling into the runtime. |
1360 AssemblerMacros::EnterStubFrame(assembler); | 1360 AssemblerMacros::EnterStubFrame(assembler); |
1361 | 1361 |
1362 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 1362 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
1363 __ pushl(EAX); // Receiver. | 1363 __ pushl(EAX); // Receiver. |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 | 1527 |
1528 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1528 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
1529 __ addl(EBX, Immediate(entry_size)); // Next entry. | 1529 __ addl(EBX, Immediate(entry_size)); // Next entry. |
1530 __ movl(EDI, Address(EBX, 0)); // Next class ID. | 1530 __ movl(EDI, Address(EBX, 0)); // Next class ID. |
1531 | 1531 |
1532 __ Bind(&test); | 1532 __ Bind(&test); |
1533 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1533 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
1534 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1534 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
1535 | 1535 |
1536 // IC miss. | 1536 // IC miss. |
1537 const Immediate raw_null = | 1537 const Immediate& raw_null = |
1538 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1538 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1539 // Compute address of arguments (first read number of arguments from | 1539 // Compute address of arguments (first read number of arguments from |
1540 // arguments descriptor array and then compute address on the stack). | 1540 // arguments descriptor array and then compute address on the stack). |
1541 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1541 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
1542 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1542 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
1543 // Create a stub frame as we are pushing some objects on the stack before | 1543 // Create a stub frame as we are pushing some objects on the stack before |
1544 // calling into the runtime. | 1544 // calling into the runtime. |
1545 AssemblerMacros::EnterStubFrame(assembler); | 1545 AssemblerMacros::EnterStubFrame(assembler); |
1546 __ pushl(EDX); // Preserve arguments descriptor array. | 1546 __ pushl(EDX); // Preserve arguments descriptor array. |
1547 __ pushl(ECX); // Preserve IC data object. | 1547 __ pushl(ECX); // Preserve IC data object. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 } | 1689 } |
1690 | 1690 |
1691 | 1691 |
1692 // EDX: Arguments descriptor array. | 1692 // EDX: Arguments descriptor array. |
1693 // TOS(0): return address (Dart code). | 1693 // TOS(0): return address (Dart code). |
1694 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1694 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
1695 // Create a stub frame as we are pushing some objects on the stack before | 1695 // Create a stub frame as we are pushing some objects on the stack before |
1696 // calling into the runtime. | 1696 // calling into the runtime. |
1697 AssemblerMacros::EnterStubFrame(assembler); | 1697 AssemblerMacros::EnterStubFrame(assembler); |
1698 __ pushl(EDX); // Preserve arguments descriptor. | 1698 __ pushl(EDX); // Preserve arguments descriptor. |
1699 const Immediate raw_null = | 1699 const Immediate& raw_null = |
1700 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1700 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1701 __ pushl(raw_null); // Room for result. | 1701 __ pushl(raw_null); // Room for result. |
1702 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1702 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
1703 __ popl(EAX); // Code object. | 1703 __ popl(EAX); // Code object. |
1704 __ popl(EDX); // Restore arguments descriptor. | 1704 __ popl(EDX); // Restore arguments descriptor. |
1705 __ LeaveFrame(); | 1705 __ LeaveFrame(); |
1706 | 1706 |
1707 // Now call the static function. The breakpoint handler function | 1707 // Now call the static function. The breakpoint handler function |
1708 // ensures that the call target is compiled. | 1708 // ensures that the call target is compiled. |
1709 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 1709 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 // TOS + 0: return address. | 1768 // TOS + 0: return address. |
1769 // TOS + 1: instantiator type arguments (can be NULL). | 1769 // TOS + 1: instantiator type arguments (can be NULL). |
1770 // TOS + 2: instance. | 1770 // TOS + 2: instance. |
1771 // TOS + 3: SubtypeTestCache. | 1771 // TOS + 3: SubtypeTestCache. |
1772 // Result in ECX: null -> not found, otherwise result (true or false). | 1772 // Result in ECX: null -> not found, otherwise result (true or false). |
1773 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1773 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
1774 ASSERT((1 <= n) && (n <= 3)); | 1774 ASSERT((1 <= n) && (n <= 3)); |
1775 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1775 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
1776 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1776 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
1777 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1777 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
1778 const Immediate raw_null = | 1778 const Immediate& raw_null = |
1779 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1779 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1780 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); | 1780 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); |
1781 if (n > 1) { | 1781 if (n > 1) { |
1782 // Get instance type arguments. | 1782 // Get instance type arguments. |
1783 __ LoadClass(ECX, EAX, EBX); | 1783 __ LoadClass(ECX, EAX, EBX); |
1784 // Compute instance type arguments into EBX. | 1784 // Compute instance type arguments into EBX. |
1785 Label has_no_type_arguments; | 1785 Label has_no_type_arguments; |
1786 __ movl(EBX, raw_null); | 1786 __ movl(EBX, raw_null); |
1787 __ movl(EDI, FieldAddress(ECX, | 1787 __ movl(EDI, FieldAddress(ECX, |
1788 Class::type_arguments_field_offset_in_words_offset())); | 1788 Class::type_arguments_field_offset_in_words_offset())); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2016 __ LeaveFrame(); | 2016 __ LeaveFrame(); |
2017 | 2017 |
2018 __ jmp(&compute_result, Assembler::kNearJump); | 2018 __ jmp(&compute_result, Assembler::kNearJump); |
2019 } | 2019 } |
2020 | 2020 |
2021 | 2021 |
2022 // Calls to runtime to ooptimized give function | 2022 // Calls to runtime to ooptimized give function |
2023 // EDI: function to be reoptimized. | 2023 // EDI: function to be reoptimized. |
2024 // EDX: argument descriptor (preserved). | 2024 // EDX: argument descriptor (preserved). |
2025 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 2025 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
2026 const Immediate raw_null = | 2026 const Immediate& raw_null = |
2027 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2027 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
2028 AssemblerMacros::EnterStubFrame(assembler); | 2028 AssemblerMacros::EnterStubFrame(assembler); |
2029 __ pushl(EDX); | 2029 __ pushl(EDX); |
2030 __ pushl(raw_null); // Setup space on stack for return value. | 2030 __ pushl(raw_null); // Setup space on stack for return value. |
2031 __ pushl(EDI); | 2031 __ pushl(EDI); |
2032 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 2032 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
2033 __ popl(EAX); // Discard argument. | 2033 __ popl(EAX); // Discard argument. |
2034 __ popl(EAX); // Get Code object | 2034 __ popl(EAX); // Get Code object |
2035 __ popl(EDX); // Restore argument descriptor. | 2035 __ popl(EDX); // Restore argument descriptor. |
2036 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 2036 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 __ Bind(&done); | 2122 __ Bind(&done); |
2123 __ popl(temp); | 2123 __ popl(temp); |
2124 __ popl(right); | 2124 __ popl(right); |
2125 __ popl(left); | 2125 __ popl(left); |
2126 __ ret(); | 2126 __ ret(); |
2127 } | 2127 } |
2128 | 2128 |
2129 } // namespace dart | 2129 } // namespace dart |
2130 | 2130 |
2131 #endif // defined TARGET_ARCH_IA32 | 2131 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |