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

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

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

Powered by Google App Engine
This is Rietveld 408576698