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

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

Powered by Google App Engine
This is Rietveld 408576698