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