OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_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" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. | 76 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
77 __ call(RBX); | 77 __ call(RBX); |
78 | 78 |
79 // Reset exit frame information in Isolate structure. | 79 // Reset exit frame information in Isolate structure. |
80 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 80 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
81 | 81 |
82 // Load Context pointer from Isolate structure into RBX. | 82 // Load Context pointer from Isolate structure into RBX. |
83 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); | 83 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
84 | 84 |
85 // Reset Context pointer in Isolate structure. | 85 // Reset Context pointer in Isolate structure. |
86 const Immediate& raw_null = | 86 __ LoadObject(R12, Object::Handle(), PP); |
87 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 87 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
88 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | |
89 | 88 |
90 // Cache Context pointer into CTX while executing Dart code. | 89 // Cache Context pointer into CTX while executing Dart code. |
91 __ movq(CTX, RBX); | 90 __ movq(CTX, RBX); |
92 | 91 |
93 __ LeaveFrame(); | 92 __ LeaveFrame(); |
94 __ ret(); | 93 __ ret(); |
95 } | 94 } |
96 | 95 |
97 | 96 |
98 // Print the stop message. | 97 // Print the stop message. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 __ movq(RSI, RBX); // Pass pointer to function entrypoint. | 164 __ movq(RSI, RBX); // Pass pointer to function entrypoint. |
166 __ call(&NativeEntry::NativeCallWrapperLabel()); | 165 __ call(&NativeEntry::NativeCallWrapperLabel()); |
167 | 166 |
168 // Reset exit frame information in Isolate structure. | 167 // Reset exit frame information in Isolate structure. |
169 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 168 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
170 | 169 |
171 // Load Context pointer from Isolate structure into R8. | 170 // Load Context pointer from Isolate structure into R8. |
172 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 171 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
173 | 172 |
174 // Reset Context pointer in Isolate structure. | 173 // Reset Context pointer in Isolate structure. |
175 const Immediate& raw_null = | 174 __ LoadObject(R12, Object::Handle(), PP); |
176 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 175 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
177 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | |
178 | 176 |
179 // Cache Context pointer into CTX while executing Dart code. | 177 // Cache Context pointer into CTX while executing Dart code. |
180 __ movq(CTX, R8); | 178 __ movq(CTX, R8); |
181 | 179 |
182 __ LeaveFrame(); | 180 __ LeaveFrame(); |
183 __ ret(); | 181 __ ret(); |
184 } | 182 } |
185 | 183 |
186 | 184 |
187 // Input parameters: | 185 // Input parameters: |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. | 231 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. |
234 __ call(RBX); | 232 __ call(RBX); |
235 | 233 |
236 // Reset exit frame information in Isolate structure. | 234 // Reset exit frame information in Isolate structure. |
237 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 235 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
238 | 236 |
239 // Load Context pointer from Isolate structure into R8. | 237 // Load Context pointer from Isolate structure into R8. |
240 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 238 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
241 | 239 |
242 // Reset Context pointer in Isolate structure. | 240 // Reset Context pointer in Isolate structure. |
243 const Immediate& raw_null = | 241 __ LoadObject(R12, Object::Handle(), PP); |
244 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 242 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
245 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | |
246 | 243 |
247 // Cache Context pointer into CTX while executing Dart code. | 244 // Cache Context pointer into CTX while executing Dart code. |
248 __ movq(CTX, R8); | 245 __ movq(CTX, R8); |
249 | 246 |
250 __ LeaveFrame(); | 247 __ LeaveFrame(); |
251 __ ret(); | 248 __ ret(); |
252 } | 249 } |
253 | 250 |
254 | 251 |
255 // Input parameters: | 252 // Input parameters: |
256 // R10: arguments descriptor array. | 253 // R10: arguments descriptor array. |
257 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 254 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
258 const Immediate& raw_null = | |
259 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
260 __ EnterStubFrame(); | 255 __ EnterStubFrame(); |
261 __ pushq(R10); // Preserve arguments descriptor array. | 256 __ pushq(R10); // Preserve arguments descriptor array. |
262 __ pushq(raw_null); // Setup space on stack for return value. | 257 // Setup space on stack for return value. |
| 258 __ PushObject(Object::Handle()); |
263 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 259 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
264 __ popq(RAX); // Get Code object result. | 260 __ popq(RAX); // Get Code object result. |
265 __ popq(R10); // Restore arguments descriptor array. | 261 __ popq(R10); // Restore arguments descriptor array. |
266 // 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. |
267 __ LeaveFrame(); | 263 __ LeaveFrame(); |
268 | 264 |
269 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 265 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
270 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 266 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
271 __ jmp(RBX); | 267 __ jmp(RBX); |
272 } | 268 } |
273 | 269 |
274 | 270 |
275 // Called from a static call only when an invalid code has been entered | 271 // Called from a static call only when an invalid code has been entered |
276 // (invalid because its function was optimized or deoptimized). | 272 // (invalid because its function was optimized or deoptimized). |
277 // R10: arguments descriptor array. | 273 // R10: arguments descriptor array. |
278 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 274 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
279 const Immediate& raw_null = | |
280 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
281 __ EnterStubFrame(); | 275 __ EnterStubFrame(); |
282 __ pushq(R10); // Preserve arguments descriptor array. | 276 __ pushq(R10); // Preserve arguments descriptor array. |
283 __ pushq(raw_null); // Setup space on stack for return value. | 277 // Setup space on stack for return value. |
| 278 __ PushObject(Object::Handle()); |
284 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 279 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
285 __ popq(RAX); // Get Code object. | 280 __ popq(RAX); // Get Code object. |
286 __ popq(R10); // Restore arguments descriptor array. | 281 __ popq(R10); // Restore arguments descriptor array. |
287 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 282 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
288 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 283 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
289 __ LeaveFrame(); | 284 __ LeaveFrame(); |
290 __ jmp(RAX); | 285 __ jmp(RAX); |
291 __ int3(); | 286 __ int3(); |
292 } | 287 } |
293 | 288 |
294 | 289 |
295 // Input parameters: | 290 // Input parameters: |
296 // R10: smi-tagged argument count, may be zero. | 291 // R10: smi-tagged argument count, may be zero. |
297 // RBP[kParamEndSlotFromFp + 1]: last argument. | 292 // RBP[kParamEndSlotFromFp + 1]: last argument. |
298 static void PushArgumentsArray(Assembler* assembler) { | 293 static void PushArgumentsArray(Assembler* assembler) { |
299 const Immediate& raw_null = | 294 __ LoadObject(R12, Object::Handle(), PP); |
300 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
301 | |
302 // Allocate array to store arguments of caller. | 295 // Allocate array to store arguments of caller. |
303 __ movq(RBX, raw_null); // Null element type for raw Array. | 296 __ movq(RBX, R12); // Null element type for raw Array. |
304 __ call(&StubCode::AllocateArrayLabel()); | 297 __ call(&StubCode::AllocateArrayLabel()); |
305 __ SmiUntag(R10); | 298 __ SmiUntag(R10); |
306 // RAX: newly allocated array. | 299 // RAX: newly allocated array. |
307 // R10: length of the array (was preserved by the stub). | 300 // R10: length of the array (was preserved by the stub). |
308 __ pushq(RAX); // Array is in RAX and on top of stack. | 301 __ pushq(RAX); // Array is in RAX and on top of stack. |
309 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); | 302 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); |
310 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 303 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
311 // R12: address of first argument on stack. | 304 // R12: address of first argument on stack. |
312 // RBX: address of first argument in array. | 305 // RBX: address of first argument in array. |
313 Label loop, loop_condition; | 306 Label loop, loop_condition; |
314 __ jmp(&loop_condition, Assembler::kNearJump); | 307 __ jmp(&loop_condition, Assembler::kNearJump); |
315 __ Bind(&loop); | 308 __ Bind(&loop); |
316 __ movq(RAX, Address(R12, 0)); | 309 __ movq(RAX, Address(R12, 0)); |
317 __ movq(Address(RBX, 0), RAX); | 310 __ movq(Address(RBX, 0), RAX); |
318 __ AddImmediate(RBX, Immediate(kWordSize)); | 311 __ AddImmediate(RBX, Immediate(kWordSize)); |
319 __ AddImmediate(R12, Immediate(-kWordSize)); | 312 __ AddImmediate(R12, Immediate(-kWordSize)); |
320 __ Bind(&loop_condition); | 313 __ Bind(&loop_condition); |
321 __ decq(R10); | 314 __ decq(R10); |
322 __ j(POSITIVE, &loop, Assembler::kNearJump); | 315 __ j(POSITIVE, &loop, Assembler::kNearJump); |
323 } | 316 } |
324 | 317 |
325 | 318 |
326 // Input parameters: | 319 // Input parameters: |
327 // RBX: ic-data. | 320 // RBX: ic-data. |
328 // R10: arguments descriptor array. | 321 // R10: arguments descriptor array. |
329 // Note: The receiver object is the first argument to the function being | 322 // Note: The receiver object is the first argument to the function being |
330 // called, the stub accesses the receiver from this location directly | 323 // called, the stub accesses the receiver from this location directly |
331 // when trying to resolve the call. | 324 // when trying to resolve the call. |
332 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 325 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
333 __ EnterStubFrame(); | 326 __ EnterStubFrameWithPP(); |
334 | 327 __ PushObject(Object::Handle()); // Space for the return value. |
335 const Immediate& raw_null = | |
336 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
337 __ pushq(raw_null); // Space for the return value. | |
338 | 328 |
339 // Push the receiver as an argument. Load the smi-tagged argument | 329 // Push the receiver as an argument. Load the smi-tagged argument |
340 // count into R13 to index the receiver in the stack. There are | 330 // count into R13 to index the receiver in the stack. There are |
341 // three words (null, stub's pc marker, saved fp) above the return | 331 // four words (null, stub's pc marker, saved pp, saved fp) above the return |
342 // address. | 332 // address. |
343 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 333 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
344 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); | 334 __ pushq(Address(RSP, R13, TIMES_4, (4 * kWordSize))); |
345 | 335 |
346 __ pushq(RBX); // Pass IC data object. | 336 __ pushq(RBX); // Pass IC data object. |
347 __ pushq(R10); // Pass arguments descriptor array. | 337 __ pushq(R10); // Pass arguments descriptor array. |
348 | 338 |
349 // Pass the call's arguments array. | 339 // Pass the call's arguments array. |
350 __ movq(R10, R13); // Smi-tagged arguments array length. | 340 __ movq(R10, R13); // Smi-tagged arguments array length. |
351 PushArgumentsArray(assembler); | 341 PushArgumentsArray(assembler); |
352 | 342 |
353 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry, 4); | 343 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry, 4); |
354 | 344 |
355 // Remove arguments. | 345 // Remove arguments. |
356 __ Drop(4); | 346 __ Drop(4); |
357 __ popq(RAX); // Get result into RAX. | 347 __ popq(RAX); // Get result into RAX. |
358 __ LeaveFrame(); | 348 __ LeaveFrameWithPP(); |
359 __ ret(); | 349 __ ret(); |
360 } | 350 } |
361 | 351 |
362 | 352 |
363 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 353 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
364 intptr_t deopt_reason, | 354 intptr_t deopt_reason, |
365 uword saved_registers_address); | 355 uword saved_registers_address); |
366 | 356 |
367 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); | 357 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
368 | 358 |
369 | 359 |
370 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. | 360 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. |
371 // This stub translates optimized frame into unoptimized frame. The optimized | 361 // This stub translates optimized frame into unoptimized frame. The optimized |
372 // frame can contain values in registers and on stack, the unoptimized | 362 // frame can contain values in registers and on stack, the unoptimized |
373 // frame contains all values on stack. | 363 // frame contains all values on stack. |
374 // Deoptimization occurs in following steps: | 364 // Deoptimization occurs in following steps: |
375 // - Push all registers that can contain values. | 365 // - Push all registers that can contain values. |
376 // - Call C routine to copy the stack and saved registers into temporary buffer. | 366 // - Call C routine to copy the stack and saved registers into temporary buffer. |
377 // - Adjust caller's frame to correct unoptimized frame size. | 367 // - Adjust caller's frame to correct unoptimized frame size. |
378 // - Fill the unoptimized frame. | 368 // - Fill the unoptimized frame. |
379 // - Materialize objects that require allocation (e.g. Double instances). | 369 // - Materialize objects that require allocation (e.g. Double instances). |
380 // GC can occur only after frame is fully rewritten. | 370 // GC can occur only after frame is fully rewritten. |
381 // Stack after EnterDartFrame(0) below: | 371 // Stack after EnterDartFrame(0, PP, kNoRegister) below: |
| 372 // +------------------+ |
| 373 // | Saved PP | <- PP |
382 // +------------------+ | 374 // +------------------+ |
383 // | PC marker | <- TOS | 375 // | PC marker | <- TOS |
384 // +------------------+ | 376 // +------------------+ |
385 // | Saved FP | <- FP of stub | 377 // | Saved FP | <- FP of stub |
386 // +------------------+ | 378 // +------------------+ |
387 // | return-address | (deoptimization point) | 379 // | return-address | (deoptimization point) |
388 // +------------------+ | 380 // +------------------+ |
389 // | ... | <- SP of optimized frame | 381 // | ... | <- SP of optimized frame |
390 // | 382 // |
391 // Parts of the code cannot GC, part of the code can GC. | 383 // Parts of the code cannot GC, part of the code can GC. |
392 static void GenerateDeoptimizationSequence(Assembler* assembler, | 384 static void GenerateDeoptimizationSequence(Assembler* assembler, |
393 bool preserve_result) { | 385 bool preserve_result) { |
394 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. | 386 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
395 __ EnterDartFrame(0); | 387 // is no need to set the correct PC marker or load PP, since they get patched. |
| 388 __ EnterFrame(0); |
| 389 __ pushq(Immediate(0)); |
| 390 __ pushq(PP); |
| 391 |
396 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 392 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
397 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 393 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
398 const intptr_t saved_result_slot_from_fp = | 394 const intptr_t saved_result_slot_from_fp = |
399 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); | 395 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); |
400 // Result in RAX is preserved as part of pushing all registers below. | 396 // Result in RAX is preserved as part of pushing all registers below. |
401 | 397 |
402 // Push registers in their enumeration order: lowest register number at | 398 // Push registers in their enumeration order: lowest register number at |
403 // lowest address. | 399 // lowest address. |
404 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 400 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
405 __ pushq(static_cast<Register>(i)); | 401 __ pushq(static_cast<Register>(i)); |
406 } | 402 } |
407 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); | 403 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); |
408 intptr_t offset = 0; | 404 intptr_t offset = 0; |
409 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 405 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
410 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 406 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
411 __ movups(Address(RSP, offset), xmm_reg); | 407 __ movups(Address(RSP, offset), xmm_reg); |
412 offset += kFpuRegisterSize; | 408 offset += kFpuRegisterSize; |
413 } | 409 } |
414 | 410 |
415 __ movq(RDI, RSP); // Pass address of saved registers block. | 411 __ movq(RDI, RSP); // Pass address of saved registers block. |
416 __ ReserveAlignedFrameSpace(0); | 412 __ ReserveAlignedFrameSpace(0); |
417 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); | 413 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); |
418 // Result (RAX) is stack-size (FP - SP) in bytes. | 414 // Result (RAX) is stack-size (FP - SP) in bytes. |
419 | 415 |
420 if (preserve_result) { | 416 if (preserve_result) { |
421 // Restore result into RBX temporarily. | 417 // Restore result into RBX temporarily. |
422 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); | 418 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); |
423 } | 419 } |
424 | 420 |
| 421 // There is a Dart Frame on the stack. We just need the PP. |
| 422 __ movq(PP, Address(RBP, -2 * kWordSize)); |
425 __ LeaveFrame(); | 423 __ LeaveFrame(); |
| 424 |
426 __ popq(RCX); // Preserve return address. | 425 __ popq(RCX); // Preserve return address. |
427 __ movq(RSP, RBP); // Discard optimized frame. | 426 __ movq(RSP, RBP); // Discard optimized frame. |
428 __ subq(RSP, RAX); // Reserve space for deoptimized frame. | 427 __ subq(RSP, RAX); // Reserve space for deoptimized frame. |
429 __ pushq(RCX); // Restore return address. | 428 __ pushq(RCX); // Restore return address. |
430 | 429 |
431 // Leaf runtime function DeoptimizeFillFrame expects a Dart frame. | 430 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
432 __ EnterDartFrame(0); | 431 // is no need to set the correct PC marker or load PP, since they get patched. |
| 432 __ EnterFrame(0); |
| 433 __ pushq(Immediate(0)); |
| 434 __ pushq(PP); |
| 435 |
433 if (preserve_result) { | 436 if (preserve_result) { |
434 __ pushq(RBX); // Preserve result as first local. | 437 __ pushq(RBX); // Preserve result as first local. |
435 } | 438 } |
436 __ ReserveAlignedFrameSpace(0); | 439 __ ReserveAlignedFrameSpace(0); |
437 __ movq(RDI, RBP); // Pass last FP as parameter in RDI. | 440 __ movq(RDI, RBP); // Pass last FP as parameter in RDI. |
438 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); | 441 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); |
439 if (preserve_result) { | 442 if (preserve_result) { |
440 // Restore result into RBX. | 443 // Restore result into RBX. |
441 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 444 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
442 } | 445 } |
443 // Code above cannot cause GC. | 446 // Code above cannot cause GC. |
| 447 // There is a Dart Frame on the stack. We just need the PP. |
| 448 __ movq(PP, Address(RBP, -2 * kWordSize)); |
444 __ LeaveFrame(); | 449 __ LeaveFrame(); |
445 | 450 |
446 // Frame is fully rewritten at this point and it is safe to perform a GC. | 451 // Frame is fully rewritten at this point and it is safe to perform a GC. |
447 // Materialize any objects that were deferred by FillFrame because they | 452 // Materialize any objects that were deferred by FillFrame because they |
448 // require allocation. | 453 // require allocation. |
449 __ EnterStubFrame(); | 454 __ EnterStubFrame(); |
450 if (preserve_result) { | 455 if (preserve_result) { |
451 __ pushq(RBX); // Preserve result, it will be GC-d here. | 456 __ pushq(RBX); // Preserve result, it will be GC-d here. |
452 } | 457 } |
453 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. | 458 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. |
(...skipping 25 matching lines...) Expand all Loading... |
479 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. | 484 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. |
480 } | 485 } |
481 | 486 |
482 | 487 |
483 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 488 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
484 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. | 489 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. |
485 } | 490 } |
486 | 491 |
487 | 492 |
488 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 493 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
489 __ EnterStubFrame(); | 494 __ EnterStubFrameWithPP(); |
490 // Load the receiver into RAX. The argument count in the arguments | 495 // Load the receiver into RAX. The argument count in the arguments |
491 // descriptor in R10 is a smi. | 496 // descriptor in R10 is a smi. |
492 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 497 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
493 // Two words (saved fp, stub's pc marker) in the stack above the return | 498 // Three words (saved pp, saved fp, stub's pc marker) |
494 // address. | 499 // in the stack above the return address. |
495 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); | 500 __ movq(RAX, Address(RSP, RAX, TIMES_4, |
| 501 kSavedAboveReturnAddress * kWordSize)); |
496 // Preserve IC data and arguments descriptor. | 502 // Preserve IC data and arguments descriptor. |
497 __ pushq(RBX); | 503 __ pushq(RBX); |
498 __ pushq(R10); | 504 __ pushq(R10); |
499 | 505 |
500 const Immediate& raw_null = | 506 // Space for the result of the runtime call. |
501 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 507 __ PushObject(Object::Handle()); |
502 __ pushq(raw_null); // Space for the result of the runtime call. | |
503 __ pushq(RAX); // Receiver. | 508 __ pushq(RAX); // Receiver. |
504 __ pushq(RBX); // IC data. | 509 __ pushq(RBX); // IC data. |
505 __ pushq(R10); // Arguments descriptor. | 510 __ pushq(R10); // Arguments descriptor. |
506 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); | 511 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); |
507 // Discard arguments. | 512 // Discard arguments. |
508 __ popq(RAX); | 513 __ popq(RAX); |
509 __ popq(RAX); | 514 __ popq(RAX); |
510 __ popq(RAX); | 515 __ popq(RAX); |
511 __ popq(RAX); // Return value from the runtime call (instructions). | 516 __ popq(RAX); // Return value from the runtime call (instructions). |
512 __ popq(R10); // Restore arguments descriptor. | 517 __ popq(R10); // Restore arguments descriptor. |
513 __ popq(RBX); // Restore IC data. | 518 __ popq(RBX); // Restore IC data. |
514 __ LeaveFrame(); | 519 __ LeaveFrameWithPP(); |
515 | 520 |
516 Label lookup; | 521 Label lookup; |
517 __ cmpq(RAX, raw_null); | 522 __ CompareObject(RAX, Object::Handle()); |
518 __ j(EQUAL, &lookup, Assembler::kNearJump); | 523 __ j(EQUAL, &lookup, Assembler::kNearJump); |
519 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 524 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
520 __ jmp(RAX); | 525 __ jmp(RAX); |
521 | 526 |
522 __ Bind(&lookup); | 527 __ Bind(&lookup); |
523 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 528 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
524 } | 529 } |
525 | 530 |
526 | 531 |
527 // Called for inline allocation of arrays. | 532 // Called for inline allocation of arrays. |
528 // Input parameters: | 533 // Input parameters: |
529 // R10 : Array length as Smi. | 534 // R10 : Array length as Smi. |
530 // RBX : array element type (either NULL or an instantiated type). | 535 // RBX : array element type (either NULL or an instantiated type). |
531 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 536 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
532 // The newly allocated object is returned in RAX. | 537 // The newly allocated object is returned in RAX. |
533 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 538 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
534 Label slow_case; | 539 Label slow_case; |
535 const Immediate& raw_null = | |
536 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
537 | 540 |
538 if (FLAG_inline_alloc) { | 541 if (FLAG_inline_alloc) { |
539 // Compute the size to be allocated, it is based on the array length | 542 // Compute the size to be allocated, it is based on the array length |
540 // and is computed as: | 543 // and is computed as: |
541 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 544 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
542 // Assert that length is a Smi. | 545 // Assert that length is a Smi. |
543 __ testq(R10, Immediate(kSmiTagMask)); | 546 __ testq(R10, Immediate(kSmiTagMask)); |
544 if (FLAG_use_slow_path) { | 547 if (FLAG_use_slow_path) { |
545 __ jmp(&slow_case); | 548 __ jmp(&slow_case); |
546 } else { | 549 } else { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | 618 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); |
616 } | 619 } |
617 | 620 |
618 // Initialize all array elements to raw_null. | 621 // Initialize all array elements to raw_null. |
619 // RAX: new object start as a tagged pointer. | 622 // RAX: new object start as a tagged pointer. |
620 // R12: new object end address. | 623 // R12: new object end address. |
621 // R10: Array length as Smi. | 624 // R10: Array length as Smi. |
622 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 625 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
623 // RBX: iterator which initially points to the start of the variable | 626 // RBX: iterator which initially points to the start of the variable |
624 // data area to be initialized. | 627 // data area to be initialized. |
| 628 __ LoadObject(R13, Object::Handle(), PP); |
625 Label done; | 629 Label done; |
626 Label init_loop; | 630 Label init_loop; |
627 __ Bind(&init_loop); | 631 __ Bind(&init_loop); |
628 __ cmpq(RBX, R12); | 632 __ cmpq(RBX, R12); |
629 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 633 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
630 // TODO(cshapiro): StoreIntoObjectNoBarrier | 634 // TODO(cshapiro): StoreIntoObjectNoBarrier |
631 __ movq(Address(RBX, 0), raw_null); | 635 __ movq(Address(RBX, 0), R13); |
632 __ addq(RBX, Immediate(kWordSize)); | 636 __ addq(RBX, Immediate(kWordSize)); |
633 __ jmp(&init_loop, Assembler::kNearJump); | 637 __ jmp(&init_loop, Assembler::kNearJump); |
634 __ Bind(&done); | 638 __ Bind(&done); |
635 | 639 |
636 // Done allocating and initializing the array. | 640 // Done allocating and initializing the array. |
637 // RAX: new object. | 641 // RAX: new object. |
638 // R10: Array length as Smi (preserved for the caller.) | 642 // R10: Array length as Smi (preserved for the caller.) |
639 __ ret(); | 643 __ ret(); |
640 } | 644 } |
641 | 645 |
642 // Unable to allocate the array using the fast inline code, just call | 646 // Unable to allocate the array using the fast inline code, just call |
643 // into the runtime. | 647 // into the runtime. |
644 __ Bind(&slow_case); | 648 __ Bind(&slow_case); |
645 // Create a stub frame as we are pushing some objects on the stack before | 649 // Create a stub frame as we are pushing some objects on the stack before |
646 // calling into the runtime. | 650 // calling into the runtime. |
647 __ EnterStubFrame(); | 651 __ EnterStubFrame(); |
648 __ pushq(raw_null); // Setup space on stack for return value. | 652 // Setup space on stack for return value. |
| 653 __ PushObject(Object::Handle()); |
649 __ pushq(R10); // Array length as Smi. | 654 __ pushq(R10); // Array length as Smi. |
650 __ pushq(RBX); // Element type. | 655 __ pushq(RBX); // Element type. |
651 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 656 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
652 __ popq(RAX); // Pop element type argument. | 657 __ popq(RAX); // Pop element type argument. |
653 __ popq(R10); // Pop array length argument. | 658 __ popq(R10); // Pop array length argument. |
654 __ popq(RAX); // Pop return value from return slot. | 659 __ popq(RAX); // Pop return value from return slot. |
655 __ LeaveFrame(); | 660 __ LeaveFrame(); |
656 __ ret(); | 661 __ ret(); |
657 } | 662 } |
658 | 663 |
659 | 664 |
660 // Input parameters: | 665 // Input parameters: |
661 // R10: Arguments descriptor array. | 666 // R10: Arguments descriptor array. |
662 // Note: The closure object is the first argument to the function being | 667 // Note: The closure object is the first argument to the function being |
663 // called, the stub accesses the closure from this location directly | 668 // called, the stub accesses the closure from this location directly |
664 // when trying to resolve the call. | 669 // when trying to resolve the call. |
665 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 670 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
666 const Immediate& raw_null = | |
667 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
668 | |
669 // Load num_args. | 671 // Load num_args. |
670 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 672 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
671 // Load closure object in R13. | 673 // Load closure object in R13. |
672 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. | 674 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. |
673 | 675 |
| 676 __ LoadObject(R12, Object::Handle(), PP); |
| 677 |
674 // Verify that R13 is a closure by checking its class. | 678 // Verify that R13 is a closure by checking its class. |
675 Label not_closure; | 679 Label not_closure; |
676 __ cmpq(R13, raw_null); | 680 __ cmpq(R13, R12); |
677 // Not a closure, but null object. | 681 // Not a closure, but null object. |
678 __ j(EQUAL, ¬_closure); | 682 __ j(EQUAL, ¬_closure); |
679 __ testq(R13, Immediate(kSmiTagMask)); | 683 __ testq(R13, Immediate(kSmiTagMask)); |
680 __ j(ZERO, ¬_closure); // Not a closure, but a smi. | 684 __ j(ZERO, ¬_closure); // Not a closure, but a smi. |
681 // Verify that the class of the object is a closure class by checking that | 685 // Verify that the class of the object is a closure class by checking that |
682 // class.signature_function() is not null. | 686 // class.signature_function() is not null. |
683 __ LoadClass(RAX, R13); | 687 __ LoadClass(RAX, R13); |
684 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); | 688 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); |
685 __ cmpq(RAX, raw_null); | 689 __ cmpq(RAX, R12); |
686 // Actual class is not a closure class. | 690 // Actual class is not a closure class. |
687 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 691 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
688 | 692 |
689 // RAX is just the signature function. Load the actual closure function. | 693 // RAX is just the signature function. Load the actual closure function. |
690 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); | 694 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); |
691 | 695 |
692 // Load closure context in CTX; note that CTX has already been preserved. | 696 // Load closure context in CTX; note that CTX has already been preserved. |
693 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); | 697 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); |
694 | 698 |
695 // Load closure function code in RAX. | 699 // Load closure function code in RAX. |
696 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); | 700 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); |
697 __ cmpq(RAX, raw_null); | 701 __ cmpq(RAX, R12); |
698 Label function_compiled; | 702 Label function_compiled; |
699 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); | 703 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump); |
700 | 704 |
701 // Create a stub frame as we are pushing some objects on the stack before | 705 // Create a stub frame as we are pushing some objects on the stack before |
702 // calling into the runtime. | 706 // calling into the runtime. |
703 __ EnterStubFrame(); | 707 __ EnterStubFrame(); |
704 | 708 |
705 __ pushq(R10); // Preserve arguments descriptor array. | 709 __ pushq(R10); // Preserve arguments descriptor array. |
706 __ pushq(RBX); // Preserve read-only function object argument. | 710 __ pushq(RBX); // Preserve read-only function object argument. |
707 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 711 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
(...skipping 18 matching lines...) Expand all Loading... |
726 // Call runtime to attempt to resolve and invoke a call method on a | 730 // Call runtime to attempt to resolve and invoke a call method on a |
727 // non-closure object, passing the non-closure object and its arguments array, | 731 // non-closure object, passing the non-closure object and its arguments array, |
728 // returning here. | 732 // returning here. |
729 // If no call method exists, throw a NoSuchMethodError. | 733 // If no call method exists, throw a NoSuchMethodError. |
730 // R13: non-closure object. | 734 // R13: non-closure object. |
731 // R10: arguments descriptor array. | 735 // R10: arguments descriptor array. |
732 | 736 |
733 // Create a stub frame as we are pushing some objects on the stack before | 737 // Create a stub frame as we are pushing some objects on the stack before |
734 // calling into the runtime. | 738 // calling into the runtime. |
735 __ EnterStubFrame(); | 739 __ EnterStubFrame(); |
736 | 740 // Setup space on stack for result from call. |
737 __ pushq(raw_null); // Setup space on stack for result from call. | 741 __ pushq(R12); |
738 __ pushq(R10); // Arguments descriptor. | 742 __ pushq(R10); // Arguments descriptor. |
739 // Load smi-tagged arguments array length, including the non-closure. | 743 // Load smi-tagged arguments array length, including the non-closure. |
740 __ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 744 __ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
741 PushArgumentsArray(assembler); | 745 PushArgumentsArray(assembler); |
742 | 746 |
743 __ CallRuntime(kInvokeNonClosureRuntimeEntry, 2); | 747 __ CallRuntime(kInvokeNonClosureRuntimeEntry, 2); |
744 | 748 |
745 // Remove arguments. | 749 // Remove arguments. |
746 __ Drop(2); | 750 __ Drop(2); |
747 __ popq(RAX); // Get result into RAX. | 751 __ popq(RAX); // Get result into RAX. |
748 | 752 |
749 // Remove the stub frame as we are about to return. | 753 // Remove the stub frame as we are about to return. |
750 __ LeaveFrame(); | 754 __ LeaveFrame(); |
751 __ ret(); | 755 __ ret(); |
752 } | 756 } |
753 | 757 |
754 | 758 |
755 // Called when invoking Dart code from C++ (VM code). | 759 // Called when invoking Dart code from C++ (VM code). |
756 // Input parameters: | 760 // Input parameters: |
757 // RSP : points to return address. | 761 // RSP : points to return address. |
758 // RDI : entrypoint of the Dart function to call. | 762 // RDI : entrypoint of the Dart function to call. |
759 // RSI : arguments descriptor array. | 763 // RSI : arguments descriptor array. |
760 // RDX : arguments array. | 764 // RDX : arguments array. |
761 // RCX : new context containing the current isolate pointer. | 765 // RCX : new context containing the current isolate pointer. |
762 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 766 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
763 // Save frame pointer coming in. | 767 // Save frame pointer coming in. |
764 __ EnterFrame(0); | 768 __ EnterStubFrame(); |
765 | 769 |
766 // Save arguments descriptor array and new context. | 770 // Save arguments descriptor array and new context. |
767 const intptr_t kArgumentsDescOffset = -1 * kWordSize; | 771 const intptr_t kArgumentsDescOffset = -2 * kWordSize; |
768 __ pushq(RSI); | 772 __ pushq(RSI); |
769 const intptr_t kNewContextOffset = -2 * kWordSize; | 773 const intptr_t kNewContextOffset = -3 * kWordSize; |
770 __ pushq(RCX); | 774 __ pushq(RCX); |
771 | 775 |
772 // Save C++ ABI callee-saved registers. | 776 // Save C++ ABI callee-saved registers. |
773 __ pushq(RBX); | 777 __ pushq(RBX); |
774 __ pushq(R12); | 778 __ pushq(R12); |
775 __ pushq(R13); | 779 __ pushq(R13); |
776 __ pushq(R14); | 780 __ pushq(R14); |
777 __ pushq(R15); | 781 __ pushq(R15); |
778 | 782 |
779 // The new Context structure contains a pointer to the current Isolate | 783 // The new Context structure contains a pointer to the current Isolate |
780 // structure. Cache the Context pointer in the CTX register so that it is | 784 // structure. Cache the Context pointer in the CTX register so that it is |
781 // available in generated code and calls to Isolate::Current() need not be | 785 // available in generated code and calls to Isolate::Current() need not be |
782 // done. The assumption is that this register will never be clobbered by | 786 // done. The assumption is that this register will never be clobbered by |
783 // compiled or runtime stub code. | 787 // compiled or runtime stub code. |
784 | 788 |
785 // Cache the new Context pointer into CTX while executing Dart code. | 789 // Cache the new Context pointer into CTX while executing Dart code. |
786 __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); | 790 __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); |
787 | 791 |
788 // Load Isolate pointer from Context structure into R8. | 792 // Load Isolate pointer from Context structure into R8. |
789 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); | 793 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); |
790 | 794 |
791 // Save the top exit frame info. Use RAX as a temporary register. | 795 // Save the top exit frame info. Use RAX as a temporary register. |
792 // StackFrameIterator reads the top exit frame info saved in this frame. | 796 // StackFrameIterator reads the top exit frame info saved in this frame. |
793 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the | 797 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the |
794 // code below. | 798 // code below. |
795 ASSERT(kExitLinkSlotFromEntryFp == -8); | 799 ASSERT(kExitLinkSlotFromEntryFp == -9); |
796 __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); | 800 __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); |
797 __ pushq(RAX); | 801 __ pushq(RAX); |
798 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 802 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
799 | 803 |
800 // Save the old Context pointer. Use RAX as a temporary register. | 804 // Save the old Context pointer. Use RAX as a temporary register. |
801 // Note that VisitObjectPointers will find this saved Context pointer during | 805 // Note that VisitObjectPointers will find this saved Context pointer during |
802 // GC marking, since it traverses any information between SP and | 806 // GC marking, since it traverses any information between SP and |
803 // FP - kExitLinkSlotFromEntryFp * kWordSize. | 807 // FP - kExitLinkSlotFromEntryFp * kWordSize. |
804 // EntryFrame::SavedContext reads the context saved in this frame. | 808 // EntryFrame::SavedContext reads the context saved in this frame. |
805 // The constant kSavedContextSlotFromEntryFp must be kept in sync with | 809 // The constant kSavedContextSlotFromEntryFp must be kept in sync with |
806 // the code below. | 810 // the code below. |
807 ASSERT(kSavedContextSlotFromEntryFp == -9); | 811 ASSERT(kSavedContextSlotFromEntryFp == -10); |
808 __ movq(RAX, Address(R8, Isolate::top_context_offset())); | 812 __ movq(RAX, Address(R8, Isolate::top_context_offset())); |
809 __ pushq(RAX); | 813 __ pushq(RAX); |
810 | 814 |
811 // Load arguments descriptor array into R10, which is passed to Dart code. | 815 // Load arguments descriptor array into R10, which is passed to Dart code. |
812 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); | 816 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); |
813 | 817 |
814 // Load number of arguments into RBX. | 818 // Load number of arguments into RBX. |
815 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 819 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
816 __ SmiUntag(RBX); | 820 __ SmiUntag(RBX); |
817 | 821 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 __ ret(); | 878 __ ret(); |
875 } | 879 } |
876 | 880 |
877 | 881 |
878 // Called for inline allocation of contexts. | 882 // Called for inline allocation of contexts. |
879 // Input: | 883 // Input: |
880 // R10: number of context variables. | 884 // R10: number of context variables. |
881 // Output: | 885 // Output: |
882 // RAX: new allocated RawContext object. | 886 // RAX: new allocated RawContext object. |
883 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 887 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
884 const Immediate& raw_null = | 888 __ LoadObject(R12, Object::Handle(), PP); |
885 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
886 if (FLAG_inline_alloc) { | 889 if (FLAG_inline_alloc) { |
887 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 890 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
888 Label slow_case; | 891 Label slow_case; |
889 Heap* heap = Isolate::Current()->heap(); | 892 Heap* heap = Isolate::Current()->heap(); |
890 // First compute the rounded instance size. | 893 // First compute the rounded instance size. |
891 // R10: number of context variables. | 894 // R10: number of context variables. |
892 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 895 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
893 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 896 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
894 __ andq(R13, Immediate(-kObjectAlignment)); | 897 __ andq(R13, Immediate(-kObjectAlignment)); |
895 | 898 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 953 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
951 | 954 |
952 // Setup isolate field. | 955 // Setup isolate field. |
953 // Load Isolate pointer from Context structure into R13. | 956 // Load Isolate pointer from Context structure into R13. |
954 // RAX: new object. | 957 // RAX: new object. |
955 // R10: number of context variables. | 958 // R10: number of context variables. |
956 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | 959 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
957 // R13: Isolate, not an object. | 960 // R13: Isolate, not an object. |
958 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); | 961 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
959 | 962 |
960 const Immediate& raw_null = | |
961 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
962 // Setup the parent field. | 963 // Setup the parent field. |
963 // RAX: new object. | 964 // RAX: new object. |
964 // R10: number of context variables. | 965 // R10: number of context variables. |
965 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); | 966 __ movq(FieldAddress(RAX, Context::parent_offset()), R12); |
966 | 967 |
967 // Initialize the context variables. | 968 // Initialize the context variables. |
968 // RAX: new object. | 969 // RAX: new object. |
969 // R10: number of context variables. | 970 // R10: number of context variables. |
970 { | 971 { |
971 Label loop, entry; | 972 Label loop, entry; |
972 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); | 973 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); |
973 | 974 |
974 __ jmp(&entry, Assembler::kNearJump); | 975 __ jmp(&entry, Assembler::kNearJump); |
975 __ Bind(&loop); | 976 __ Bind(&loop); |
976 __ decq(R10); | 977 __ decq(R10); |
977 __ movq(Address(R13, R10, TIMES_8, 0), raw_null); | 978 __ movq(Address(R13, R10, TIMES_8, 0), R12); |
978 __ Bind(&entry); | 979 __ Bind(&entry); |
979 __ cmpq(R10, Immediate(0)); | 980 __ cmpq(R10, Immediate(0)); |
980 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 981 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
981 } | 982 } |
982 | 983 |
983 // Done allocating and initializing the context. | 984 // Done allocating and initializing the context. |
984 // RAX: new object. | 985 // RAX: new object. |
985 __ ret(); | 986 __ ret(); |
986 | 987 |
987 __ Bind(&slow_case); | 988 __ Bind(&slow_case); |
988 } | 989 } |
989 // Create a stub frame. | 990 // Create a stub frame. |
990 __ EnterStubFrame(); | 991 __ EnterStubFrame(); |
991 __ pushq(raw_null); // Setup space on stack for the return value. | 992 __ pushq(R12); // Setup space on stack for the return value. |
992 __ SmiTag(R10); | 993 __ SmiTag(R10); |
993 __ pushq(R10); // Push number of context variables. | 994 __ pushq(R10); // Push number of context variables. |
994 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. | 995 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. |
995 __ popq(RAX); // Pop number of context variables argument. | 996 __ popq(RAX); // Pop number of context variables argument. |
996 __ popq(RAX); // Pop the new context object. | 997 __ popq(RAX); // Pop the new context object. |
997 // RAX: new object | 998 // RAX: new object |
998 // Restore the frame pointer. | 999 // Restore the frame pointer. |
999 __ LeaveFrame(); | 1000 __ LeaveFrame(); |
1000 __ ret(); | 1001 __ ret(); |
1001 } | 1002 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 | 1066 |
1066 // Called for inline allocation of objects. | 1067 // Called for inline allocation of objects. |
1067 // Input parameters: | 1068 // Input parameters: |
1068 // RSP + 16 : type arguments object (only if class is parameterized). | 1069 // RSP + 16 : type arguments object (only if class is parameterized). |
1069 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 1070 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
1070 // RSP : points to return address. | 1071 // RSP : points to return address. |
1071 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1072 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
1072 const Class& cls) { | 1073 const Class& cls) { |
1073 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1074 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
1074 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1075 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
1075 const Immediate& raw_null = | |
1076 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1077 // The generated code is different if the class is parameterized. | 1076 // The generated code is different if the class is parameterized. |
1078 const bool is_cls_parameterized = cls.HasTypeArguments(); | 1077 const bool is_cls_parameterized = cls.HasTypeArguments(); |
1079 ASSERT(!cls.HasTypeArguments() || | 1078 ASSERT(!cls.HasTypeArguments() || |
1080 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1079 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1081 // kInlineInstanceSize is a constant used as a threshold for determining | 1080 // kInlineInstanceSize is a constant used as a threshold for determining |
1082 // when the object initialization should be done as a loop or as | 1081 // when the object initialization should be done as a loop or as |
1083 // straight line code. | 1082 // straight line code. |
1084 const int kInlineInstanceSize = 12; // In words. | 1083 const int kInlineInstanceSize = 12; // In words. |
1085 const intptr_t instance_size = cls.instance_size(); | 1084 const intptr_t instance_size = cls.instance_size(); |
1086 ASSERT(instance_size > 0); | 1085 ASSERT(instance_size > 0); |
1087 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); | 1086 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); |
| 1087 __ LoadObject(R12, Object::Handle(), PP); |
1088 if (FLAG_inline_alloc && | 1088 if (FLAG_inline_alloc && |
1089 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { | 1089 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { |
1090 Label slow_case; | 1090 Label slow_case; |
1091 Heap* heap = Isolate::Current()->heap(); | 1091 Heap* heap = Isolate::Current()->heap(); |
1092 __ movq(RAX, Immediate(heap->TopAddress())); | 1092 __ movq(RAX, Immediate(heap->TopAddress())); |
1093 __ movq(RAX, Address(RAX, 0)); | 1093 __ movq(RAX, Address(RAX, 0)); |
1094 __ leaq(RBX, Address(RAX, instance_size)); | 1094 __ leaq(RBX, Address(RAX, instance_size)); |
1095 if (is_cls_parameterized) { | 1095 if (is_cls_parameterized) { |
1096 __ movq(RCX, RBX); | 1096 __ movq(RCX, RBX); |
1097 // A new InstantiatedTypeArguments object only needs to be allocated if | 1097 // A new InstantiatedTypeArguments object only needs to be allocated if |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 // RBX: next object start. | 1161 // RBX: next object start. |
1162 // RDI: new object type arguments (if is_cls_parameterized). | 1162 // RDI: new object type arguments (if is_cls_parameterized). |
1163 // Set the tags. | 1163 // Set the tags. |
1164 uword tags = 0; | 1164 uword tags = 0; |
1165 tags = RawObject::SizeTag::update(instance_size, tags); | 1165 tags = RawObject::SizeTag::update(instance_size, tags); |
1166 ASSERT(cls.id() != kIllegalCid); | 1166 ASSERT(cls.id() != kIllegalCid); |
1167 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1167 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1168 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1168 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
1169 | 1169 |
1170 // Initialize the remaining words of the object. | 1170 // Initialize the remaining words of the object. |
1171 const Immediate& raw_null = | |
1172 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1173 | |
1174 // RAX: new object start. | 1171 // RAX: new object start. |
1175 // RBX: next object start. | 1172 // RBX: next object start. |
1176 // RDI: new object type arguments (if is_cls_parameterized). | 1173 // RDI: new object type arguments (if is_cls_parameterized). |
1177 // First try inlining the initialization without a loop. | 1174 // First try inlining the initialization without a loop. |
1178 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1175 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1179 // Check if the object contains any non-header fields. | 1176 // Check if the object contains any non-header fields. |
1180 // Small objects are initialized using a consecutive set of writes. | 1177 // Small objects are initialized using a consecutive set of writes. |
1181 for (intptr_t current_offset = sizeof(RawObject); | 1178 for (intptr_t current_offset = sizeof(RawObject); |
1182 current_offset < instance_size; | 1179 current_offset < instance_size; |
1183 current_offset += kWordSize) { | 1180 current_offset += kWordSize) { |
1184 __ movq(Address(RAX, current_offset), raw_null); | 1181 __ movq(Address(RAX, current_offset), R12); |
1185 } | 1182 } |
1186 } else { | 1183 } else { |
1187 __ leaq(RCX, Address(RAX, sizeof(RawObject))); | 1184 __ leaq(RCX, Address(RAX, sizeof(RawObject))); |
1188 // Loop until the whole object is initialized. | 1185 // Loop until the whole object is initialized. |
1189 // RAX: new object. | 1186 // RAX: new object. |
1190 // RBX: next object start. | 1187 // RBX: next object start. |
1191 // RCX: next word to be initialized. | 1188 // RCX: next word to be initialized. |
1192 // RDI: new object type arguments (if is_cls_parameterized). | 1189 // RDI: new object type arguments (if is_cls_parameterized). |
1193 Label init_loop; | 1190 Label init_loop; |
1194 Label done; | 1191 Label done; |
1195 __ Bind(&init_loop); | 1192 __ Bind(&init_loop); |
1196 __ cmpq(RCX, RBX); | 1193 __ cmpq(RCX, RBX); |
1197 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1194 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
1198 __ movq(Address(RCX, 0), raw_null); | 1195 __ movq(Address(RCX, 0), R12); |
1199 __ addq(RCX, Immediate(kWordSize)); | 1196 __ addq(RCX, Immediate(kWordSize)); |
1200 __ jmp(&init_loop, Assembler::kNearJump); | 1197 __ jmp(&init_loop, Assembler::kNearJump); |
1201 __ Bind(&done); | 1198 __ Bind(&done); |
1202 } | 1199 } |
1203 if (is_cls_parameterized) { | 1200 if (is_cls_parameterized) { |
1204 // RDI: new object type arguments. | 1201 // RDI: new object type arguments. |
1205 // Set the type arguments in the new object. | 1202 // Set the type arguments in the new object. |
1206 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDI); | 1203 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDI); |
1207 } | 1204 } |
1208 // Done allocating and initializing the instance. | 1205 // Done allocating and initializing the instance. |
1209 // RAX: new object. | 1206 // RAX: new object. |
1210 __ addq(RAX, Immediate(kHeapObjectTag)); | 1207 __ addq(RAX, Immediate(kHeapObjectTag)); |
1211 __ ret(); | 1208 __ ret(); |
1212 | 1209 |
1213 __ Bind(&slow_case); | 1210 __ Bind(&slow_case); |
1214 } | 1211 } |
1215 if (is_cls_parameterized) { | 1212 if (is_cls_parameterized) { |
1216 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); | 1213 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); |
1217 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); | 1214 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
1218 } | 1215 } |
1219 // Create a stub frame. | 1216 // Create a stub frame. |
1220 __ EnterStubFrame(); | 1217 __ EnterStubFrameWithPP(); |
1221 __ pushq(raw_null); // Setup space on stack for return value. | 1218 __ pushq(R12); // Setup space on stack for return value. |
1222 __ PushObject(cls); // Push class of object to be allocated. | 1219 __ PushObject(cls); // Push class of object to be allocated. |
1223 if (is_cls_parameterized) { | 1220 if (is_cls_parameterized) { |
1224 __ pushq(RAX); // Push type arguments of object to be allocated. | 1221 __ pushq(RAX); // Push type arguments of object to be allocated. |
1225 __ pushq(RDX); // Push type arguments of instantiator. | 1222 __ pushq(RDX); // Push type arguments of instantiator. |
1226 } else { | 1223 } else { |
1227 __ pushq(raw_null); // Push null type arguments. | 1224 __ pushq(R12); // Push null type arguments. |
1228 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1225 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
1229 } | 1226 } |
1230 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. | 1227 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. |
1231 __ popq(RAX); // Pop argument (instantiator). | 1228 __ popq(RAX); // Pop argument (instantiator). |
1232 __ popq(RAX); // Pop argument (type arguments of object). | 1229 __ popq(RAX); // Pop argument (type arguments of object). |
1233 __ popq(RAX); // Pop argument (class of object). | 1230 __ popq(RAX); // Pop argument (class of object). |
1234 __ popq(RAX); // Pop result (newly allocated object). | 1231 __ popq(RAX); // Pop result (newly allocated object). |
1235 // RAX: new object | 1232 // RAX: new object |
1236 // Restore the frame pointer. | 1233 // Restore the frame pointer. |
1237 __ LeaveFrame(); | 1234 __ LeaveFrameWithPP(); |
1238 __ ret(); | 1235 __ ret(); |
1239 } | 1236 } |
1240 | 1237 |
1241 | 1238 |
1242 // Called for inline allocation of closures. | 1239 // Called for inline allocation of closures. |
1243 // Input parameters: | 1240 // Input parameters: |
1244 // RSP + 16 : receiver (null if not an implicit instance closure). | 1241 // RSP + 16 : receiver (null if not an implicit instance closure). |
1245 // RSP + 8 : type arguments object (null if class is not parameterized). | 1242 // RSP + 8 : type arguments object (null if class is not parameterized). |
1246 // RSP : points to return address. | 1243 // RSP : points to return address. |
1247 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1244 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
1248 const Function& func) { | 1245 const Function& func) { |
1249 const Immediate& raw_null = | |
1250 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1251 ASSERT(func.IsClosureFunction()); | 1246 ASSERT(func.IsClosureFunction()); |
1252 ASSERT(!func.IsImplicitStaticClosureFunction()); | 1247 ASSERT(!func.IsImplicitStaticClosureFunction()); |
1253 const bool is_implicit_instance_closure = | 1248 const bool is_implicit_instance_closure = |
1254 func.IsImplicitInstanceClosureFunction(); | 1249 func.IsImplicitInstanceClosureFunction(); |
1255 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1250 const Class& cls = Class::ZoneHandle(func.signature_class()); |
1256 const bool has_type_arguments = cls.HasTypeArguments(); | 1251 const bool has_type_arguments = cls.HasTypeArguments(); |
1257 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1252 |
1258 const intptr_t kReceiverOffset = 2 * kWordSize; | 1253 __ EnterStubFrameWithPP(); // Uses pool pointer to refer to function. |
| 1254 __ LoadObject(R12, Object::Handle(), PP); |
| 1255 const intptr_t kTypeArgumentsOffset = 4 * kWordSize; |
| 1256 const intptr_t kReceiverOffset = 5 * kWordSize; |
1259 const intptr_t closure_size = Closure::InstanceSize(); | 1257 const intptr_t closure_size = Closure::InstanceSize(); |
1260 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. | 1258 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
1261 if (FLAG_inline_alloc && | 1259 if (FLAG_inline_alloc && |
1262 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { | 1260 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { |
1263 Label slow_case; | 1261 Label slow_case; |
1264 Heap* heap = Isolate::Current()->heap(); | 1262 Heap* heap = Isolate::Current()->heap(); |
1265 __ movq(RAX, Immediate(heap->TopAddress())); | 1263 __ movq(RAX, Immediate(heap->TopAddress())); |
1266 __ movq(RAX, Address(RAX, 0)); | 1264 __ movq(RAX, Address(RAX, 0)); |
1267 __ leaq(R13, Address(RAX, closure_size)); | 1265 __ leaq(R13, Address(RAX, closure_size)); |
1268 if (is_implicit_instance_closure) { | 1266 if (is_implicit_instance_closure) { |
(...skipping 22 matching lines...) Expand all Loading... |
1291 // Set the tags. | 1289 // Set the tags. |
1292 uword tags = 0; | 1290 uword tags = 0; |
1293 tags = RawObject::SizeTag::update(closure_size, tags); | 1291 tags = RawObject::SizeTag::update(closure_size, tags); |
1294 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1292 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1295 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1293 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
1296 | 1294 |
1297 // Initialize the function field in the object. | 1295 // Initialize the function field in the object. |
1298 // RAX: new closure object. | 1296 // RAX: new closure object. |
1299 // RBX: new context object (only if is_implicit_closure). | 1297 // RBX: new context object (only if is_implicit_closure). |
1300 // R13: next object start. | 1298 // R13: next object start. |
1301 __ LoadObject(R10, func); // Load function of closure to be allocated. | 1299 // Load function of closure to be allocated. |
| 1300 __ LoadObject(R10, func, PP); |
1302 __ movq(Address(RAX, Closure::function_offset()), R10); | 1301 __ movq(Address(RAX, Closure::function_offset()), R10); |
1303 | 1302 |
1304 // Setup the context for this closure. | 1303 // Setup the context for this closure. |
1305 if (is_implicit_instance_closure) { | 1304 if (is_implicit_instance_closure) { |
1306 // Initialize the new context capturing the receiver. | 1305 // Initialize the new context capturing the receiver. |
1307 | 1306 |
1308 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 1307 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
1309 // Set the tags. | 1308 // Set the tags. |
1310 uword tags = 0; | 1309 uword tags = 0; |
1311 tags = RawObject::SizeTag::update(context_size, tags); | 1310 tags = RawObject::SizeTag::update(context_size, tags); |
1312 tags = RawObject::ClassIdTag::update(context_class.id(), tags); | 1311 tags = RawObject::ClassIdTag::update(context_class.id(), tags); |
1313 __ movq(Address(RBX, Context::tags_offset()), Immediate(tags)); | 1312 __ movq(Address(RBX, Context::tags_offset()), Immediate(tags)); |
1314 | 1313 |
1315 // Set number of variables field to 1 (for captured receiver). | 1314 // Set number of variables field to 1 (for captured receiver). |
1316 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); | 1315 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); |
1317 | 1316 |
1318 // Set isolate field to isolate of current context. | 1317 // Set isolate field to isolate of current context. |
1319 __ movq(R10, FieldAddress(CTX, Context::isolate_offset())); | 1318 __ movq(R10, FieldAddress(CTX, Context::isolate_offset())); |
1320 __ movq(Address(RBX, Context::isolate_offset()), R10); | 1319 __ movq(Address(RBX, Context::isolate_offset()), R10); |
1321 | 1320 |
1322 // Set the parent to null. | 1321 // Set the parent to null. |
1323 __ movq(Address(RBX, Context::parent_offset()), raw_null); | 1322 __ movq(Address(RBX, Context::parent_offset()), R12); |
1324 | 1323 |
1325 // Initialize the context variable to the receiver. | 1324 // Initialize the context variable to the receiver. |
1326 __ movq(R10, Address(RSP, kReceiverOffset)); | 1325 __ movq(R10, Address(RSP, kReceiverOffset)); |
1327 __ movq(Address(RBX, Context::variable_offset(0)), R10); | 1326 __ movq(Address(RBX, Context::variable_offset(0)), R10); |
1328 | 1327 |
1329 // Set the newly allocated context in the newly allocated closure. | 1328 // Set the newly allocated context in the newly allocated closure. |
1330 __ addq(RBX, Immediate(kHeapObjectTag)); | 1329 __ addq(RBX, Immediate(kHeapObjectTag)); |
1331 __ movq(Address(RAX, Closure::context_offset()), RBX); | 1330 __ movq(Address(RAX, Closure::context_offset()), RBX); |
1332 } else { | 1331 } else { |
1333 __ movq(Address(RAX, Closure::context_offset()), CTX); | 1332 __ movq(Address(RAX, Closure::context_offset()), CTX); |
1334 } | 1333 } |
1335 | 1334 |
1336 // Set the type arguments field in the newly allocated closure. | 1335 // Set the type arguments field in the newly allocated closure. |
1337 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); | 1336 __ movq(R10, Address(RSP, kTypeArgumentsOffset)); |
1338 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); | 1337 __ movq(Address(RAX, Closure::type_arguments_offset()), R10); |
1339 | 1338 |
1340 // Done allocating and initializing the instance. | 1339 // Done allocating and initializing the instance. |
1341 // RAX: new object. | 1340 // RAX: new object. |
1342 __ addq(RAX, Immediate(kHeapObjectTag)); | 1341 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1342 __ LeaveFrameWithPP(); |
1343 __ ret(); | 1343 __ ret(); |
1344 | 1344 |
1345 __ Bind(&slow_case); | 1345 __ Bind(&slow_case); |
1346 } | 1346 } |
1347 if (has_type_arguments) { | 1347 if (has_type_arguments) { |
1348 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); | 1348 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); |
1349 } | 1349 } |
1350 if (is_implicit_instance_closure) { | 1350 if (is_implicit_instance_closure) { |
1351 __ movq(RAX, Address(RSP, kReceiverOffset)); | 1351 __ movq(RAX, Address(RSP, kReceiverOffset)); |
1352 } | 1352 } |
1353 // Create the stub frame. | 1353 |
1354 __ EnterStubFrame(); | 1354 __ pushq(R12); // Setup space on stack for the return value. |
1355 __ pushq(raw_null); // Setup space on stack for the return value. | |
1356 __ PushObject(func); | 1355 __ PushObject(func); |
1357 if (is_implicit_instance_closure) { | 1356 if (is_implicit_instance_closure) { |
1358 __ pushq(RAX); // Receiver. | 1357 __ pushq(RAX); // Receiver. |
1359 } | 1358 } |
1360 if (has_type_arguments) { | 1359 if (has_type_arguments) { |
1361 __ pushq(RCX); // Push type arguments of closure to be allocated. | 1360 __ pushq(RCX); // Push type arguments of closure to be allocated. |
1362 } else { | 1361 } else { |
1363 __ pushq(raw_null); // Push null type arguments. | 1362 __ pushq(R12); // Push null type arguments. |
1364 } | 1363 } |
1365 if (is_implicit_instance_closure) { | 1364 if (is_implicit_instance_closure) { |
1366 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); | 1365 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry, 3); |
1367 __ popq(RAX); // Pop type arguments. | 1366 __ popq(RAX); // Pop type arguments. |
1368 __ popq(RAX); // Pop receiver. | 1367 __ popq(RAX); // Pop receiver. |
1369 } else { | 1368 } else { |
1370 ASSERT(func.IsNonImplicitClosureFunction()); | 1369 ASSERT(func.IsNonImplicitClosureFunction()); |
1371 __ CallRuntime(kAllocateClosureRuntimeEntry, 2); | 1370 __ CallRuntime(kAllocateClosureRuntimeEntry, 2); |
1372 __ popq(RAX); // Pop type arguments. | 1371 __ popq(RAX); // Pop type arguments. |
1373 } | 1372 } |
1374 __ popq(RAX); // Pop the function object. | 1373 __ popq(RAX); // Pop the function object. |
1375 __ popq(RAX); // Pop the result. | 1374 __ popq(RAX); // Pop the result. |
1376 // RAX: New closure object. | 1375 // RAX: New closure object. |
1377 // Restore the calling frame. | 1376 // Restore the calling frame. |
1378 __ LeaveFrame(); | 1377 __ LeaveFrameWithPP(); |
1379 __ ret(); | 1378 __ ret(); |
1380 } | 1379 } |
1381 | 1380 |
1382 | 1381 |
1383 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1382 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1384 // from the entry code of a dart function after an error in passed argument | 1383 // from the entry code of a dart function after an error in passed argument |
1385 // name or number is detected. | 1384 // name or number is detected. |
1386 // Input parameters: | 1385 // Input parameters: |
1387 // RSP : points to return address. | 1386 // RSP : points to return address. |
1388 // RSP + 8 : address of last argument. | 1387 // RSP + 8 : address of last argument. |
1389 // RBX : ic-data. | 1388 // RBX : ic-data. |
1390 // R10 : arguments descriptor array. | 1389 // R10 : arguments descriptor array. |
1391 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1390 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1392 __ EnterStubFrame(); | 1391 __ EnterStubFrame(); |
1393 | 1392 |
1394 // Load the receiver. | 1393 // Load the receiver. |
1395 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1394 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1396 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 1395 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
1397 | 1396 |
1398 const Immediate& raw_null = | 1397 __ LoadObject(R12, Object::Handle(), PP); |
1399 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1398 __ pushq(R12); // Setup space on stack for result from noSuchMethod. |
1400 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. | |
1401 __ pushq(RAX); // Receiver. | 1399 __ pushq(RAX); // Receiver. |
1402 __ pushq(RBX); // IC data array. | 1400 __ pushq(RBX); // IC data array. |
1403 __ pushq(R10); // Arguments descriptor array. | 1401 __ pushq(R10); // Arguments descriptor array. |
1404 | 1402 |
1405 __ movq(R10, R13); // Smi-tagged arguments array length. | 1403 __ movq(R10, R13); // Smi-tagged arguments array length. |
1406 PushArgumentsArray(assembler); | 1404 PushArgumentsArray(assembler); |
1407 | 1405 |
1408 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry, 4); | 1406 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry, 4); |
1409 | 1407 |
1410 // Remove arguments. | 1408 // Remove arguments. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1538 | 1536 |
1539 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1537 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
1540 __ addq(R12, Immediate(entry_size)); // Next entry. | 1538 __ addq(R12, Immediate(entry_size)); // Next entry. |
1541 __ movq(R13, Address(R12, 0)); // Next class ID. | 1539 __ movq(R13, Address(R12, 0)); // Next class ID. |
1542 | 1540 |
1543 __ Bind(&test); | 1541 __ Bind(&test); |
1544 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1542 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
1545 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1543 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
1546 | 1544 |
1547 // IC miss. | 1545 // IC miss. |
1548 const Immediate& raw_null = | 1546 __ LoadObject(R12, Object::Handle(), PP); |
1549 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1550 // Compute address of arguments (first read number of arguments from | 1547 // Compute address of arguments (first read number of arguments from |
1551 // arguments descriptor array and then compute address on the stack). | 1548 // arguments descriptor array and then compute address on the stack). |
1552 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1549 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1553 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1550 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
1554 __ EnterStubFrame(); | 1551 __ EnterStubFrame(); |
1555 __ pushq(R10); // Preserve arguments descriptor array. | 1552 __ pushq(R10); // Preserve arguments descriptor array. |
1556 __ pushq(RBX); // Preserve IC data object. | 1553 __ pushq(RBX); // Preserve IC data object. |
1557 __ pushq(raw_null); // Setup space on stack for result (target code object). | 1554 __ pushq(R12); // Setup space on stack for result (target code object). |
1558 // Push call arguments. | 1555 // Push call arguments. |
1559 for (intptr_t i = 0; i < num_args; i++) { | 1556 for (intptr_t i = 0; i < num_args; i++) { |
1560 __ movq(RCX, Address(RAX, -kWordSize * i)); | 1557 __ movq(RCX, Address(RAX, -kWordSize * i)); |
1561 __ pushq(RCX); | 1558 __ pushq(RCX); |
1562 } | 1559 } |
1563 __ pushq(RBX); // Pass IC data object. | 1560 __ pushq(RBX); // Pass IC data object. |
1564 __ CallRuntime(handle_ic_miss, num_args + 1); | 1561 __ CallRuntime(handle_ic_miss, num_args + 1); |
1565 // Remove the call arguments pushed earlier, including the IC data object. | 1562 // Remove the call arguments pushed earlier, including the IC data object. |
1566 for (intptr_t i = 0; i < num_args + 1; i++) { | 1563 for (intptr_t i = 0; i < num_args + 1; i++) { |
1567 __ popq(RAX); | 1564 __ popq(RAX); |
1568 } | 1565 } |
1569 __ popq(RAX); // Pop returned code object into RAX (null if not found). | 1566 __ popq(RAX); // Pop returned code object into RAX (null if not found). |
1570 __ popq(RBX); // Restore IC data array. | 1567 __ popq(RBX); // Restore IC data array. |
1571 __ popq(R10); // Restore arguments descriptor array. | 1568 __ popq(R10); // Restore arguments descriptor array. |
1572 __ LeaveFrame(); | 1569 __ LeaveFrame(); |
1573 Label call_target_function; | 1570 Label call_target_function; |
1574 __ cmpq(RAX, raw_null); | 1571 __ cmpq(RAX, R12); |
1575 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1572 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
1576 // NoSuchMethod or closure. | 1573 // NoSuchMethod or closure. |
1577 // Mark IC call that it may be a closure call that does not collect | 1574 // Mark IC call that it may be a closure call that does not collect |
1578 // type feedback. | 1575 // type feedback. |
1579 __ movb(FieldAddress(RBX, ICData::is_closure_call_offset()), Immediate(1)); | 1576 __ movb(FieldAddress(RBX, ICData::is_closure_call_offset()), Immediate(1)); |
1580 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 1577 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
1581 | 1578 |
1582 __ Bind(&found); | 1579 __ Bind(&found); |
1583 // R12: Pointer to an IC data check group. | 1580 // R12: Pointer to an IC data check group. |
1584 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1581 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1730 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1727 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1731 | 1728 |
1732 // Increment count for this call. | 1729 // Increment count for this call. |
1733 Label increment_done; | 1730 Label increment_done; |
1734 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); | 1731 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); |
1735 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); | 1732 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); |
1736 __ movq(Address(R12, count_offset), | 1733 __ movq(Address(R12, count_offset), |
1737 Immediate(Smi::RawValue(Smi::kMaxValue))); | 1734 Immediate(Smi::RawValue(Smi::kMaxValue))); |
1738 __ Bind(&increment_done); | 1735 __ Bind(&increment_done); |
1739 | 1736 |
1740 const Immediate& raw_null = | |
1741 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1742 Label target_is_compiled; | 1737 Label target_is_compiled; |
1743 // Get function and call it, if possible. | 1738 // Get function and call it, if possible. |
1744 __ movq(R13, Address(R12, target_offset)); | 1739 __ movq(R13, Address(R12, target_offset)); |
1745 __ movq(RAX, FieldAddress(R13, Function::code_offset())); | 1740 __ movq(RAX, FieldAddress(R13, Function::code_offset())); |
1746 __ cmpq(RAX, raw_null); | 1741 __ LoadObject(R12, Object::Handle(), PP); |
| 1742 __ cmpq(RAX, R12); |
1747 __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); | 1743 __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); |
1748 | 1744 |
1749 __ EnterStubFrame(); | 1745 __ EnterStubFrame(); |
1750 __ pushq(R13); // Preserve target function. | 1746 __ pushq(R13); // Preserve target function. |
1751 __ pushq(RBX); // Preserve IC data object. | 1747 __ pushq(RBX); // Preserve IC data object. |
1752 __ pushq(R13); // Pass function. | 1748 __ pushq(R13); // Pass function. |
1753 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1749 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
1754 __ popq(RAX); // Discard argument. | 1750 __ popq(RAX); // Discard argument. |
1755 __ popq(RBX); // Restore IC data object. | 1751 __ popq(RBX); // Restore IC data object. |
1756 __ popq(R13); // Restore target function. | 1752 __ popq(R13); // Restore target function. |
(...skipping 19 matching lines...) Expand all Loading... |
1776 | 1772 |
1777 // RBX, R10: May contain arguments to runtime stub. | 1773 // RBX, R10: May contain arguments to runtime stub. |
1778 // TOS(0): return address (Dart code). | 1774 // TOS(0): return address (Dart code). |
1779 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1775 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
1780 __ EnterStubFrame(); | 1776 __ EnterStubFrame(); |
1781 // Preserve runtime args. | 1777 // Preserve runtime args. |
1782 __ pushq(RBX); | 1778 __ pushq(RBX); |
1783 __ pushq(R10); | 1779 __ pushq(R10); |
1784 // Room for result. Debugger stub returns address of the | 1780 // Room for result. Debugger stub returns address of the |
1785 // unpatched runtime stub. | 1781 // unpatched runtime stub. |
1786 const Immediate& raw_null = | 1782 __ LoadObject(R12, Object::Handle(), PP); |
1787 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1783 __ pushq(R12); // Room for result. |
1788 __ pushq(raw_null); // Room for result. | |
1789 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1784 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1790 __ popq(RAX); // Address of original. | 1785 __ popq(RAX); // Address of original. |
1791 __ popq(R10); // Restore arguments. | 1786 __ popq(R10); // Restore arguments. |
1792 __ popq(RBX); | 1787 __ popq(RBX); |
1793 __ LeaveFrame(); | 1788 __ LeaveFrame(); |
1794 __ jmp(RAX); // Jump to original stub. | 1789 __ jmp(RAX); // Jump to original stub. |
1795 } | 1790 } |
1796 | 1791 |
1797 | 1792 |
1798 // RBX: ICData (unoptimized static call) | 1793 // RBX: ICData (unoptimized static call) |
1799 // TOS(0): return address (Dart code). | 1794 // TOS(0): return address (Dart code). |
1800 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1795 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
1801 const Immediate& raw_null = | |
1802 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1803 __ EnterStubFrame(); | 1796 __ EnterStubFrame(); |
| 1797 __ LoadObject(R12, Object::Handle(), PP); |
1804 __ pushq(RBX); // Preserve IC data for unoptimized call. | 1798 __ pushq(RBX); // Preserve IC data for unoptimized call. |
1805 __ pushq(raw_null); // Room for result. | 1799 __ pushq(R12); // Room for result. |
1806 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); | 1800 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); |
1807 __ popq(RAX); // Code object. | 1801 __ popq(RAX); // Code object. |
1808 __ popq(RBX); // Restore IC data. | 1802 __ popq(RBX); // Restore IC data. |
1809 __ LeaveFrame(); | 1803 __ LeaveFrame(); |
1810 | 1804 |
1811 // Load arguments descriptor into R10. | 1805 // Load arguments descriptor into R10. |
1812 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1806 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1813 // Now call the static function. The breakpoint handler function | 1807 // Now call the static function. The breakpoint handler function |
1814 // ensures that the call target is compiled. | 1808 // ensures that the call target is compiled. |
1815 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 1809 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
1816 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1810 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1817 __ jmp(RBX); | 1811 __ jmp(RBX); |
1818 } | 1812 } |
1819 | 1813 |
1820 | 1814 |
1821 // TOS(0): return address (Dart code). | 1815 // TOS(0): return address (Dart code). |
1822 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { | 1816 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { |
1823 __ EnterStubFrame(); | 1817 __ EnterStubFrame(); |
1824 __ pushq(RAX); | 1818 __ pushq(RAX); |
1825 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry, 0); | 1819 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry, 0); |
1826 __ popq(RAX); | 1820 __ popq(RAX); |
1827 __ LeaveFrame(); | 1821 __ LeaveFrame(); |
1828 | 1822 |
1829 __ popq(R11); // discard return address of call to this stub. | 1823 __ popq(R11); // discard return address of call to this stub. |
1830 __ LeaveFrame(); | 1824 __ LeaveFrameWithPP(); |
1831 __ ret(); | 1825 __ ret(); |
1832 } | 1826 } |
1833 | 1827 |
1834 | 1828 |
1835 // RBX: Inline cache data array. | 1829 // RBX: Inline cache data array. |
1836 // TOS(0): return address (Dart code). | 1830 // TOS(0): return address (Dart code). |
1837 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1831 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1838 __ EnterStubFrame(); | 1832 __ EnterStubFrame(); |
1839 __ pushq(RBX); | 1833 __ pushq(RBX); |
1840 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry, 0); | 1834 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry, 0); |
(...skipping 20 matching lines...) Expand all Loading... |
1861 | 1855 |
1862 | 1856 |
1863 // Used to check class and type arguments. Arguments passed on stack: | 1857 // Used to check class and type arguments. Arguments passed on stack: |
1864 // TOS + 0: return address. | 1858 // TOS + 0: return address. |
1865 // TOS + 1: instantiator type arguments (can be NULL). | 1859 // TOS + 1: instantiator type arguments (can be NULL). |
1866 // TOS + 2: instance. | 1860 // TOS + 2: instance. |
1867 // TOS + 3: SubtypeTestCache. | 1861 // TOS + 3: SubtypeTestCache. |
1868 // Result in RCX: null -> not found, otherwise result (true or false). | 1862 // Result in RCX: null -> not found, otherwise result (true or false). |
1869 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1863 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
1870 ASSERT((1 <= n) && (n <= 3)); | 1864 ASSERT((1 <= n) && (n <= 3)); |
1871 const Immediate& raw_null = | |
1872 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1873 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1865 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
1874 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1866 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
1875 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1867 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
1876 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1868 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
| 1869 __ LoadObject(R12, Object::Handle(), PP); |
1877 if (n > 1) { | 1870 if (n > 1) { |
1878 __ LoadClass(R10, RAX); | 1871 __ LoadClass(R10, RAX); |
1879 // Compute instance type arguments into R13. | 1872 // Compute instance type arguments into R13. |
1880 Label has_no_type_arguments; | 1873 Label has_no_type_arguments; |
1881 __ movq(R13, raw_null); | 1874 __ movq(R13, R12); |
1882 __ movq(RDI, FieldAddress(R10, | 1875 __ movq(RDI, FieldAddress(R10, |
1883 Class::type_arguments_field_offset_in_words_offset())); | 1876 Class::type_arguments_field_offset_in_words_offset())); |
1884 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); | 1877 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); |
1885 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1878 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
1886 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); | 1879 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); |
1887 __ Bind(&has_no_type_arguments); | 1880 __ Bind(&has_no_type_arguments); |
1888 } | 1881 } |
1889 __ LoadClassId(R10, RAX); | 1882 __ LoadClassId(R10, RAX); |
1890 // RAX: instance, R10: instance class id. | 1883 // RAX: instance, R10: instance class id. |
1891 // R13: instance type arguments or null, used only if n > 1. | 1884 // R13: instance type arguments or null, used only if n > 1. |
1892 __ movq(RDX, Address(RSP, kCacheOffsetInBytes)); | 1885 __ movq(RDX, Address(RSP, kCacheOffsetInBytes)); |
1893 // RDX: SubtypeTestCache. | 1886 // RDX: SubtypeTestCache. |
1894 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset())); | 1887 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset())); |
1895 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag)); | 1888 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag)); |
1896 // RDX: Entry start. | 1889 // RDX: Entry start. |
1897 // R10: instance class id. | 1890 // R10: instance class id. |
1898 // R13: instance type arguments. | 1891 // R13: instance type arguments. |
1899 Label loop, found, not_found, next_iteration; | 1892 Label loop, found, not_found, next_iteration; |
1900 __ SmiTag(R10); | 1893 __ SmiTag(R10); |
1901 __ Bind(&loop); | 1894 __ Bind(&loop); |
1902 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId)); | 1895 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId)); |
1903 __ cmpq(RDI, raw_null); | 1896 __ cmpq(RDI, R12); |
1904 __ j(EQUAL, ¬_found, Assembler::kNearJump); | 1897 __ j(EQUAL, ¬_found, Assembler::kNearJump); |
1905 __ cmpq(RDI, R10); | 1898 __ cmpq(RDI, R10); |
1906 if (n == 1) { | 1899 if (n == 1) { |
1907 __ j(EQUAL, &found, Assembler::kNearJump); | 1900 __ j(EQUAL, &found, Assembler::kNearJump); |
1908 } else { | 1901 } else { |
1909 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 1902 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
1910 __ movq(RDI, | 1903 __ movq(RDI, |
1911 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); | 1904 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); |
1912 __ cmpq(RDI, R13); | 1905 __ cmpq(RDI, R13); |
1913 if (n == 2) { | 1906 if (n == 2) { |
1914 __ j(EQUAL, &found, Assembler::kNearJump); | 1907 __ j(EQUAL, &found, Assembler::kNearJump); |
1915 } else { | 1908 } else { |
1916 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 1909 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
1917 __ movq(RDI, | 1910 __ movq(RDI, |
1918 Address(RDX, | 1911 Address(RDX, |
1919 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments)); | 1912 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments)); |
1920 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes)); | 1913 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes)); |
1921 __ j(EQUAL, &found, Assembler::kNearJump); | 1914 __ j(EQUAL, &found, Assembler::kNearJump); |
1922 } | 1915 } |
1923 } | 1916 } |
1924 | 1917 |
1925 __ Bind(&next_iteration); | 1918 __ Bind(&next_iteration); |
1926 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); | 1919 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); |
1927 __ jmp(&loop, Assembler::kNearJump); | 1920 __ jmp(&loop, Assembler::kNearJump); |
1928 // Fall through to not found. | 1921 // Fall through to not found. |
1929 __ Bind(¬_found); | 1922 __ Bind(¬_found); |
1930 __ movq(RCX, raw_null); | 1923 __ movq(RCX, R12); |
1931 __ ret(); | 1924 __ ret(); |
1932 | 1925 |
1933 __ Bind(&found); | 1926 __ Bind(&found); |
1934 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); | 1927 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); |
1935 __ ret(); | 1928 __ ret(); |
1936 } | 1929 } |
1937 | 1930 |
1938 | 1931 |
1939 // Used to check class and type arguments. Arguments passed on stack: | 1932 // Used to check class and type arguments. Arguments passed on stack: |
1940 // TOS + 0: return address. | 1933 // TOS + 0: return address. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2053 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); | 2046 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); |
2054 __ j(NO_OVERFLOW, &compute_result); | 2047 __ j(NO_OVERFLOW, &compute_result); |
2055 __ movq(Address(R12, count_offset), | 2048 __ movq(Address(R12, count_offset), |
2056 Immediate(Smi::RawValue(Smi::kMaxValue))); | 2049 Immediate(Smi::RawValue(Smi::kMaxValue))); |
2057 | 2050 |
2058 __ Bind(&compute_result); | 2051 __ Bind(&compute_result); |
2059 Label true_label; | 2052 Label true_label; |
2060 __ movq(RAX, Address(RSP, 1 * kWordSize)); | 2053 __ movq(RAX, Address(RSP, 1 * kWordSize)); |
2061 __ cmpq(RAX, Address(RSP, 2 * kWordSize)); | 2054 __ cmpq(RAX, Address(RSP, 2 * kWordSize)); |
2062 __ j(EQUAL, &true_label, Assembler::kNearJump); | 2055 __ j(EQUAL, &true_label, Assembler::kNearJump); |
2063 __ LoadObject(RAX, Bool::False()); | 2056 __ LoadObject(RAX, Bool::False(), PP); |
2064 __ ret(); | 2057 __ ret(); |
2065 __ Bind(&true_label); | 2058 __ Bind(&true_label); |
2066 __ LoadObject(RAX, Bool::True()); | 2059 __ LoadObject(RAX, Bool::True(), PP); |
2067 __ ret(); | 2060 __ ret(); |
2068 | 2061 |
2069 __ Bind(&get_class_id_as_smi); | 2062 __ Bind(&get_class_id_as_smi); |
2070 Label not_smi; | 2063 Label not_smi; |
2071 // Test if Smi -> load Smi class for comparison. | 2064 // Test if Smi -> load Smi class for comparison. |
2072 __ testq(RAX, Immediate(kSmiTagMask)); | 2065 __ testq(RAX, Immediate(kSmiTagMask)); |
2073 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 2066 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
2074 __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); | 2067 __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); |
2075 __ ret(); | 2068 __ ret(); |
2076 | 2069 |
2077 __ Bind(¬_smi); | 2070 __ Bind(¬_smi); |
2078 __ LoadClassId(RAX, RAX); | 2071 __ LoadClassId(RAX, RAX); |
2079 __ SmiTag(RAX); | 2072 __ SmiTag(RAX); |
2080 __ ret(); | 2073 __ ret(); |
2081 | 2074 |
2082 __ Bind(&update_ic_data); | 2075 __ Bind(&update_ic_data); |
2083 | 2076 |
2084 // RCX: ICData | 2077 // RBX: ICData |
2085 __ movq(RAX, Address(RSP, 1 * kWordSize)); | 2078 __ movq(RAX, Address(RSP, 1 * kWordSize)); |
2086 __ movq(R13, Address(RSP, 2 * kWordSize)); | 2079 __ movq(R13, Address(RSP, 2 * kWordSize)); |
2087 __ EnterStubFrame(); | 2080 __ EnterStubFrame(); |
2088 __ pushq(R13); // arg 0 | 2081 __ pushq(R13); // arg 0 |
2089 __ pushq(RAX); // arg 1 | 2082 __ pushq(RAX); // arg 1 |
2090 __ PushObject(Symbols::EqualOperator()); // Target's name. | 2083 __ PushObject(Symbols::EqualOperator()); // Target's name. |
2091 __ pushq(RBX); // ICData | 2084 __ pushq(RBX); // ICData |
2092 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); | 2085 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); |
2093 __ Drop(4); | 2086 __ Drop(4); |
2094 __ LeaveFrame(); | 2087 __ LeaveFrame(); |
2095 | 2088 |
2096 __ jmp(&compute_result, Assembler::kNearJump); | 2089 __ jmp(&compute_result, Assembler::kNearJump); |
2097 } | 2090 } |
2098 | 2091 |
2099 // Calls to the runtime to optimize the given function. | 2092 // Calls to the runtime to optimize the given function. |
2100 // RDI: function to be reoptimized. | 2093 // RDI: function to be reoptimized. |
2101 // R10: argument descriptor (preserved). | 2094 // R10: argument descriptor (preserved). |
2102 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 2095 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
2103 const Immediate& raw_null = | 2096 __ EnterStubFrameWithPP(); |
2104 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2097 __ LoadObject(R12, Object::Handle(), PP); |
2105 __ EnterStubFrame(); | |
2106 __ pushq(R10); | 2098 __ pushq(R10); |
2107 __ pushq(raw_null); // Setup space on stack for return value. | 2099 __ pushq(R12); // Setup space on stack for return value. |
2108 __ pushq(RDI); | 2100 __ pushq(RDI); |
2109 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 2101 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
2110 __ popq(RAX); // Disard argument. | 2102 __ popq(RAX); // Disard argument. |
2111 __ popq(RAX); // Get Code object. | 2103 __ popq(RAX); // Get Code object. |
2112 __ popq(R10); // Restore argument descriptor. | 2104 __ popq(R10); // Restore argument descriptor. |
2113 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 2105 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
2114 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 2106 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
2115 __ LeaveFrame(); | 2107 __ LeaveFrameWithPP(); |
2116 __ jmp(RAX); | 2108 __ jmp(RAX); |
2117 __ int3(); | 2109 __ int3(); |
2118 } | 2110 } |
2119 | 2111 |
2120 | 2112 |
2121 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, | 2113 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, |
2122 BigintCompare, | 2114 BigintCompare, |
2123 RawBigint* left, | 2115 RawBigint* left, |
2124 RawBigint* right); | 2116 RawBigint* right); |
2125 | 2117 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 __ movq(right, Address(RSP, 3 * kWordSize)); | 2220 __ movq(right, Address(RSP, 3 * kWordSize)); |
2229 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2221 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2230 __ popq(right); | 2222 __ popq(right); |
2231 __ popq(left); | 2223 __ popq(left); |
2232 __ ret(); | 2224 __ ret(); |
2233 } | 2225 } |
2234 | 2226 |
2235 } // namespace dart | 2227 } // namespace dart |
2236 | 2228 |
2237 #endif // defined TARGET_ARCH_X64 | 2229 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |