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