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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code_dbc.cc ('k') | runtime/vm/stub_code_ia32_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/heap.h"
12 #include "vm/instructions.h" 13 #include "vm/instructions.h"
13 #include "vm/heap.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/resolver.h" 15 #include "vm/resolver.h"
16 #include "vm/scavenger.h" 16 #include "vm/scavenger.h"
17 #include "vm/stack_frame.h" 17 #include "vm/stack_frame.h"
18 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
19 #include "vm/tags.h" 19 #include "vm/tags.h"
20 20
21
22 #define __ assembler-> 21 #define __ assembler->
23 22
24 namespace dart { 23 namespace dart {
25 24
26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
27 DEFINE_FLAG(bool, 26 DEFINE_FLAG(bool,
28 use_slow_path, 27 use_slow_path,
29 false, 28 false,
30 "Set to true for debugging & verifying the slow paths."); 29 "Set to true for debugging & verifying the slow paths.");
31 DECLARE_FLAG(bool, trace_optimized_ic_calls); 30 DECLARE_FLAG(bool, trace_optimized_ic_calls);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 85
87 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 86 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
88 87
89 // Reset exit frame information in Isolate structure. 88 // Reset exit frame information in Isolate structure.
90 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 89 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
91 90
92 __ LeaveFrame(); 91 __ LeaveFrame();
93 __ ret(); 92 __ ret();
94 } 93 }
95 94
96
97 // Print the stop message. 95 // Print the stop message.
98 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { 96 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) {
99 OS::Print("Stop message: %s\n", message); 97 OS::Print("Stop message: %s\n", message);
100 } 98 }
101 END_LEAF_RUNTIME_ENTRY 99 END_LEAF_RUNTIME_ENTRY
102 100
103
104 // Input parameters: 101 // Input parameters:
105 // ESP : points to return address. 102 // ESP : points to return address.
106 // EAX : stop message (const char*). 103 // EAX : stop message (const char*).
107 // Must preserve all registers, except EAX. 104 // Must preserve all registers, except EAX.
108 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { 105 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
109 __ EnterCallRuntimeFrame(1 * kWordSize); 106 __ EnterCallRuntimeFrame(1 * kWordSize);
110 __ movl(Address(ESP, 0), EAX); 107 __ movl(Address(ESP, 0), EAX);
111 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); 108 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1);
112 __ LeaveCallRuntimeFrame(); 109 __ LeaveCallRuntimeFrame();
113 __ ret(); 110 __ ret();
114 } 111 }
115 112
116
117 // Input parameters: 113 // Input parameters:
118 // ESP : points to return address. 114 // ESP : points to return address.
119 // ESP + 4 : address of return value. 115 // ESP + 4 : address of return value.
120 // EAX : address of first argument in argument array. 116 // EAX : address of first argument in argument array.
121 // ECX : address of the native function to call. 117 // ECX : address of the native function to call.
122 // EDX : argc_tag including number of arguments and function kind. 118 // EDX : argc_tag including number of arguments and function kind.
123 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, 119 static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
124 ExternalLabel* wrapper) { 120 ExternalLabel* wrapper) {
125 const intptr_t native_args_struct_offset = 121 const intptr_t native_args_struct_offset =
126 NativeEntry::kNumCallWrapperArguments * kWordSize; 122 NativeEntry::kNumCallWrapperArguments * kWordSize;
127 const intptr_t thread_offset = 123 const intptr_t thread_offset =
128 NativeArguments::thread_offset() + native_args_struct_offset; 124 NativeArguments::thread_offset() + native_args_struct_offset;
129 const intptr_t argc_tag_offset = 125 const intptr_t argc_tag_offset =
130 NativeArguments::argc_tag_offset() + native_args_struct_offset; 126 NativeArguments::argc_tag_offset() + native_args_struct_offset;
131 const intptr_t argv_offset = 127 const intptr_t argv_offset =
132 NativeArguments::argv_offset() + native_args_struct_offset; 128 NativeArguments::argv_offset() + native_args_struct_offset;
133 const intptr_t retval_offset = 129 const intptr_t retval_offset =
134 NativeArguments::retval_offset() + native_args_struct_offset; 130 NativeArguments::retval_offset() + native_args_struct_offset;
135 131
136 __ EnterFrame(0); 132 __ EnterFrame(0);
137 133
138
139 // Save exit frame information to enable stack walking as we are about 134 // Save exit frame information to enable stack walking as we are about
140 // to transition to dart VM code. 135 // to transition to dart VM code.
141 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP); 136 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
142 137
143 #if defined(DEBUG) 138 #if defined(DEBUG)
144 { 139 {
145 Label ok; 140 Label ok;
146 // Check that we are always entering from Dart code. 141 // Check that we are always entering from Dart code.
147 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 142 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
148 __ j(EQUAL, &ok, Assembler::kNearJump); 143 __ j(EQUAL, &ok, Assembler::kNearJump);
(...skipping 28 matching lines...) Expand all
177 172
178 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 173 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
179 174
180 // Reset exit frame information in Isolate structure. 175 // Reset exit frame information in Isolate structure.
181 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 176 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
182 177
183 __ LeaveFrame(); 178 __ LeaveFrame();
184 __ ret(); 179 __ ret();
185 } 180 }
186 181
187
188 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { 182 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
189 ExternalLabel wrapper(NativeEntry::NoScopeNativeCallWrapperEntry()); 183 ExternalLabel wrapper(NativeEntry::NoScopeNativeCallWrapperEntry());
190 GenerateCallNativeWithWrapperStub(assembler, &wrapper); 184 GenerateCallNativeWithWrapperStub(assembler, &wrapper);
191 } 185 }
192 186
193
194 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { 187 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
195 ExternalLabel wrapper(NativeEntry::AutoScopeNativeCallWrapperEntry()); 188 ExternalLabel wrapper(NativeEntry::AutoScopeNativeCallWrapperEntry());
196 GenerateCallNativeWithWrapperStub(assembler, &wrapper); 189 GenerateCallNativeWithWrapperStub(assembler, &wrapper);
197 } 190 }
198 191
199
200 // Input parameters: 192 // Input parameters:
201 // ESP : points to return address. 193 // ESP : points to return address.
202 // ESP + 4 : address of return value. 194 // ESP + 4 : address of return value.
203 // EAX : address of first argument in argument array. 195 // EAX : address of first argument in argument array.
204 // ECX : address of the native function to call. 196 // ECX : address of the native function to call.
205 // EDX : argc_tag including number of arguments and function kind. 197 // EDX : argc_tag including number of arguments and function kind.
206 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { 198 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
207 const intptr_t native_args_struct_offset = kWordSize; 199 const intptr_t native_args_struct_offset = kWordSize;
208 const intptr_t thread_offset = 200 const intptr_t thread_offset =
209 NativeArguments::thread_offset() + native_args_struct_offset; 201 NativeArguments::thread_offset() + native_args_struct_offset;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 246
255 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 247 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
256 248
257 // Reset exit frame information in Isolate structure. 249 // Reset exit frame information in Isolate structure.
258 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 250 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
259 251
260 __ LeaveFrame(); 252 __ LeaveFrame();
261 __ ret(); 253 __ ret();
262 } 254 }
263 255
264
265 // Input parameters: 256 // Input parameters:
266 // EDX: arguments descriptor array. 257 // EDX: arguments descriptor array.
267 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 258 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
268 __ EnterStubFrame(); 259 __ EnterStubFrame();
269 __ pushl(EDX); // Preserve arguments descriptor array. 260 __ pushl(EDX); // Preserve arguments descriptor array.
270 __ pushl(Immediate(0)); // Setup space on stack for return value. 261 __ pushl(Immediate(0)); // Setup space on stack for return value.
271 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 262 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
272 __ popl(EAX); // Get Code object result. 263 __ popl(EAX); // Get Code object result.
273 __ popl(EDX); // Restore arguments descriptor array. 264 __ popl(EDX); // Restore arguments descriptor array.
274 // Remove the stub frame as we are about to jump to the dart function. 265 // Remove the stub frame as we are about to jump to the dart function.
275 __ LeaveFrame(); 266 __ LeaveFrame();
276 267
277 __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset())); 268 __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset()));
278 __ jmp(ECX); 269 __ jmp(ECX);
279 } 270 }
280 271
281
282 // Called from a static call only when an invalid code has been entered 272 // Called from a static call only when an invalid code has been entered
283 // (invalid because its function was optimized or deoptimized). 273 // (invalid because its function was optimized or deoptimized).
284 // EDX: arguments descriptor array. 274 // EDX: arguments descriptor array.
285 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 275 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
286 // Create a stub frame as we are pushing some objects on the stack before 276 // Create a stub frame as we are pushing some objects on the stack before
287 // calling into the runtime. 277 // calling into the runtime.
288 __ EnterStubFrame(); 278 __ EnterStubFrame();
289 __ pushl(EDX); // Preserve arguments descriptor array. 279 __ pushl(EDX); // Preserve arguments descriptor array.
290 __ pushl(Immediate(0)); // Setup space on stack for return value. 280 __ pushl(Immediate(0)); // Setup space on stack for return value.
291 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 281 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
292 __ popl(EAX); // Get Code object. 282 __ popl(EAX); // Get Code object.
293 __ popl(EDX); // Restore arguments descriptor array. 283 __ popl(EDX); // Restore arguments descriptor array.
294 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); 284 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
295 __ LeaveFrame(); 285 __ LeaveFrame();
296 __ jmp(EAX); 286 __ jmp(EAX);
297 __ int3(); 287 __ int3();
298 } 288 }
299 289
300
301 // Called from object allocate instruction when the allocation stub has been 290 // Called from object allocate instruction when the allocation stub has been
302 // disabled. 291 // disabled.
303 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 292 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
304 __ EnterStubFrame(); 293 __ EnterStubFrame();
305 __ pushl(Immediate(0)); // Setup space on stack for return value. 294 __ pushl(Immediate(0)); // Setup space on stack for return value.
306 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 295 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
307 __ popl(EAX); // Get Code object. 296 __ popl(EAX); // Get Code object.
308 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); 297 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
309 __ LeaveFrame(); 298 __ LeaveFrame();
310 __ jmp(EAX); 299 __ jmp(EAX);
311 __ int3(); 300 __ int3();
312 } 301 }
313 302
314
315 // Input parameters: 303 // Input parameters:
316 // EDX: smi-tagged argument count, may be zero. 304 // EDX: smi-tagged argument count, may be zero.
317 // EBP[kParamEndSlotFromFp + 1]: last argument. 305 // EBP[kParamEndSlotFromFp + 1]: last argument.
318 // Uses EAX, EBX, ECX, EDX, EDI. 306 // Uses EAX, EBX, ECX, EDX, EDI.
319 static void PushArgumentsArray(Assembler* assembler) { 307 static void PushArgumentsArray(Assembler* assembler) {
320 // Allocate array to store arguments of caller. 308 // Allocate array to store arguments of caller.
321 const Immediate& raw_null = 309 const Immediate& raw_null =
322 Immediate(reinterpret_cast<intptr_t>(Object::null())); 310 Immediate(reinterpret_cast<intptr_t>(Object::null()));
323 __ movl(ECX, raw_null); // Null element type for raw Array. 311 __ movl(ECX, raw_null); // Null element type for raw Array.
324 __ Call(*StubCode::AllocateArray_entry()); 312 __ Call(*StubCode::AllocateArray_entry());
(...skipping 11 matching lines...) Expand all
336 __ movl(EDI, Address(EBX, 0)); 324 __ movl(EDI, Address(EBX, 0));
337 // Generational barrier is needed, array is not necessarily in new space. 325 // Generational barrier is needed, array is not necessarily in new space.
338 __ StoreIntoObject(EAX, Address(ECX, 0), EDI); 326 __ StoreIntoObject(EAX, Address(ECX, 0), EDI);
339 __ AddImmediate(ECX, Immediate(kWordSize)); 327 __ AddImmediate(ECX, Immediate(kWordSize));
340 __ AddImmediate(EBX, Immediate(-kWordSize)); 328 __ AddImmediate(EBX, Immediate(-kWordSize));
341 __ Bind(&loop_condition); 329 __ Bind(&loop_condition);
342 __ decl(EDX); 330 __ decl(EDX);
343 __ j(POSITIVE, &loop, Assembler::kNearJump); 331 __ j(POSITIVE, &loop, Assembler::kNearJump);
344 } 332 }
345 333
346
347 // Used by eager and lazy deoptimization. Preserve result in EAX if necessary. 334 // Used by eager and lazy deoptimization. Preserve result in EAX if necessary.
348 // This stub translates optimized frame into unoptimized frame. The optimized 335 // This stub translates optimized frame into unoptimized frame. The optimized
349 // frame can contain values in registers and on stack, the unoptimized 336 // frame can contain values in registers and on stack, the unoptimized
350 // frame contains all values on stack. 337 // frame contains all values on stack.
351 // Deoptimization occurs in following steps: 338 // Deoptimization occurs in following steps:
352 // - Push all registers that can contain values. 339 // - Push all registers that can contain values.
353 // - Call C routine to copy the stack and saved registers into temporary buffer. 340 // - Call C routine to copy the stack and saved registers into temporary buffer.
354 // - Adjust caller's frame to correct unoptimized frame size. 341 // - Adjust caller's frame to correct unoptimized frame size.
355 // - Fill the unoptimized frame. 342 // - Fill the unoptimized frame.
356 // - Materialize objects that require allocation (e.g. Double instances). 343 // - Materialize objects that require allocation (e.g. Double instances).
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 __ popl(EAX); // Restore stacktrace. 455 __ popl(EAX); // Restore stacktrace.
469 } 456 }
470 __ LeaveFrame(); 457 __ LeaveFrame();
471 458
472 __ popl(ECX); // Pop return address. 459 __ popl(ECX); // Pop return address.
473 __ addl(ESP, EBX); // Remove materialization arguments. 460 __ addl(ESP, EBX); // Remove materialization arguments.
474 __ pushl(ECX); // Push return address. 461 __ pushl(ECX); // Push return address.
475 // The caller is responsible for emitting the return instruction. 462 // The caller is responsible for emitting the return instruction.
476 } 463 }
477 464
478
479 // EAX: result, must be preserved 465 // EAX: result, must be preserved
480 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { 466 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
481 // Return address for "call" to deopt stub. 467 // Return address for "call" to deopt stub.
482 __ pushl(Immediate(kZapReturnAddress)); 468 __ pushl(Immediate(kZapReturnAddress));
483 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); 469 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
484 __ ret(); 470 __ ret();
485 } 471 }
486 472
487
488 // EAX: exception, must be preserved 473 // EAX: exception, must be preserved
489 // EDX: stacktrace, must be preserved 474 // EDX: stacktrace, must be preserved
490 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { 475 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
491 // Return address for "call" to deopt stub. 476 // Return address for "call" to deopt stub.
492 __ pushl(Immediate(kZapReturnAddress)); 477 __ pushl(Immediate(kZapReturnAddress));
493 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); 478 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
494 __ ret(); 479 __ ret();
495 } 480 }
496 481
497
498 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 482 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
499 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 483 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
500 __ ret(); 484 __ ret();
501 } 485 }
502 486
503
504 static void GenerateDispatcherCode(Assembler* assembler, 487 static void GenerateDispatcherCode(Assembler* assembler,
505 Label* call_target_function) { 488 Label* call_target_function) {
506 __ Comment("NoSuchMethodDispatch"); 489 __ Comment("NoSuchMethodDispatch");
507 // When lazily generated invocation dispatchers are disabled, the 490 // When lazily generated invocation dispatchers are disabled, the
508 // miss-handler may return null. 491 // miss-handler may return null.
509 const Immediate& raw_null = 492 const Immediate& raw_null =
510 Immediate(reinterpret_cast<intptr_t>(Object::null())); 493 Immediate(reinterpret_cast<intptr_t>(Object::null()));
511 __ cmpl(EAX, raw_null); 494 __ cmpl(EAX, raw_null);
512 __ j(NOT_EQUAL, call_target_function); 495 __ j(NOT_EQUAL, call_target_function);
513 __ EnterStubFrame(); 496 __ EnterStubFrame();
(...skipping 18 matching lines...) Expand all
532 // EDX: Smi-tagged arguments array length. 515 // EDX: Smi-tagged arguments array length.
533 PushArgumentsArray(assembler); 516 PushArgumentsArray(assembler);
534 const intptr_t kNumArgs = 4; 517 const intptr_t kNumArgs = 4;
535 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); 518 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
536 __ Drop(4); 519 __ Drop(4);
537 __ popl(EAX); // Return value. 520 __ popl(EAX); // Return value.
538 __ LeaveFrame(); 521 __ LeaveFrame();
539 __ ret(); 522 __ ret();
540 } 523 }
541 524
542
543 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 525 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
544 __ EnterStubFrame(); 526 __ EnterStubFrame();
545 // Load the receiver into EAX. The argument count in the arguments 527 // Load the receiver into EAX. The argument count in the arguments
546 // descriptor in EDX is a smi. 528 // descriptor in EDX is a smi.
547 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 529 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
548 // Two words (saved fp, stub's pc marker) in the stack above the return 530 // Two words (saved fp, stub's pc marker) in the stack above the return
549 // address. 531 // address.
550 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); 532 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize));
551 // Preserve IC data and arguments descriptor. 533 // Preserve IC data and arguments descriptor.
552 __ pushl(ECX); 534 __ pushl(ECX);
(...skipping 16 matching lines...) Expand all
569 if (!FLAG_lazy_dispatchers) { 551 if (!FLAG_lazy_dispatchers) {
570 Label call_target_function; 552 Label call_target_function;
571 GenerateDispatcherCode(assembler, &call_target_function); 553 GenerateDispatcherCode(assembler, &call_target_function);
572 __ Bind(&call_target_function); 554 __ Bind(&call_target_function);
573 } 555 }
574 556
575 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); 557 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
576 __ jmp(EBX); 558 __ jmp(EBX);
577 } 559 }
578 560
579
580 // Called for inline allocation of arrays. 561 // Called for inline allocation of arrays.
581 // Input parameters: 562 // Input parameters:
582 // EDX : Array length as Smi (must be preserved). 563 // EDX : Array length as Smi (must be preserved).
583 // ECX : array element type (either NULL or an instantiated type). 564 // ECX : array element type (either NULL or an instantiated type).
584 // Uses EAX, EBX, ECX, EDI as temporary registers. 565 // Uses EAX, EBX, ECX, EDI as temporary registers.
585 // The newly allocated object is returned in EAX. 566 // The newly allocated object is returned in EAX.
586 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 567 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
587 Label slow_case; 568 Label slow_case;
588 // Compute the size to be allocated, it is based on the array length 569 // Compute the size to be allocated, it is based on the array length
589 // and is computed as: 570 // and is computed as:
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 __ pushl(EDX); // Array length as Smi. 688 __ pushl(EDX); // Array length as Smi.
708 __ pushl(ECX); // Element type. 689 __ pushl(ECX); // Element type.
709 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 690 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
710 __ popl(EAX); // Pop element type argument. 691 __ popl(EAX); // Pop element type argument.
711 __ popl(EDX); // Pop array length argument (preserved). 692 __ popl(EDX); // Pop array length argument (preserved).
712 __ popl(EAX); // Pop return value from return slot. 693 __ popl(EAX); // Pop return value from return slot.
713 __ LeaveFrame(); 694 __ LeaveFrame();
714 __ ret(); 695 __ ret();
715 } 696 }
716 697
717
718 // Called when invoking dart code from C++ (VM code). 698 // Called when invoking dart code from C++ (VM code).
719 // Input parameters: 699 // Input parameters:
720 // ESP : points to return address. 700 // ESP : points to return address.
721 // ESP + 4 : code object of the dart function to call. 701 // ESP + 4 : code object of the dart function to call.
722 // ESP + 8 : arguments descriptor array. 702 // ESP + 8 : arguments descriptor array.
723 // ESP + 12 : arguments array. 703 // ESP + 12 : arguments array.
724 // ESP + 16 : current thread. 704 // ESP + 16 : current thread.
725 // Uses EAX, EDX, ECX, EDI as temporary registers. 705 // Uses EAX, EDX, ECX, EDI as temporary registers.
726 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 706 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
727 const intptr_t kTargetCodeOffset = 2 * kWordSize; 707 const intptr_t kTargetCodeOffset = 2 * kWordSize;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 __ popl(EDI); 797 __ popl(EDI);
818 __ popl(ESI); 798 __ popl(ESI);
819 __ popl(EBX); 799 __ popl(EBX);
820 800
821 // Restore the frame pointer. 801 // Restore the frame pointer.
822 __ LeaveFrame(); 802 __ LeaveFrame();
823 803
824 __ ret(); 804 __ ret();
825 } 805 }
826 806
827
828 // Called for inline allocation of contexts. 807 // Called for inline allocation of contexts.
829 // Input: 808 // Input:
830 // EDX: number of context variables. 809 // EDX: number of context variables.
831 // Output: 810 // Output:
832 // EAX: new allocated RawContext object. 811 // EAX: new allocated RawContext object.
833 // EBX and EDX are destroyed. 812 // EBX and EDX are destroyed.
834 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 813 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
835 if (FLAG_inline_alloc) { 814 if (FLAG_inline_alloc) {
836 Label slow_case; 815 Label slow_case;
837 // First compute the rounded instance size. 816 // First compute the rounded instance size.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
948 __ pushl(EDX); 927 __ pushl(EDX);
949 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. 928 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
950 __ popl(EAX); // Pop number of context variables argument. 929 __ popl(EAX); // Pop number of context variables argument.
951 __ popl(EAX); // Pop the new context object. 930 __ popl(EAX); // Pop the new context object.
952 // EAX: new object 931 // EAX: new object
953 // Restore the frame pointer. 932 // Restore the frame pointer.
954 __ LeaveFrame(); 933 __ LeaveFrame();
955 __ ret(); 934 __ ret();
956 } 935 }
957 936
958
959 // Helper stub to implement Assembler::StoreIntoObject. 937 // Helper stub to implement Assembler::StoreIntoObject.
960 // Input parameters: 938 // Input parameters:
961 // EDX: Address being stored 939 // EDX: Address being stored
962 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { 940 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
963 // Save values being destroyed. 941 // Save values being destroyed.
964 __ pushl(EAX); 942 __ pushl(EAX);
965 __ pushl(ECX); 943 __ pushl(ECX);
966 944
967 Label add_to_buffer; 945 Label add_to_buffer;
968 // Check whether this object has already been remembered. Skip adding to the 946 // Check whether this object has already been remembered. Skip adding to the
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 // Setup frame, push callee-saved registers. 994 // Setup frame, push callee-saved registers.
1017 995
1018 __ EnterCallRuntimeFrame(1 * kWordSize); 996 __ EnterCallRuntimeFrame(1 * kWordSize);
1019 __ movl(Address(ESP, 0), THR); // Push the thread as the only argument. 997 __ movl(Address(ESP, 0), THR); // Push the thread as the only argument.
1020 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); 998 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
1021 // Restore callee-saved registers, tear down frame. 999 // Restore callee-saved registers, tear down frame.
1022 __ LeaveCallRuntimeFrame(); 1000 __ LeaveCallRuntimeFrame();
1023 __ ret(); 1001 __ ret();
1024 } 1002 }
1025 1003
1026
1027 // Called for inline allocation of objects. 1004 // Called for inline allocation of objects.
1028 // Input parameters: 1005 // Input parameters:
1029 // ESP + 4 : type arguments object (only if class is parameterized). 1006 // ESP + 4 : type arguments object (only if class is parameterized).
1030 // ESP : points to return address. 1007 // ESP : points to return address.
1031 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. 1008 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers.
1032 // Returns patch_code_pc offset where patching code for disabling the stub 1009 // Returns patch_code_pc offset where patching code for disabling the stub
1033 // has been generated (similar to regularly generated Dart code). 1010 // has been generated (similar to regularly generated Dart code).
1034 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1011 void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
1035 const Class& cls) { 1012 const Class& cls) {
1036 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; 1013 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1121 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1145 __ popl(EAX); // Pop argument (type arguments of object). 1122 __ popl(EAX); // Pop argument (type arguments of object).
1146 __ popl(EAX); // Pop argument (class of object). 1123 __ popl(EAX); // Pop argument (class of object).
1147 __ popl(EAX); // Pop result (newly allocated object). 1124 __ popl(EAX); // Pop result (newly allocated object).
1148 // EAX: new object 1125 // EAX: new object
1149 // Restore the frame pointer. 1126 // Restore the frame pointer.
1150 __ LeaveFrame(); 1127 __ LeaveFrame();
1151 __ ret(); 1128 __ ret();
1152 } 1129 }
1153 1130
1154
1155 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function 1131 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
1156 // from the entry code of a dart function after an error in passed argument 1132 // from the entry code of a dart function after an error in passed argument
1157 // name or number is detected. 1133 // name or number is detected.
1158 // Input parameters: 1134 // Input parameters:
1159 // ESP : points to return address. 1135 // ESP : points to return address.
1160 // ESP + 4 : address of last argument. 1136 // ESP + 4 : address of last argument.
1161 // EDX : arguments descriptor array. 1137 // EDX : arguments descriptor array.
1162 // Uses EAX, EBX, EDI as temporary registers. 1138 // Uses EAX, EBX, EDI as temporary registers.
1163 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { 1139 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
1164 __ EnterStubFrame(); 1140 __ EnterStubFrame();
(...skipping 17 matching lines...) Expand all
1182 1158
1183 // EDX: Smi-tagged arguments array length. 1159 // EDX: Smi-tagged arguments array length.
1184 PushArgumentsArray(assembler); 1160 PushArgumentsArray(assembler);
1185 1161
1186 const intptr_t kNumArgs = 3; 1162 const intptr_t kNumArgs = 3;
1187 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); 1163 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
1188 // noSuchMethod on closures always throws an error, so it will never return. 1164 // noSuchMethod on closures always throws an error, so it will never return.
1189 __ int3(); 1165 __ int3();
1190 } 1166 }
1191 1167
1192
1193 // Cannot use function object from ICData as it may be the inlined 1168 // Cannot use function object from ICData as it may be the inlined
1194 // function and not the top-scope function. 1169 // function and not the top-scope function.
1195 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1170 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1196 Register ic_reg = ECX; 1171 Register ic_reg = ECX;
1197 Register func_reg = EBX; 1172 Register func_reg = EBX;
1198 if (FLAG_trace_optimized_ic_calls) { 1173 if (FLAG_trace_optimized_ic_calls) {
1199 __ EnterStubFrame(); 1174 __ EnterStubFrame();
1200 __ pushl(func_reg); // Preserve 1175 __ pushl(func_reg); // Preserve
1201 __ pushl(ic_reg); // Preserve. 1176 __ pushl(ic_reg); // Preserve.
1202 __ pushl(ic_reg); // Argument. 1177 __ pushl(ic_reg); // Argument.
1203 __ pushl(func_reg); // Argument. 1178 __ pushl(func_reg); // Argument.
1204 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1179 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1205 __ popl(EAX); // Discard argument; 1180 __ popl(EAX); // Discard argument;
1206 __ popl(EAX); // Discard argument; 1181 __ popl(EAX); // Discard argument;
1207 __ popl(ic_reg); // Restore. 1182 __ popl(ic_reg); // Restore.
1208 __ popl(func_reg); // Restore. 1183 __ popl(func_reg); // Restore.
1209 __ LeaveFrame(); 1184 __ LeaveFrame();
1210 } 1185 }
1211 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); 1186 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1212 } 1187 }
1213 1188
1214
1215 // Loads function into 'temp_reg'. 1189 // Loads function into 'temp_reg'.
1216 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1190 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1217 Register temp_reg) { 1191 Register temp_reg) {
1218 if (FLAG_optimization_counter_threshold >= 0) { 1192 if (FLAG_optimization_counter_threshold >= 0) {
1219 Register ic_reg = ECX; 1193 Register ic_reg = ECX;
1220 Register func_reg = temp_reg; 1194 Register func_reg = temp_reg;
1221 ASSERT(ic_reg != func_reg); 1195 ASSERT(ic_reg != func_reg);
1222 __ Comment("Increment function counter"); 1196 __ Comment("Increment function counter");
1223 __ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); 1197 __ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
1224 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); 1198 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1225 } 1199 }
1226 } 1200 }
1227 1201
1228
1229 // Note: ECX must be preserved. 1202 // Note: ECX must be preserved.
1230 // Attempt a quick Smi operation for known operations ('kind'). The ICData 1203 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1231 // must have been primed with a Smi/Smi check that will be used for counting 1204 // must have been primed with a Smi/Smi check that will be used for counting
1232 // the invocations. 1205 // the invocations.
1233 static void EmitFastSmiOp(Assembler* assembler, 1206 static void EmitFastSmiOp(Assembler* assembler,
1234 Token::Kind kind, 1207 Token::Kind kind,
1235 intptr_t num_args, 1208 intptr_t num_args,
1236 Label* not_smi_or_overflow) { 1209 Label* not_smi_or_overflow) {
1237 __ Comment("Fast Smi op"); 1210 __ Comment("Fast Smi op");
1238 ASSERT(num_args == 2); 1211 ASSERT(num_args == 2);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 __ Bind(&ok); 1265 __ Bind(&ok);
1293 #endif 1266 #endif
1294 if (FLAG_optimization_counter_threshold >= 0) { 1267 if (FLAG_optimization_counter_threshold >= 0) {
1295 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1268 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1296 // Update counter, ignore overflow. 1269 // Update counter, ignore overflow.
1297 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); 1270 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
1298 } 1271 }
1299 __ ret(); 1272 __ ret();
1300 } 1273 }
1301 1274
1302
1303 // Generate inline cache check for 'num_args'. 1275 // Generate inline cache check for 'num_args'.
1304 // ECX: Inline cache data object. 1276 // ECX: Inline cache data object.
1305 // TOS(0): return address 1277 // TOS(0): return address
1306 // Control flow: 1278 // Control flow:
1307 // - If receiver is null -> jump to IC miss. 1279 // - If receiver is null -> jump to IC miss.
1308 // - If receiver is Smi -> load Smi class. 1280 // - If receiver is Smi -> load Smi class.
1309 // - If receiver is not-Smi -> load receiver's class. 1281 // - If receiver is not-Smi -> load receiver's class.
1310 // - Check if 'num_args' (including receiver) match any IC data group. 1282 // - Check if 'num_args' (including receiver) match any IC data group.
1311 // - Match found -> jump to target. 1283 // - Match found -> jump to target.
1312 // - Match not found -> jump to IC miss. 1284 // - Match not found -> jump to IC miss.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1393 // Load receiver into EDI. 1365 // Load receiver into EDI.
1394 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); 1366 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0));
1395 __ LoadTaggedClassIdMayBeSmi(EDI, EDI); 1367 __ LoadTaggedClassIdMayBeSmi(EDI, EDI);
1396 __ cmpl(EDI, Address(EBX, 0)); // Class id match? 1368 __ cmpl(EDI, Address(EBX, 0)); // Class id match?
1397 __ j(NOT_EQUAL, &update); // Continue. 1369 __ j(NOT_EQUAL, &update); // Continue.
1398 1370
1399 // Load second argument into EDI. 1371 // Load second argument into EDI.
1400 __ movl(EDI, Address(ESP, EAX, TIMES_2, -kWordSize)); 1372 __ movl(EDI, Address(ESP, EAX, TIMES_2, -kWordSize));
1401 __ LoadTaggedClassIdMayBeSmi(EDI, EDI); 1373 __ LoadTaggedClassIdMayBeSmi(EDI, EDI);
1402 __ cmpl(EDI, Address(EBX, kWordSize)); // Class id match? 1374 __ cmpl(EDI, Address(EBX, kWordSize)); // Class id match?
1403 __ j(EQUAL, &found); // Break. 1375 __ j(EQUAL, &found); // Break.
1404 1376
1405 __ Bind(&update); 1377 __ Bind(&update);
1406 __ addl(EBX, Immediate(entry_size)); // Next entry. 1378 __ addl(EBX, Immediate(entry_size)); // Next entry.
1407 __ cmpl(Address(EBX, -entry_size), 1379 __ cmpl(Address(EBX, -entry_size),
1408 Immediate(Smi::RawValue(kIllegalCid))); // Done? 1380 Immediate(Smi::RawValue(kIllegalCid))); // Done?
1409 } 1381 }
1410 1382
1411 if (unroll == 0) { 1383 if (unroll == 0) {
1412 __ j(NOT_EQUAL, &loop); 1384 __ j(NOT_EQUAL, &loop);
1413 } else { 1385 } else {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 __ Bind(&stepping); 1441 __ Bind(&stepping);
1470 __ EnterStubFrame(); 1442 __ EnterStubFrame();
1471 __ pushl(ECX); 1443 __ pushl(ECX);
1472 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1444 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1473 __ popl(ECX); 1445 __ popl(ECX);
1474 __ LeaveFrame(); 1446 __ LeaveFrame();
1475 __ jmp(&done_stepping); 1447 __ jmp(&done_stepping);
1476 } 1448 }
1477 } 1449 }
1478 1450
1479
1480 // Use inline cache data array to invoke the target or continue in inline 1451 // Use inline cache data array to invoke the target or continue in inline
1481 // cache miss handler. Stub for 1-argument check (receiver class). 1452 // cache miss handler. Stub for 1-argument check (receiver class).
1482 // ECX: Inline cache data object. 1453 // ECX: Inline cache data object.
1483 // TOS(0): Return address. 1454 // TOS(0): Return address.
1484 // Inline cache data object structure: 1455 // Inline cache data object structure:
1485 // 0: function-name 1456 // 0: function-name
1486 // 1: N, number of arguments checked. 1457 // 1: N, number of arguments checked.
1487 // 2 .. (length - 1): group of checks, each check containing: 1458 // 2 .. (length - 1): group of checks, each check containing:
1488 // - N classes. 1459 // - N classes.
1489 // - 1 target function. 1460 // - 1 target function.
1490 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1461 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1491 GenerateUsageCounterIncrement(assembler, EBX); 1462 GenerateUsageCounterIncrement(assembler, EBX);
1492 GenerateNArgsCheckInlineCacheStub( 1463 GenerateNArgsCheckInlineCacheStub(
1493 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1464 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1494 } 1465 }
1495 1466
1496
1497 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1467 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1498 GenerateUsageCounterIncrement(assembler, EBX); 1468 GenerateUsageCounterIncrement(assembler, EBX);
1499 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1469 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1500 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1470 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1501 Token::kILLEGAL); 1471 Token::kILLEGAL);
1502 } 1472 }
1503 1473
1504
1505 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { 1474 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1506 GenerateUsageCounterIncrement(assembler, EBX); 1475 GenerateUsageCounterIncrement(assembler, EBX);
1507 GenerateNArgsCheckInlineCacheStub( 1476 GenerateNArgsCheckInlineCacheStub(
1508 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); 1477 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1509 } 1478 }
1510 1479
1511
1512 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { 1480 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1513 GenerateUsageCounterIncrement(assembler, EBX); 1481 GenerateUsageCounterIncrement(assembler, EBX);
1514 GenerateNArgsCheckInlineCacheStub( 1482 GenerateNArgsCheckInlineCacheStub(
1515 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); 1483 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1516 } 1484 }
1517 1485
1518
1519 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { 1486 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1520 GenerateUsageCounterIncrement(assembler, EBX); 1487 GenerateUsageCounterIncrement(assembler, EBX);
1521 GenerateNArgsCheckInlineCacheStub( 1488 GenerateNArgsCheckInlineCacheStub(
1522 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); 1489 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1523 } 1490 }
1524 1491
1525
1526 // Use inline cache data array to invoke the target or continue in inline 1492 // Use inline cache data array to invoke the target or continue in inline
1527 // cache miss handler. Stub for 1-argument check (receiver class). 1493 // cache miss handler. Stub for 1-argument check (receiver class).
1528 // EDI: function which counter needs to be incremented. 1494 // EDI: function which counter needs to be incremented.
1529 // ECX: Inline cache data object. 1495 // ECX: Inline cache data object.
1530 // TOS(0): Return address. 1496 // TOS(0): Return address.
1531 // Inline cache data object structure: 1497 // Inline cache data object structure:
1532 // 0: function-name 1498 // 0: function-name
1533 // 1: N, number of arguments checked. 1499 // 1: N, number of arguments checked.
1534 // 2 .. (length - 1): group of checks, each check containing: 1500 // 2 .. (length - 1): group of checks, each check containing:
1535 // - N classes. 1501 // - N classes.
1536 // - 1 target function. 1502 // - 1 target function.
1537 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1503 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1538 Assembler* assembler) { 1504 Assembler* assembler) {
1539 GenerateOptimizedUsageCounterIncrement(assembler); 1505 GenerateOptimizedUsageCounterIncrement(assembler);
1540 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1506 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1541 kInlineCacheMissHandlerOneArgRuntimeEntry, 1507 kInlineCacheMissHandlerOneArgRuntimeEntry,
1542 Token::kILLEGAL, true /* optimized */); 1508 Token::kILLEGAL, true /* optimized */);
1543 } 1509 }
1544 1510
1545
1546 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1511 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1547 Assembler* assembler) { 1512 Assembler* assembler) {
1548 GenerateOptimizedUsageCounterIncrement(assembler); 1513 GenerateOptimizedUsageCounterIncrement(assembler);
1549 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1514 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1550 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1515 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1551 Token::kILLEGAL, true /* optimized */); 1516 Token::kILLEGAL, true /* optimized */);
1552 } 1517 }
1553 1518
1554
1555 // Intermediary stub between a static call and its target. ICData contains 1519 // Intermediary stub between a static call and its target. ICData contains
1556 // the target function and the call count. 1520 // the target function and the call count.
1557 // ECX: ICData 1521 // ECX: ICData
1558 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1522 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1559 GenerateUsageCounterIncrement(assembler, EBX); 1523 GenerateUsageCounterIncrement(assembler, EBX);
1560 1524
1561 #if defined(DEBUG) 1525 #if defined(DEBUG)
1562 { 1526 {
1563 Label ok; 1527 Label ok;
1564 // Check that the IC data array has NumArgsTested() == num_args. 1528 // Check that the IC data array has NumArgsTested() == num_args.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 __ Bind(&stepping); 1570 __ Bind(&stepping);
1607 __ EnterStubFrame(); 1571 __ EnterStubFrame();
1608 __ pushl(ECX); 1572 __ pushl(ECX);
1609 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1573 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1610 __ popl(ECX); 1574 __ popl(ECX);
1611 __ LeaveFrame(); 1575 __ LeaveFrame();
1612 __ jmp(&done_stepping, Assembler::kNearJump); 1576 __ jmp(&done_stepping, Assembler::kNearJump);
1613 } 1577 }
1614 } 1578 }
1615 1579
1616
1617 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1580 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1618 GenerateUsageCounterIncrement(assembler, EBX); 1581 GenerateUsageCounterIncrement(assembler, EBX);
1619 GenerateNArgsCheckInlineCacheStub( 1582 GenerateNArgsCheckInlineCacheStub(
1620 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1583 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1621 } 1584 }
1622 1585
1623
1624 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1586 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1625 GenerateUsageCounterIncrement(assembler, EBX); 1587 GenerateUsageCounterIncrement(assembler, EBX);
1626 GenerateNArgsCheckInlineCacheStub( 1588 GenerateNArgsCheckInlineCacheStub(
1627 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); 1589 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1628 } 1590 }
1629 1591
1630
1631 // Stub for compiling a function and jumping to the compiled code. 1592 // Stub for compiling a function and jumping to the compiled code.
1632 // ECX: IC-Data (for methods). 1593 // ECX: IC-Data (for methods).
1633 // EDX: Arguments descriptor. 1594 // EDX: Arguments descriptor.
1634 // EAX: Function. 1595 // EAX: Function.
1635 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1596 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1636 __ EnterStubFrame(); 1597 __ EnterStubFrame();
1637 __ pushl(EDX); // Preserve arguments descriptor array. 1598 __ pushl(EDX); // Preserve arguments descriptor array.
1638 __ pushl(ECX); // Preserve IC data object. 1599 __ pushl(ECX); // Preserve IC data object.
1639 __ pushl(EAX); // Pass function. 1600 __ pushl(EAX); // Pass function.
1640 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1601 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1641 __ popl(EAX); // Restore function. 1602 __ popl(EAX); // Restore function.
1642 __ popl(ECX); // Restore IC data array. 1603 __ popl(ECX); // Restore IC data array.
1643 __ popl(EDX); // Restore arguments descriptor array. 1604 __ popl(EDX); // Restore arguments descriptor array.
1644 __ LeaveFrame(); 1605 __ LeaveFrame();
1645 1606
1646 __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset())); 1607 __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset()));
1647 __ jmp(EAX); 1608 __ jmp(EAX);
1648 } 1609 }
1649 1610
1650
1651 // ECX: Contains an ICData. 1611 // ECX: Contains an ICData.
1652 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1612 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1653 __ EnterStubFrame(); 1613 __ EnterStubFrame();
1654 // Save IC data. 1614 // Save IC data.
1655 __ pushl(ECX); 1615 __ pushl(ECX);
1656 // Room for result. Debugger stub returns address of the 1616 // Room for result. Debugger stub returns address of the
1657 // unpatched runtime stub. 1617 // unpatched runtime stub.
1658 __ pushl(Immediate(0)); // Room for result. 1618 __ pushl(Immediate(0)); // Room for result.
1659 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1619 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1660 __ popl(EAX); // Code of original stub. 1620 __ popl(EAX); // Code of original stub.
1661 __ popl(ECX); // Restore IC data. 1621 __ popl(ECX); // Restore IC data.
1662 __ LeaveFrame(); 1622 __ LeaveFrame();
1663 // Jump to original stub. 1623 // Jump to original stub.
1664 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); 1624 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
1665 __ jmp(EAX); 1625 __ jmp(EAX);
1666 } 1626 }
1667 1627
1668
1669 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1628 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1670 __ EnterStubFrame(); 1629 __ EnterStubFrame();
1671 // Room for result. Debugger stub returns address of the 1630 // Room for result. Debugger stub returns address of the
1672 // unpatched runtime stub. 1631 // unpatched runtime stub.
1673 __ pushl(Immediate(0)); // Room for result. 1632 __ pushl(Immediate(0)); // Room for result.
1674 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1633 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1675 __ popl(EAX); // Code of the original stub 1634 __ popl(EAX); // Code of the original stub
1676 __ LeaveFrame(); 1635 __ LeaveFrame();
1677 // Jump to original stub. 1636 // Jump to original stub.
1678 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); 1637 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
1679 __ jmp(EAX); 1638 __ jmp(EAX);
1680 } 1639 }
1681 1640
1682
1683 // Called only from unoptimized code. 1641 // Called only from unoptimized code.
1684 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { 1642 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
1685 // Check single stepping. 1643 // Check single stepping.
1686 Label stepping, done_stepping; 1644 Label stepping, done_stepping;
1687 __ LoadIsolate(EAX); 1645 __ LoadIsolate(EAX);
1688 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); 1646 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset()));
1689 __ cmpl(EAX, Immediate(0)); 1647 __ cmpl(EAX, Immediate(0));
1690 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); 1648 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump);
1691 __ Bind(&done_stepping); 1649 __ Bind(&done_stepping);
1692 __ ret(); 1650 __ ret();
1693 1651
1694 __ Bind(&stepping); 1652 __ Bind(&stepping);
1695 __ EnterStubFrame(); 1653 __ EnterStubFrame();
1696 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1654 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1697 __ LeaveFrame(); 1655 __ LeaveFrame();
1698 __ jmp(&done_stepping, Assembler::kNearJump); 1656 __ jmp(&done_stepping, Assembler::kNearJump);
1699 } 1657 }
1700 1658
1701
1702 // Used to check class and type arguments. Arguments passed on stack: 1659 // Used to check class and type arguments. Arguments passed on stack:
1703 // TOS + 0: return address. 1660 // TOS + 0: return address.
1704 // TOS + 1: function type arguments (only if n == 4, can be raw_null). 1661 // TOS + 1: function type arguments (only if n == 4, can be raw_null).
1705 // TOS + 2: instantiator type arguments (only if n == 4, can be raw_null). 1662 // TOS + 2: instantiator type arguments (only if n == 4, can be raw_null).
1706 // TOS + 3: instance. 1663 // TOS + 3: instance.
1707 // TOS + 4: SubtypeTestCache. 1664 // TOS + 4: SubtypeTestCache.
1708 // Result in ECX: null -> not found, otherwise result (true or false). 1665 // Result in ECX: null -> not found, otherwise result (true or false).
1709 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1666 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1710 ASSERT((n == 1) || (n == 2) || (n == 4)); 1667 ASSERT((n == 1) || (n == 2) || (n == 4));
1711 const intptr_t kFunctionTypeArgumentsInBytes = 1 * kWordSize; 1668 const intptr_t kFunctionTypeArgumentsInBytes = 1 * kWordSize;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 // Fall through to not found. 1741 // Fall through to not found.
1785 __ Bind(&not_found); 1742 __ Bind(&not_found);
1786 __ movl(ECX, raw_null); 1743 __ movl(ECX, raw_null);
1787 __ ret(); 1744 __ ret();
1788 1745
1789 __ Bind(&found); 1746 __ Bind(&found);
1790 __ movl(ECX, Address(EDX, kWordSize * SubtypeTestCache::kTestResult)); 1747 __ movl(ECX, Address(EDX, kWordSize * SubtypeTestCache::kTestResult));
1791 __ ret(); 1748 __ ret();
1792 } 1749 }
1793 1750
1794
1795 // Used to check class and type arguments. Arguments passed on stack: 1751 // Used to check class and type arguments. Arguments passed on stack:
1796 // TOS + 0: return address. 1752 // TOS + 0: return address.
1797 // TOS + 1: raw_null. 1753 // TOS + 1: raw_null.
1798 // TOS + 2: raw_null. 1754 // TOS + 2: raw_null.
1799 // TOS + 3: instance. 1755 // TOS + 3: instance.
1800 // TOS + 4: SubtypeTestCache. 1756 // TOS + 4: SubtypeTestCache.
1801 // Result in ECX: null -> not found, otherwise result (true or false). 1757 // Result in ECX: null -> not found, otherwise result (true or false).
1802 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { 1758 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
1803 GenerateSubtypeNTestCacheStub(assembler, 1); 1759 GenerateSubtypeNTestCacheStub(assembler, 1);
1804 } 1760 }
1805 1761
1806
1807 // Used to check class and type arguments. Arguments passed on stack: 1762 // Used to check class and type arguments. Arguments passed on stack:
1808 // TOS + 0: return address. 1763 // TOS + 0: return address.
1809 // TOS + 1: raw_null. 1764 // TOS + 1: raw_null.
1810 // TOS + 2: raw_null. 1765 // TOS + 2: raw_null.
1811 // TOS + 3: instance. 1766 // TOS + 3: instance.
1812 // TOS + 4: SubtypeTestCache. 1767 // TOS + 4: SubtypeTestCache.
1813 // Result in ECX: null -> not found, otherwise result (true or false). 1768 // Result in ECX: null -> not found, otherwise result (true or false).
1814 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { 1769 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
1815 GenerateSubtypeNTestCacheStub(assembler, 2); 1770 GenerateSubtypeNTestCacheStub(assembler, 2);
1816 } 1771 }
1817 1772
1818
1819 // Used to check class and type arguments. Arguments passed on stack: 1773 // Used to check class and type arguments. Arguments passed on stack:
1820 // TOS + 0: return address. 1774 // TOS + 0: return address.
1821 // TOS + 1: function type arguments (can be raw_null). 1775 // TOS + 1: function type arguments (can be raw_null).
1822 // TOS + 2: instantiator type arguments (can be raw_null). 1776 // TOS + 2: instantiator type arguments (can be raw_null).
1823 // TOS + 3: instance. 1777 // TOS + 3: instance.
1824 // TOS + 4: SubtypeTestCache. 1778 // TOS + 4: SubtypeTestCache.
1825 // Result in ECX: null -> not found, otherwise result (true or false). 1779 // Result in ECX: null -> not found, otherwise result (true or false).
1826 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { 1780 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
1827 GenerateSubtypeNTestCacheStub(assembler, 4); 1781 GenerateSubtypeNTestCacheStub(assembler, 4);
1828 } 1782 }
1829 1783
1830
1831 // Return the current stack pointer address, used to do stack alignment checks. 1784 // Return the current stack pointer address, used to do stack alignment checks.
1832 // TOS + 0: return address 1785 // TOS + 0: return address
1833 // Result in EAX. 1786 // Result in EAX.
1834 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { 1787 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
1835 __ leal(EAX, Address(ESP, kWordSize)); 1788 __ leal(EAX, Address(ESP, kWordSize));
1836 __ ret(); 1789 __ ret();
1837 } 1790 }
1838 1791
1839
1840 // Jump to a frame on the call stack. 1792 // Jump to a frame on the call stack.
1841 // TOS + 0: return address 1793 // TOS + 0: return address
1842 // TOS + 1: program_counter 1794 // TOS + 1: program_counter
1843 // TOS + 2: stack_pointer 1795 // TOS + 2: stack_pointer
1844 // TOS + 3: frame_pointer 1796 // TOS + 3: frame_pointer
1845 // TOS + 4: thread 1797 // TOS + 4: thread
1846 // No Result. 1798 // No Result.
1847 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { 1799 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
1848 __ movl(THR, Address(ESP, 4 * kWordSize)); // Load target thread. 1800 __ movl(THR, Address(ESP, 4 * kWordSize)); // Load target thread.
1849 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer. 1801 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer.
1850 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX. 1802 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX.
1851 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer. 1803 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer.
1852 // Set tag. 1804 // Set tag.
1853 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 1805 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
1854 // Clear top exit frame. 1806 // Clear top exit frame.
1855 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 1807 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
1856 __ jmp(EBX); // Jump to the exception handler code. 1808 __ jmp(EBX); // Jump to the exception handler code.
1857 } 1809 }
1858 1810
1859
1860 // Run an exception handler. Execution comes from JumpToFrame stub. 1811 // Run an exception handler. Execution comes from JumpToFrame stub.
1861 // 1812 //
1862 // The arguments are stored in the Thread object. 1813 // The arguments are stored in the Thread object.
1863 // No result. 1814 // No result.
1864 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { 1815 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
1865 ASSERT(kExceptionObjectReg == EAX); 1816 ASSERT(kExceptionObjectReg == EAX);
1866 ASSERT(kStackTraceObjectReg == EDX); 1817 ASSERT(kStackTraceObjectReg == EDX);
1867 __ movl(EBX, Address(THR, Thread::resume_pc_offset())); 1818 __ movl(EBX, Address(THR, Thread::resume_pc_offset()));
1868 1819
1869 // Load the exception from the current thread. 1820 // Load the exception from the current thread.
1870 Address exception_addr(THR, Thread::active_exception_offset()); 1821 Address exception_addr(THR, Thread::active_exception_offset());
1871 __ movl(kExceptionObjectReg, exception_addr); 1822 __ movl(kExceptionObjectReg, exception_addr);
1872 __ movl(exception_addr, Immediate(0)); 1823 __ movl(exception_addr, Immediate(0));
1873 1824
1874 // Load the stacktrace from the current thread. 1825 // Load the stacktrace from the current thread.
1875 Address stacktrace_addr(THR, Thread::active_stacktrace_offset()); 1826 Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
1876 __ movl(kStackTraceObjectReg, stacktrace_addr); 1827 __ movl(kStackTraceObjectReg, stacktrace_addr);
1877 __ movl(stacktrace_addr, Immediate(0)); 1828 __ movl(stacktrace_addr, Immediate(0));
1878 1829
1879 __ jmp(EBX); // Jump to continuation point. 1830 __ jmp(EBX); // Jump to continuation point.
1880 } 1831 }
1881 1832
1882
1883 // Deoptimize a frame on the call stack before rewinding. 1833 // Deoptimize a frame on the call stack before rewinding.
1884 // The arguments are stored in the Thread object. 1834 // The arguments are stored in the Thread object.
1885 // No result. 1835 // No result.
1886 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { 1836 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
1887 // Push the deopt pc. 1837 // Push the deopt pc.
1888 __ pushl(Address(THR, Thread::resume_pc_offset())); 1838 __ pushl(Address(THR, Thread::resume_pc_offset()));
1889 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 1839 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
1890 1840
1891 // After we have deoptimized, jump to the correct frame. 1841 // After we have deoptimized, jump to the correct frame.
1892 __ EnterStubFrame(); 1842 __ EnterStubFrame();
1893 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); 1843 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0);
1894 __ LeaveFrame(); 1844 __ LeaveFrame();
1895 __ int3(); 1845 __ int3();
1896 } 1846 }
1897 1847
1898
1899 // Calls to the runtime to optimize the given function. 1848 // Calls to the runtime to optimize the given function.
1900 // EBX: function to be reoptimized. 1849 // EBX: function to be reoptimized.
1901 // EDX: argument descriptor (preserved). 1850 // EDX: argument descriptor (preserved).
1902 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1851 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1903 __ EnterStubFrame(); 1852 __ EnterStubFrame();
1904 __ pushl(EDX); 1853 __ pushl(EDX);
1905 __ pushl(Immediate(0)); // Setup space on stack for return value. 1854 __ pushl(Immediate(0)); // Setup space on stack for return value.
1906 __ pushl(EBX); 1855 __ pushl(EBX);
1907 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1856 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1908 __ popl(EAX); // Discard argument. 1857 __ popl(EAX); // Discard argument.
1909 __ popl(EAX); // Get Function object 1858 __ popl(EAX); // Get Function object
1910 __ popl(EDX); // Restore argument descriptor. 1859 __ popl(EDX); // Restore argument descriptor.
1911 __ LeaveFrame(); 1860 __ LeaveFrame();
1912 __ movl(CODE_REG, FieldAddress(EAX, Function::code_offset())); 1861 __ movl(CODE_REG, FieldAddress(EAX, Function::code_offset()));
1913 __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset())); 1862 __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset()));
1914 __ jmp(EAX); 1863 __ jmp(EAX);
1915 __ int3(); 1864 __ int3();
1916 } 1865 }
1917 1866
1918
1919 // Does identical check (object references are equal or not equal) with special 1867 // Does identical check (object references are equal or not equal) with special
1920 // checks for boxed numbers. 1868 // checks for boxed numbers.
1921 // Return ZF set. 1869 // Return ZF set.
1922 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 1870 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
1923 // cannot contain a value that fits in Mint or Smi. 1871 // cannot contain a value that fits in Mint or Smi.
1924 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, 1872 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
1925 const Register left, 1873 const Register left,
1926 const Register right, 1874 const Register right,
1927 const Register temp) { 1875 const Register temp) {
1928 Label reference_compare, done, check_mint, check_bigint; 1876 Label reference_compare, done, check_mint, check_bigint;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 // Result in EAX, 0 means equal. 1919 // Result in EAX, 0 means equal.
1972 __ LeaveFrame(); 1920 __ LeaveFrame();
1973 __ cmpl(EAX, Immediate(0)); 1921 __ cmpl(EAX, Immediate(0));
1974 __ jmp(&done); 1922 __ jmp(&done);
1975 1923
1976 __ Bind(&reference_compare); 1924 __ Bind(&reference_compare);
1977 __ cmpl(left, right); 1925 __ cmpl(left, right);
1978 __ Bind(&done); 1926 __ Bind(&done);
1979 } 1927 }
1980 1928
1981
1982 // Called only from unoptimized code. All relevant registers have been saved. 1929 // Called only from unoptimized code. All relevant registers have been saved.
1983 // TOS + 0: return address 1930 // TOS + 0: return address
1984 // TOS + 1: right argument. 1931 // TOS + 1: right argument.
1985 // TOS + 2: left argument. 1932 // TOS + 2: left argument.
1986 // Returns ZF set. 1933 // Returns ZF set.
1987 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( 1934 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
1988 Assembler* assembler) { 1935 Assembler* assembler) {
1989 // Check single stepping. 1936 // Check single stepping.
1990 Label stepping, done_stepping; 1937 Label stepping, done_stepping;
1991 if (FLAG_support_debugger) { 1938 if (FLAG_support_debugger) {
(...skipping 14 matching lines...) Expand all
2006 1953
2007 if (FLAG_support_debugger) { 1954 if (FLAG_support_debugger) {
2008 __ Bind(&stepping); 1955 __ Bind(&stepping);
2009 __ EnterStubFrame(); 1956 __ EnterStubFrame();
2010 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1957 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2011 __ LeaveFrame(); 1958 __ LeaveFrame();
2012 __ jmp(&done_stepping); 1959 __ jmp(&done_stepping);
2013 } 1960 }
2014 } 1961 }
2015 1962
2016
2017 // Called from optimized code only. 1963 // Called from optimized code only.
2018 // TOS + 0: return address 1964 // TOS + 0: return address
2019 // TOS + 1: right argument. 1965 // TOS + 1: right argument.
2020 // TOS + 2: left argument. 1966 // TOS + 2: left argument.
2021 // Returns ZF set. 1967 // Returns ZF set.
2022 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( 1968 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
2023 Assembler* assembler) { 1969 Assembler* assembler) {
2024 const Register left = EAX; 1970 const Register left = EAX;
2025 const Register right = EDX; 1971 const Register right = EDX;
2026 const Register temp = ECX; 1972 const Register temp = ECX;
2027 __ movl(left, Address(ESP, 2 * kWordSize)); 1973 __ movl(left, Address(ESP, 2 * kWordSize));
2028 __ movl(right, Address(ESP, 1 * kWordSize)); 1974 __ movl(right, Address(ESP, 1 * kWordSize));
2029 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1975 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
2030 __ ret(); 1976 __ ret();
2031 } 1977 }
2032 1978
2033
2034 // Called from megamorphic calls. 1979 // Called from megamorphic calls.
2035 // EBX: receiver 1980 // EBX: receiver
2036 // ECX: MegamorphicCache (preserved) 1981 // ECX: MegamorphicCache (preserved)
2037 // Passed to target: 1982 // Passed to target:
2038 // EBX: target entry point 1983 // EBX: target entry point
2039 // EDX: argument descriptor 1984 // EDX: argument descriptor
2040 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { 1985 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
2041 // Jump if receiver is a smi. 1986 // Jump if receiver is a smi.
2042 Label smi_case; 1987 Label smi_case;
2043 // Check if object (in tmp) is a Smi. 1988 // Check if object (in tmp) is a Smi.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 2048
2104 // Called from switchable IC calls. 2049 // Called from switchable IC calls.
2105 // EBX: receiver 2050 // EBX: receiver
2106 // ECX: ICData (preserved) 2051 // ECX: ICData (preserved)
2107 // Passed to target: 2052 // Passed to target:
2108 // EDX: arguments descriptor 2053 // EDX: arguments descriptor
2109 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { 2054 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
2110 __ int3(); 2055 __ int3();
2111 } 2056 }
2112 2057
2113
2114 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { 2058 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
2115 __ int3(); 2059 __ int3();
2116 } 2060 }
2117 2061
2118
2119 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { 2062 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
2120 __ int3(); 2063 __ int3();
2121 } 2064 }
2122 2065
2123
2124 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { 2066 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
2125 __ int3(); 2067 __ int3();
2126 } 2068 }
2127 2069
2128
2129 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { 2070 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
2130 __ int3(); 2071 __ int3();
2131 } 2072 }
2132 2073
2133
2134 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2074 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2135 __ int3(); 2075 __ int3();
2136 } 2076 }
2137 2077
2138
2139 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { 2078 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
2140 __ int3(); 2079 __ int3();
2141 } 2080 }
2142 2081
2143 } // namespace dart 2082 } // namespace dart
2144 2083
2145 #endif // defined TARGET_ARCH_IA32 2084 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_dbc.cc ('k') | runtime/vm/stub_code_ia32_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698