| 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 |