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

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

Powered by Google App Engine
This is Rietveld 408576698