| OLD | NEW |
| 1 // Copyright (c) 2013, 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" | |
| 10 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 11 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/instructions.h" | 12 #include "vm/instructions.h" |
| 14 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 15 #include "vm/pages.h" | 14 #include "vm/pages.h" |
| 16 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
| 17 #include "vm/scavenger.h" | 16 #include "vm/scavenger.h" |
| 18 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 19 | 18 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 __ LeaveFrame(); | 180 __ LeaveFrame(); |
| 182 __ ret(); | 181 __ ret(); |
| 183 } | 182 } |
| 184 | 183 |
| 185 | 184 |
| 186 // Input parameters: | 185 // Input parameters: |
| 187 // EDX: arguments descriptor array. | 186 // EDX: arguments descriptor array. |
| 188 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| 189 const Immediate& raw_null = | 188 const Immediate& raw_null = |
| 190 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 189 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 191 AssemblerMacros::EnterStubFrame(assembler); | 190 __ EnterStubFrame(); |
| 192 __ pushl(EDX); // Preserve arguments descriptor array. | 191 __ pushl(EDX); // Preserve arguments descriptor array. |
| 193 __ pushl(raw_null); // Setup space on stack for return value. | 192 __ pushl(raw_null); // Setup space on stack for return value. |
| 194 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 193 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
| 195 __ popl(EAX); // Get Code object result. | 194 __ popl(EAX); // Get Code object result. |
| 196 __ popl(EDX); // Restore arguments descriptor array. | 195 __ popl(EDX); // Restore arguments descriptor array. |
| 197 // 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. |
| 198 __ LeaveFrame(); | 197 __ LeaveFrame(); |
| 199 | 198 |
| 200 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 199 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 201 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 200 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 202 __ jmp(ECX); | 201 __ jmp(ECX); |
| 203 } | 202 } |
| 204 | 203 |
| 205 | 204 |
| 206 // 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 |
| 207 // (invalid because its function was optimized or deoptimized). | 206 // (invalid because its function was optimized or deoptimized). |
| 208 // EDX: arguments descriptor array. | 207 // EDX: arguments descriptor array. |
| 209 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 210 const Immediate& raw_null = | 209 const Immediate& raw_null = |
| 211 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 210 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 212 // Create a stub frame as we are pushing some objects on the stack before | 211 // Create a stub frame as we are pushing some objects on the stack before |
| 213 // calling into the runtime. | 212 // calling into the runtime. |
| 214 AssemblerMacros::EnterStubFrame(assembler); | 213 __ EnterStubFrame(); |
| 215 __ pushl(EDX); // Preserve arguments descriptor array. | 214 __ pushl(EDX); // Preserve arguments descriptor array. |
| 216 __ pushl(raw_null); // Setup space on stack for return value. | 215 __ pushl(raw_null); // Setup space on stack for return value. |
| 217 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 216 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
| 218 __ popl(EAX); // Get Code object. | 217 __ popl(EAX); // Get Code object. |
| 219 __ popl(EDX); // Restore arguments descriptor array. | 218 __ popl(EDX); // Restore arguments descriptor array. |
| 220 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 219 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 221 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 220 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 222 __ LeaveFrame(); | 221 __ LeaveFrame(); |
| 223 __ jmp(EAX); | 222 __ jmp(EAX); |
| 224 __ int3(); | 223 __ int3(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 255 | 254 |
| 256 | 255 |
| 257 // Input parameters: | 256 // Input parameters: |
| 258 // ECX: ic-data. | 257 // ECX: ic-data. |
| 259 // EDX: arguments descriptor array. | 258 // EDX: arguments descriptor array. |
| 260 // Note: The receiver object is the first argument to the function being | 259 // Note: The receiver object is the first argument to the function being |
| 261 // called, the stub accesses the receiver from this location directly | 260 // called, the stub accesses the receiver from this location directly |
| 262 // when trying to resolve the call. | 261 // when trying to resolve the call. |
| 263 // Uses EDI. | 262 // Uses EDI. |
| 264 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 263 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| 265 AssemblerMacros::EnterStubFrame(assembler); | 264 __ EnterStubFrame(); |
| 266 | 265 |
| 267 const Immediate& raw_null = | 266 const Immediate& raw_null = |
| 268 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 267 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 269 __ pushl(raw_null); // Space for the return value. | 268 __ pushl(raw_null); // Space for the return value. |
| 270 | 269 |
| 271 // Push the receiver as an argument. Load the smi-tagged argument | 270 // Push the receiver as an argument. Load the smi-tagged argument |
| 272 // count into EDI to index the receiver in the stack. There are | 271 // 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 | 272 // three words (null, stub's pc marker, saved fp) above the return |
| 274 // address. | 273 // address. |
| 275 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 274 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // Restore result into EBX. | 384 // Restore result into EBX. |
| 386 __ movl(EBX, Address(EBP, -1 * kWordSize)); | 385 __ movl(EBX, Address(EBP, -1 * kWordSize)); |
| 387 } | 386 } |
| 388 // Code above cannot cause GC. | 387 // Code above cannot cause GC. |
| 389 __ LeaveFrame(); | 388 __ LeaveFrame(); |
| 390 __ movl(EBP, EAX); | 389 __ movl(EBP, EAX); |
| 391 | 390 |
| 392 // Frame is fully rewritten at this point and it is safe to perform a GC. | 391 // Frame is fully rewritten at this point and it is safe to perform a GC. |
| 393 // Materialize any objects that were deferred by FillFrame because they | 392 // Materialize any objects that were deferred by FillFrame because they |
| 394 // require allocation. | 393 // require allocation. |
| 395 AssemblerMacros::EnterStubFrame(assembler); | 394 __ EnterStubFrame(); |
| 396 if (preserve_eax) { | 395 if (preserve_eax) { |
| 397 __ pushl(EBX); // Preserve result, it will be GC-d here. | 396 __ pushl(EBX); // Preserve result, it will be GC-d here. |
| 398 } | 397 } |
| 399 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); | 398 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); |
| 400 if (preserve_eax) { | 399 if (preserve_eax) { |
| 401 __ popl(EAX); // Restore result. | 400 __ popl(EAX); // Restore result. |
| 402 } | 401 } |
| 403 __ LeaveFrame(); | 402 __ LeaveFrame(); |
| 404 __ ret(); | 403 __ ret(); |
| 405 } | 404 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 416 GenerateDeoptimizationSequence(assembler, true); // Preserve EAX. | 415 GenerateDeoptimizationSequence(assembler, true); // Preserve EAX. |
| 417 } | 416 } |
| 418 | 417 |
| 419 | 418 |
| 420 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 419 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 421 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. | 420 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. |
| 422 } | 421 } |
| 423 | 422 |
| 424 | 423 |
| 425 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 424 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 426 AssemblerMacros::EnterStubFrame(assembler); | 425 __ EnterStubFrame(); |
| 427 // Load the receiver into EAX. The argument count in the arguments | 426 // Load the receiver into EAX. The argument count in the arguments |
| 428 // descriptor in EDX is a smi. | 427 // descriptor in EDX is a smi. |
| 429 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 428 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 430 // Two words (saved fp, stub's pc marker) in the stack above the return | 429 // Two words (saved fp, stub's pc marker) in the stack above the return |
| 431 // address. | 430 // address. |
| 432 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); | 431 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); |
| 433 // Preserve IC data and arguments descriptor. | 432 // Preserve IC data and arguments descriptor. |
| 434 __ pushl(ECX); | 433 __ pushl(ECX); |
| 435 __ pushl(EDX); | 434 __ pushl(EDX); |
| 436 | 435 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 // EAX: new object. | 579 // EAX: new object. |
| 581 // EDX: Array length as Smi (preserved for the caller.) | 580 // EDX: Array length as Smi (preserved for the caller.) |
| 582 __ ret(); | 581 __ ret(); |
| 583 } | 582 } |
| 584 | 583 |
| 585 // Unable to allocate the array using the fast inline code, just call | 584 // Unable to allocate the array using the fast inline code, just call |
| 586 // into the runtime. | 585 // into the runtime. |
| 587 __ Bind(&slow_case); | 586 __ Bind(&slow_case); |
| 588 // Create a stub frame as we are pushing some objects on the stack before | 587 // Create a stub frame as we are pushing some objects on the stack before |
| 589 // calling into the runtime. | 588 // calling into the runtime. |
| 590 AssemblerMacros::EnterStubFrame(assembler); | 589 __ EnterStubFrame(); |
| 591 __ pushl(raw_null); // Setup space on stack for return value. | 590 __ pushl(raw_null); // Setup space on stack for return value. |
| 592 __ pushl(EDX); // Array length as Smi. | 591 __ pushl(EDX); // Array length as Smi. |
| 593 __ pushl(ECX); // Element type. | 592 __ pushl(ECX); // Element type. |
| 594 __ CallRuntime(kAllocateArrayRuntimeEntry); | 593 __ CallRuntime(kAllocateArrayRuntimeEntry); |
| 595 __ popl(EAX); // Pop element type argument. | 594 __ popl(EAX); // Pop element type argument. |
| 596 __ popl(EDX); // Pop array length argument. | 595 __ popl(EDX); // Pop array length argument. |
| 597 __ popl(EAX); // Pop return value from return slot. | 596 __ popl(EAX); // Pop return value from return slot. |
| 598 __ LeaveFrame(); | 597 __ LeaveFrame(); |
| 599 __ ret(); | 598 __ ret(); |
| 600 } | 599 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); | 636 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); |
| 638 | 637 |
| 639 // Load closure function code in EAX. | 638 // Load closure function code in EAX. |
| 640 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 639 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 641 __ cmpl(EAX, raw_null); | 640 __ cmpl(EAX, raw_null); |
| 642 Label function_compiled; | 641 Label function_compiled; |
| 643 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); | 642 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
| 644 | 643 |
| 645 // Create a stub frame as we are pushing some objects on the stack before | 644 // Create a stub frame as we are pushing some objects on the stack before |
| 646 // calling into the runtime. | 645 // calling into the runtime. |
| 647 AssemblerMacros::EnterStubFrame(assembler); | 646 __ EnterStubFrame(); |
| 648 | 647 |
| 649 __ pushl(EDX); // Preserve arguments descriptor array. | 648 __ pushl(EDX); // Preserve arguments descriptor array. |
| 650 __ pushl(ECX); // Preserve read-only function object argument. | 649 __ pushl(ECX); // Preserve read-only function object argument. |
| 651 __ CallRuntime(kCompileFunctionRuntimeEntry); | 650 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| 652 __ popl(ECX); // Restore read-only function object argument in ECX. | 651 __ popl(ECX); // Restore read-only function object argument in ECX. |
| 653 __ popl(EDX); // Restore arguments descriptor array. | 652 __ popl(EDX); // Restore arguments descriptor array. |
| 654 // Restore EAX. | 653 // Restore EAX. |
| 655 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); | 654 __ movl(EAX, FieldAddress(ECX, Function::code_offset())); |
| 656 | 655 |
| 657 // Remove the stub frame as we are about to jump to the closure function. | 656 // Remove the stub frame as we are about to jump to the closure function. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 669 __ Bind(¬_closure); | 668 __ Bind(¬_closure); |
| 670 // Call runtime to attempt to resolve and invoke a call method on a | 669 // Call runtime to attempt to resolve and invoke a call method on a |
| 671 // non-closure object, passing the non-closure object and its arguments array, | 670 // non-closure object, passing the non-closure object and its arguments array, |
| 672 // returning here. | 671 // returning here. |
| 673 // If no call method exists, throw a NoSuchMethodError. | 672 // If no call method exists, throw a NoSuchMethodError. |
| 674 // EDI: non-closure object. | 673 // EDI: non-closure object. |
| 675 // EDX: arguments descriptor array. | 674 // EDX: arguments descriptor array. |
| 676 | 675 |
| 677 // Create a stub frame as we are pushing some objects on the stack before | 676 // Create a stub frame as we are pushing some objects on the stack before |
| 678 // calling into the runtime. | 677 // calling into the runtime. |
| 679 AssemblerMacros::EnterStubFrame(assembler); | 678 __ EnterStubFrame(); |
| 680 | 679 |
| 681 __ pushl(raw_null); // Setup space on stack for result from error reporting. | 680 __ pushl(raw_null); // Setup space on stack for result from error reporting. |
| 682 __ pushl(EDX); // Arguments descriptor. | 681 __ pushl(EDX); // Arguments descriptor. |
| 683 // Load smi-tagged arguments array length, including the non-closure. | 682 // Load smi-tagged arguments array length, including the non-closure. |
| 684 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 683 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 685 // See stack layout below explaining "wordSize * 5" offset. | 684 // See stack layout below explaining "wordSize * 5" offset. |
| 686 PushArgumentsArray(assembler, (kWordSize * 5)); | 685 PushArgumentsArray(assembler, (kWordSize * 5)); |
| 687 | 686 |
| 688 // Stack: | 687 // Stack: |
| 689 // TOS + 0: Argument array. | 688 // TOS + 0: Argument array. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 } | 930 } |
| 932 | 931 |
| 933 // Done allocating and initializing the context. | 932 // Done allocating and initializing the context. |
| 934 // EAX: new object. | 933 // EAX: new object. |
| 935 __ ret(); | 934 __ ret(); |
| 936 | 935 |
| 937 __ Bind(&slow_case); | 936 __ Bind(&slow_case); |
| 938 } | 937 } |
| 939 // Create a stub frame as we are pushing some objects on the stack before | 938 // Create a stub frame as we are pushing some objects on the stack before |
| 940 // calling into the runtime. | 939 // calling into the runtime. |
| 941 AssemblerMacros::EnterStubFrame(assembler); | 940 __ EnterStubFrame(); |
| 942 __ pushl(raw_null); // Setup space on stack for return value. | 941 __ pushl(raw_null); // Setup space on stack for return value. |
| 943 __ SmiTag(EDX); | 942 __ SmiTag(EDX); |
| 944 __ pushl(EDX); | 943 __ pushl(EDX); |
| 945 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. | 944 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. |
| 946 __ popl(EAX); // Pop number of context variables argument. | 945 __ popl(EAX); // Pop number of context variables argument. |
| 947 __ popl(EAX); // Pop the new context object. | 946 __ popl(EAX); // Pop the new context object. |
| 948 // EAX: new object | 947 // EAX: new object |
| 949 // Restore the frame pointer. | 948 // Restore the frame pointer. |
| 950 __ LeaveFrame(); | 949 __ LeaveFrame(); |
| 951 __ ret(); | 950 __ ret(); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 __ ret(); | 1154 __ ret(); |
| 1156 | 1155 |
| 1157 __ Bind(&slow_case); | 1156 __ Bind(&slow_case); |
| 1158 } | 1157 } |
| 1159 if (is_cls_parameterized) { | 1158 if (is_cls_parameterized) { |
| 1160 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); | 1159 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); |
| 1161 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); | 1160 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); |
| 1162 } | 1161 } |
| 1163 // Create a stub frame as we are pushing some objects on the stack before | 1162 // Create a stub frame as we are pushing some objects on the stack before |
| 1164 // calling into the runtime. | 1163 // calling into the runtime. |
| 1165 AssemblerMacros::EnterStubFrame(assembler); | 1164 __ EnterStubFrame(); |
| 1166 __ pushl(raw_null); // Setup space on stack for return value. | 1165 __ pushl(raw_null); // Setup space on stack for return value. |
| 1167 __ PushObject(cls); // Push class of object to be allocated. | 1166 __ PushObject(cls); // Push class of object to be allocated. |
| 1168 if (is_cls_parameterized) { | 1167 if (is_cls_parameterized) { |
| 1169 __ pushl(EAX); // Push type arguments of object to be allocated. | 1168 __ pushl(EAX); // Push type arguments of object to be allocated. |
| 1170 __ pushl(EDX); // Push type arguments of instantiator. | 1169 __ pushl(EDX); // Push type arguments of instantiator. |
| 1171 } else { | 1170 } else { |
| 1172 __ pushl(raw_null); // Push null type arguments. | 1171 __ pushl(raw_null); // Push null type arguments. |
| 1173 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1172 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1174 } | 1173 } |
| 1175 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. | 1174 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 __ Bind(&slow_case); | 1294 __ Bind(&slow_case); |
| 1296 } | 1295 } |
| 1297 if (has_type_arguments) { | 1296 if (has_type_arguments) { |
| 1298 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); | 1297 __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); |
| 1299 } | 1298 } |
| 1300 if (is_implicit_instance_closure) { | 1299 if (is_implicit_instance_closure) { |
| 1301 __ movl(EAX, Address(ESP, kReceiverOffset)); | 1300 __ movl(EAX, Address(ESP, kReceiverOffset)); |
| 1302 } | 1301 } |
| 1303 // Create a stub frame as we are pushing some objects on the stack before | 1302 // Create a stub frame as we are pushing some objects on the stack before |
| 1304 // calling into the runtime. | 1303 // calling into the runtime. |
| 1305 AssemblerMacros::EnterStubFrame(assembler); | 1304 __ EnterStubFrame(); |
| 1306 __ pushl(raw_null); // Setup space on stack for return value. | 1305 __ pushl(raw_null); // Setup space on stack for return value. |
| 1307 __ PushObject(func); | 1306 __ PushObject(func); |
| 1308 if (is_implicit_static_closure) { | 1307 if (is_implicit_static_closure) { |
| 1309 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); | 1308 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); |
| 1310 } else { | 1309 } else { |
| 1311 if (is_implicit_instance_closure) { | 1310 if (is_implicit_instance_closure) { |
| 1312 __ pushl(EAX); // Receiver. | 1311 __ pushl(EAX); // Receiver. |
| 1313 } | 1312 } |
| 1314 if (has_type_arguments) { | 1313 if (has_type_arguments) { |
| 1315 __ pushl(ECX); // Push type arguments of closure to be allocated. | 1314 __ pushl(ECX); // Push type arguments of closure to be allocated. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1348 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1350 // The target function was not found, so invoke method | 1349 // The target function was not found, so invoke method |
| 1351 // "dynamic noSuchMethod(InvocationMirror invocation)". | 1350 // "dynamic noSuchMethod(InvocationMirror invocation)". |
| 1352 const Immediate& raw_null = | 1351 const Immediate& raw_null = |
| 1353 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1352 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1354 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1353 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1355 __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize)); // Get receiver. | 1354 __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize)); // Get receiver. |
| 1356 | 1355 |
| 1357 // Create a stub frame as we are pushing some objects on the stack before | 1356 // Create a stub frame as we are pushing some objects on the stack before |
| 1358 // calling into the runtime. | 1357 // calling into the runtime. |
| 1359 AssemblerMacros::EnterStubFrame(assembler); | 1358 __ EnterStubFrame(); |
| 1360 | 1359 |
| 1361 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 1360 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 1362 __ pushl(EAX); // Receiver. | 1361 __ pushl(EAX); // Receiver. |
| 1363 __ pushl(ECX); // IC data array. | 1362 __ pushl(ECX); // IC data array. |
| 1364 __ pushl(EDX); // Arguments descriptor array. | 1363 __ pushl(EDX); // Arguments descriptor array. |
| 1365 | 1364 |
| 1366 __ movl(EDX, EDI); | 1365 __ movl(EDX, EDI); |
| 1367 // See stack layout below explaining "wordSize * 10" offset. | 1366 // See stack layout below explaining "wordSize * 10" offset. |
| 1368 PushArgumentsArray(assembler, (kWordSize * 10)); | 1367 PushArgumentsArray(assembler, (kWordSize * 10)); |
| 1369 | 1368 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1393 __ LeaveFrame(); | 1392 __ LeaveFrame(); |
| 1394 __ ret(); | 1393 __ ret(); |
| 1395 } | 1394 } |
| 1396 | 1395 |
| 1397 | 1396 |
| 1398 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1397 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
| 1399 Register argdesc_reg = EDX; | 1398 Register argdesc_reg = EDX; |
| 1400 Register ic_reg = ECX; | 1399 Register ic_reg = ECX; |
| 1401 Register func_reg = EDI; | 1400 Register func_reg = EDI; |
| 1402 if (FLAG_trace_optimized_ic_calls) { | 1401 if (FLAG_trace_optimized_ic_calls) { |
| 1403 AssemblerMacros::EnterStubFrame(assembler); | 1402 __ EnterStubFrame(); |
| 1404 __ pushl(func_reg); // Preserve | 1403 __ pushl(func_reg); // Preserve |
| 1405 __ pushl(argdesc_reg); // Preserve. | 1404 __ pushl(argdesc_reg); // Preserve. |
| 1406 __ pushl(ic_reg); // Preserve. | 1405 __ pushl(ic_reg); // Preserve. |
| 1407 __ pushl(ic_reg); // Argument. | 1406 __ pushl(ic_reg); // Argument. |
| 1408 __ pushl(func_reg); // Argument. | 1407 __ pushl(func_reg); // Argument. |
| 1409 __ CallRuntime(kTraceICCallRuntimeEntry); | 1408 __ CallRuntime(kTraceICCallRuntimeEntry); |
| 1410 __ popl(EAX); // Discard argument; | 1409 __ popl(EAX); // Discard argument; |
| 1411 __ popl(EAX); // Discard argument; | 1410 __ popl(EAX); // Discard argument; |
| 1412 __ popl(ic_reg); // Restore. | 1411 __ popl(ic_reg); // Restore. |
| 1413 __ popl(argdesc_reg); // Restore. | 1412 __ popl(argdesc_reg); // Restore. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 | 1533 |
| 1535 // IC miss. | 1534 // IC miss. |
| 1536 const Immediate& raw_null = | 1535 const Immediate& raw_null = |
| 1537 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1536 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1538 // Compute address of arguments (first read number of arguments from | 1537 // Compute address of arguments (first read number of arguments from |
| 1539 // arguments descriptor array and then compute address on the stack). | 1538 // arguments descriptor array and then compute address on the stack). |
| 1540 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1539 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1541 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1540 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1542 // Create a stub frame as we are pushing some objects on the stack before | 1541 // Create a stub frame as we are pushing some objects on the stack before |
| 1543 // calling into the runtime. | 1542 // calling into the runtime. |
| 1544 AssemblerMacros::EnterStubFrame(assembler); | 1543 __ EnterStubFrame(); |
| 1545 __ pushl(EDX); // Preserve arguments descriptor array. | 1544 __ pushl(EDX); // Preserve arguments descriptor array. |
| 1546 __ pushl(ECX); // Preserve IC data object. | 1545 __ pushl(ECX); // Preserve IC data object. |
| 1547 __ pushl(raw_null); // Setup space on stack for result (target code object). | 1546 __ pushl(raw_null); // Setup space on stack for result (target code object). |
| 1548 // Push call arguments. | 1547 // Push call arguments. |
| 1549 for (intptr_t i = 0; i < num_args; i++) { | 1548 for (intptr_t i = 0; i < num_args; i++) { |
| 1550 __ movl(EBX, Address(EAX, -kWordSize * i)); | 1549 __ movl(EBX, Address(EAX, -kWordSize * i)); |
| 1551 __ pushl(EBX); | 1550 __ pushl(EBX); |
| 1552 } | 1551 } |
| 1553 __ pushl(ECX); // Pass IC data object. | 1552 __ pushl(ECX); // Pass IC data object. |
| 1554 __ pushl(EDX); // Pass arguments descriptor array. | 1553 __ pushl(EDX); // Pass arguments descriptor array. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1686 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1685 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1687 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1686 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
| 1688 } | 1687 } |
| 1689 | 1688 |
| 1690 | 1689 |
| 1691 // EDX: Arguments descriptor array. | 1690 // EDX: Arguments descriptor array. |
| 1692 // TOS(0): return address (Dart code). | 1691 // TOS(0): return address (Dart code). |
| 1693 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1692 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1694 // Create a stub frame as we are pushing some objects on the stack before | 1693 // Create a stub frame as we are pushing some objects on the stack before |
| 1695 // calling into the runtime. | 1694 // calling into the runtime. |
| 1696 AssemblerMacros::EnterStubFrame(assembler); | 1695 __ EnterStubFrame(); |
| 1697 __ pushl(EDX); // Preserve arguments descriptor. | 1696 __ pushl(EDX); // Preserve arguments descriptor. |
| 1698 const Immediate& raw_null = | 1697 const Immediate& raw_null = |
| 1699 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1698 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1700 __ pushl(raw_null); // Room for result. | 1699 __ pushl(raw_null); // Room for result. |
| 1701 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1700 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
| 1702 __ popl(EAX); // Code object. | 1701 __ popl(EAX); // Code object. |
| 1703 __ popl(EDX); // Restore arguments descriptor. | 1702 __ popl(EDX); // Restore arguments descriptor. |
| 1704 __ LeaveFrame(); | 1703 __ LeaveFrame(); |
| 1705 | 1704 |
| 1706 // Now call the static function. The breakpoint handler function | 1705 // Now call the static function. The breakpoint handler function |
| 1707 // ensures that the call target is compiled. | 1706 // ensures that the call target is compiled. |
| 1708 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 1707 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 1709 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1708 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1710 __ jmp(ECX); | 1709 __ jmp(ECX); |
| 1711 } | 1710 } |
| 1712 | 1711 |
| 1713 | 1712 |
| 1714 // TOS(0): return address (Dart code). | 1713 // TOS(0): return address (Dart code). |
| 1715 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { | 1714 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { |
| 1716 // Create a stub frame as we are pushing some objects on the stack before | 1715 // Create a stub frame as we are pushing some objects on the stack before |
| 1717 // calling into the runtime. | 1716 // calling into the runtime. |
| 1718 AssemblerMacros::EnterStubFrame(assembler); | 1717 __ EnterStubFrame(); |
| 1719 __ pushl(EAX); | 1718 __ pushl(EAX); |
| 1720 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); | 1719 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); |
| 1721 __ popl(EAX); | 1720 __ popl(EAX); |
| 1722 __ LeaveFrame(); | 1721 __ LeaveFrame(); |
| 1723 | 1722 |
| 1724 // Instead of returning to the patched Dart function, emulate the | 1723 // Instead of returning to the patched Dart function, emulate the |
| 1725 // smashed return code pattern and return to the function's caller. | 1724 // smashed return code pattern and return to the function's caller. |
| 1726 __ popl(ECX); // Discard return address to patched dart code. | 1725 __ popl(ECX); // Discard return address to patched dart code. |
| 1727 // Execute function epilog code that was smashed in the Dart code. | 1726 // Execute function epilog code that was smashed in the Dart code. |
| 1728 __ LeaveFrame(); | 1727 __ LeaveFrame(); |
| 1729 __ ret(); | 1728 __ ret(); |
| 1730 } | 1729 } |
| 1731 | 1730 |
| 1732 | 1731 |
| 1733 // ECX: Inline cache data array. | 1732 // ECX: Inline cache data array. |
| 1734 // EDX: Arguments descriptor array. | 1733 // EDX: Arguments descriptor array. |
| 1735 // TOS(0): return address (Dart code). | 1734 // TOS(0): return address (Dart code). |
| 1736 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1735 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1737 // Create a stub frame as we are pushing some objects on the stack before | 1736 // Create a stub frame as we are pushing some objects on the stack before |
| 1738 // calling into the runtime. | 1737 // calling into the runtime. |
| 1739 AssemblerMacros::EnterStubFrame(assembler); | 1738 __ EnterStubFrame(); |
| 1740 __ pushl(ECX); | 1739 __ pushl(ECX); |
| 1741 __ pushl(EDX); | 1740 __ pushl(EDX); |
| 1742 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1741 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| 1743 __ popl(EDX); | 1742 __ popl(EDX); |
| 1744 __ popl(ECX); | 1743 __ popl(ECX); |
| 1745 __ LeaveFrame(); | 1744 __ LeaveFrame(); |
| 1746 | 1745 |
| 1747 // Find out which dispatch stub to call. | 1746 // Find out which dispatch stub to call. |
| 1748 Label test_two, test_three, test_four; | 1747 Label test_two, test_three, test_four; |
| 1749 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1748 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1998 __ Bind(¬_smi); | 1997 __ Bind(¬_smi); |
| 1999 __ LoadClassId(EAX, EAX); | 1998 __ LoadClassId(EAX, EAX); |
| 2000 __ SmiTag(EAX); | 1999 __ SmiTag(EAX); |
| 2001 __ ret(); | 2000 __ ret(); |
| 2002 | 2001 |
| 2003 __ Bind(&update_ic_data); | 2002 __ Bind(&update_ic_data); |
| 2004 | 2003 |
| 2005 // ECX: ICData | 2004 // ECX: ICData |
| 2006 __ movl(EAX, Address(ESP, 1 * kWordSize)); | 2005 __ movl(EAX, Address(ESP, 1 * kWordSize)); |
| 2007 __ movl(EDI, Address(ESP, 2 * kWordSize)); | 2006 __ movl(EDI, Address(ESP, 2 * kWordSize)); |
| 2008 AssemblerMacros::EnterStubFrame(assembler); | 2007 __ EnterStubFrame(); |
| 2009 __ pushl(EDI); // arg 0 | 2008 __ pushl(EDI); // arg 0 |
| 2010 __ pushl(EAX); // arg 1 | 2009 __ pushl(EAX); // arg 1 |
| 2011 __ PushObject(Symbols::EqualOperator()); // Target's name. | 2010 __ PushObject(Symbols::EqualOperator()); // Target's name. |
| 2012 __ pushl(ECX); // ICData | 2011 __ pushl(ECX); // ICData |
| 2013 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); | 2012 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); |
| 2014 __ Drop(4); | 2013 __ Drop(4); |
| 2015 __ LeaveFrame(); | 2014 __ LeaveFrame(); |
| 2016 | 2015 |
| 2017 __ jmp(&compute_result, Assembler::kNearJump); | 2016 __ jmp(&compute_result, Assembler::kNearJump); |
| 2018 } | 2017 } |
| 2019 | 2018 |
| 2020 | 2019 |
| 2021 // Calls to runtime to ooptimized give function | 2020 // Calls to runtime to ooptimized give function |
| 2022 // EDI: function to be reoptimized. | 2021 // EDI: function to be reoptimized. |
| 2023 // EDX: argument descriptor (preserved). | 2022 // EDX: argument descriptor (preserved). |
| 2024 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 2023 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| 2025 const Immediate& raw_null = | 2024 const Immediate& raw_null = |
| 2026 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2025 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2027 AssemblerMacros::EnterStubFrame(assembler); | 2026 __ EnterStubFrame(); |
| 2028 __ pushl(EDX); | 2027 __ pushl(EDX); |
| 2029 __ pushl(raw_null); // Setup space on stack for return value. | 2028 __ pushl(raw_null); // Setup space on stack for return value. |
| 2030 __ pushl(EDI); | 2029 __ pushl(EDI); |
| 2031 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 2030 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 2032 __ popl(EAX); // Discard argument. | 2031 __ popl(EAX); // Discard argument. |
| 2033 __ popl(EAX); // Get Code object | 2032 __ popl(EAX); // Get Code object |
| 2034 __ popl(EDX); // Restore argument descriptor. | 2033 __ popl(EDX); // Restore argument descriptor. |
| 2035 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 2034 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 2036 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 2035 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 2037 __ LeaveFrame(); | 2036 __ LeaveFrame(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 __ Bind(&done); | 2120 __ Bind(&done); |
| 2122 __ popl(temp); | 2121 __ popl(temp); |
| 2123 __ popl(right); | 2122 __ popl(right); |
| 2124 __ popl(left); | 2123 __ popl(left); |
| 2125 __ ret(); | 2124 __ ret(); |
| 2126 } | 2125 } |
| 2127 | 2126 |
| 2128 } // namespace dart | 2127 } // namespace dart |
| 2129 | 2128 |
| 2130 #endif // defined TARGET_ARCH_IA32 | 2129 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |