| 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_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. | 75 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
| 76 __ call(RBX); | 76 __ call(RBX); |
| 77 | 77 |
| 78 // Reset exit frame information in Isolate structure. | 78 // Reset exit frame information in Isolate structure. |
| 79 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 79 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 80 | 80 |
| 81 // Load Context pointer from Isolate structure into RBX. | 81 // Load Context pointer from Isolate structure into RBX. |
| 82 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); | 82 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
| 83 | 83 |
| 84 // Reset Context pointer in Isolate structure. | 84 // Reset Context pointer in Isolate structure. |
| 85 const Immediate raw_null = | 85 const Immediate& raw_null = |
| 86 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 86 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 87 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | 87 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 88 | 88 |
| 89 // Cache Context pointer into CTX while executing Dart code. | 89 // Cache Context pointer into CTX while executing Dart code. |
| 90 __ movq(CTX, RBX); | 90 __ movq(CTX, RBX); |
| 91 | 91 |
| 92 __ LeaveFrame(); | 92 __ LeaveFrame(); |
| 93 __ ret(); | 93 __ ret(); |
| 94 } | 94 } |
| 95 | 95 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. | 163 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. |
| 164 __ call(RBX); | 164 __ call(RBX); |
| 165 | 165 |
| 166 // Reset exit frame information in Isolate structure. | 166 // Reset exit frame information in Isolate structure. |
| 167 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 167 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 168 | 168 |
| 169 // Load Context pointer from Isolate structure into R8. | 169 // Load Context pointer from Isolate structure into R8. |
| 170 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 170 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| 171 | 171 |
| 172 // Reset Context pointer in Isolate structure. | 172 // Reset Context pointer in Isolate structure. |
| 173 const Immediate raw_null = | 173 const Immediate& raw_null = |
| 174 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 174 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 175 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | 175 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 176 | 176 |
| 177 // Cache Context pointer into CTX while executing Dart code. | 177 // Cache Context pointer into CTX while executing Dart code. |
| 178 __ movq(CTX, R8); | 178 __ movq(CTX, R8); |
| 179 | 179 |
| 180 __ LeaveFrame(); | 180 __ LeaveFrame(); |
| 181 __ ret(); | 181 __ ret(); |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| 185 // Input parameters: | 185 // Input parameters: |
| 186 // R10: arguments descriptor array. | 186 // R10: arguments descriptor array. |
| 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| 188 const Immediate raw_null = | 188 const Immediate& raw_null = |
| 189 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 189 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 190 AssemblerMacros::EnterStubFrame(assembler); | 190 AssemblerMacros::EnterStubFrame(assembler); |
| 191 __ pushq(R10); // Preserve arguments descriptor array. | 191 __ pushq(R10); // Preserve arguments descriptor array. |
| 192 __ pushq(raw_null); // Setup space on stack for return value. | 192 __ pushq(raw_null); // Setup space on stack for return value. |
| 193 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 193 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
| 194 __ popq(RAX); // Get Code object result. | 194 __ popq(RAX); // Get Code object result. |
| 195 __ popq(R10); // Restore arguments descriptor array. | 195 __ popq(R10); // Restore arguments descriptor array. |
| 196 // Remove the stub frame as we are about to jump to the dart function. | 196 // Remove the stub frame as we are about to jump to the dart function. |
| 197 __ LeaveFrame(); | 197 __ LeaveFrame(); |
| 198 | 198 |
| 199 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 199 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
| 200 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 200 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 201 __ jmp(RBX); | 201 __ jmp(RBX); |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 // Called from a static call only when an invalid code has been entered | 205 // Called from a static call only when an invalid code has been entered |
| 206 // (invalid because its function was optimized or deoptimized). | 206 // (invalid because its function was optimized or deoptimized). |
| 207 // R10: arguments descriptor array. | 207 // R10: arguments descriptor array. |
| 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 209 const Immediate raw_null = | 209 const Immediate& raw_null = |
| 210 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 210 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 211 AssemblerMacros::EnterStubFrame(assembler); | 211 AssemblerMacros::EnterStubFrame(assembler); |
| 212 __ pushq(R10); // Preserve arguments descriptor array. | 212 __ pushq(R10); // Preserve arguments descriptor array. |
| 213 __ pushq(raw_null); // Setup space on stack for return value. | 213 __ pushq(raw_null); // Setup space on stack for return value. |
| 214 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 214 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
| 215 __ popq(RAX); // Get Code object. | 215 __ popq(RAX); // Get Code object. |
| 216 __ popq(R10); // Restore arguments descriptor array. | 216 __ popq(R10); // Restore arguments descriptor array. |
| 217 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 217 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 218 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 218 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 219 __ LeaveFrame(); | 219 __ LeaveFrame(); |
| 220 __ jmp(RAX); | 220 __ jmp(RAX); |
| 221 __ int3(); | 221 __ int3(); |
| 222 } | 222 } |
| 223 | 223 |
| 224 | 224 |
| 225 // Input parameters: | 225 // Input parameters: |
| 226 // R10: smi-tagged argument count, may be zero. | 226 // R10: smi-tagged argument count, may be zero. |
| 227 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 227 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
| 228 const Immediate raw_null = | 228 const Immediate& raw_null = |
| 229 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 229 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 230 | 230 |
| 231 // Allocate array to store arguments of caller. | 231 // Allocate array to store arguments of caller. |
| 232 __ movq(RBX, raw_null); // Null element type for raw Array. | 232 __ movq(RBX, raw_null); // Null element type for raw Array. |
| 233 __ call(&StubCode::AllocateArrayLabel()); | 233 __ call(&StubCode::AllocateArrayLabel()); |
| 234 __ SmiUntag(R10); | 234 __ SmiUntag(R10); |
| 235 // RAX: newly allocated array. | 235 // RAX: newly allocated array. |
| 236 // R10: length of the array (was preserved by the stub). | 236 // R10: length of the array (was preserved by the stub). |
| 237 __ pushq(RAX); // Array is in RAX and on top of stack. | 237 __ pushq(RAX); // Array is in RAX and on top of stack. |
| 238 __ leaq(R12, Address(RSP, R10, TIMES_8, arg_offset)); // Addr of first arg. | 238 __ leaq(R12, Address(RSP, R10, TIMES_8, arg_offset)); // Addr of first arg. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 252 | 252 |
| 253 // Input parameters: | 253 // Input parameters: |
| 254 // RBX: ic-data. | 254 // RBX: ic-data. |
| 255 // R10: arguments descriptor array. | 255 // R10: arguments descriptor array. |
| 256 // Note: The receiver object is the first argument to the function being | 256 // Note: The receiver object is the first argument to the function being |
| 257 // called, the stub accesses the receiver from this location directly | 257 // called, the stub accesses the receiver from this location directly |
| 258 // when trying to resolve the call. | 258 // when trying to resolve the call. |
| 259 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 259 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| 260 AssemblerMacros::EnterStubFrame(assembler); | 260 AssemblerMacros::EnterStubFrame(assembler); |
| 261 | 261 |
| 262 const Immediate raw_null = | 262 const Immediate& raw_null = |
| 263 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 263 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 264 __ pushq(raw_null); // Space for the return value. | 264 __ pushq(raw_null); // Space for the return value. |
| 265 | 265 |
| 266 // Push the receiver as an argument. Load the smi-tagged argument | 266 // Push the receiver as an argument. Load the smi-tagged argument |
| 267 // count into R13 to index the receiver in the stack. There are | 267 // count into R13 to index the receiver in the stack. There are |
| 268 // three words (null, stub's pc marker, saved fp) above the return | 268 // three words (null, stub's pc marker, saved fp) above the return |
| 269 // address. | 269 // address. |
| 270 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 270 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 271 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); | 271 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); |
| 272 | 272 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 // Load the receiver into RAX. The argument count in the arguments | 423 // Load the receiver into RAX. The argument count in the arguments |
| 424 // descriptor in R10 is a smi. | 424 // descriptor in R10 is a smi. |
| 425 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 425 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 426 // Two words (saved fp, stub's pc marker) in the stack above the return | 426 // Two words (saved fp, stub's pc marker) in the stack above the return |
| 427 // address. | 427 // address. |
| 428 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); | 428 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); |
| 429 // Preserve IC data and arguments descriptor. | 429 // Preserve IC data and arguments descriptor. |
| 430 __ pushq(RBX); | 430 __ pushq(RBX); |
| 431 __ pushq(R10); | 431 __ pushq(R10); |
| 432 | 432 |
| 433 const Immediate raw_null = | 433 const Immediate& raw_null = |
| 434 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 434 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
| 435 __ pushq(raw_null); // Space for the result of the runtime call. | 435 __ pushq(raw_null); // Space for the result of the runtime call. |
| 436 __ pushq(RAX); // Receiver. | 436 __ pushq(RAX); // Receiver. |
| 437 __ pushq(RBX); // IC data. | 437 __ pushq(RBX); // IC data. |
| 438 __ pushq(R10); // Arguments descriptor. | 438 __ pushq(R10); // Arguments descriptor. |
| 439 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); | 439 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); |
| 440 // Discard arguments. | 440 // Discard arguments. |
| 441 __ popq(RAX); | 441 __ popq(RAX); |
| 442 __ popq(RAX); | 442 __ popq(RAX); |
| 443 __ popq(RAX); | 443 __ popq(RAX); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 458 | 458 |
| 459 | 459 |
| 460 // Called for inline allocation of arrays. | 460 // Called for inline allocation of arrays. |
| 461 // Input parameters: | 461 // Input parameters: |
| 462 // R10 : Array length as Smi. | 462 // R10 : Array length as Smi. |
| 463 // RBX : array element type (either NULL or an instantiated type). | 463 // RBX : array element type (either NULL or an instantiated type). |
| 464 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 464 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
| 465 // The newly allocated object is returned in RAX. | 465 // The newly allocated object is returned in RAX. |
| 466 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 466 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 467 Label slow_case; | 467 Label slow_case; |
| 468 const Immediate raw_null = | 468 const Immediate& raw_null = |
| 469 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 469 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 470 | 470 |
| 471 if (FLAG_inline_alloc) { | 471 if (FLAG_inline_alloc) { |
| 472 // Compute the size to be allocated, it is based on the array length | 472 // Compute the size to be allocated, it is based on the array length |
| 473 // and is computed as: | 473 // and is computed as: |
| 474 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 474 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 475 // Assert that length is a Smi. | 475 // Assert that length is a Smi. |
| 476 __ testq(R10, Immediate(kSmiTagSize)); | 476 __ testq(R10, Immediate(kSmiTagSize)); |
| 477 if (FLAG_use_slow_path) { | 477 if (FLAG_use_slow_path) { |
| 478 __ jmp(&slow_case); | 478 __ jmp(&slow_case); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 __ ret(); | 589 __ ret(); |
| 590 } | 590 } |
| 591 | 591 |
| 592 | 592 |
| 593 // Input parameters: | 593 // Input parameters: |
| 594 // R10: Arguments descriptor array. | 594 // R10: Arguments descriptor array. |
| 595 // Note: The closure object is the first argument to the function being | 595 // Note: The closure object is the first argument to the function being |
| 596 // called, the stub accesses the closure from this location directly | 596 // called, the stub accesses the closure from this location directly |
| 597 // when trying to resolve the call. | 597 // when trying to resolve the call. |
| 598 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 598 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
| 599 const Immediate raw_null = | 599 const Immediate& raw_null = |
| 600 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 600 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 601 | 601 |
| 602 // Load num_args. | 602 // Load num_args. |
| 603 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 603 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 604 // Load closure object in R13. | 604 // Load closure object in R13. |
| 605 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. | 605 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. |
| 606 | 606 |
| 607 // Verify that R13 is a closure by checking its class. | 607 // Verify that R13 is a closure by checking its class. |
| 608 Label not_closure; | 608 Label not_closure; |
| 609 __ cmpq(R13, raw_null); | 609 __ cmpq(R13, raw_null); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 __ ret(); | 816 __ ret(); |
| 817 } | 817 } |
| 818 | 818 |
| 819 | 819 |
| 820 // Called for inline allocation of contexts. | 820 // Called for inline allocation of contexts. |
| 821 // Input: | 821 // Input: |
| 822 // R10: number of context variables. | 822 // R10: number of context variables. |
| 823 // Output: | 823 // Output: |
| 824 // RAX: new allocated RawContext object. | 824 // RAX: new allocated RawContext object. |
| 825 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 825 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 826 const Immediate raw_null = | 826 const Immediate& raw_null = |
| 827 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 827 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 828 if (FLAG_inline_alloc) { | 828 if (FLAG_inline_alloc) { |
| 829 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 829 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 830 Label slow_case; | 830 Label slow_case; |
| 831 Heap* heap = Isolate::Current()->heap(); | 831 Heap* heap = Isolate::Current()->heap(); |
| 832 // First compute the rounded instance size. | 832 // First compute the rounded instance size. |
| 833 // R10: number of context variables. | 833 // R10: number of context variables. |
| 834 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 834 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 835 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 835 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 836 __ andq(R13, Immediate(-kObjectAlignment)); | 836 __ andq(R13, Immediate(-kObjectAlignment)); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 892 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
| 893 | 893 |
| 894 // Setup isolate field. | 894 // Setup isolate field. |
| 895 // Load Isolate pointer from Context structure into R13. | 895 // Load Isolate pointer from Context structure into R13. |
| 896 // RAX: new object. | 896 // RAX: new object. |
| 897 // R10: number of context variables. | 897 // R10: number of context variables. |
| 898 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | 898 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
| 899 // R13: Isolate, not an object. | 899 // R13: Isolate, not an object. |
| 900 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); | 900 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
| 901 | 901 |
| 902 const Immediate raw_null = | 902 const Immediate& raw_null = |
| 903 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 903 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 904 // Setup the parent field. | 904 // Setup the parent field. |
| 905 // RAX: new object. | 905 // RAX: new object. |
| 906 // R10: number of context variables. | 906 // R10: number of context variables. |
| 907 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); | 907 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); |
| 908 | 908 |
| 909 // Initialize the context variables. | 909 // Initialize the context variables. |
| 910 // RAX: new object. | 910 // RAX: new object. |
| 911 // R10: number of context variables. | 911 // R10: number of context variables. |
| 912 { | 912 { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 | 995 |
| 996 // Called for inline allocation of objects. | 996 // Called for inline allocation of objects. |
| 997 // Input parameters: | 997 // Input parameters: |
| 998 // RSP + 16 : type arguments object (only if class is parameterized). | 998 // RSP + 16 : type arguments object (only if class is parameterized). |
| 999 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 999 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
| 1000 // RSP : points to return address. | 1000 // RSP : points to return address. |
| 1001 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1001 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
| 1002 const Class& cls) { | 1002 const Class& cls) { |
| 1003 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1003 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
| 1004 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1004 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
| 1005 const Immediate raw_null = | 1005 const Immediate& raw_null = |
| 1006 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1006 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1007 // The generated code is different if the class is parameterized. | 1007 // The generated code is different if the class is parameterized. |
| 1008 const bool is_cls_parameterized = | 1008 const bool is_cls_parameterized = |
| 1009 cls.type_arguments_field_offset() != Class::kNoTypeArguments; | 1009 cls.type_arguments_field_offset() != Class::kNoTypeArguments; |
| 1010 // kInlineInstanceSize is a constant used as a threshold for determining | 1010 // kInlineInstanceSize is a constant used as a threshold for determining |
| 1011 // when the object initialization should be done as a loop or as | 1011 // when the object initialization should be done as a loop or as |
| 1012 // straight line code. | 1012 // straight line code. |
| 1013 const int kInlineInstanceSize = 12; // In words. | 1013 const int kInlineInstanceSize = 12; // In words. |
| 1014 const intptr_t instance_size = cls.instance_size(); | 1014 const intptr_t instance_size = cls.instance_size(); |
| 1015 ASSERT(instance_size > 0); | 1015 ASSERT(instance_size > 0); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 // RDI: new object type arguments (if is_cls_parameterized). | 1091 // RDI: new object type arguments (if is_cls_parameterized). |
| 1092 __ LoadObject(RDX, cls); // Load class of object to be allocated. | 1092 __ LoadObject(RDX, cls); // Load class of object to be allocated. |
| 1093 // Set the tags. | 1093 // Set the tags. |
| 1094 uword tags = 0; | 1094 uword tags = 0; |
| 1095 tags = RawObject::SizeTag::update(instance_size, tags); | 1095 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1096 ASSERT(cls.id() != kIllegalCid); | 1096 ASSERT(cls.id() != kIllegalCid); |
| 1097 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1097 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1098 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1098 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
| 1099 | 1099 |
| 1100 // Initialize the remaining words of the object. | 1100 // Initialize the remaining words of the object. |
| 1101 const Immediate raw_null = | 1101 const Immediate& raw_null = |
| 1102 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1102 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1103 | 1103 |
| 1104 // RAX: new object start. | 1104 // RAX: new object start. |
| 1105 // RBX: next object start. | 1105 // RBX: next object start. |
| 1106 // RDX: class of the object to be allocated. | 1106 // RDX: class of the object to be allocated. |
| 1107 // RDI: new object type arguments (if is_cls_parameterized). | 1107 // RDI: new object type arguments (if is_cls_parameterized). |
| 1108 // First try inlining the initialization without a loop. | 1108 // First try inlining the initialization without a loop. |
| 1109 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1109 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1110 // Check if the object contains any non-header fields. | 1110 // Check if the object contains any non-header fields. |
| 1111 // Small objects are initialized using a consecutive set of writes. | 1111 // Small objects are initialized using a consecutive set of writes. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 | 1172 |
| 1173 // Called for inline allocation of closures. | 1173 // Called for inline allocation of closures. |
| 1174 // Input parameters: | 1174 // Input parameters: |
| 1175 // RSP + 16 : receiver (null if not an implicit instance closure). | 1175 // RSP + 16 : receiver (null if not an implicit instance closure). |
| 1176 // RSP + 8 : type arguments object (null if class is not parameterized). | 1176 // RSP + 8 : type arguments object (null if class is not parameterized). |
| 1177 // RSP : points to return address. | 1177 // RSP : points to return address. |
| 1178 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1178 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| 1179 const Function& func) { | 1179 const Function& func) { |
| 1180 const Immediate raw_null = | 1180 const Immediate& raw_null = |
| 1181 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1181 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1182 ASSERT(func.IsClosureFunction()); | 1182 ASSERT(func.IsClosureFunction()); |
| 1183 const bool is_implicit_static_closure = | 1183 const bool is_implicit_static_closure = |
| 1184 func.IsImplicitStaticClosureFunction(); | 1184 func.IsImplicitStaticClosureFunction(); |
| 1185 const bool is_implicit_instance_closure = | 1185 const bool is_implicit_instance_closure = |
| 1186 func.IsImplicitInstanceClosureFunction(); | 1186 func.IsImplicitInstanceClosureFunction(); |
| 1187 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1187 const Class& cls = Class::ZoneHandle(func.signature_class()); |
| 1188 const bool has_type_arguments = cls.HasTypeArguments(); | 1188 const bool has_type_arguments = cls.HasTypeArguments(); |
| 1189 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1189 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
| 1190 const intptr_t kReceiverOffset = 2 * kWordSize; | 1190 const intptr_t kReceiverOffset = 2 * kWordSize; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 // RBP - 8 : PC marker => RawInstruction object. | 1329 // RBP - 8 : PC marker => RawInstruction object. |
| 1330 // RBP : points to previous frame pointer. | 1330 // RBP : points to previous frame pointer. |
| 1331 // RBP + 8 : points to return address. | 1331 // RBP + 8 : points to return address. |
| 1332 // RBP + 16 : address of last argument (arg n-1). | 1332 // RBP + 16 : address of last argument (arg n-1). |
| 1333 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). | 1333 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1334 // RBX : ic-data. | 1334 // RBX : ic-data. |
| 1335 // R10 : arguments descriptor array. | 1335 // R10 : arguments descriptor array. |
| 1336 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1336 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1337 // The target function was not found, so invoke method | 1337 // The target function was not found, so invoke method |
| 1338 // "dynamic noSuchMethod(InvocationMirror invocation)". | 1338 // "dynamic noSuchMethod(InvocationMirror invocation)". |
| 1339 const Immediate raw_null = | 1339 const Immediate& raw_null = |
| 1340 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1340 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1341 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1341 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 1342 __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver. | 1342 __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver. |
| 1343 | 1343 |
| 1344 // Create a stub frame. | 1344 // Create a stub frame. |
| 1345 AssemblerMacros::EnterStubFrame(assembler); | 1345 AssemblerMacros::EnterStubFrame(assembler); |
| 1346 | 1346 |
| 1347 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. | 1347 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1348 __ pushq(RAX); // Receiver. | 1348 __ pushq(RAX); // Receiver. |
| 1349 __ pushq(RBX); // IC data array. | 1349 __ pushq(RBX); // IC data array. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 | 1510 |
| 1511 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1511 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1512 __ addq(R12, Immediate(entry_size)); // Next entry. | 1512 __ addq(R12, Immediate(entry_size)); // Next entry. |
| 1513 __ movq(R13, Address(R12, 0)); // Next class ID. | 1513 __ movq(R13, Address(R12, 0)); // Next class ID. |
| 1514 | 1514 |
| 1515 __ Bind(&test); | 1515 __ Bind(&test); |
| 1516 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1516 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1517 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1517 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1518 | 1518 |
| 1519 // IC miss. | 1519 // IC miss. |
| 1520 const Immediate raw_null = | 1520 const Immediate& raw_null = |
| 1521 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1521 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1522 // Compute address of arguments (first read number of arguments from | 1522 // Compute address of arguments (first read number of arguments from |
| 1523 // arguments descriptor array and then compute address on the stack). | 1523 // arguments descriptor array and then compute address on the stack). |
| 1524 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1524 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 1525 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1525 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
| 1526 AssemblerMacros::EnterStubFrame(assembler); | 1526 AssemblerMacros::EnterStubFrame(assembler); |
| 1527 __ pushq(R10); // Preserve arguments descriptor array. | 1527 __ pushq(R10); // Preserve arguments descriptor array. |
| 1528 __ pushq(RBX); // Preserve IC data object. | 1528 __ pushq(RBX); // Preserve IC data object. |
| 1529 __ pushq(raw_null); // Setup space on stack for result (target code object). | 1529 __ pushq(raw_null); // Setup space on stack for result (target code object). |
| 1530 // Push call arguments. | 1530 // Push call arguments. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 | 1662 |
| 1663 // Megamorphic call is currently implemented as IC call but through a stub | 1663 // Megamorphic call is currently implemented as IC call but through a stub |
| 1664 // that does not check/count function invocations. | 1664 // that does not check/count function invocations. |
| 1665 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1665 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1666 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1666 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1667 } | 1667 } |
| 1668 | 1668 |
| 1669 // R10: Arguments descriptor array. | 1669 // R10: Arguments descriptor array. |
| 1670 // TOS(0): return address (Dart code). | 1670 // TOS(0): return address (Dart code). |
| 1671 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1671 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1672 const Immediate raw_null = | 1672 const Immediate& raw_null = |
| 1673 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1673 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1674 AssemblerMacros::EnterStubFrame(assembler); | 1674 AssemblerMacros::EnterStubFrame(assembler); |
| 1675 __ pushq(R10); // Preserve arguments descriptor. | 1675 __ pushq(R10); // Preserve arguments descriptor. |
| 1676 __ pushq(raw_null); // Room for result. | 1676 __ pushq(raw_null); // Room for result. |
| 1677 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1677 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| 1678 __ popq(RAX); // Code object. | 1678 __ popq(RAX); // Code object. |
| 1679 __ popq(R10); // Restore arguments descriptor. | 1679 __ popq(R10); // Restore arguments descriptor. |
| 1680 __ LeaveFrame(); | 1680 __ LeaveFrame(); |
| 1681 | 1681 |
| 1682 // Now call the static function. The breakpoint handler function | 1682 // Now call the static function. The breakpoint handler function |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1733 | 1733 |
| 1734 | 1734 |
| 1735 // Used to check class and type arguments. Arguments passed on stack: | 1735 // Used to check class and type arguments. Arguments passed on stack: |
| 1736 // TOS + 0: return address. | 1736 // TOS + 0: return address. |
| 1737 // TOS + 1: instantiator type arguments (can be NULL). | 1737 // TOS + 1: instantiator type arguments (can be NULL). |
| 1738 // TOS + 2: instance. | 1738 // TOS + 2: instance. |
| 1739 // TOS + 3: SubtypeTestCache. | 1739 // TOS + 3: SubtypeTestCache. |
| 1740 // Result in RCX: null -> not found, otherwise result (true or false). | 1740 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1741 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1741 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1742 ASSERT((1 <= n) && (n <= 3)); | 1742 ASSERT((1 <= n) && (n <= 3)); |
| 1743 const Immediate raw_null = | 1743 const Immediate& raw_null = |
| 1744 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1744 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1745 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1745 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1746 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1746 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1747 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1747 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1748 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1748 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
| 1749 if (n > 1) { | 1749 if (n > 1) { |
| 1750 __ LoadClass(R10, RAX); | 1750 __ LoadClass(R10, RAX); |
| 1751 // Compute instance type arguments into R13. | 1751 // Compute instance type arguments into R13. |
| 1752 Label has_no_type_arguments; | 1752 Label has_no_type_arguments; |
| 1753 __ movq(R13, raw_null); | 1753 __ movq(R13, raw_null); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1980 __ Drop(4); | 1980 __ Drop(4); |
| 1981 __ LeaveFrame(); | 1981 __ LeaveFrame(); |
| 1982 | 1982 |
| 1983 __ jmp(&compute_result, Assembler::kNearJump); | 1983 __ jmp(&compute_result, Assembler::kNearJump); |
| 1984 } | 1984 } |
| 1985 | 1985 |
| 1986 // Calls to the runtime to optimize the given function. | 1986 // Calls to the runtime to optimize the given function. |
| 1987 // RDI: function to be reoptimized. | 1987 // RDI: function to be reoptimized. |
| 1988 // R10: argument descriptor (preserved). | 1988 // R10: argument descriptor (preserved). |
| 1989 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1989 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| 1990 const Immediate raw_null = | 1990 const Immediate& raw_null = |
| 1991 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1991 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1992 AssemblerMacros::EnterStubFrame(assembler); | 1992 AssemblerMacros::EnterStubFrame(assembler); |
| 1993 __ pushq(R10); | 1993 __ pushq(R10); |
| 1994 __ pushq(raw_null); // Setup space on stack for return value. | 1994 __ pushq(raw_null); // Setup space on stack for return value. |
| 1995 __ pushq(RDI); | 1995 __ pushq(RDI); |
| 1996 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 1996 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 1997 __ popq(RAX); // Disard argument. | 1997 __ popq(RAX); // Disard argument. |
| 1998 __ popq(RAX); // Get Code object. | 1998 __ popq(RAX); // Get Code object. |
| 1999 __ popq(R10); // Restore argument descriptor. | 1999 __ popq(R10); // Restore argument descriptor. |
| 2000 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 2000 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2076 __ cmpq(left, right); | 2076 __ cmpq(left, right); |
| 2077 __ Bind(&done); | 2077 __ Bind(&done); |
| 2078 __ popq(right); | 2078 __ popq(right); |
| 2079 __ popq(left); | 2079 __ popq(left); |
| 2080 __ ret(); | 2080 __ ret(); |
| 2081 } | 2081 } |
| 2082 | 2082 |
| 2083 } // namespace dart | 2083 } // namespace dart |
| 2084 | 2084 |
| 2085 #endif // defined TARGET_ARCH_X64 | 2085 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |