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