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

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

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

Powered by Google App Engine
This is Rietveld 408576698