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

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

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month 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/instructions.h" 12 #include "vm/instructions.h"
13 #include "vm/heap.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 21
22 #define __ assembler-> 22 #define __ assembler->
23 23
24 namespace dart { 24 namespace dart {
25 25
26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
27 DEFINE_FLAG(bool, use_slow_path, false, 27 DEFINE_FLAG(bool,
28 "Set to true for debugging & verifying the slow paths."); 28 use_slow_path,
29 false,
30 "Set to true for debugging & verifying the slow paths.");
29 DECLARE_FLAG(bool, trace_optimized_ic_calls); 31 DECLARE_FLAG(bool, trace_optimized_ic_calls);
30 32
31 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x)) 33 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))
32 34
33 // Input parameters: 35 // Input parameters:
34 // ESP : points to return address. 36 // ESP : points to return address.
35 // ESP + 4 : address of last argument in argument array. 37 // ESP + 4 : address of last argument in argument array.
36 // ESP + 4*EDX : address of first argument in argument array. 38 // ESP + 4*EDX : address of first argument in argument array.
37 // ESP + 4*EDX + 4 : address of return value. 39 // ESP + 4*EDX + 4 : address of return value.
38 // ECX : address of the runtime function to call. 40 // ECX : address of the runtime function to call.
39 // EDX : number of arguments to the call. 41 // EDX : number of arguments to the call.
40 // Must preserve callee saved registers EDI and EBX. 42 // Must preserve callee saved registers EDI and EBX.
41 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 43 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
42 const intptr_t thread_offset = NativeArguments::thread_offset(); 44 const intptr_t thread_offset = NativeArguments::thread_offset();
43 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 45 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
44 const intptr_t argv_offset = NativeArguments::argv_offset(); 46 const intptr_t argv_offset = NativeArguments::argv_offset();
45 const intptr_t retval_offset = NativeArguments::retval_offset(); 47 const intptr_t retval_offset = NativeArguments::retval_offset();
46 48
47 __ EnterFrame(0); 49 __ EnterFrame(0);
48 50
49 // Save exit frame information to enable stack walking as we are about 51 // Save exit frame information to enable stack walking as we are about
50 // to transition to Dart VM C++ code. 52 // to transition to Dart VM C++ code.
51 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP); 53 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
52 54
53 #if defined(DEBUG) 55 #if defined(DEBUG)
54 { Label ok; 56 {
57 Label ok;
55 // Check that we are always entering from Dart code. 58 // Check that we are always entering from Dart code.
56 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 59 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
57 __ j(EQUAL, &ok, Assembler::kNearJump); 60 __ j(EQUAL, &ok, Assembler::kNearJump);
58 __ Stop("Not coming from Dart code."); 61 __ Stop("Not coming from Dart code.");
59 __ Bind(&ok); 62 __ Bind(&ok);
60 } 63 }
61 #endif 64 #endif
62 65
63 // Mark that the thread is executing VM code. 66 // Mark that the thread is executing VM code.
64 __ movl(Assembler::VMTagAddress(), ECX); 67 __ movl(Assembler::VMTagAddress(), ECX);
65 68
66 // Reserve space for arguments and align frame before entering C++ world. 69 // Reserve space for arguments and align frame before entering C++ world.
67 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments))); 70 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments)));
68 if (OS::ActivationFrameAlignment() > 1) { 71 if (OS::ActivationFrameAlignment() > 1) {
69 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 72 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
70 } 73 }
71 74
72 // Pass NativeArguments structure by value and call runtime. 75 // Pass NativeArguments structure by value and call runtime.
73 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs. 76 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs.
74 // There are no runtime calls to closures, so we do not need to set the tag 77 // There are no runtime calls to closures, so we do not need to set the tag
75 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 78 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
76 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments. 79 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments.
77 // Compute argv. 80 // Compute argv.
78 __ leal(EAX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize)); 81 __ leal(EAX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize));
79 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. 82 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments.
80 __ addl(EAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. 83 __ addl(EAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument.
81 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. 84 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
82 __ call(ECX); 85 __ call(ECX);
83 86
84 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 87 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
85 88
86 // Reset exit frame information in Isolate structure. 89 // Reset exit frame information in Isolate structure.
87 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 90 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
88 91
89 __ LeaveFrame(); 92 __ LeaveFrame();
90 __ ret(); 93 __ ret();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 NativeArguments::retval_offset() + native_args_struct_offset; 133 NativeArguments::retval_offset() + native_args_struct_offset;
131 134
132 __ EnterFrame(0); 135 __ EnterFrame(0);
133 136
134 137
135 // Save exit frame information to enable stack walking as we are about 138 // Save exit frame information to enable stack walking as we are about
136 // to transition to dart VM code. 139 // to transition to dart VM code.
137 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP); 140 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
138 141
139 #if defined(DEBUG) 142 #if defined(DEBUG)
140 { Label ok; 143 {
144 Label ok;
141 // Check that we are always entering from Dart code. 145 // Check that we are always entering from Dart code.
142 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 146 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
143 __ j(EQUAL, &ok, Assembler::kNearJump); 147 __ j(EQUAL, &ok, Assembler::kNearJump);
144 __ Stop("Not coming from Dart code."); 148 __ Stop("Not coming from Dart code.");
145 __ Bind(&ok); 149 __ Bind(&ok);
146 } 150 }
147 #endif 151 #endif
148 152
149 // Mark that the thread is executing native code. 153 // Mark that the thread is executing native code.
150 __ movl(Assembler::VMTagAddress(), ECX); 154 __ movl(Assembler::VMTagAddress(), ECX);
151 155
152 // Reserve space for the native arguments structure, the outgoing parameters 156 // Reserve space for the native arguments structure, the outgoing parameters
153 // (pointer to the native arguments structure, the C function entry point) 157 // (pointer to the native arguments structure, the C function entry point)
154 // and align frame before entering the C++ world. 158 // and align frame before entering the C++ world.
155 __ AddImmediate(ESP, 159 __ AddImmediate(ESP,
156 Immediate(-INT32_SIZEOF(NativeArguments) - (2 * kWordSize))); 160 Immediate(-INT32_SIZEOF(NativeArguments) - (2 * kWordSize)));
157 if (OS::ActivationFrameAlignment() > 1) { 161 if (OS::ActivationFrameAlignment() > 1) {
158 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 162 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
159 } 163 }
160 164
161 // Pass NativeArguments structure by value and call native function. 165 // Pass NativeArguments structure by value and call native function.
162 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs. 166 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs.
163 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments. 167 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments.
164 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. 168 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments.
165 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr. 169 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr.
166 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. 170 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
167 __ leal(EAX, Address(ESP, 2 * kWordSize)); // Pointer to the NativeArguments. 171 __ leal(EAX, Address(ESP, 2 * kWordSize)); // Pointer to the NativeArguments.
168 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. 172 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments.
169 173
170 __ movl(Address(ESP, kWordSize), ECX); // Function to call. 174 __ movl(Address(ESP, kWordSize), ECX); // Function to call.
171 ExternalLabel label(NativeEntry::NativeCallWrapperEntry()); 175 ExternalLabel label(NativeEntry::NativeCallWrapperEntry());
172 __ call(&label); 176 __ call(&label);
173 177
174 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 178 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
175 179
(...skipping 22 matching lines...) Expand all
198 const intptr_t retval_offset = 202 const intptr_t retval_offset =
199 NativeArguments::retval_offset() + native_args_struct_offset; 203 NativeArguments::retval_offset() + native_args_struct_offset;
200 204
201 __ EnterFrame(0); 205 __ EnterFrame(0);
202 206
203 // Save exit frame information to enable stack walking as we are about 207 // Save exit frame information to enable stack walking as we are about
204 // to transition to dart VM code. 208 // to transition to dart VM code.
205 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP); 209 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
206 210
207 #if defined(DEBUG) 211 #if defined(DEBUG)
208 { Label ok; 212 {
213 Label ok;
209 // Check that we are always entering from Dart code. 214 // Check that we are always entering from Dart code.
210 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 215 __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
211 __ j(EQUAL, &ok, Assembler::kNearJump); 216 __ j(EQUAL, &ok, Assembler::kNearJump);
212 __ Stop("Not coming from Dart code."); 217 __ Stop("Not coming from Dart code.");
213 __ Bind(&ok); 218 __ Bind(&ok);
214 } 219 }
215 #endif 220 #endif
216 221
217 // Mark that the thread is executing native code. 222 // Mark that the thread is executing native code.
218 __ movl(Assembler::VMTagAddress(), ECX); 223 __ movl(Assembler::VMTagAddress(), ECX);
219 224
220 // Reserve space for the native arguments structure, the outgoing parameter 225 // Reserve space for the native arguments structure, the outgoing parameter
221 // (pointer to the native arguments structure) and align frame before 226 // (pointer to the native arguments structure) and align frame before
222 // entering the C++ world. 227 // entering the C++ world.
223 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments) - kWordSize)); 228 __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments) - kWordSize));
224 if (OS::ActivationFrameAlignment() > 1) { 229 if (OS::ActivationFrameAlignment() > 1) {
225 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 230 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
226 } 231 }
227 232
228 // Pass NativeArguments structure by value and call native function. 233 // Pass NativeArguments structure by value and call native function.
229 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs. 234 __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs.
230 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments. 235 __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments.
231 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. 236 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments.
232 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr. 237 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr.
233 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. 238 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
234 __ leal(EAX, Address(ESP, kWordSize)); // Pointer to the NativeArguments. 239 __ leal(EAX, Address(ESP, kWordSize)); // Pointer to the NativeArguments.
235 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. 240 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments.
236 __ call(ECX); 241 __ call(ECX);
237 242
238 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 243 __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
239 244
240 // Reset exit frame information in Isolate structure. 245 // Reset exit frame information in Isolate structure.
241 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 246 __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
242 247
243 __ LeaveFrame(); 248 __ LeaveFrame();
244 __ ret(); 249 __ ret();
245 } 250 }
246 251
247 252
248 // Input parameters: 253 // Input parameters:
249 // EDX: arguments descriptor array. 254 // EDX: arguments descriptor array.
250 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 255 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
251 __ EnterStubFrame(); 256 __ EnterStubFrame();
252 __ pushl(EDX); // Preserve arguments descriptor array. 257 __ pushl(EDX); // Preserve arguments descriptor array.
253 __ pushl(Immediate(0)); // Setup space on stack for return value. 258 __ pushl(Immediate(0)); // Setup space on stack for return value.
254 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 259 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
255 __ popl(EAX); // Get Code object result. 260 __ popl(EAX); // Get Code object result.
256 __ popl(EDX); // Restore arguments descriptor array. 261 __ popl(EDX); // Restore arguments descriptor array.
257 // Remove the stub frame as we are about to jump to the dart function. 262 // Remove the stub frame as we are about to jump to the dart function.
258 __ LeaveFrame(); 263 __ LeaveFrame();
259 264
260 __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset())); 265 __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset()));
261 __ jmp(ECX); 266 __ jmp(ECX);
262 } 267 }
263 268
264 269
265 // Called from a static call only when an invalid code has been entered 270 // Called from a static call only when an invalid code has been entered
266 // (invalid because its function was optimized or deoptimized). 271 // (invalid because its function was optimized or deoptimized).
267 // EDX: arguments descriptor array. 272 // EDX: arguments descriptor array.
268 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 273 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
269 // Create a stub frame as we are pushing some objects on the stack before 274 // Create a stub frame as we are pushing some objects on the stack before
270 // calling into the runtime. 275 // calling into the runtime.
271 __ EnterStubFrame(); 276 __ EnterStubFrame();
272 __ pushl(EDX); // Preserve arguments descriptor array. 277 __ pushl(EDX); // Preserve arguments descriptor array.
273 __ pushl(Immediate(0)); // Setup space on stack for return value. 278 __ pushl(Immediate(0)); // Setup space on stack for return value.
274 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 279 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
275 __ popl(EAX); // Get Code object. 280 __ popl(EAX); // Get Code object.
276 __ popl(EDX); // Restore arguments descriptor array. 281 __ popl(EDX); // Restore arguments descriptor array.
277 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset())); 282 __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
278 __ LeaveFrame(); 283 __ LeaveFrame();
279 __ jmp(EAX); 284 __ jmp(EAX);
280 __ int3(); 285 __ int3();
281 } 286 }
282 287
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 intptr_t offset = 0; 385 intptr_t offset = 0;
381 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { 386 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
382 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); 387 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
383 __ movups(Address(ESP, offset), xmm_reg); 388 __ movups(Address(ESP, offset), xmm_reg);
384 offset += kFpuRegisterSize; 389 offset += kFpuRegisterSize;
385 } 390 }
386 391
387 __ movl(ECX, ESP); // Preserve saved registers block. 392 __ movl(ECX, ESP); // Preserve saved registers block.
388 __ ReserveAlignedFrameSpace(2 * kWordSize); 393 __ ReserveAlignedFrameSpace(2 * kWordSize);
389 __ movl(Address(ESP, 0 * kWordSize), ECX); // Start of register block. 394 __ movl(Address(ESP, 0 * kWordSize), ECX); // Start of register block.
390 bool is_lazy = (kind == kLazyDeoptFromReturn) || 395 bool is_lazy =
391 (kind == kLazyDeoptFromThrow); 396 (kind == kLazyDeoptFromReturn) || (kind == kLazyDeoptFromThrow);
392 __ movl(Address(ESP, 1 * kWordSize), Immediate(is_lazy ? 1 : 0)); 397 __ movl(Address(ESP, 1 * kWordSize), Immediate(is_lazy ? 1 : 0));
393 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 398 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
394 // Result (EAX) is stack-size (FP - SP) in bytes. 399 // Result (EAX) is stack-size (FP - SP) in bytes.
395 400
396 if (kind == kLazyDeoptFromReturn) { 401 if (kind == kLazyDeoptFromReturn) {
397 // Restore result into EBX temporarily. 402 // Restore result into EBX temporarily.
398 __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize)); 403 __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize));
399 } else if (kind == kLazyDeoptFromThrow) { 404 } else if (kind == kLazyDeoptFromThrow) {
400 // Restore result into EBX temporarily. 405 // Restore result into EBX temporarily.
401 __ movl(EBX, Address(EBP, saved_exception_slot_from_fp * kWordSize)); 406 __ movl(EBX, Address(EBP, saved_exception_slot_from_fp * kWordSize));
402 __ movl(ECX, Address(EBP, saved_stacktrace_slot_from_fp * kWordSize)); 407 __ movl(ECX, Address(EBP, saved_stacktrace_slot_from_fp * kWordSize));
403 } 408 }
404 409
405 __ LeaveFrame(); 410 __ LeaveFrame();
406 __ popl(EDX); // Preserve return address. 411 __ popl(EDX); // Preserve return address.
407 __ movl(ESP, EBP); // Discard optimized frame. 412 __ movl(ESP, EBP); // Discard optimized frame.
408 __ subl(ESP, EAX); // Reserve space for deoptimized frame. 413 __ subl(ESP, EAX); // Reserve space for deoptimized frame.
409 __ pushl(EDX); // Restore return address. 414 __ pushl(EDX); // Restore return address.
410 415
411 // Leaf runtime function DeoptimizeFillFrame expects a Dart frame. 416 // Leaf runtime function DeoptimizeFillFrame expects a Dart frame.
412 __ EnterDartFrame(0); 417 __ EnterDartFrame(0);
413 if (kind == kLazyDeoptFromReturn) { 418 if (kind == kLazyDeoptFromReturn) {
414 __ pushl(EBX); // Preserve result as first local. 419 __ pushl(EBX); // Preserve result as first local.
415 } else if (kind == kLazyDeoptFromThrow) { 420 } else if (kind == kLazyDeoptFromThrow) {
416 __ pushl(EBX); // Preserve exception as first local. 421 __ pushl(EBX); // Preserve exception as first local.
417 __ pushl(ECX); // Preserve stacktrace as first local. 422 __ pushl(ECX); // Preserve stacktrace as first local.
418 } 423 }
419 __ ReserveAlignedFrameSpace(1 * kWordSize); 424 __ ReserveAlignedFrameSpace(1 * kWordSize);
(...skipping 27 matching lines...) Expand all
447 __ popl(EBX); 452 __ popl(EBX);
448 __ SmiUntag(EBX); 453 __ SmiUntag(EBX);
449 if (kind == kLazyDeoptFromReturn) { 454 if (kind == kLazyDeoptFromReturn) {
450 __ popl(EAX); // Restore result. 455 __ popl(EAX); // Restore result.
451 } else if (kind == kLazyDeoptFromThrow) { 456 } else if (kind == kLazyDeoptFromThrow) {
452 __ popl(EDX); // Restore exception. 457 __ popl(EDX); // Restore exception.
453 __ popl(EAX); // Restore stacktrace. 458 __ popl(EAX); // Restore stacktrace.
454 } 459 }
455 __ LeaveFrame(); 460 __ LeaveFrame();
456 461
457 __ popl(ECX); // Pop return address. 462 __ popl(ECX); // Pop return address.
458 __ addl(ESP, EBX); // Remove materialization arguments. 463 __ addl(ESP, EBX); // Remove materialization arguments.
459 __ pushl(ECX); // Push return address. 464 __ pushl(ECX); // Push return address.
460 __ ret(); 465 __ ret();
461 } 466 }
462 467
463 468
464 // EAX: result, must be preserved 469 // EAX: result, must be preserved
465 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { 470 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
466 // Return address for "call" to deopt stub. 471 // Return address for "call" to deopt stub.
467 __ pushl(Immediate(0xe1e1e1e1)); 472 __ pushl(Immediate(0xe1e1e1e1));
468 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); 473 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
469 } 474 }
(...skipping 18 matching lines...) Expand all
488 __ Comment("NoSuchMethodDispatch"); 493 __ Comment("NoSuchMethodDispatch");
489 // When lazily generated invocation dispatchers are disabled, the 494 // When lazily generated invocation dispatchers are disabled, the
490 // miss-handler may return null. 495 // miss-handler may return null.
491 const Immediate& raw_null = 496 const Immediate& raw_null =
492 Immediate(reinterpret_cast<intptr_t>(Object::null())); 497 Immediate(reinterpret_cast<intptr_t>(Object::null()));
493 __ cmpl(EAX, raw_null); 498 __ cmpl(EAX, raw_null);
494 __ j(NOT_EQUAL, call_target_function); 499 __ j(NOT_EQUAL, call_target_function);
495 __ EnterStubFrame(); 500 __ EnterStubFrame();
496 // Load the receiver. 501 // Load the receiver.
497 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 502 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
498 __ movl(EAX, Address( 503 __ movl(EAX, Address(EBP, EDI, TIMES_HALF_WORD_SIZE,
499 EBP, EDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize)); 504 kParamEndSlotFromFp * kWordSize));
500 __ pushl(Immediate(0)); // Setup space on stack for result. 505 __ pushl(Immediate(0)); // Setup space on stack for result.
501 __ pushl(EAX); // Receiver. 506 __ pushl(EAX); // Receiver.
502 __ pushl(ECX); // ICData/MegamorphicCache. 507 __ pushl(ECX); // ICData/MegamorphicCache.
503 __ pushl(EDX); // Arguments descriptor array. 508 __ pushl(EDX); // Arguments descriptor array.
504 __ movl(EDX, EDI); 509 __ movl(EDX, EDI);
505 // EDX: Smi-tagged arguments array length. 510 // EDX: Smi-tagged arguments array length.
506 PushArgumentsArray(assembler); 511 PushArgumentsArray(assembler);
507 const intptr_t kNumArgs = 4; 512 const intptr_t kNumArgs = 4;
508 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); 513 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
509 __ Drop(4); 514 __ Drop(4);
510 __ popl(EAX); // Return value. 515 __ popl(EAX); // Return value.
511 __ LeaveFrame(); 516 __ LeaveFrame();
512 __ ret(); 517 __ ret();
513 } 518 }
514 519
515 520
516 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 521 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
517 __ EnterStubFrame(); 522 __ EnterStubFrame();
518 // Load the receiver into EAX. The argument count in the arguments 523 // Load the receiver into EAX. The argument count in the arguments
519 // descriptor in EDX is a smi. 524 // descriptor in EDX is a smi.
520 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 525 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
521 // Two words (saved fp, stub's pc marker) in the stack above the return 526 // Two words (saved fp, stub's pc marker) in the stack above the return
522 // address. 527 // address.
523 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); 528 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize));
524 // Preserve IC data and arguments descriptor. 529 // Preserve IC data and arguments descriptor.
525 __ pushl(ECX); 530 __ pushl(ECX);
526 __ pushl(EDX); 531 __ pushl(EDX);
527 532
528 __ pushl(Immediate(0)); // Space for the result of the runtime call. 533 __ pushl(Immediate(0)); // Space for the result of the runtime call.
529 __ pushl(EAX); // Pass receiver. 534 __ pushl(EAX); // Pass receiver.
530 __ pushl(ECX); // Pass IC data. 535 __ pushl(ECX); // Pass IC data.
531 __ pushl(EDX); // Pass arguments descriptor. 536 __ pushl(EDX); // Pass arguments descriptor.
532 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 537 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
533 // Discard arguments. 538 // Discard arguments.
534 __ popl(EAX); 539 __ popl(EAX);
535 __ popl(EAX); 540 __ popl(EAX);
536 __ popl(EAX); 541 __ popl(EAX);
537 __ popl(EAX); // Return value from the runtime call (function). 542 __ popl(EAX); // Return value from the runtime call (function).
538 __ popl(EDX); // Restore arguments descriptor. 543 __ popl(EDX); // Restore arguments descriptor.
539 __ popl(ECX); // Restore IC data. 544 __ popl(ECX); // Restore IC data.
540 __ LeaveFrame(); 545 __ LeaveFrame();
541 546
(...skipping 21 matching lines...) Expand all
563 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 568 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
564 // Assert that length is a Smi. 569 // Assert that length is a Smi.
565 __ testl(EDX, Immediate(kSmiTagMask)); 570 __ testl(EDX, Immediate(kSmiTagMask));
566 571
567 if (FLAG_use_slow_path) { 572 if (FLAG_use_slow_path) {
568 __ jmp(&slow_case); 573 __ jmp(&slow_case);
569 } else { 574 } else {
570 __ j(NOT_ZERO, &slow_case); 575 __ j(NOT_ZERO, &slow_case);
571 } 576 }
572 __ cmpl(EDX, Immediate(0)); 577 __ cmpl(EDX, Immediate(0));
573 __ j(LESS, &slow_case); 578 __ j(LESS, &slow_case);
574 579
575 // Check for maximum allowed length. 580 // Check for maximum allowed length.
576 const Immediate& max_len = 581 const Immediate& max_len =
577 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); 582 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)));
578 __ cmpl(EDX, max_len); 583 __ cmpl(EDX, max_len);
579 __ j(GREATER, &slow_case); 584 __ j(GREATER, &slow_case);
580 585
581 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid, 586 NOT_IN_PRODUCT(
582 EAX, 587 __ MaybeTraceAllocation(kArrayCid, EAX, &slow_case, Assembler::kFarJump));
583 &slow_case,
584 Assembler::kFarJump));
585 588
586 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 589 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
587 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. 590 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi.
588 ASSERT(kSmiTagShift == 1); 591 ASSERT(kSmiTagShift == 1);
589 __ andl(EBX, Immediate(-kObjectAlignment)); 592 __ andl(EBX, Immediate(-kObjectAlignment));
590 593
591 // ECX: array element type. 594 // ECX: array element type.
592 // EDX: array length as Smi. 595 // EDX: array length as Smi.
593 // EBX: allocation size. 596 // EBX: allocation size.
594 597
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 // Get the class index and insert it into the tags. 638 // Get the class index and insert it into the tags.
636 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid))); 639 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cid)));
637 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. 640 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags.
638 } 641 }
639 // EAX: new object start as a tagged pointer. 642 // EAX: new object start as a tagged pointer.
640 // EBX: allocation size. 643 // EBX: allocation size.
641 // ECX: array element type. 644 // ECX: array element type.
642 // EDX: Array length as Smi (preserved). 645 // EDX: Array length as Smi (preserved).
643 // Store the type argument field. 646 // Store the type argument field.
644 // No generetional barrier needed, since we store into a new object. 647 // No generetional barrier needed, since we store into a new object.
645 __ StoreIntoObjectNoBarrier(EAX, 648 __ StoreIntoObjectNoBarrier(
646 FieldAddress(EAX, Array::type_arguments_offset()), 649 EAX, FieldAddress(EAX, Array::type_arguments_offset()), ECX);
647 ECX);
648 650
649 // Set the length field. 651 // Set the length field.
650 __ StoreIntoObjectNoBarrier(EAX, 652 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, Array::length_offset()),
651 FieldAddress(EAX, Array::length_offset()),
652 EDX); 653 EDX);
653 654
654 // Initialize all array elements to raw_null. 655 // Initialize all array elements to raw_null.
655 // EAX: new object start as a tagged pointer. 656 // EAX: new object start as a tagged pointer.
656 // EBX: allocation size. 657 // EBX: allocation size.
657 // EDI: iterator which initially points to the start of the variable 658 // EDI: iterator which initially points to the start of the variable
658 // data area to be initialized. 659 // data area to be initialized.
659 // ECX: array element type. 660 // ECX: array element type.
660 // EDX: array length as Smi. 661 // EDX: array length as Smi.
661 __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0)); 662 __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0));
(...skipping 10 matching lines...) Expand all
672 __ Bind(&done); 673 __ Bind(&done);
673 __ ret(); // returns the newly allocated object in EAX. 674 __ ret(); // returns the newly allocated object in EAX.
674 675
675 // Unable to allocate the array using the fast inline code, just call 676 // Unable to allocate the array using the fast inline code, just call
676 // into the runtime. 677 // into the runtime.
677 __ Bind(&slow_case); 678 __ Bind(&slow_case);
678 // Create a stub frame as we are pushing some objects on the stack before 679 // Create a stub frame as we are pushing some objects on the stack before
679 // calling into the runtime. 680 // calling into the runtime.
680 __ EnterStubFrame(); 681 __ EnterStubFrame();
681 __ pushl(Immediate(0)); // Setup space on stack for return value. 682 __ pushl(Immediate(0)); // Setup space on stack for return value.
682 __ pushl(EDX); // Array length as Smi. 683 __ pushl(EDX); // Array length as Smi.
683 __ pushl(ECX); // Element type. 684 __ pushl(ECX); // Element type.
684 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 685 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
685 __ popl(EAX); // Pop element type argument. 686 __ popl(EAX); // Pop element type argument.
686 __ popl(EDX); // Pop array length argument (preserved). 687 __ popl(EDX); // Pop array length argument (preserved).
687 __ popl(EAX); // Pop return value from return slot. 688 __ popl(EAX); // Pop return value from return slot.
688 __ LeaveFrame(); 689 __ LeaveFrame();
689 __ ret(); 690 __ ret();
690 } 691 }
691 692
692 693
693 // Called when invoking dart code from C++ (VM code). 694 // Called when invoking dart code from C++ (VM code).
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 // EBX and EDX are destroyed. 808 // EBX and EDX are destroyed.
808 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 809 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
809 if (FLAG_inline_alloc) { 810 if (FLAG_inline_alloc) {
810 Label slow_case; 811 Label slow_case;
811 // First compute the rounded instance size. 812 // First compute the rounded instance size.
812 // EDX: number of context variables. 813 // EDX: number of context variables.
813 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); 814 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
814 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); 815 __ leal(EBX, Address(EDX, TIMES_4, fixed_size));
815 __ andl(EBX, Immediate(-kObjectAlignment)); 816 __ andl(EBX, Immediate(-kObjectAlignment));
816 817
817 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, 818 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, EAX, &slow_case,
818 EAX,
819 &slow_case,
820 Assembler::kFarJump)); 819 Assembler::kFarJump));
821 820
822 // Now allocate the object. 821 // Now allocate the object.
823 // EDX: number of context variables. 822 // EDX: number of context variables.
824 const intptr_t cid = kContextCid; 823 const intptr_t cid = kContextCid;
825 Heap::Space space = Heap::kNew; 824 Heap::Space space = Heap::kNew;
826 __ movl(ECX, Address(THR, Thread::heap_offset())); 825 __ movl(ECX, Address(THR, Thread::heap_offset()));
827 __ movl(EAX, Address(ECX, Heap::TopOffset(space))); 826 __ movl(EAX, Address(ECX, Heap::TopOffset(space)));
828 __ addl(EBX, EAX); 827 __ addl(EBX, EAX);
829 // Check if the allocation fits into the remaining space. 828 // Check if the allocation fits into the remaining space.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 __ jmp(&done); 866 __ jmp(&done);
868 867
869 __ Bind(&size_tag_overflow); 868 __ Bind(&size_tag_overflow);
870 // Set overflow size tag value. 869 // Set overflow size tag value.
871 __ movl(EBX, Immediate(0)); 870 __ movl(EBX, Immediate(0));
872 871
873 __ Bind(&done); 872 __ Bind(&done);
874 // EAX: new object. 873 // EAX: new object.
875 // EDX: number of context variables. 874 // EDX: number of context variables.
876 // EBX: size and bit tags. 875 // EBX: size and bit tags.
877 __ orl(EBX, 876 __ orl(EBX, Immediate(RawObject::ClassIdTag::encode(cid)));
878 Immediate(RawObject::ClassIdTag::encode(cid)));
879 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags. 877 __ movl(FieldAddress(EAX, Context::tags_offset()), EBX); // Tags.
880 } 878 }
881 879
882 // Setup up number of context variables field. 880 // Setup up number of context variables field.
883 // EAX: new object. 881 // EAX: new object.
884 // EDX: number of context variables as integer value (not object). 882 // EDX: number of context variables as integer value (not object).
885 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX); 883 __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX);
886 884
887 // Setup the parent field. 885 // Setup the parent field.
888 // EAX: new object. 886 // EAX: new object.
889 // EDX: number of context variables. 887 // EDX: number of context variables.
890 // No generational barrier needed, since we are storing null. 888 // No generational barrier needed, since we are storing null.
891 __ StoreIntoObjectNoBarrier(EAX, 889 __ StoreIntoObjectNoBarrier(EAX,
892 FieldAddress(EAX, Context::parent_offset()), 890 FieldAddress(EAX, Context::parent_offset()),
893 Object::null_object()); 891 Object::null_object());
894 892
895 // Initialize the context variables. 893 // Initialize the context variables.
896 // EAX: new object. 894 // EAX: new object.
897 // EDX: number of context variables. 895 // EDX: number of context variables.
898 { 896 {
899 Label loop, entry; 897 Label loop, entry;
900 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0))); 898 __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0)));
901 899
902 __ jmp(&entry, Assembler::kNearJump); 900 __ jmp(&entry, Assembler::kNearJump);
903 __ Bind(&loop); 901 __ Bind(&loop);
904 __ decl(EDX); 902 __ decl(EDX);
905 // No generational barrier needed, since we are storing null. 903 // No generational barrier needed, since we are storing null.
906 __ StoreIntoObjectNoBarrier(EAX, 904 __ StoreIntoObjectNoBarrier(EAX, Address(EBX, EDX, TIMES_4, 0),
907 Address(EBX, EDX, TIMES_4, 0),
908 Object::null_object()); 905 Object::null_object());
909 __ Bind(&entry); 906 __ Bind(&entry);
910 __ cmpl(EDX, Immediate(0)); 907 __ cmpl(EDX, Immediate(0));
911 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 908 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
912 } 909 }
913 910
914 // Done allocating and initializing the context. 911 // Done allocating and initializing the context.
915 // EAX: new object. 912 // EAX: new object.
916 __ ret(); 913 __ ret();
917 914
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 } 998 }
1002 999
1003 1000
1004 // Called for inline allocation of objects. 1001 // Called for inline allocation of objects.
1005 // Input parameters: 1002 // Input parameters:
1006 // ESP + 4 : type arguments object (only if class is parameterized). 1003 // ESP + 4 : type arguments object (only if class is parameterized).
1007 // ESP : points to return address. 1004 // ESP : points to return address.
1008 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers. 1005 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers.
1009 // Returns patch_code_pc offset where patching code for disabling the stub 1006 // Returns patch_code_pc offset where patching code for disabling the stub
1010 // has been generated (similar to regularly generated Dart code). 1007 // has been generated (similar to regularly generated Dart code).
1011 void StubCode::GenerateAllocationStubForClass( 1008 void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
1012 Assembler* assembler, const Class& cls) { 1009 const Class& cls) {
1013 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; 1010 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
1014 const Immediate& raw_null = 1011 const Immediate& raw_null =
1015 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1012 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1016 // The generated code is different if the class is parameterized. 1013 // The generated code is different if the class is parameterized.
1017 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1014 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1018 ASSERT(!is_cls_parameterized || 1015 ASSERT(!is_cls_parameterized ||
1019 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1016 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1020 // kInlineInstanceSize is a constant used as a threshold for determining 1017 // kInlineInstanceSize is a constant used as a threshold for determining
1021 // when the object initialization should be done as a loop or as 1018 // when the object initialization should be done as a loop or as
1022 // straight line code. 1019 // straight line code.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 // Initialize the remaining words of the object. 1062 // Initialize the remaining words of the object.
1066 1063
1067 // EAX: new object (tagged). 1064 // EAX: new object (tagged).
1068 // EBX: next object start. 1065 // EBX: next object start.
1069 // EDX: new object type arguments (if is_cls_parameterized). 1066 // EDX: new object type arguments (if is_cls_parameterized).
1070 // First try inlining the initialization without a loop. 1067 // First try inlining the initialization without a loop.
1071 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1068 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1072 // Check if the object contains any non-header fields. 1069 // Check if the object contains any non-header fields.
1073 // Small objects are initialized using a consecutive set of writes. 1070 // Small objects are initialized using a consecutive set of writes.
1074 for (intptr_t current_offset = Instance::NextFieldOffset(); 1071 for (intptr_t current_offset = Instance::NextFieldOffset();
1075 current_offset < instance_size; 1072 current_offset < instance_size; current_offset += kWordSize) {
1076 current_offset += kWordSize) { 1073 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, current_offset),
1077 __ StoreIntoObjectNoBarrier(EAX,
1078 FieldAddress(EAX, current_offset),
1079 Object::null_object()); 1074 Object::null_object());
1080 } 1075 }
1081 } else { 1076 } else {
1082 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset())); 1077 __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset()));
1083 // Loop until the whole object is initialized. 1078 // Loop until the whole object is initialized.
1084 // EAX: new object (tagged). 1079 // EAX: new object (tagged).
1085 // EBX: next object start. 1080 // EBX: next object start.
1086 // ECX: next word to be initialized. 1081 // ECX: next word to be initialized.
1087 // EDX: new object type arguments (if is_cls_parameterized). 1082 // EDX: new object type arguments (if is_cls_parameterized).
1088 Label init_loop; 1083 Label init_loop;
1089 Label done; 1084 Label done;
1090 __ Bind(&init_loop); 1085 __ Bind(&init_loop);
1091 __ cmpl(ECX, EBX); 1086 __ cmpl(ECX, EBX);
1092 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 1087 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
1093 __ StoreIntoObjectNoBarrier(EAX, 1088 __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), Object::null_object());
1094 Address(ECX, 0),
1095 Object::null_object());
1096 __ addl(ECX, Immediate(kWordSize)); 1089 __ addl(ECX, Immediate(kWordSize));
1097 __ jmp(&init_loop, Assembler::kNearJump); 1090 __ jmp(&init_loop, Assembler::kNearJump);
1098 __ Bind(&done); 1091 __ Bind(&done);
1099 } 1092 }
1100 if (is_cls_parameterized) { 1093 if (is_cls_parameterized) {
1101 // EAX: new object (tagged). 1094 // EAX: new object (tagged).
1102 // EDX: new object type arguments. 1095 // EDX: new object type arguments.
1103 // Set the type arguments in the new object. 1096 // Set the type arguments in the new object.
1104 intptr_t offset = cls.type_arguments_field_offset(); 1097 intptr_t offset = cls.type_arguments_field_offset();
1105 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX); 1098 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 // EDX : arguments descriptor array. 1135 // EDX : arguments descriptor array.
1143 // Uses EAX, EBX, EDI as temporary registers. 1136 // Uses EAX, EBX, EDI as temporary registers.
1144 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { 1137 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
1145 __ EnterStubFrame(); 1138 __ EnterStubFrame();
1146 1139
1147 // Load the receiver. 1140 // Load the receiver.
1148 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 1141 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
1149 __ movl(EAX, Address(EBP, EDI, TIMES_2, kParamEndSlotFromFp * kWordSize)); 1142 __ movl(EAX, Address(EBP, EDI, TIMES_2, kParamEndSlotFromFp * kWordSize));
1150 1143
1151 __ pushl(Immediate(0)); // Setup space on stack for result from noSuchMethod. 1144 __ pushl(Immediate(0)); // Setup space on stack for result from noSuchMethod.
1152 __ pushl(EAX); // Receiver. 1145 __ pushl(EAX); // Receiver.
1153 __ pushl(EDX); // Arguments descriptor array. 1146 __ pushl(EDX); // Arguments descriptor array.
1154 1147
1155 __ movl(EDX, EDI); 1148 __ movl(EDX, EDI);
1156 // EDX: Smi-tagged arguments array length. 1149 // EDX: Smi-tagged arguments array length.
1157 PushArgumentsArray(assembler); 1150 PushArgumentsArray(assembler);
1158 1151
1159 const intptr_t kNumArgs = 3; 1152 const intptr_t kNumArgs = 3;
1160 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); 1153 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
1161 // noSuchMethod on closures always throws an error, so it will never return. 1154 // noSuchMethod on closures always throws an error, so it will never return.
1162 __ int3(); 1155 __ int3();
1163 } 1156 }
1164 1157
1165 1158
1166 // Cannot use function object from ICData as it may be the inlined 1159 // Cannot use function object from ICData as it may be the inlined
1167 // function and not the top-scope function. 1160 // function and not the top-scope function.
1168 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1161 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1169 Register ic_reg = ECX; 1162 Register ic_reg = ECX;
1170 Register func_reg = EBX; 1163 Register func_reg = EBX;
1171 if (FLAG_trace_optimized_ic_calls) { 1164 if (FLAG_trace_optimized_ic_calls) {
1172 __ EnterStubFrame(); 1165 __ EnterStubFrame();
1173 __ pushl(func_reg); // Preserve 1166 __ pushl(func_reg); // Preserve
1174 __ pushl(ic_reg); // Preserve. 1167 __ pushl(ic_reg); // Preserve.
1175 __ pushl(ic_reg); // Argument. 1168 __ pushl(ic_reg); // Argument.
1176 __ pushl(func_reg); // Argument. 1169 __ pushl(func_reg); // Argument.
1177 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1170 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1178 __ popl(EAX); // Discard argument; 1171 __ popl(EAX); // Discard argument;
1179 __ popl(EAX); // Discard argument; 1172 __ popl(EAX); // Discard argument;
1180 __ popl(ic_reg); // Restore. 1173 __ popl(ic_reg); // Restore.
1181 __ popl(func_reg); // Restore. 1174 __ popl(func_reg); // Restore.
1182 __ LeaveFrame(); 1175 __ LeaveFrame();
1183 } 1176 }
1184 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); 1177 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1185 } 1178 }
1186 1179
1187 1180
1188 // Loads function into 'temp_reg'. 1181 // Loads function into 'temp_reg'.
1189 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1182 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1190 Register temp_reg) { 1183 Register temp_reg) {
1191 if (FLAG_optimization_counter_threshold >= 0) { 1184 if (FLAG_optimization_counter_threshold >= 0) {
(...skipping 10 matching lines...) Expand all
1202 // Note: ECX must be preserved. 1195 // Note: ECX must be preserved.
1203 // Attempt a quick Smi operation for known operations ('kind'). The ICData 1196 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1204 // must have been primed with a Smi/Smi check that will be used for counting 1197 // must have been primed with a Smi/Smi check that will be used for counting
1205 // the invocations. 1198 // the invocations.
1206 static void EmitFastSmiOp(Assembler* assembler, 1199 static void EmitFastSmiOp(Assembler* assembler,
1207 Token::Kind kind, 1200 Token::Kind kind,
1208 intptr_t num_args, 1201 intptr_t num_args,
1209 Label* not_smi_or_overflow) { 1202 Label* not_smi_or_overflow) {
1210 __ Comment("Fast Smi op"); 1203 __ Comment("Fast Smi op");
1211 ASSERT(num_args == 2); 1204 ASSERT(num_args == 2);
1212 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Right 1205 __ movl(EDI, Address(ESP, +1 * kWordSize)); // Right
1213 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left 1206 __ movl(EAX, Address(ESP, +2 * kWordSize)); // Left
1214 __ movl(EBX, EDI); 1207 __ movl(EBX, EDI);
1215 __ orl(EBX, EAX); 1208 __ orl(EBX, EAX);
1216 __ testl(EBX, Immediate(kSmiTagMask)); 1209 __ testl(EBX, Immediate(kSmiTagMask));
1217 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump); 1210 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump);
1218 switch (kind) { 1211 switch (kind) {
1219 case Token::kADD: { 1212 case Token::kADD: {
1220 __ addl(EAX, EDI); 1213 __ addl(EAX, EDI);
1221 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump); 1214 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump);
1222 break; 1215 break;
1223 } 1216 }
(...skipping 12 matching lines...) Expand all
1236 Label done, is_true; 1229 Label done, is_true;
1237 __ cmpl(EAX, EDI); 1230 __ cmpl(EAX, EDI);
1238 __ j(EQUAL, &is_true, Assembler::kNearJump); 1231 __ j(EQUAL, &is_true, Assembler::kNearJump);
1239 __ LoadObject(EAX, Bool::False()); 1232 __ LoadObject(EAX, Bool::False());
1240 __ jmp(&done, Assembler::kNearJump); 1233 __ jmp(&done, Assembler::kNearJump);
1241 __ Bind(&is_true); 1234 __ Bind(&is_true);
1242 __ LoadObject(EAX, Bool::True()); 1235 __ LoadObject(EAX, Bool::True());
1243 __ Bind(&done); 1236 __ Bind(&done);
1244 break; 1237 break;
1245 } 1238 }
1246 default: UNIMPLEMENTED(); 1239 default:
1240 UNIMPLEMENTED();
1247 } 1241 }
1248 1242
1249 // ECX: IC data object. 1243 // ECX: IC data object.
1250 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); 1244 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
1251 // EBX: ic_data_array with check entries: classes and target functions. 1245 // EBX: ic_data_array with check entries: classes and target functions.
1252 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); 1246 __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
1253 #if defined(DEBUG) 1247 #if defined(DEBUG)
1254 // Check that first entry is for Smi/Smi. 1248 // Check that first entry is for Smi/Smi.
1255 Label error, ok; 1249 Label error, ok;
1256 const Immediate& imm_smi_cid = 1250 const Immediate& imm_smi_cid =
(...skipping 30 matching lines...) Expand all
1287 // - Match found -> jump to target. 1281 // - Match found -> jump to target.
1288 // - Match not found -> jump to IC miss. 1282 // - Match not found -> jump to IC miss.
1289 void StubCode::GenerateNArgsCheckInlineCacheStub( 1283 void StubCode::GenerateNArgsCheckInlineCacheStub(
1290 Assembler* assembler, 1284 Assembler* assembler,
1291 intptr_t num_args, 1285 intptr_t num_args,
1292 const RuntimeEntry& handle_ic_miss, 1286 const RuntimeEntry& handle_ic_miss,
1293 Token::Kind kind, 1287 Token::Kind kind,
1294 bool optimized) { 1288 bool optimized) {
1295 ASSERT(num_args > 0); 1289 ASSERT(num_args > 0);
1296 #if defined(DEBUG) 1290 #if defined(DEBUG)
1297 { Label ok; 1291 {
1292 Label ok;
1298 // Check that the IC data array has NumArgsTested() == num_args. 1293 // Check that the IC data array has NumArgsTested() == num_args.
1299 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1294 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1300 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); 1295 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset()));
1301 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1296 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1302 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); 1297 __ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
1303 __ cmpl(EBX, Immediate(num_args)); 1298 __ cmpl(EBX, Immediate(num_args));
1304 __ j(EQUAL, &ok, Assembler::kNearJump); 1299 __ j(EQUAL, &ok, Assembler::kNearJump);
1305 __ Stop("Incorrect stub for IC data"); 1300 __ Stop("Incorrect stub for IC data");
1306 __ Bind(&ok); 1301 __ Bind(&ok);
1307 } 1302 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check. 1337 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check.
1343 Label loop, update, test, found; 1338 Label loop, update, test, found;
1344 __ jmp(&test); 1339 __ jmp(&test);
1345 1340
1346 __ Comment("ICData loop"); 1341 __ Comment("ICData loop");
1347 __ Bind(&loop); 1342 __ Bind(&loop);
1348 for (int i = 0; i < num_args; i++) { 1343 for (int i = 0; i < num_args; i++) {
1349 if (i > 0) { 1344 if (i > 0) {
1350 // If not the first, load the next argument's class ID. 1345 // If not the first, load the next argument's class ID.
1351 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 1346 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
1352 __ movl(EDI, Address(ESP, EAX, TIMES_2, - i * kWordSize)); 1347 __ movl(EDI, Address(ESP, EAX, TIMES_2, -i * kWordSize));
1353 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); 1348 __ LoadTaggedClassIdMayBeSmi(EAX, EDI);
1354 1349
1355 // EAX: next argument class ID (smi). 1350 // EAX: next argument class ID (smi).
1356 __ movl(EDI, Address(EBX, i * kWordSize)); 1351 __ movl(EDI, Address(EBX, i * kWordSize));
1357 // EDI: next class ID to check (smi). 1352 // EDI: next class ID to check (smi).
1358 } 1353 }
1359 __ cmpl(EAX, EDI); // Class id match? 1354 __ cmpl(EAX, EDI); // Class id match?
1360 if (i < (num_args - 1)) { 1355 if (i < (num_args - 1)) {
1361 __ j(NOT_EQUAL, &update); // Continue. 1356 __ j(NOT_EQUAL, &update); // Continue.
1362 } else { 1357 } else {
1363 // Last check, all checks before matched. 1358 // Last check, all checks before matched.
1364 __ j(EQUAL, &found); // Break. 1359 __ j(EQUAL, &found); // Break.
1365 } 1360 }
1366 } 1361 }
1367 __ Bind(&update); 1362 __ Bind(&update);
1368 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1363 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1369 if (num_args > 1) { 1364 if (num_args > 1) {
1370 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 1365 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
1371 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); 1366 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0));
1372 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); 1367 __ LoadTaggedClassIdMayBeSmi(EAX, EDI);
1373 } 1368 }
1374 1369
1375 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1370 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1376 __ addl(EBX, Immediate(entry_size)); // Next entry. 1371 __ addl(EBX, Immediate(entry_size)); // Next entry.
1377 __ movl(EDI, Address(EBX, 0)); // Next class ID. 1372 __ movl(EDI, Address(EBX, 0)); // Next class ID.
1378 1373
1379 __ Bind(&test); 1374 __ Bind(&test);
1380 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1375 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1381 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1376 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1382 1377
1383 __ Comment("IC miss"); 1378 __ Comment("IC miss");
1384 // Compute address of arguments (first read number of arguments from 1379 // Compute address of arguments (first read number of arguments from
1385 // arguments descriptor array and then compute address on the stack). 1380 // arguments descriptor array and then compute address on the stack).
1386 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 1381 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
1387 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. 1382 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi.
1388 // Create a stub frame as we are pushing some objects on the stack before 1383 // Create a stub frame as we are pushing some objects on the stack before
1389 // calling into the runtime. 1384 // calling into the runtime.
1390 __ EnterStubFrame(); 1385 __ EnterStubFrame();
1391 __ pushl(EDX); // Preserve arguments descriptor array. 1386 __ pushl(EDX); // Preserve arguments descriptor array.
1392 __ pushl(ECX); // Preserve IC data object. 1387 __ pushl(ECX); // Preserve IC data object.
1393 __ pushl(Immediate(0)); // Result slot. 1388 __ pushl(Immediate(0)); // Result slot.
1394 // Push call arguments. 1389 // Push call arguments.
1395 for (intptr_t i = 0; i < num_args; i++) { 1390 for (intptr_t i = 0; i < num_args; i++) {
1396 __ movl(EBX, Address(EAX, -kWordSize * i)); 1391 __ movl(EBX, Address(EAX, -kWordSize * i));
1397 __ pushl(EBX); 1392 __ pushl(EBX);
1398 } 1393 }
1399 __ pushl(ECX); // Pass IC data object. 1394 __ pushl(ECX); // Pass IC data object.
1400 __ CallRuntime(handle_ic_miss, num_args + 1); 1395 __ CallRuntime(handle_ic_miss, num_args + 1);
1401 // Remove the call arguments pushed earlier, including the IC data object. 1396 // Remove the call arguments pushed earlier, including the IC data object.
1402 for (intptr_t i = 0; i < num_args + 1; i++) { 1397 for (intptr_t i = 0; i < num_args + 1; i++) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 // ECX: Inline cache data object. 1446 // ECX: Inline cache data object.
1452 // TOS(0): Return address. 1447 // TOS(0): Return address.
1453 // Inline cache data object structure: 1448 // Inline cache data object structure:
1454 // 0: function-name 1449 // 0: function-name
1455 // 1: N, number of arguments checked. 1450 // 1: N, number of arguments checked.
1456 // 2 .. (length - 1): group of checks, each check containing: 1451 // 2 .. (length - 1): group of checks, each check containing:
1457 // - N classes. 1452 // - N classes.
1458 // - 1 target function. 1453 // - 1 target function.
1459 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1454 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1460 GenerateUsageCounterIncrement(assembler, EBX); 1455 GenerateUsageCounterIncrement(assembler, EBX);
1461 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1456 GenerateNArgsCheckInlineCacheStub(
1462 kInlineCacheMissHandlerOneArgRuntimeEntry, 1457 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1463 Token::kILLEGAL);
1464 } 1458 }
1465 1459
1466 1460
1467 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1461 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1468 GenerateUsageCounterIncrement(assembler, EBX); 1462 GenerateUsageCounterIncrement(assembler, EBX);
1469 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1463 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1470 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1464 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1471 Token::kILLEGAL); 1465 Token::kILLEGAL);
1472 } 1466 }
1473 1467
1474 1468
1475 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { 1469 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1476 GenerateUsageCounterIncrement(assembler, EBX); 1470 GenerateUsageCounterIncrement(assembler, EBX);
1477 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1471 GenerateNArgsCheckInlineCacheStub(
1478 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1472 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1479 Token::kADD);
1480 } 1473 }
1481 1474
1482 1475
1483 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { 1476 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1484 GenerateUsageCounterIncrement(assembler, EBX); 1477 GenerateUsageCounterIncrement(assembler, EBX);
1485 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1478 GenerateNArgsCheckInlineCacheStub(
1486 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1479 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1487 Token::kSUB);
1488 } 1480 }
1489 1481
1490 1482
1491 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { 1483 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1492 GenerateUsageCounterIncrement(assembler, EBX); 1484 GenerateUsageCounterIncrement(assembler, EBX);
1493 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1485 GenerateNArgsCheckInlineCacheStub(
1494 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1486 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1495 Token::kEQ);
1496 } 1487 }
1497 1488
1498 1489
1499 // Use inline cache data array to invoke the target or continue in inline 1490 // Use inline cache data array to invoke the target or continue in inline
1500 // cache miss handler. Stub for 1-argument check (receiver class). 1491 // cache miss handler. Stub for 1-argument check (receiver class).
1501 // EDI: function which counter needs to be incremented. 1492 // EDI: function which counter needs to be incremented.
1502 // ECX: Inline cache data object. 1493 // ECX: Inline cache data object.
1503 // TOS(0): Return address. 1494 // TOS(0): Return address.
1504 // Inline cache data object structure: 1495 // Inline cache data object structure:
1505 // 0: function-name 1496 // 0: function-name
1506 // 1: N, number of arguments checked. 1497 // 1: N, number of arguments checked.
1507 // 2 .. (length - 1): group of checks, each check containing: 1498 // 2 .. (length - 1): group of checks, each check containing:
1508 // - N classes. 1499 // - N classes.
1509 // - 1 target function. 1500 // - 1 target function.
1510 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1501 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1511 Assembler* assembler) { 1502 Assembler* assembler) {
1512 GenerateOptimizedUsageCounterIncrement(assembler); 1503 GenerateOptimizedUsageCounterIncrement(assembler);
1513 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1504 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1514 kInlineCacheMissHandlerOneArgRuntimeEntry, 1505 kInlineCacheMissHandlerOneArgRuntimeEntry,
1515 Token::kILLEGAL, 1506 Token::kILLEGAL, true /* optimized */);
1516 true /* optimized */);
1517 } 1507 }
1518 1508
1519 1509
1520 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1510 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1521 Assembler* assembler) { 1511 Assembler* assembler) {
1522 GenerateOptimizedUsageCounterIncrement(assembler); 1512 GenerateOptimizedUsageCounterIncrement(assembler);
1523 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1513 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1524 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1514 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1525 Token::kILLEGAL, 1515 Token::kILLEGAL, true /* optimized */);
1526 true /* optimized */);
1527 } 1516 }
1528 1517
1529 1518
1530 // Intermediary stub between a static call and its target. ICData contains 1519 // Intermediary stub between a static call and its target. ICData contains
1531 // the target function and the call count. 1520 // the target function and the call count.
1532 // ECX: ICData 1521 // ECX: ICData
1533 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1522 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1534 GenerateUsageCounterIncrement(assembler, EBX); 1523 GenerateUsageCounterIncrement(assembler, EBX);
1535 1524
1536 #if defined(DEBUG) 1525 #if defined(DEBUG)
1537 { Label ok; 1526 {
1527 Label ok;
1538 // Check that the IC data array has NumArgsTested() == num_args. 1528 // Check that the IC data array has NumArgsTested() == num_args.
1539 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1529 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1540 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); 1530 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset()));
1541 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1531 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1542 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); 1532 __ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
1543 __ cmpl(EBX, Immediate(0)); 1533 __ cmpl(EBX, Immediate(0));
1544 __ j(EQUAL, &ok, Assembler::kNearJump); 1534 __ j(EQUAL, &ok, Assembler::kNearJump);
1545 __ Stop("Incorrect IC data for unoptimized static call"); 1535 __ Stop("Incorrect IC data for unoptimized static call");
1546 __ Bind(&ok); 1536 __ Bind(&ok);
1547 } 1537 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1588 __ popl(ECX); 1578 __ popl(ECX);
1589 __ LeaveFrame(); 1579 __ LeaveFrame();
1590 __ jmp(&done_stepping, Assembler::kNearJump); 1580 __ jmp(&done_stepping, Assembler::kNearJump);
1591 } 1581 }
1592 } 1582 }
1593 1583
1594 1584
1595 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1585 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1596 GenerateUsageCounterIncrement(assembler, EBX); 1586 GenerateUsageCounterIncrement(assembler, EBX);
1597 GenerateNArgsCheckInlineCacheStub( 1587 GenerateNArgsCheckInlineCacheStub(
1598 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, 1588 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1599 Token::kILLEGAL);
1600 } 1589 }
1601 1590
1602 1591
1603 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1592 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1604 GenerateUsageCounterIncrement(assembler, EBX); 1593 GenerateUsageCounterIncrement(assembler, EBX);
1605 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1594 GenerateNArgsCheckInlineCacheStub(
1606 kStaticCallMissHandlerTwoArgsRuntimeEntry, 1595 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1607 Token::kILLEGAL);
1608 } 1596 }
1609 1597
1610 1598
1611 // Stub for compiling a function and jumping to the compiled code. 1599 // Stub for compiling a function and jumping to the compiled code.
1612 // ECX: IC-Data (for methods). 1600 // ECX: IC-Data (for methods).
1613 // EDX: Arguments descriptor. 1601 // EDX: Arguments descriptor.
1614 // EAX: Function. 1602 // EAX: Function.
1615 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1603 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1616 __ EnterStubFrame(); 1604 __ EnterStubFrame();
1617 __ pushl(EDX); // Preserve arguments descriptor array. 1605 __ pushl(EDX); // Preserve arguments descriptor array.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1680 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1693 const Immediate& raw_null = 1681 const Immediate& raw_null =
1694 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1682 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1695 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); 1683 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes));
1696 if (n > 1) { 1684 if (n > 1) {
1697 // Get instance type arguments. 1685 // Get instance type arguments.
1698 __ LoadClass(ECX, EAX, EBX); 1686 __ LoadClass(ECX, EAX, EBX);
1699 // Compute instance type arguments into EBX. 1687 // Compute instance type arguments into EBX.
1700 Label has_no_type_arguments; 1688 Label has_no_type_arguments;
1701 __ movl(EBX, raw_null); 1689 __ movl(EBX, raw_null);
1702 __ movl(EDI, FieldAddress(ECX, 1690 __ movl(EDI,
1703 Class::type_arguments_field_offset_in_words_offset())); 1691 FieldAddress(ECX,
1692 Class::type_arguments_field_offset_in_words_offset()));
1704 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); 1693 __ cmpl(EDI, Immediate(Class::kNoTypeArguments));
1705 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1694 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
1706 __ movl(EBX, FieldAddress(EAX, EDI, TIMES_4, 0)); 1695 __ movl(EBX, FieldAddress(EAX, EDI, TIMES_4, 0));
1707 __ Bind(&has_no_type_arguments); 1696 __ Bind(&has_no_type_arguments);
1708 } 1697 }
1709 __ LoadClassId(ECX, EAX); 1698 __ LoadClassId(ECX, EAX);
1710 // EAX: instance, ECX: instance class id. 1699 // EAX: instance, ECX: instance class id.
1711 // EBX: instance type arguments (null if none), used only if n > 1. 1700 // EBX: instance type arguments (null if none), used only if n > 1.
1712 __ movl(EDX, Address(ESP, kCacheOffsetInBytes)); 1701 __ movl(EDX, Address(ESP, kCacheOffsetInBytes));
1713 // EDX: SubtypeTestCache. 1702 // EDX: SubtypeTestCache.
1714 __ movl(EDX, FieldAddress(EDX, SubtypeTestCache::cache_offset())); 1703 __ movl(EDX, FieldAddress(EDX, SubtypeTestCache::cache_offset()));
1715 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1704 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
1716 1705
1717 Label loop, found, not_found, next_iteration; 1706 Label loop, found, not_found, next_iteration;
1718 // EDX: Entry start. 1707 // EDX: Entry start.
1719 // ECX: instance class id. 1708 // ECX: instance class id.
1720 // EBX: instance type arguments. 1709 // EBX: instance type arguments.
1721 __ SmiTag(ECX); 1710 __ SmiTag(ECX);
1722 __ cmpl(ECX, Immediate(Smi::RawValue(kClosureCid))); 1711 __ cmpl(ECX, Immediate(Smi::RawValue(kClosureCid)));
1723 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1712 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1724 __ movl(ECX, FieldAddress(EAX, Closure::function_offset())); 1713 __ movl(ECX, FieldAddress(EAX, Closure::function_offset()));
1725 // ECX: instance class id as Smi or function. 1714 // ECX: instance class id as Smi or function.
1726 __ Bind(&loop); 1715 __ Bind(&loop);
1727 __ movl(EDI, 1716 __ movl(EDI, Address(EDX, kWordSize *
1728 Address(EDX, 1717 SubtypeTestCache::kInstanceClassIdOrFunction));
1729 kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
1730 __ cmpl(EDI, raw_null); 1718 __ cmpl(EDI, raw_null);
1731 __ j(EQUAL, &not_found, Assembler::kNearJump); 1719 __ j(EQUAL, &not_found, Assembler::kNearJump);
1732 __ cmpl(EDI, ECX); 1720 __ cmpl(EDI, ECX);
1733 if (n == 1) { 1721 if (n == 1) {
1734 __ j(EQUAL, &found, Assembler::kNearJump); 1722 __ j(EQUAL, &found, Assembler::kNearJump);
1735 } else { 1723 } else {
1736 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1724 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1737 __ movl(EDI, 1725 __ movl(EDI,
1738 Address(EDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1726 Address(EDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1739 __ cmpl(EDI, EBX); 1727 __ cmpl(EDI, EBX);
1740 if (n == 2) { 1728 if (n == 2) {
1741 __ j(EQUAL, &found, Assembler::kNearJump); 1729 __ j(EQUAL, &found, Assembler::kNearJump);
1742 } else { 1730 } else {
1743 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1731 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1744 __ movl(EDI, 1732 __ movl(EDI,
1745 Address(EDX, kWordSize * 1733 Address(EDX, kWordSize *
1746 SubtypeTestCache::kInstantiatorTypeArguments)); 1734 SubtypeTestCache::kInstantiatorTypeArguments));
1747 __ cmpl(EDI, Address(ESP, kInstantiatorTypeArgumentsInBytes)); 1735 __ cmpl(EDI, Address(ESP, kInstantiatorTypeArgumentsInBytes));
1748 __ j(EQUAL, &found, Assembler::kNearJump); 1736 __ j(EQUAL, &found, Assembler::kNearJump);
1749 } 1737 }
1750 } 1738 }
1751 __ Bind(&next_iteration); 1739 __ Bind(&next_iteration);
1752 __ addl(EDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1740 __ addl(EDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1753 __ jmp(&loop, Assembler::kNearJump); 1741 __ jmp(&loop, Assembler::kNearJump);
1754 // Fall through to not found. 1742 // Fall through to not found.
1755 __ Bind(&not_found); 1743 __ Bind(&not_found);
1756 __ movl(ECX, raw_null); 1744 __ movl(ECX, raw_null);
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
2065 } 2053 }
2066 2054
2067 2055
2068 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2056 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2069 __ int3(); 2057 __ int3();
2070 } 2058 }
2071 2059
2072 } // namespace dart 2060 } // namespace dart
2073 2061
2074 #endif // defined TARGET_ARCH_IA32 2062 #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