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

Side by Side Diff: runtime/vm/stub_code_x64.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_mips_test.cc ('k') | runtime/vm/stub_code_x64_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_X64) 6 #if defined(TARGET_ARCH_X64)
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/heap.h"
13 #include "vm/instructions.h" 13 #include "vm/instructions.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 #define __ assembler-> 21 #define __ assembler->
22 22
23 namespace dart { 23 namespace dart {
24 24
25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
26 DEFINE_FLAG(bool, use_slow_path, false, 26 DEFINE_FLAG(bool,
27 "Set to true for debugging & verifying the slow paths."); 27 use_slow_path,
28 false,
29 "Set to true for debugging & verifying the slow paths.");
28 DECLARE_FLAG(bool, trace_optimized_ic_calls); 30 DECLARE_FLAG(bool, trace_optimized_ic_calls);
29 31
30 // Input parameters: 32 // Input parameters:
31 // RSP : points to return address. 33 // RSP : points to return address.
32 // RSP + 8 : address of last argument in argument array. 34 // RSP + 8 : address of last argument in argument array.
33 // RSP + 8*R10 : address of first argument in argument array. 35 // RSP + 8*R10 : address of first argument in argument array.
34 // RSP + 8*R10 + 8 : address of return value. 36 // RSP + 8*R10 + 8 : address of return value.
35 // RBX : address of the runtime function to call. 37 // RBX : address of the runtime function to call.
36 // R10 : number of arguments to the call. 38 // R10 : number of arguments to the call.
37 // Must preserve callee saved registers R12 and R13. 39 // Must preserve callee saved registers R12 and R13.
38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 40 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
39 const intptr_t thread_offset = NativeArguments::thread_offset(); 41 const intptr_t thread_offset = NativeArguments::thread_offset();
40 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 42 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
41 const intptr_t argv_offset = NativeArguments::argv_offset(); 43 const intptr_t argv_offset = NativeArguments::argv_offset();
42 const intptr_t retval_offset = NativeArguments::retval_offset(); 44 const intptr_t retval_offset = NativeArguments::retval_offset();
43 45
44 __ EnterStubFrame(); 46 __ EnterStubFrame();
45 47
46 // Save exit frame information to enable stack walking as we are about 48 // Save exit frame information to enable stack walking as we are about
47 // to transition to Dart VM C++ code. 49 // to transition to Dart VM C++ code.
48 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP); 50 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
49 51
50 #if defined(DEBUG) 52 #if defined(DEBUG)
51 { Label ok; 53 {
54 Label ok;
52 // Check that we are always entering from Dart code. 55 // Check that we are always entering from Dart code.
53 __ movq(RAX, Immediate(VMTag::kDartTagId)); 56 __ movq(RAX, Immediate(VMTag::kDartTagId));
54 __ cmpq(RAX, Assembler::VMTagAddress()); 57 __ cmpq(RAX, Assembler::VMTagAddress());
55 __ j(EQUAL, &ok, Assembler::kNearJump); 58 __ j(EQUAL, &ok, Assembler::kNearJump);
56 __ Stop("Not coming from Dart code."); 59 __ Stop("Not coming from Dart code.");
57 __ Bind(&ok); 60 __ Bind(&ok);
58 } 61 }
59 #endif 62 #endif
60 63
61 // Mark that the thread is executing VM code. 64 // Mark that the thread is executing VM code.
62 __ movq(Assembler::VMTagAddress(), RBX); 65 __ movq(Assembler::VMTagAddress(), RBX);
63 66
64 // Reserve space for arguments and align frame before entering C++ world. 67 // Reserve space for arguments and align frame before entering C++ world.
65 __ subq(RSP, Immediate(sizeof(NativeArguments))); 68 __ subq(RSP, Immediate(sizeof(NativeArguments)));
66 if (OS::ActivationFrameAlignment() > 1) { 69 if (OS::ActivationFrameAlignment() > 1) {
67 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 70 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
68 } 71 }
69 72
70 // Pass NativeArguments structure by value and call runtime. 73 // Pass NativeArguments structure by value and call runtime.
71 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs. 74 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs.
72 // There are no runtime calls to closures, so we do not need to set the tag 75 // There are no runtime calls to closures, so we do not need to set the tag
73 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 76 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
74 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments. 77 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments.
75 // Compute argv. 78 // Compute argv.
76 __ leaq(RAX, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); 79 __ leaq(RAX, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
77 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. 80 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
78 __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. 81 __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument.
79 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. 82 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
80 #if defined(_WIN64) 83 #if defined(_WIN64)
81 ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit); 84 ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit);
82 __ movq(CallingConventions::kArg1Reg, RSP); 85 __ movq(CallingConventions::kArg1Reg, RSP);
83 #endif 86 #endif
84 __ CallCFunction(RBX); 87 __ CallCFunction(RBX);
85 88
86 // Mark that the thread is executing Dart code. 89 // Mark that the thread is executing Dart code.
87 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 90 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
88 91
(...skipping 11 matching lines...) Expand all
100 } 103 }
101 END_LEAF_RUNTIME_ENTRY 104 END_LEAF_RUNTIME_ENTRY
102 105
103 106
104 // Input parameters: 107 // Input parameters:
105 // RSP : points to return address. 108 // RSP : points to return address.
106 // RDI : stop message (const char*). 109 // RDI : stop message (const char*).
107 // Must preserve all registers. 110 // Must preserve all registers.
108 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { 111 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
109 __ EnterCallRuntimeFrame(0); 112 __ EnterCallRuntimeFrame(0);
110 // Call the runtime leaf function. RDI already contains the parameter. 113 // Call the runtime leaf function. RDI already contains the parameter.
111 #if defined(_WIN64) 114 #if defined(_WIN64)
112 __ movq(CallingConventions::kArg1Reg, RDI); 115 __ movq(CallingConventions::kArg1Reg, RDI);
113 #endif 116 #endif
114 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); 117 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1);
115 __ LeaveCallRuntimeFrame(); 118 __ LeaveCallRuntimeFrame();
116 __ ret(); 119 __ ret();
117 } 120 }
118 121
119 122
120 // Input parameters: 123 // Input parameters:
(...skipping 13 matching lines...) Expand all
134 const intptr_t retval_offset = 137 const intptr_t retval_offset =
135 NativeArguments::retval_offset() + native_args_struct_offset; 138 NativeArguments::retval_offset() + native_args_struct_offset;
136 139
137 __ EnterStubFrame(); 140 __ EnterStubFrame();
138 141
139 // Save exit frame information to enable stack walking as we are about 142 // Save exit frame information to enable stack walking as we are about
140 // to transition to native code. 143 // to transition to native code.
141 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP); 144 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
142 145
143 #if defined(DEBUG) 146 #if defined(DEBUG)
144 { Label ok; 147 {
148 Label ok;
145 // Check that we are always entering from Dart code. 149 // Check that we are always entering from Dart code.
146 __ movq(R8, Immediate(VMTag::kDartTagId)); 150 __ movq(R8, Immediate(VMTag::kDartTagId));
147 __ cmpq(R8, Assembler::VMTagAddress()); 151 __ cmpq(R8, Assembler::VMTagAddress());
148 __ j(EQUAL, &ok, Assembler::kNearJump); 152 __ j(EQUAL, &ok, Assembler::kNearJump);
149 __ Stop("Not coming from Dart code."); 153 __ Stop("Not coming from Dart code.");
150 __ Bind(&ok); 154 __ Bind(&ok);
151 } 155 }
152 #endif 156 #endif
153 157
154 // Mark that the thread is executing native code. 158 // Mark that the thread is executing native code.
155 __ movq(Assembler::VMTagAddress(), RBX); 159 __ movq(Assembler::VMTagAddress(), RBX);
156 160
157 // Reserve space for the native arguments structure passed on the stack (the 161 // Reserve space for the native arguments structure passed on the stack (the
158 // outgoing pointer parameter to the native arguments structure is passed in 162 // outgoing pointer parameter to the native arguments structure is passed in
159 // RDI) and align frame before entering the C++ world. 163 // RDI) and align frame before entering the C++ world.
160 __ subq(RSP, Immediate(sizeof(NativeArguments))); 164 __ subq(RSP, Immediate(sizeof(NativeArguments)));
161 if (OS::ActivationFrameAlignment() > 1) { 165 if (OS::ActivationFrameAlignment() > 1) {
162 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 166 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
163 } 167 }
164 168
165 // Pass NativeArguments structure by value and call native function. 169 // Pass NativeArguments structure by value and call native function.
166 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs. 170 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs.
167 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments. 171 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments.
168 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. 172 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
169 __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr. 173 __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr.
170 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. 174 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
171 175
172 // Pass the pointer to the NativeArguments. 176 // Pass the pointer to the NativeArguments.
173 __ movq(CallingConventions::kArg1Reg, RSP); 177 __ movq(CallingConventions::kArg1Reg, RSP);
174 // Pass pointer to function entrypoint. 178 // Pass pointer to function entrypoint.
175 __ movq(CallingConventions::kArg2Reg, RBX); 179 __ movq(CallingConventions::kArg2Reg, RBX);
176 180
177 __ movq(RAX, Address(THR, Thread::native_call_wrapper_entry_point_offset())); 181 __ movq(RAX, Address(THR, Thread::native_call_wrapper_entry_point_offset()));
178 __ CallCFunction(RAX); 182 __ CallCFunction(RAX);
179 183
(...skipping 25 matching lines...) Expand all
205 const intptr_t retval_offset = 209 const intptr_t retval_offset =
206 NativeArguments::retval_offset() + native_args_struct_offset; 210 NativeArguments::retval_offset() + native_args_struct_offset;
207 211
208 __ EnterStubFrame(); 212 __ EnterStubFrame();
209 213
210 // Save exit frame information to enable stack walking as we are about 214 // Save exit frame information to enable stack walking as we are about
211 // to transition to native code. 215 // to transition to native code.
212 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP); 216 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
213 217
214 #if defined(DEBUG) 218 #if defined(DEBUG)
215 { Label ok; 219 {
220 Label ok;
216 // Check that we are always entering from Dart code. 221 // Check that we are always entering from Dart code.
217 __ movq(R8, Immediate(VMTag::kDartTagId)); 222 __ movq(R8, Immediate(VMTag::kDartTagId));
218 __ cmpq(R8, Assembler::VMTagAddress()); 223 __ cmpq(R8, Assembler::VMTagAddress());
219 __ j(EQUAL, &ok, Assembler::kNearJump); 224 __ j(EQUAL, &ok, Assembler::kNearJump);
220 __ Stop("Not coming from Dart code."); 225 __ Stop("Not coming from Dart code.");
221 __ Bind(&ok); 226 __ Bind(&ok);
222 } 227 }
223 #endif 228 #endif
224 229
225 // Mark that the thread is executing native code. 230 // Mark that the thread is executing native code.
226 __ movq(Assembler::VMTagAddress(), RBX); 231 __ movq(Assembler::VMTagAddress(), RBX);
227 232
228 // Reserve space for the native arguments structure passed on the stack (the 233 // Reserve space for the native arguments structure passed on the stack (the
229 // outgoing pointer parameter to the native arguments structure is passed in 234 // outgoing pointer parameter to the native arguments structure is passed in
230 // RDI) and align frame before entering the C++ world. 235 // RDI) and align frame before entering the C++ world.
231 __ subq(RSP, Immediate(sizeof(NativeArguments))); 236 __ subq(RSP, Immediate(sizeof(NativeArguments)));
232 if (OS::ActivationFrameAlignment() > 1) { 237 if (OS::ActivationFrameAlignment() > 1) {
233 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 238 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
234 } 239 }
235 240
236 // Pass NativeArguments structure by value and call native function. 241 // Pass NativeArguments structure by value and call native function.
237 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs. 242 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs.
238 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments. 243 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments.
239 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. 244 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
240 __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr. 245 __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr.
241 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. 246 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
242 247
243 // Pass the pointer to the NativeArguments. 248 // Pass the pointer to the NativeArguments.
244 __ movq(CallingConventions::kArg1Reg, RSP); 249 __ movq(CallingConventions::kArg1Reg, RSP);
245 __ CallCFunction(RBX); 250 __ CallCFunction(RBX);
246 251
247 // Mark that the thread is executing Dart code. 252 // Mark that the thread is executing Dart code.
248 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 253 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
249 254
250 // Reset exit frame information in Isolate structure. 255 // Reset exit frame information in Isolate structure.
251 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); 256 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
252 257
253 __ LeaveStubFrame(); 258 __ LeaveStubFrame();
254 __ ret(); 259 __ ret();
255 } 260 }
256 261
257 262
258 // Input parameters: 263 // Input parameters:
259 // R10: arguments descriptor array. 264 // R10: arguments descriptor array.
260 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 265 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
261 __ EnterStubFrame(); 266 __ EnterStubFrame();
262 __ pushq(R10); // Preserve arguments descriptor array. 267 __ pushq(R10); // Preserve arguments descriptor array.
263 // Setup space on stack for return value. 268 // Setup space on stack for return value.
264 __ pushq(Immediate(0)); 269 __ pushq(Immediate(0));
265 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 270 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
266 __ popq(CODE_REG); // Get Code object result. 271 __ popq(CODE_REG); // Get Code object result.
267 __ popq(R10); // Restore arguments descriptor array. 272 __ popq(R10); // Restore arguments descriptor array.
268 // Remove the stub frame as we are about to jump to the dart function. 273 // Remove the stub frame as we are about to jump to the dart function.
269 __ LeaveStubFrame(); 274 __ LeaveStubFrame();
270 275
271 __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset())); 276 __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset()));
272 __ jmp(RBX); 277 __ jmp(RBX);
273 } 278 }
274 279
275 280
276 // Called from a static call only when an invalid code has been entered 281 // Called from a static call only when an invalid code has been entered
277 // (invalid because its function was optimized or deoptimized). 282 // (invalid because its function was optimized or deoptimized).
278 // R10: arguments descriptor array. 283 // R10: arguments descriptor array.
279 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 284 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
280 // Load code pointer to this stub from the thread: 285 // Load code pointer to this stub from the thread:
281 // The one that is passed in, is not correct - it points to the code object 286 // The one that is passed in, is not correct - it points to the code object
282 // that needs to be replaced. 287 // that needs to be replaced.
283 __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); 288 __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
284 __ EnterStubFrame(); 289 __ EnterStubFrame();
285 __ pushq(R10); // Preserve arguments descriptor array. 290 __ pushq(R10); // Preserve arguments descriptor array.
286 // Setup space on stack for return value. 291 // Setup space on stack for return value.
287 __ pushq(Immediate(0)); 292 __ pushq(Immediate(0));
288 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 293 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
289 __ popq(CODE_REG); // Get Code object. 294 __ popq(CODE_REG); // Get Code object.
290 __ popq(R10); // Restore arguments descriptor array. 295 __ popq(R10); // Restore arguments descriptor array.
291 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 296 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
292 __ LeaveStubFrame(); 297 __ LeaveStubFrame();
293 __ jmp(RAX); 298 __ jmp(RAX);
294 __ int3(); 299 __ int3();
295 } 300 }
296 301
297 302
298 // Called from object allocate instruction when the allocation stub has been 303 // Called from object allocate instruction when the allocation stub has been
299 // disabled. 304 // disabled.
300 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 305 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); 410 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
406 intptr_t offset = 0; 411 intptr_t offset = 0;
407 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { 412 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
408 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); 413 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
409 __ movups(Address(RSP, offset), xmm_reg); 414 __ movups(Address(RSP, offset), xmm_reg);
410 offset += kFpuRegisterSize; 415 offset += kFpuRegisterSize;
411 } 416 }
412 417
413 // Pass address of saved registers block. 418 // Pass address of saved registers block.
414 __ movq(CallingConventions::kArg1Reg, RSP); 419 __ movq(CallingConventions::kArg1Reg, RSP);
415 bool is_lazy = (kind == kLazyDeoptFromReturn) || 420 bool is_lazy =
416 (kind == kLazyDeoptFromThrow); 421 (kind == kLazyDeoptFromReturn) || (kind == kLazyDeoptFromThrow);
417 __ movq(CallingConventions::kArg2Reg, Immediate(is_lazy ? 1 : 0)); 422 __ movq(CallingConventions::kArg2Reg, Immediate(is_lazy ? 1 : 0));
418 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call. 423 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call.
419 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 424 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
420 // Result (RAX) is stack-size (FP - SP) in bytes. 425 // Result (RAX) is stack-size (FP - SP) in bytes.
421 426
422 if (kind == kLazyDeoptFromReturn) { 427 if (kind == kLazyDeoptFromReturn) {
423 // Restore result into RBX temporarily. 428 // Restore result into RBX temporarily.
424 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); 429 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
425 } else if (kind == kLazyDeoptFromThrow) { 430 } else if (kind == kLazyDeoptFromThrow) {
426 // Restore result into RBX temporarily. 431 // Restore result into RBX temporarily.
427 __ movq(RBX, Address(RBP, saved_exception_slot_from_fp * kWordSize)); 432 __ movq(RBX, Address(RBP, saved_exception_slot_from_fp * kWordSize));
428 __ movq(RDX, Address(RBP, saved_stacktrace_slot_from_fp * kWordSize)); 433 __ movq(RDX, Address(RBP, saved_stacktrace_slot_from_fp * kWordSize));
429 } 434 }
430 435
431 // There is a Dart Frame on the stack. We must restore PP and leave frame. 436 // There is a Dart Frame on the stack. We must restore PP and leave frame.
432 __ RestoreCodePointer(); 437 __ RestoreCodePointer();
433 __ LeaveStubFrame(); 438 __ LeaveStubFrame();
434 439
435 __ popq(RCX); // Preserve return address. 440 __ popq(RCX); // Preserve return address.
436 __ movq(RSP, RBP); // Discard optimized frame. 441 __ movq(RSP, RBP); // Discard optimized frame.
437 __ subq(RSP, RAX); // Reserve space for deoptimized frame. 442 __ subq(RSP, RAX); // Reserve space for deoptimized frame.
438 __ pushq(RCX); // Restore return address. 443 __ pushq(RCX); // Restore return address.
439 444
440 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 445 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
441 // is no need to set the correct PC marker or load PP, since they get patched. 446 // is no need to set the correct PC marker or load PP, since they get patched.
442 __ EnterStubFrame(); 447 __ EnterStubFrame();
443 448
444 if (kind == kLazyDeoptFromReturn) { 449 if (kind == kLazyDeoptFromReturn) {
445 __ pushq(RBX); // Preserve result as first local. 450 __ pushq(RBX); // Preserve result as first local.
446 } else if (kind == kLazyDeoptFromThrow) { 451 } else if (kind == kLazyDeoptFromThrow) {
447 __ pushq(RBX); // Preserve exception as first local. 452 __ pushq(RBX); // Preserve exception as first local.
448 __ pushq(RDX); // Preserve stacktrace as second local. 453 __ pushq(RDX); // Preserve stacktrace as second local.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 __ popq(RBX); 488 __ popq(RBX);
484 __ SmiUntag(RBX); 489 __ SmiUntag(RBX);
485 if (kind == kLazyDeoptFromReturn) { 490 if (kind == kLazyDeoptFromReturn) {
486 __ popq(RAX); // Restore result. 491 __ popq(RAX); // Restore result.
487 } else if (kind == kLazyDeoptFromThrow) { 492 } else if (kind == kLazyDeoptFromThrow) {
488 __ popq(RDX); // Restore stacktrace. 493 __ popq(RDX); // Restore stacktrace.
489 __ popq(RAX); // Restore exception. 494 __ popq(RAX); // Restore exception.
490 } 495 }
491 __ LeaveStubFrame(); 496 __ LeaveStubFrame();
492 497
493 __ popq(RCX); // Pop return address. 498 __ popq(RCX); // Pop return address.
494 __ addq(RSP, RBX); // Remove materialization arguments. 499 __ addq(RSP, RBX); // Remove materialization arguments.
495 __ pushq(RCX); // Push return address. 500 __ pushq(RCX); // Push return address.
496 __ ret(); 501 __ ret();
497 } 502 }
498 503
499 504
500 // RAX: result, must be preserved 505 // RAX: result, must be preserved
501 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { 506 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
502 // Push zap value instead of CODE_REG for lazy deopt. 507 // Push zap value instead of CODE_REG for lazy deopt.
503 __ pushq(Immediate(0xf1f1f1f1)); 508 __ pushq(Immediate(0xf1f1f1f1));
504 // Return address for "call" to deopt stub. 509 // Return address for "call" to deopt stub.
505 __ pushq(Immediate(0xe1e1e1e1)); 510 __ pushq(Immediate(0xe1e1e1e1));
(...skipping 22 matching lines...) Expand all
528 static void GenerateDispatcherCode(Assembler* assembler, 533 static void GenerateDispatcherCode(Assembler* assembler,
529 Label* call_target_function) { 534 Label* call_target_function) {
530 __ Comment("NoSuchMethodDispatch"); 535 __ Comment("NoSuchMethodDispatch");
531 // When lazily generated invocation dispatchers are disabled, the 536 // When lazily generated invocation dispatchers are disabled, the
532 // miss-handler may return null. 537 // miss-handler may return null.
533 __ CompareObject(RAX, Object::null_object()); 538 __ CompareObject(RAX, Object::null_object());
534 __ j(NOT_EQUAL, call_target_function); 539 __ j(NOT_EQUAL, call_target_function);
535 __ EnterStubFrame(); 540 __ EnterStubFrame();
536 // Load the receiver. 541 // Load the receiver.
537 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 542 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
538 __ movq(RAX, Address( 543 __ movq(RAX, Address(RBP, RDI, TIMES_HALF_WORD_SIZE,
539 RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize)); 544 kParamEndSlotFromFp * kWordSize));
540 __ pushq(Immediate(0)); // Setup space on stack for result. 545 __ pushq(Immediate(0)); // Setup space on stack for result.
541 __ pushq(RAX); // Receiver. 546 __ pushq(RAX); // Receiver.
542 __ pushq(RBX); // ICData/MegamorphicCache. 547 __ pushq(RBX); // ICData/MegamorphicCache.
543 __ pushq(R10); // Arguments descriptor array. 548 __ pushq(R10); // Arguments descriptor array.
544 __ movq(R10, RDI); 549 __ movq(R10, RDI);
545 // EDX: Smi-tagged arguments array length. 550 // EDX: Smi-tagged arguments array length.
546 PushArgumentsArray(assembler); 551 PushArgumentsArray(assembler);
547 const intptr_t kNumArgs = 4; 552 const intptr_t kNumArgs = 4;
548 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); 553 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
549 __ Drop(4); 554 __ Drop(4);
550 __ popq(RAX); // Return value. 555 __ popq(RAX); // Return value.
551 __ LeaveStubFrame(); 556 __ LeaveStubFrame();
552 __ ret(); 557 __ ret();
553 } 558 }
554 559
555 560
556 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 561 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
557 __ EnterStubFrame(); 562 __ EnterStubFrame();
558 // Load the receiver into RAX. The argument count in the arguments 563 // Load the receiver into RAX. The argument count in the arguments
559 // descriptor in R10 is a smi. 564 // descriptor in R10 is a smi.
560 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 565 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
561 // Three words (saved pp, saved fp, stub's pc marker) 566 // Three words (saved pp, saved fp, stub's pc marker)
562 // in the stack above the return address. 567 // in the stack above the return address.
563 __ movq(RAX, Address(RSP, RAX, TIMES_4, 568 __ movq(RAX,
564 kSavedAboveReturnAddress * kWordSize)); 569 Address(RSP, RAX, TIMES_4, kSavedAboveReturnAddress * kWordSize));
565 // Preserve IC data and arguments descriptor. 570 // Preserve IC data and arguments descriptor.
566 __ pushq(RBX); 571 __ pushq(RBX);
567 __ pushq(R10); 572 __ pushq(R10);
568 573
569 // Space for the result of the runtime call. 574 // Space for the result of the runtime call.
570 __ pushq(Immediate(0)); 575 __ pushq(Immediate(0));
571 __ pushq(RAX); // Receiver. 576 __ pushq(RAX); // Receiver.
572 __ pushq(RBX); // IC data. 577 __ pushq(RBX); // IC data.
573 __ pushq(R10); // Arguments descriptor. 578 __ pushq(R10); // Arguments descriptor.
574 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 579 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 } 618 }
614 __ cmpq(RDI, Immediate(0)); 619 __ cmpq(RDI, Immediate(0));
615 __ j(LESS, &slow_case); 620 __ j(LESS, &slow_case);
616 // Check for maximum allowed length. 621 // Check for maximum allowed length.
617 const Immediate& max_len = 622 const Immediate& max_len =
618 Immediate(reinterpret_cast<int64_t>(Smi::New(Array::kMaxElements))); 623 Immediate(reinterpret_cast<int64_t>(Smi::New(Array::kMaxElements)));
619 __ cmpq(RDI, max_len); 624 __ cmpq(RDI, max_len);
620 __ j(GREATER, &slow_case); 625 __ j(GREATER, &slow_case);
621 626
622 // Check for allocation tracing. 627 // Check for allocation tracing.
623 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid, 628 NOT_IN_PRODUCT(
624 &slow_case, 629 __ MaybeTraceAllocation(kArrayCid, &slow_case, Assembler::kFarJump));
625 Assembler::kFarJump));
626 630
627 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 631 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
628 __ leaq(RDI, Address(RDI, TIMES_4, fixed_size)); // RDI is a Smi. 632 __ leaq(RDI, Address(RDI, TIMES_4, fixed_size)); // RDI is a Smi.
629 ASSERT(kSmiTagShift == 1); 633 ASSERT(kSmiTagShift == 1);
630 __ andq(RDI, Immediate(-kObjectAlignment)); 634 __ andq(RDI, Immediate(-kObjectAlignment));
631 635
632 const intptr_t cid = kArrayCid; 636 const intptr_t cid = kArrayCid;
633 Heap::Space space = Heap::kNew; 637 Heap::Space space = Heap::kNew;
634 __ movq(R13, Address(THR, Thread::heap_offset())); 638 __ movq(R13, Address(THR, Thread::heap_offset()));
635 __ movq(RAX, Address(R13, Heap::TopOffset(space))); 639 __ movq(RAX, Address(R13, Heap::TopOffset(space)));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 __ Bind(&done); 671 __ Bind(&done);
668 672
669 // Get the class index and insert it into the tags. 673 // Get the class index and insert it into the tags.
670 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); 674 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid)));
671 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags. 675 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags.
672 } 676 }
673 677
674 // RAX: new object start as a tagged pointer. 678 // RAX: new object start as a tagged pointer.
675 // Store the type argument field. 679 // Store the type argument field.
676 // No generetional barrier needed, since we store into a new object. 680 // No generetional barrier needed, since we store into a new object.
677 __ StoreIntoObjectNoBarrier(RAX, 681 __ StoreIntoObjectNoBarrier(
678 FieldAddress(RAX, Array::type_arguments_offset()), 682 RAX, FieldAddress(RAX, Array::type_arguments_offset()), RBX);
679 RBX);
680 683
681 // Set the length field. 684 // Set the length field.
682 __ StoreIntoObjectNoBarrier(RAX, 685 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, Array::length_offset()),
683 FieldAddress(RAX, Array::length_offset()),
684 R10); 686 R10);
685 687
686 // Initialize all array elements to raw_null. 688 // Initialize all array elements to raw_null.
687 // RAX: new object start as a tagged pointer. 689 // RAX: new object start as a tagged pointer.
688 // RCX: new object end address. 690 // RCX: new object end address.
689 // RDI: iterator which initially points to the start of the variable 691 // RDI: iterator which initially points to the start of the variable
690 // data area to be initialized. 692 // data area to be initialized.
691 __ LoadObject(R12, Object::null_object()); 693 __ LoadObject(R12, Object::null_object());
692 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); 694 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray)));
693 Label done; 695 Label done;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 // RSP : points to return address. 733 // RSP : points to return address.
732 // RDI : target code 734 // RDI : target code
733 // RSI : arguments descriptor array. 735 // RSI : arguments descriptor array.
734 // RDX : arguments array. 736 // RDX : arguments array.
735 // RCX : current thread. 737 // RCX : current thread.
736 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 738 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
737 // Save frame pointer coming in. 739 // Save frame pointer coming in.
738 __ EnterFrame(0); 740 __ EnterFrame(0);
739 741
740 const Register kTargetCodeReg = CallingConventions::kArg1Reg; 742 const Register kTargetCodeReg = CallingConventions::kArg1Reg;
741 const Register kArgDescReg = CallingConventions::kArg2Reg; 743 const Register kArgDescReg = CallingConventions::kArg2Reg;
742 const Register kArgsReg = CallingConventions::kArg3Reg; 744 const Register kArgsReg = CallingConventions::kArg3Reg;
743 const Register kThreadReg = CallingConventions::kArg4Reg; 745 const Register kThreadReg = CallingConventions::kArg4Reg;
744 746
745 // Push code object to PC marker slot. 747 // Push code object to PC marker slot.
746 __ pushq(Address(kThreadReg, Thread::invoke_dart_code_stub_offset())); 748 __ pushq(Address(kThreadReg, Thread::invoke_dart_code_stub_offset()));
747 749
748 // At this point, the stack looks like: 750 // At this point, the stack looks like:
749 // | stub code object 751 // | stub code object
750 // | saved RBP | <-- RBP 752 // | saved RBP | <-- RBP
751 // | saved PC (return to DartEntry::InvokeFunction) | 753 // | saved PC (return to DartEntry::InvokeFunction) |
752 754
753 const intptr_t kInitialOffset = 2; 755 const intptr_t kInitialOffset = 2;
754 // Save arguments descriptor array. 756 // Save arguments descriptor array.
755 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; 757 const intptr_t kArgumentsDescOffset = -(kInitialOffset)*kWordSize;
756 __ pushq(kArgDescReg); 758 __ pushq(kArgDescReg);
757 759
758 // Save C++ ABI callee-saved registers. 760 // Save C++ ABI callee-saved registers.
759 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, 761 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
760 CallingConventions::kCalleeSaveXmmRegisters); 762 CallingConventions::kCalleeSaveXmmRegisters);
761 763
762 // If any additional (or fewer) values are pushed, the offsets in 764 // If any additional (or fewer) values are pushed, the offsets in
763 // kExitLinkSlotFromEntryFp will need to be changed. 765 // kExitLinkSlotFromEntryFp will need to be changed.
764 766
765 // Set up THR, which caches the current thread in Dart code. 767 // Set up THR, which caches the current thread in Dart code.
766 if (THR != kThreadReg) { 768 if (THR != kThreadReg) {
767 __ movq(THR, kThreadReg); 769 __ movq(THR, kThreadReg);
768 } 770 }
769 771
770 // Save the current VMTag on the stack. 772 // Save the current VMTag on the stack.
771 __ movq(RAX, Assembler::VMTagAddress()); 773 __ movq(RAX, Assembler::VMTagAddress());
772 __ pushq(RAX); 774 __ pushq(RAX);
773 775
774 // Mark that the thread is executing Dart code. 776 // Mark that the thread is executing Dart code.
775 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 777 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
776 778
777 // Save top resource and top exit frame info. Use RAX as a temporary register. 779 // Save top resource and top exit frame info. Use RAX as a temporary register.
778 // StackFrameIterator reads the top exit frame info saved in this frame. 780 // StackFrameIterator reads the top exit frame info saved in this frame.
779 __ movq(RAX, Address(THR, Thread::top_resource_offset())); 781 __ movq(RAX, Address(THR, Thread::top_resource_offset()));
780 __ pushq(RAX); 782 __ pushq(RAX);
781 __ movq(Address(THR, Thread::top_resource_offset()), 783 __ movq(Address(THR, Thread::top_resource_offset()), Immediate(0));
782 Immediate(0));
783 __ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset())); 784 __ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset()));
784 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the 785 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
785 // code below. 786 // code below.
786 __ pushq(RAX); 787 __ pushq(RAX);
787 #if defined(DEBUG) 788 #if defined(DEBUG)
788 { 789 {
789 Label ok; 790 Label ok;
790 __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize)); 791 __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize));
791 __ cmpq(RAX, RSP); 792 __ cmpq(RAX, RSP);
792 __ j(EQUAL, &ok); 793 __ j(EQUAL, &ok);
793 __ Stop("kExitLinkSlotFromEntryFp mismatch"); 794 __ Stop("kExitLinkSlotFromEntryFp mismatch");
794 __ Bind(&ok); 795 __ Bind(&ok);
795 } 796 }
796 #endif 797 #endif
797 798
798 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), 799 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
799 Immediate(0));
800 800
801 // Load arguments descriptor array into R10, which is passed to Dart code. 801 // Load arguments descriptor array into R10, which is passed to Dart code.
802 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); 802 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
803 803
804 // Push arguments. At this point we only need to preserve kTargetCodeReg. 804 // Push arguments. At this point we only need to preserve kTargetCodeReg.
805 ASSERT(kTargetCodeReg != RDX); 805 ASSERT(kTargetCodeReg != RDX);
806 806
807 // Load number of arguments into RBX. 807 // Load number of arguments into RBX.
808 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 808 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
809 __ SmiUntag(RBX); 809 __ SmiUntag(RBX);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 __ LoadObject(R9, Object::null_object()); 868 __ LoadObject(R9, Object::null_object());
869 if (FLAG_inline_alloc) { 869 if (FLAG_inline_alloc) {
870 Label slow_case; 870 Label slow_case;
871 // First compute the rounded instance size. 871 // First compute the rounded instance size.
872 // R10: number of context variables. 872 // R10: number of context variables.
873 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); 873 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
874 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); 874 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
875 __ andq(R13, Immediate(-kObjectAlignment)); 875 __ andq(R13, Immediate(-kObjectAlignment));
876 876
877 // Check for allocation tracing. 877 // Check for allocation tracing.
878 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, 878 NOT_IN_PRODUCT(
879 &slow_case, 879 __ MaybeTraceAllocation(kContextCid, &slow_case, Assembler::kFarJump));
880 Assembler::kFarJump));
881 880
882 // Now allocate the object. 881 // Now allocate the object.
883 // R10: number of context variables. 882 // R10: number of context variables.
884 const intptr_t cid = kContextCid; 883 const intptr_t cid = kContextCid;
885 Heap::Space space = Heap::kNew; 884 Heap::Space space = Heap::kNew;
886 __ movq(RCX, Address(THR, Thread::heap_offset())); 885 __ movq(RCX, Address(THR, Thread::heap_offset()));
887 __ movq(RAX, Address(RCX, Heap::TopOffset(space))); 886 __ movq(RAX, Address(RCX, Heap::TopOffset(space)));
888 __ addq(R13, RAX); 887 __ addq(R13, RAX);
889 // Check if the allocation fits into the remaining space. 888 // Check if the allocation fits into the remaining space.
890 // RAX: potential new object. 889 // RAX: potential new object.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 __ jmp(&done); 923 __ jmp(&done);
925 924
926 __ Bind(&size_tag_overflow); 925 __ Bind(&size_tag_overflow);
927 // Set overflow size tag value. 926 // Set overflow size tag value.
928 __ movq(R13, Immediate(0)); 927 __ movq(R13, Immediate(0));
929 928
930 __ Bind(&done); 929 __ Bind(&done);
931 // RAX: new object. 930 // RAX: new object.
932 // R10: number of context variables. 931 // R10: number of context variables.
933 // R13: size and bit tags. 932 // R13: size and bit tags.
934 __ orq(R13, 933 __ orq(R13, Immediate(RawObject::ClassIdTag::encode(cid)));
935 Immediate(RawObject::ClassIdTag::encode(cid)));
936 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags. 934 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags.
937 } 935 }
938 936
939 // Setup up number of context variables field. 937 // Setup up number of context variables field.
940 // RAX: new object. 938 // RAX: new object.
941 // R10: number of context variables as integer value (not object). 939 // R10: number of context variables as integer value (not object).
942 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); 940 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
943 941
944 // Setup the parent field. 942 // Setup the parent field.
945 // RAX: new object. 943 // RAX: new object.
946 // R10: number of context variables. 944 // R10: number of context variables.
947 // No generational barrier needed, since we are storing null. 945 // No generational barrier needed, since we are storing null.
948 __ StoreIntoObjectNoBarrier(RAX, 946 __ StoreIntoObjectNoBarrier(
949 FieldAddress(RAX, Context::parent_offset()), 947 RAX, FieldAddress(RAX, Context::parent_offset()), R9);
950 R9);
951 948
952 // Initialize the context variables. 949 // Initialize the context variables.
953 // RAX: new object. 950 // RAX: new object.
954 // R10: number of context variables. 951 // R10: number of context variables.
955 { 952 {
956 Label loop, entry; 953 Label loop, entry;
957 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); 954 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
958 #if defined(DEBUG) 955 #if defined(DEBUG)
959 static const bool kJumpLength = Assembler::kFarJump; 956 static const bool kJumpLength = Assembler::kFarJump;
960 #else 957 #else
961 static const bool kJumpLength = Assembler::kNearJump; 958 static const bool kJumpLength = Assembler::kNearJump;
962 #endif // DEBUG 959 #endif // DEBUG
963 __ jmp(&entry, kJumpLength); 960 __ jmp(&entry, kJumpLength);
964 __ Bind(&loop); 961 __ Bind(&loop);
965 __ decq(R10); 962 __ decq(R10);
966 // No generational barrier needed, since we are storing null. 963 // No generational barrier needed, since we are storing null.
967 __ StoreIntoObjectNoBarrier(RAX, 964 __ StoreIntoObjectNoBarrier(RAX, Address(R13, R10, TIMES_8, 0), R9);
968 Address(R13, R10, TIMES_8, 0),
969 R9);
970 __ Bind(&entry); 965 __ Bind(&entry);
971 __ cmpq(R10, Immediate(0)); 966 __ cmpq(R10, Immediate(0));
972 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 967 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
973 } 968 }
974 969
975 // Done allocating and initializing the context. 970 // Done allocating and initializing the context.
976 // RAX: new object. 971 // RAX: new object.
977 __ ret(); 972 __ ret();
978 973
979 __ Bind(&slow_case); 974 __ Bind(&slow_case);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 // Initialize the remaining words of the object. 1111 // Initialize the remaining words of the object.
1117 // RAX: new object (tagged). 1112 // RAX: new object (tagged).
1118 // RBX: next object start. 1113 // RBX: next object start.
1119 // RDX: new object type arguments (if is_cls_parameterized). 1114 // RDX: new object type arguments (if is_cls_parameterized).
1120 // R9: raw null. 1115 // R9: raw null.
1121 // First try inlining the initialization without a loop. 1116 // First try inlining the initialization without a loop.
1122 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1117 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1123 // Check if the object contains any non-header fields. 1118 // Check if the object contains any non-header fields.
1124 // Small objects are initialized using a consecutive set of writes. 1119 // Small objects are initialized using a consecutive set of writes.
1125 for (intptr_t current_offset = Instance::NextFieldOffset(); 1120 for (intptr_t current_offset = Instance::NextFieldOffset();
1126 current_offset < instance_size; 1121 current_offset < instance_size; current_offset += kWordSize) {
1127 current_offset += kWordSize) { 1122 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, current_offset), R9);
1128 __ StoreIntoObjectNoBarrier(RAX,
1129 FieldAddress(RAX, current_offset),
1130 R9);
1131 } 1123 }
1132 } else { 1124 } else {
1133 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); 1125 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset()));
1134 // Loop until the whole object is initialized. 1126 // Loop until the whole object is initialized.
1135 // RAX: new object (tagged). 1127 // RAX: new object (tagged).
1136 // RBX: next object start. 1128 // RBX: next object start.
1137 // RCX: next word to be initialized. 1129 // RCX: next word to be initialized.
1138 // RDX: new object type arguments (if is_cls_parameterized). 1130 // RDX: new object type arguments (if is_cls_parameterized).
1139 Label init_loop; 1131 Label init_loop;
1140 Label done; 1132 Label done;
(...skipping 20 matching lines...) Expand all
1161 // Done allocating and initializing the instance. 1153 // Done allocating and initializing the instance.
1162 // RAX: new object (tagged). 1154 // RAX: new object (tagged).
1163 __ ret(); 1155 __ ret();
1164 1156
1165 __ Bind(&slow_case); 1157 __ Bind(&slow_case);
1166 } 1158 }
1167 // If is_cls_parameterized: 1159 // If is_cls_parameterized:
1168 // RDX: new object type arguments. 1160 // RDX: new object type arguments.
1169 // Create a stub frame. 1161 // Create a stub frame.
1170 __ EnterStubFrame(); // Uses PP to access class object. 1162 __ EnterStubFrame(); // Uses PP to access class object.
1171 __ pushq(R9); // Setup space on stack for return value. 1163 __ pushq(R9); // Setup space on stack for return value.
1172 __ PushObject(cls); // Push class of object to be allocated. 1164 __ PushObject(cls); // Push class of object to be allocated.
1173 if (is_cls_parameterized) { 1165 if (is_cls_parameterized) {
1174 __ pushq(RDX); // Push type arguments of object to be allocated. 1166 __ pushq(RDX); // Push type arguments of object to be allocated.
1175 } else { 1167 } else {
1176 __ pushq(R9); // Push null type arguments. 1168 __ pushq(R9); // Push null type arguments.
1177 } 1169 }
1178 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1170 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1179 __ popq(RAX); // Pop argument (type arguments of object). 1171 __ popq(RAX); // Pop argument (type arguments of object).
1180 __ popq(RAX); // Pop argument (class of object). 1172 __ popq(RAX); // Pop argument (class of object).
1181 __ popq(RAX); // Pop result (newly allocated object). 1173 __ popq(RAX); // Pop result (newly allocated object).
1182 // RAX: new object 1174 // RAX: new object
(...skipping 11 matching lines...) Expand all
1194 // RSP + 8 : address of last argument. 1186 // RSP + 8 : address of last argument.
1195 // R10 : arguments descriptor array. 1187 // R10 : arguments descriptor array.
1196 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { 1188 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
1197 __ EnterStubFrame(); 1189 __ EnterStubFrame();
1198 1190
1199 // Load the receiver. 1191 // Load the receiver.
1200 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1192 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1201 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); 1193 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize));
1202 1194
1203 __ pushq(Immediate(0)); // Result slot. 1195 __ pushq(Immediate(0)); // Result slot.
1204 __ pushq(RAX); // Receiver. 1196 __ pushq(RAX); // Receiver.
1205 __ pushq(R10); // Arguments descriptor array. 1197 __ pushq(R10); // Arguments descriptor array.
1206 1198
1207 __ movq(R10, R13); // Smi-tagged arguments array length. 1199 __ movq(R10, R13); // Smi-tagged arguments array length.
1208 PushArgumentsArray(assembler); 1200 PushArgumentsArray(assembler);
1209 1201
1210 const intptr_t kNumArgs = 3; 1202 const intptr_t kNumArgs = 3;
1211 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); 1203 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
1212 // noSuchMethod on closures always throws an error, so it will never return. 1204 // noSuchMethod on closures always throws an error, so it will never return.
1213 __ int3(); 1205 __ int3();
1214 } 1206 }
1215 1207
1216 1208
1217 // Cannot use function object from ICData as it may be the inlined 1209 // Cannot use function object from ICData as it may be the inlined
1218 // function and not the top-scope function. 1210 // function and not the top-scope function.
1219 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1211 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1220 Register ic_reg = RBX; 1212 Register ic_reg = RBX;
1221 Register func_reg = RDI; 1213 Register func_reg = RDI;
1222 if (FLAG_trace_optimized_ic_calls) { 1214 if (FLAG_trace_optimized_ic_calls) {
1223 __ EnterStubFrame(); 1215 __ EnterStubFrame();
1224 __ pushq(func_reg); // Preserve 1216 __ pushq(func_reg); // Preserve
1225 __ pushq(ic_reg); // Preserve. 1217 __ pushq(ic_reg); // Preserve.
1226 __ pushq(ic_reg); // Argument. 1218 __ pushq(ic_reg); // Argument.
1227 __ pushq(func_reg); // Argument. 1219 __ pushq(func_reg); // Argument.
1228 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1220 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1229 __ popq(RAX); // Discard argument; 1221 __ popq(RAX); // Discard argument;
1230 __ popq(RAX); // Discard argument; 1222 __ popq(RAX); // Discard argument;
1231 __ popq(ic_reg); // Restore. 1223 __ popq(ic_reg); // Restore.
1232 __ popq(func_reg); // Restore. 1224 __ popq(func_reg); // Restore.
1233 __ LeaveStubFrame(); 1225 __ LeaveStubFrame();
1234 } 1226 }
1235 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); 1227 __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
1236 } 1228 }
1237 1229
1238 1230
1239 // Loads function into 'temp_reg', preserves 'ic_reg'. 1231 // Loads function into 'temp_reg', preserves 'ic_reg'.
1240 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1232 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1241 Register temp_reg) { 1233 Register temp_reg) {
1242 if (FLAG_optimization_counter_threshold >= 0) { 1234 if (FLAG_optimization_counter_threshold >= 0) {
(...skipping 10 matching lines...) Expand all
1253 // Note: RBX must be preserved. 1245 // Note: RBX must be preserved.
1254 // Attempt a quick Smi operation for known operations ('kind'). The ICData 1246 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1255 // must have been primed with a Smi/Smi check that will be used for counting 1247 // must have been primed with a Smi/Smi check that will be used for counting
1256 // the invocations. 1248 // the invocations.
1257 static void EmitFastSmiOp(Assembler* assembler, 1249 static void EmitFastSmiOp(Assembler* assembler,
1258 Token::Kind kind, 1250 Token::Kind kind,
1259 intptr_t num_args, 1251 intptr_t num_args,
1260 Label* not_smi_or_overflow) { 1252 Label* not_smi_or_overflow) {
1261 __ Comment("Fast Smi op"); 1253 __ Comment("Fast Smi op");
1262 ASSERT(num_args == 2); 1254 ASSERT(num_args == 2);
1263 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right 1255 __ movq(RCX, Address(RSP, +1 * kWordSize)); // Right
1264 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. 1256 __ movq(RAX, Address(RSP, +2 * kWordSize)); // Left.
1265 __ movq(R13, RCX); 1257 __ movq(R13, RCX);
1266 __ orq(R13, RAX); 1258 __ orq(R13, RAX);
1267 __ testq(R13, Immediate(kSmiTagMask)); 1259 __ testq(R13, Immediate(kSmiTagMask));
1268 __ j(NOT_ZERO, not_smi_or_overflow); 1260 __ j(NOT_ZERO, not_smi_or_overflow);
1269 switch (kind) { 1261 switch (kind) {
1270 case Token::kADD: { 1262 case Token::kADD: {
1271 __ addq(RAX, RCX); 1263 __ addq(RAX, RCX);
1272 __ j(OVERFLOW, not_smi_or_overflow); 1264 __ j(OVERFLOW, not_smi_or_overflow);
1273 break; 1265 break;
1274 } 1266 }
1275 case Token::kSUB: { 1267 case Token::kSUB: {
1276 __ subq(RAX, RCX); 1268 __ subq(RAX, RCX);
1277 __ j(OVERFLOW, not_smi_or_overflow); 1269 __ j(OVERFLOW, not_smi_or_overflow);
1278 break; 1270 break;
1279 } 1271 }
1280 case Token::kEQ: { 1272 case Token::kEQ: {
1281 Label done, is_true; 1273 Label done, is_true;
1282 __ cmpq(RAX, RCX); 1274 __ cmpq(RAX, RCX);
1283 __ j(EQUAL, &is_true, Assembler::kNearJump); 1275 __ j(EQUAL, &is_true, Assembler::kNearJump);
1284 __ LoadObject(RAX, Bool::False()); 1276 __ LoadObject(RAX, Bool::False());
1285 __ jmp(&done, Assembler::kNearJump); 1277 __ jmp(&done, Assembler::kNearJump);
1286 __ Bind(&is_true); 1278 __ Bind(&is_true);
1287 __ LoadObject(RAX, Bool::True()); 1279 __ LoadObject(RAX, Bool::True());
1288 __ Bind(&done); 1280 __ Bind(&done);
1289 break; 1281 break;
1290 } 1282 }
1291 default: UNIMPLEMENTED(); 1283 default:
1284 UNIMPLEMENTED();
1292 } 1285 }
1293 1286
1294 // RBX: IC data object (preserved). 1287 // RBX: IC data object (preserved).
1295 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); 1288 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
1296 // R13: ic_data_array with check entries: classes and target functions. 1289 // R13: ic_data_array with check entries: classes and target functions.
1297 __ leaq(R13, FieldAddress(R13, Array::data_offset())); 1290 __ leaq(R13, FieldAddress(R13, Array::data_offset()));
1298 // R13: points directly to the first ic data array element. 1291 // R13: points directly to the first ic data array element.
1299 #if defined(DEBUG) 1292 #if defined(DEBUG)
1300 // Check that first entry is for Smi/Smi. 1293 // Check that first entry is for Smi/Smi.
1301 Label error, ok; 1294 Label error, ok;
1302 const Immediate& imm_smi_cid = 1295 const Immediate& imm_smi_cid =
1303 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid))); 1296 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
1304 __ cmpq(Address(R13, 0 * kWordSize), imm_smi_cid); 1297 __ cmpq(Address(R13, 0 * kWordSize), imm_smi_cid);
1305 __ j(NOT_EQUAL, &error, Assembler::kNearJump); 1298 __ j(NOT_EQUAL, &error, Assembler::kNearJump);
1306 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid); 1299 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid);
1307 __ j(EQUAL, &ok, Assembler::kNearJump); 1300 __ j(EQUAL, &ok, Assembler::kNearJump);
1308 __ Bind(&error); 1301 __ Bind(&error);
(...skipping 26 matching lines...) Expand all
1335 // - Match found -> jump to target. 1328 // - Match found -> jump to target.
1336 // - Match not found -> jump to IC miss. 1329 // - Match not found -> jump to IC miss.
1337 void StubCode::GenerateNArgsCheckInlineCacheStub( 1330 void StubCode::GenerateNArgsCheckInlineCacheStub(
1338 Assembler* assembler, 1331 Assembler* assembler,
1339 intptr_t num_args, 1332 intptr_t num_args,
1340 const RuntimeEntry& handle_ic_miss, 1333 const RuntimeEntry& handle_ic_miss,
1341 Token::Kind kind, 1334 Token::Kind kind,
1342 bool optimized) { 1335 bool optimized) {
1343 ASSERT(num_args > 0); 1336 ASSERT(num_args > 0);
1344 #if defined(DEBUG) 1337 #if defined(DEBUG)
1345 { Label ok; 1338 {
1339 Label ok;
1346 // Check that the IC data array has NumArgsTested() == num_args. 1340 // Check that the IC data array has NumArgsTested() == num_args.
1347 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1341 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1348 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); 1342 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
1349 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1343 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1350 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); 1344 __ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
1351 __ cmpq(RCX, Immediate(num_args)); 1345 __ cmpq(RCX, Immediate(num_args));
1352 __ j(EQUAL, &ok, Assembler::kNearJump); 1346 __ j(EQUAL, &ok, Assembler::kNearJump);
1353 __ Stop("Incorrect stub for IC data"); 1347 __ Stop("Incorrect stub for IC data");
1354 __ Bind(&ok); 1348 __ Bind(&ok);
1355 } 1349 }
1356 #endif // DEBUG 1350 #endif // DEBUG
1357 1351
1358 Label stepping, done_stepping; 1352 Label stepping, done_stepping;
1359 if (FLAG_support_debugger && !optimized) { 1353 if (FLAG_support_debugger && !optimized) {
1360 __ Comment("Check single stepping"); 1354 __ Comment("Check single stepping");
1361 __ LoadIsolate(RAX); 1355 __ LoadIsolate(RAX);
1362 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); 1356 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0));
1363 __ j(NOT_EQUAL, &stepping); 1357 __ j(NOT_EQUAL, &stepping);
1364 __ Bind(&done_stepping); 1358 __ Bind(&done_stepping);
1365 } 1359 }
1366 1360
1367 Label not_smi_or_overflow; 1361 Label not_smi_or_overflow;
1368 if (kind != Token::kILLEGAL) { 1362 if (kind != Token::kILLEGAL) {
1369 EmitFastSmiOp( 1363 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1370 assembler,
1371 kind,
1372 num_args,
1373 &not_smi_or_overflow);
1374 } 1364 }
1375 __ Bind(&not_smi_or_overflow); 1365 __ Bind(&not_smi_or_overflow);
1376 1366
1377 __ Comment("Extract ICData initial values and receiver cid"); 1367 __ Comment("Extract ICData initial values and receiver cid");
1378 // Load arguments descriptor into R10. 1368 // Load arguments descriptor into R10.
1379 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1369 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1380 // Loop that checks if there is an IC data match. 1370 // Loop that checks if there is an IC data match.
1381 Label loop, update, test, found; 1371 Label loop, update, test, found;
1382 // RBX: IC data object (preserved). 1372 // RBX: IC data object (preserved).
1383 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); 1373 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
1384 // R13: ic_data_array with check entries: classes and target functions. 1374 // R13: ic_data_array with check entries: classes and target functions.
1385 __ leaq(R13, FieldAddress(R13, Array::data_offset())); 1375 __ leaq(R13, FieldAddress(R13, Array::data_offset()));
1386 // R13: points directly to the first ic data array element. 1376 // R13: points directly to the first ic data array element.
1387 1377
1388 // Get the receiver's class ID (first read number of arguments from 1378 // Get the receiver's class ID (first read number of arguments from
1389 // arguments descriptor array and then access the receiver from the stack). 1379 // arguments descriptor array and then access the receiver from the stack).
1390 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1380 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1391 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. 1381 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1392 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1382 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1393 // RAX: receiver's class ID as smi. 1383 // RAX: receiver's class ID as smi.
1394 __ movq(R9, Address(R13, 0)); // First class ID (Smi) to check. 1384 __ movq(R9, Address(R13, 0)); // First class ID (Smi) to check.
1395 __ jmp(&test); 1385 __ jmp(&test);
1396 1386
1397 __ Comment("ICData loop"); 1387 __ Comment("ICData loop");
1398 __ Bind(&loop); 1388 __ Bind(&loop);
1399 for (int i = 0; i < num_args; i++) { 1389 for (int i = 0; i < num_args; i++) {
1400 if (i > 0) { 1390 if (i > 0) {
1401 // If not the first, load the next argument's class ID. 1391 // If not the first, load the next argument's class ID.
1402 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1392 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1403 __ movq(R9, Address(RSP, RAX, TIMES_4, - i * kWordSize)); 1393 __ movq(R9, Address(RSP, RAX, TIMES_4, -i * kWordSize));
1404 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1394 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1405 // RAX: next argument class ID (smi). 1395 // RAX: next argument class ID (smi).
1406 __ movq(R9, Address(R13, i * kWordSize)); 1396 __ movq(R9, Address(R13, i * kWordSize));
1407 // R9: next class ID to check (smi). 1397 // R9: next class ID to check (smi).
1408 } 1398 }
1409 __ cmpq(RAX, R9); // Class id match? 1399 __ cmpq(RAX, R9); // Class id match?
1410 if (i < (num_args - 1)) { 1400 if (i < (num_args - 1)) {
1411 __ j(NOT_EQUAL, &update); // Continue. 1401 __ j(NOT_EQUAL, &update); // Continue.
1412 } else { 1402 } else {
1413 // Last check, all checks before matched. 1403 // Last check, all checks before matched.
1414 __ j(EQUAL, &found); // Break. 1404 __ j(EQUAL, &found); // Break.
1415 } 1405 }
1416 } 1406 }
1417 __ Bind(&update); 1407 __ Bind(&update);
1418 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1408 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1419 if (num_args > 1) { 1409 if (num_args > 1) {
1420 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1410 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1421 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); 1411 __ movq(R9, Address(RSP, RAX, TIMES_4, 0));
1422 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1412 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1423 } 1413 }
1424 1414
1425 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1415 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1426 __ addq(R13, Immediate(entry_size)); // Next entry. 1416 __ addq(R13, Immediate(entry_size)); // Next entry.
1427 __ movq(R9, Address(R13, 0)); // Next class ID. 1417 __ movq(R9, Address(R13, 0)); // Next class ID.
1428 1418
1429 __ Bind(&test); 1419 __ Bind(&test);
1430 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1420 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1431 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1421 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1432 1422
1433 __ Comment("IC miss"); 1423 __ Comment("IC miss");
1434 // Compute address of arguments (first read number of arguments from 1424 // Compute address of arguments (first read number of arguments from
1435 // arguments descriptor array and then compute address on the stack). 1425 // arguments descriptor array and then compute address on the stack).
1436 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1426 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1437 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1427 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1438 __ EnterStubFrame(); 1428 __ EnterStubFrame();
1439 __ pushq(R10); // Preserve arguments descriptor array. 1429 __ pushq(R10); // Preserve arguments descriptor array.
1440 __ pushq(RBX); // Preserve IC data object. 1430 __ pushq(RBX); // Preserve IC data object.
1441 __ pushq(Immediate(0)); // Result slot. 1431 __ pushq(Immediate(0)); // Result slot.
1442 // Push call arguments. 1432 // Push call arguments.
1443 for (intptr_t i = 0; i < num_args; i++) { 1433 for (intptr_t i = 0; i < num_args; i++) {
1444 __ movq(RCX, Address(RAX, -kWordSize * i)); 1434 __ movq(RCX, Address(RAX, -kWordSize * i));
1445 __ pushq(RCX); 1435 __ pushq(RCX);
1446 } 1436 }
1447 __ pushq(RBX); // Pass IC data object. 1437 __ pushq(RBX); // Pass IC data object.
1448 __ CallRuntime(handle_ic_miss, num_args + 1); 1438 __ CallRuntime(handle_ic_miss, num_args + 1);
1449 // Remove the call arguments pushed earlier, including the IC data object. 1439 // Remove the call arguments pushed earlier, including the IC data object.
1450 for (intptr_t i = 0; i < num_args + 1; i++) { 1440 for (intptr_t i = 0; i < num_args + 1; i++) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 // RBX: Inline cache data object. 1494 // RBX: Inline cache data object.
1505 // TOS(0): Return address. 1495 // TOS(0): Return address.
1506 // Inline cache data object structure: 1496 // Inline cache data object structure:
1507 // 0: function-name 1497 // 0: function-name
1508 // 1: N, number of arguments checked. 1498 // 1: N, number of arguments checked.
1509 // 2 .. (length - 1): group of checks, each check containing: 1499 // 2 .. (length - 1): group of checks, each check containing:
1510 // - N classes. 1500 // - N classes.
1511 // - 1 target function. 1501 // - 1 target function.
1512 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1502 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1513 GenerateUsageCounterIncrement(assembler, RCX); 1503 GenerateUsageCounterIncrement(assembler, RCX);
1514 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1504 GenerateNArgsCheckInlineCacheStub(
1515 kInlineCacheMissHandlerOneArgRuntimeEntry, 1505 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1516 Token::kILLEGAL);
1517 } 1506 }
1518 1507
1519 1508
1520 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1509 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1521 GenerateUsageCounterIncrement(assembler, RCX); 1510 GenerateUsageCounterIncrement(assembler, RCX);
1522 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1511 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1523 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1512 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1524 Token::kILLEGAL); 1513 Token::kILLEGAL);
1525 } 1514 }
1526 1515
1527 1516
1528 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { 1517 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1529 GenerateUsageCounterIncrement(assembler, RCX); 1518 GenerateUsageCounterIncrement(assembler, RCX);
1530 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1519 GenerateNArgsCheckInlineCacheStub(
1531 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1520 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1532 Token::kADD);
1533 } 1521 }
1534 1522
1535 1523
1536 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { 1524 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1537 GenerateUsageCounterIncrement(assembler, RCX); 1525 GenerateUsageCounterIncrement(assembler, RCX);
1538 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1526 GenerateNArgsCheckInlineCacheStub(
1539 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1527 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1540 Token::kSUB);
1541 } 1528 }
1542 1529
1543 1530
1544 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { 1531 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1545 GenerateUsageCounterIncrement(assembler, RCX); 1532 GenerateUsageCounterIncrement(assembler, RCX);
1546 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1533 GenerateNArgsCheckInlineCacheStub(
1547 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1534 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1548 Token::kEQ);
1549 } 1535 }
1550 1536
1551 1537
1552 // Use inline cache data array to invoke the target or continue in inline 1538 // Use inline cache data array to invoke the target or continue in inline
1553 // cache miss handler. Stub for 1-argument check (receiver class). 1539 // cache miss handler. Stub for 1-argument check (receiver class).
1554 // RDI: function which counter needs to be incremented. 1540 // RDI: function which counter needs to be incremented.
1555 // RBX: Inline cache data object. 1541 // RBX: Inline cache data object.
1556 // TOS(0): Return address. 1542 // TOS(0): Return address.
1557 // Inline cache data object structure: 1543 // Inline cache data object structure:
1558 // 0: function-name 1544 // 0: function-name
1559 // 1: N, number of arguments checked. 1545 // 1: N, number of arguments checked.
1560 // 2 .. (length - 1): group of checks, each check containing: 1546 // 2 .. (length - 1): group of checks, each check containing:
1561 // - N classes. 1547 // - N classes.
1562 // - 1 target function. 1548 // - 1 target function.
1563 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1549 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1564 Assembler* assembler) { 1550 Assembler* assembler) {
1565 GenerateOptimizedUsageCounterIncrement(assembler); 1551 GenerateOptimizedUsageCounterIncrement(assembler);
1566 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1552 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1567 kInlineCacheMissHandlerOneArgRuntimeEntry, 1553 kInlineCacheMissHandlerOneArgRuntimeEntry,
1568 Token::kILLEGAL, 1554 Token::kILLEGAL, true /* optimized */);
1569 true /* optimized */);
1570 } 1555 }
1571 1556
1572 1557
1573 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1558 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1574 Assembler* assembler) { 1559 Assembler* assembler) {
1575 GenerateOptimizedUsageCounterIncrement(assembler); 1560 GenerateOptimizedUsageCounterIncrement(assembler);
1576 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1561 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1577 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1562 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1578 Token::kILLEGAL, 1563 Token::kILLEGAL, true /* optimized */);
1579 true /* optimized */);
1580 } 1564 }
1581 1565
1582 1566
1583 // Intermediary stub between a static call and its target. ICData contains 1567 // Intermediary stub between a static call and its target. ICData contains
1584 // the target function and the call count. 1568 // the target function and the call count.
1585 // RBX: ICData 1569 // RBX: ICData
1586 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1570 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1587 GenerateUsageCounterIncrement(assembler, RCX); 1571 GenerateUsageCounterIncrement(assembler, RCX);
1588 #if defined(DEBUG) 1572 #if defined(DEBUG)
1589 { Label ok; 1573 {
1574 Label ok;
1590 // Check that the IC data array has NumArgsTested() == 0. 1575 // Check that the IC data array has NumArgsTested() == 0.
1591 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1576 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1592 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); 1577 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
1593 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1578 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1594 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); 1579 __ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
1595 __ cmpq(RCX, Immediate(0)); 1580 __ cmpq(RCX, Immediate(0));
1596 __ j(EQUAL, &ok, Assembler::kNearJump); 1581 __ j(EQUAL, &ok, Assembler::kNearJump);
1597 __ Stop("Incorrect IC data for unoptimized static call"); 1582 __ Stop("Incorrect IC data for unoptimized static call");
1598 __ Bind(&ok); 1583 __ Bind(&ok);
1599 } 1584 }
1600 #endif // DEBUG 1585 #endif // DEBUG
1601 1586
1602 // Check single stepping. 1587 // Check single stepping.
1603 Label stepping, done_stepping; 1588 Label stepping, done_stepping;
1604 if (FLAG_support_debugger) { 1589 if (FLAG_support_debugger) {
1605 __ LoadIsolate(RAX); 1590 __ LoadIsolate(RAX);
1606 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); 1591 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
1607 __ cmpq(RAX, Immediate(0)); 1592 __ cmpq(RAX, Immediate(0));
1608 #if defined(DEBUG) 1593 #if defined(DEBUG)
1609 static const bool kJumpLength = Assembler::kFarJump; 1594 static const bool kJumpLength = Assembler::kFarJump;
1610 #else 1595 #else
1611 static const bool kJumpLength = Assembler::kNearJump; 1596 static const bool kJumpLength = Assembler::kNearJump;
1612 #endif // DEBUG 1597 #endif // DEBUG
1613 __ j(NOT_EQUAL, &stepping, kJumpLength); 1598 __ j(NOT_EQUAL, &stepping, kJumpLength);
1614 __ Bind(&done_stepping); 1599 __ Bind(&done_stepping);
1615 } 1600 }
1616 1601
1617 // RBX: IC data object (preserved). 1602 // RBX: IC data object (preserved).
1618 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1603 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1619 // R12: ic_data_array with entries: target functions and count. 1604 // R12: ic_data_array with entries: target functions and count.
1620 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1605 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1621 // R12: points directly to the first ic data array element. 1606 // R12: points directly to the first ic data array element.
(...skipping 27 matching lines...) Expand all
1649 __ RestoreCodePointer(); 1634 __ RestoreCodePointer();
1650 __ LeaveStubFrame(); 1635 __ LeaveStubFrame();
1651 __ jmp(&done_stepping, Assembler::kNearJump); 1636 __ jmp(&done_stepping, Assembler::kNearJump);
1652 } 1637 }
1653 } 1638 }
1654 1639
1655 1640
1656 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1641 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1657 GenerateUsageCounterIncrement(assembler, RCX); 1642 GenerateUsageCounterIncrement(assembler, RCX);
1658 GenerateNArgsCheckInlineCacheStub( 1643 GenerateNArgsCheckInlineCacheStub(
1659 assembler, 1644 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1660 1,
1661 kStaticCallMissHandlerOneArgRuntimeEntry,
1662 Token::kILLEGAL);
1663 } 1645 }
1664 1646
1665 1647
1666 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1648 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1667 GenerateUsageCounterIncrement(assembler, RCX); 1649 GenerateUsageCounterIncrement(assembler, RCX);
1668 GenerateNArgsCheckInlineCacheStub(assembler, 1650 GenerateNArgsCheckInlineCacheStub(
1669 2, 1651 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1670 kStaticCallMissHandlerTwoArgsRuntimeEntry,
1671 Token::kILLEGAL);
1672 } 1652 }
1673 1653
1674 1654
1675 // Stub for compiling a function and jumping to the compiled code. 1655 // Stub for compiling a function and jumping to the compiled code.
1676 // RCX: IC-Data (for methods). 1656 // RCX: IC-Data (for methods).
1677 // R10: Arguments descriptor. 1657 // R10: Arguments descriptor.
1678 // RAX: Function. 1658 // RAX: Function.
1679 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1659 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1680 __ EnterStubFrame(); 1660 __ EnterStubFrame();
1681 __ pushq(R10); // Preserve arguments descriptor array. 1661 __ pushq(R10); // Preserve arguments descriptor array.
1682 __ pushq(RBX); // Preserve IC data object. 1662 __ pushq(RBX); // Preserve IC data object.
1683 __ pushq(RAX); // Pass function. 1663 __ pushq(RAX); // Pass function.
1684 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1664 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1685 __ popq(RAX); // Restore function. 1665 __ popq(RAX); // Restore function.
1686 __ popq(RBX); // Restore IC data array. 1666 __ popq(RBX); // Restore IC data array.
1687 __ popq(R10); // Restore arguments descriptor array. 1667 __ popq(R10); // Restore arguments descriptor array.
1688 __ LeaveStubFrame(); 1668 __ LeaveStubFrame();
1689 1669
1690 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); 1670 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1691 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset())); 1671 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset()));
1692 __ jmp(RAX); 1672 __ jmp(RAX);
1693 } 1673 }
1694 1674
1695 1675
1696 // RBX: Contains an ICData. 1676 // RBX: Contains an ICData.
1697 // TOS(0): return address (Dart code). 1677 // TOS(0): return address (Dart code).
1698 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1678 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1699 __ EnterStubFrame(); 1679 __ EnterStubFrame();
1700 __ pushq(RBX); // Preserve IC data. 1680 __ pushq(RBX); // Preserve IC data.
1701 __ pushq(Immediate(0)); // Result slot. 1681 __ pushq(Immediate(0)); // Result slot.
1702 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1682 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1703 __ popq(CODE_REG); // Original stub. 1683 __ popq(CODE_REG); // Original stub.
1704 __ popq(RBX); // Restore IC data. 1684 __ popq(RBX); // Restore IC data.
1705 __ LeaveStubFrame(); 1685 __ LeaveStubFrame();
1706 1686
1707 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 1687 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
1708 __ jmp(RAX); // Jump to original stub. 1688 __ jmp(RAX); // Jump to original stub.
1709 } 1689 }
1710 1690
1711 1691
1712 // TOS(0): return address (Dart code). 1692 // TOS(0): return address (Dart code).
1713 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1693 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1714 __ EnterStubFrame(); 1694 __ EnterStubFrame();
1715 __ pushq(Immediate(0)); // Result slot. 1695 __ pushq(Immediate(0)); // Result slot.
1716 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1696 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1717 __ popq(CODE_REG); // Original stub. 1697 __ popq(CODE_REG); // Original stub.
1718 __ LeaveStubFrame(); 1698 __ LeaveStubFrame();
1719 1699
1720 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 1700 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
1721 __ jmp(RAX); // Jump to original stub. 1701 __ jmp(RAX); // Jump to original stub.
1722 } 1702 }
1723 1703
1724 1704
1725 // Called only from unoptimized code. 1705 // Called only from unoptimized code.
1726 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { 1706 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
1727 // Check single stepping. 1707 // Check single stepping.
1728 Label stepping, done_stepping; 1708 Label stepping, done_stepping;
1729 __ LoadIsolate(RAX); 1709 __ LoadIsolate(RAX);
1730 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); 1710 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
1731 __ cmpq(RAX, Immediate(0)); 1711 __ cmpq(RAX, Immediate(0));
(...skipping 20 matching lines...) Expand all
1752 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; 1732 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize;
1753 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; 1733 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
1754 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1734 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1755 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); 1735 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes));
1756 __ LoadObject(R9, Object::null_object()); 1736 __ LoadObject(R9, Object::null_object());
1757 if (n > 1) { 1737 if (n > 1) {
1758 __ LoadClass(R10, RAX); 1738 __ LoadClass(R10, RAX);
1759 // Compute instance type arguments into R13. 1739 // Compute instance type arguments into R13.
1760 Label has_no_type_arguments; 1740 Label has_no_type_arguments;
1761 __ movq(R13, R9); 1741 __ movq(R13, R9);
1762 __ movl(RDI, FieldAddress(R10, 1742 __ movl(RDI,
1763 Class::type_arguments_field_offset_in_words_offset())); 1743 FieldAddress(R10,
1744 Class::type_arguments_field_offset_in_words_offset()));
1764 __ cmpl(RDI, Immediate(Class::kNoTypeArguments)); 1745 __ cmpl(RDI, Immediate(Class::kNoTypeArguments));
1765 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1746 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
1766 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); 1747 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0));
1767 __ Bind(&has_no_type_arguments); 1748 __ Bind(&has_no_type_arguments);
1768 } 1749 }
1769 __ LoadClassId(R10, RAX); 1750 __ LoadClassId(R10, RAX);
1770 // RAX: instance, R10: instance class id. 1751 // RAX: instance, R10: instance class id.
1771 // R13: instance type arguments or null, used only if n > 1. 1752 // R13: instance type arguments or null, used only if n > 1.
1772 __ movq(RDX, Address(RSP, kCacheOffsetInBytes)); 1753 __ movq(RDX, Address(RSP, kCacheOffsetInBytes));
1773 // RDX: SubtypeTestCache. 1754 // RDX: SubtypeTestCache.
1774 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset())); 1755 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset()));
1775 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1756 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag));
1776 // RDX: Entry start. 1757 // RDX: Entry start.
1777 // R10: instance class id. 1758 // R10: instance class id.
1778 // R13: instance type arguments. 1759 // R13: instance type arguments.
1779 Label loop, found, not_found, next_iteration; 1760 Label loop, found, not_found, next_iteration;
1780 __ SmiTag(R10); 1761 __ SmiTag(R10);
1781 __ cmpq(R10, Immediate(Smi::RawValue(kClosureCid))); 1762 __ cmpq(R10, Immediate(Smi::RawValue(kClosureCid)));
1782 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1763 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1783 __ movq(R10, FieldAddress(RAX, Closure::function_offset())); 1764 __ movq(R10, FieldAddress(RAX, Closure::function_offset()));
1784 // R10: instance class id as Smi or function. 1765 // R10: instance class id as Smi or function.
1785 __ Bind(&loop); 1766 __ Bind(&loop);
1786 __ movq(RDI, 1767 __ movq(RDI, Address(RDX, kWordSize *
1787 Address(RDX, 1768 SubtypeTestCache::kInstanceClassIdOrFunction));
1788 kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
1789 __ cmpq(RDI, R9); 1769 __ cmpq(RDI, R9);
1790 __ j(EQUAL, &not_found, Assembler::kNearJump); 1770 __ j(EQUAL, &not_found, Assembler::kNearJump);
1791 __ cmpq(RDI, R10); 1771 __ cmpq(RDI, R10);
1792 if (n == 1) { 1772 if (n == 1) {
1793 __ j(EQUAL, &found, Assembler::kNearJump); 1773 __ j(EQUAL, &found, Assembler::kNearJump);
1794 } else { 1774 } else {
1795 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1775 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1796 __ movq(RDI, 1776 __ movq(RDI,
1797 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1777 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1798 __ cmpq(RDI, R13); 1778 __ cmpq(RDI, R13);
1799 if (n == 2) { 1779 if (n == 2) {
1800 __ j(EQUAL, &found, Assembler::kNearJump); 1780 __ j(EQUAL, &found, Assembler::kNearJump);
1801 } else { 1781 } else {
1802 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1782 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1803 __ movq(RDI, 1783 __ movq(RDI,
1804 Address(RDX, 1784 Address(RDX, kWordSize *
1805 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments)); 1785 SubtypeTestCache::kInstantiatorTypeArguments));
1806 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes)); 1786 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes));
1807 __ j(EQUAL, &found, Assembler::kNearJump); 1787 __ j(EQUAL, &found, Assembler::kNearJump);
1808 } 1788 }
1809 } 1789 }
1810 1790
1811 __ Bind(&next_iteration); 1791 __ Bind(&next_iteration);
1812 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1792 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1813 __ jmp(&loop, Assembler::kNearJump); 1793 __ jmp(&loop, Assembler::kNearJump);
1814 // Fall through to not found. 1794 // Fall through to not found.
1815 __ Bind(&not_found); 1795 __ Bind(&not_found);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 Register stacktrace_reg = CallingConventions::kArg5Reg; 1868 Register stacktrace_reg = CallingConventions::kArg5Reg;
1889 __ movq(THR, CallingConventions::kArg6Reg); 1869 __ movq(THR, CallingConventions::kArg6Reg);
1890 #endif 1870 #endif
1891 __ movq(RBP, CallingConventions::kArg3Reg); 1871 __ movq(RBP, CallingConventions::kArg3Reg);
1892 __ movq(RSP, CallingConventions::kArg2Reg); 1872 __ movq(RSP, CallingConventions::kArg2Reg);
1893 __ movq(kStackTraceObjectReg, stacktrace_reg); 1873 __ movq(kStackTraceObjectReg, stacktrace_reg);
1894 __ movq(kExceptionObjectReg, CallingConventions::kArg4Reg); 1874 __ movq(kExceptionObjectReg, CallingConventions::kArg4Reg);
1895 // Set the tag. 1875 // Set the tag.
1896 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); 1876 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
1897 // Clear top exit frame. 1877 // Clear top exit frame.
1898 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), 1878 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
1899 Immediate(0));
1900 // Restore the pool pointer. 1879 // Restore the pool pointer.
1901 __ RestoreCodePointer(); 1880 __ RestoreCodePointer();
1902 __ LoadPoolPointer(PP); 1881 __ LoadPoolPointer(PP);
1903 __ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code. 1882 __ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code.
1904 } 1883 }
1905 1884
1906 1885
1907 // Calls to the runtime to optimize the given function. 1886 // Calls to the runtime to optimize the given function.
1908 // RDI: function to be reoptimized. 1887 // RDI: function to be reoptimized.
1909 // R10: argument descriptor (preserved). 1888 // R10: argument descriptor (preserved).
1910 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1889 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1911 __ EnterStubFrame(); 1890 __ EnterStubFrame();
1912 __ pushq(R10); // Preserve args descriptor. 1891 __ pushq(R10); // Preserve args descriptor.
1913 __ pushq(Immediate(0)); // Result slot. 1892 __ pushq(Immediate(0)); // Result slot.
1914 __ pushq(RDI); // Arg0: function to optimize 1893 __ pushq(RDI); // Arg0: function to optimize
1915 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1894 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1916 __ popq(RAX); // Disard argument. 1895 __ popq(RAX); // Disard argument.
1917 __ popq(RAX); // Get Code object. 1896 __ popq(RAX); // Get Code object.
1918 __ popq(R10); // Restore argument descriptor. 1897 __ popq(R10); // Restore argument descriptor.
1919 __ LeaveStubFrame(); 1898 __ LeaveStubFrame();
1920 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); 1899 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1921 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); 1900 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1922 __ jmp(RCX); 1901 __ jmp(RCX);
1923 __ int3(); 1902 __ int3();
1924 } 1903 }
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
2267 } 2246 }
2268 2247
2269 2248
2270 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2249 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2271 __ int3(); 2250 __ int3();
2272 } 2251 }
2273 2252
2274 } // namespace dart 2253 } // namespace dart
2275 2254
2276 #endif // defined TARGET_ARCH_X64 2255 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_mips_test.cc ('k') | runtime/vm/stub_code_x64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698