| 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 // - Push all registers that can contain values. | 326 // - Push all registers that can contain values. |
| 327 // - Call C routine to copy the stack and saved registers into temporary buffer. | 327 // - Call C routine to copy the stack and saved registers into temporary buffer. |
| 328 // - Adjust caller's frame to correct unoptimized frame size. | 328 // - Adjust caller's frame to correct unoptimized frame size. |
| 329 // - Fill the unoptimized frame. | 329 // - Fill the unoptimized frame. |
| 330 // - Materialize objects that require allocation (e.g. Double instances). | 330 // - Materialize objects that require allocation (e.g. Double instances). |
| 331 // GC can occur only after frame is fully rewritten. | 331 // GC can occur only after frame is fully rewritten. |
| 332 // Stack after EnterFrame(...) below: | 332 // Stack after EnterFrame(...) below: |
| 333 // +------------------+ | 333 // +------------------+ |
| 334 // | Saved FP | <- TOS | 334 // | Saved FP | <- TOS |
| 335 // +------------------+ | 335 // +------------------+ |
| 336 // | return-address | (deoptimization point) | 336 // | Saved LR | (deoptimization point) |
| 337 // +------------------+ | 337 // +------------------+ |
| 338 // | optimized frame | | 338 // | stub pc marker | (necessary to keep constant offset SP - Saved LR. |
| 339 // +------------------+ |
| 340 // | optimized frame | <- SP of optimized code |
| 339 // | ... | | 341 // | ... | |
| 340 // | 342 // |
| 341 // Parts of the code cannot GC, part of the code can GC. | 343 // Parts of the code cannot GC, part of the code can GC. |
| 342 static void GenerateDeoptimizationSequence(Assembler* assembler, | 344 static void GenerateDeoptimizationSequence(Assembler* assembler, |
| 343 bool preserve_result) { | 345 bool preserve_result) { |
| 344 __ EnterFrame((1 << FP) | (1 << LR), 0); | 346 __ EnterStubFrame(); // Do not save pp (implicit saved regs to fp offset). |
| 345 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 347 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 346 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 348 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 347 const intptr_t saved_r0_offset_from_fp = -(kNumberOfCpuRegisters - R0); | 349 const intptr_t saved_r0_offset_from_fp = -(kNumberOfCpuRegisters - R0); |
| 348 // Result in R0 is preserved as part of pushing all registers below. | 350 // Result in R0 is preserved as part of pushing all registers below. |
| 349 | 351 |
| 352 // TODO(regis): Should we align the stack before pushing the fpu registers? |
| 353 // If we do, saved_r0_offset_from_fp is not constant anymore. |
| 354 |
| 350 // Push registers in their enumeration order: lowest register number at | 355 // Push registers in their enumeration order: lowest register number at |
| 351 // lowest address. | 356 // lowest address. |
| 352 __ PushList(kAllCpuRegistersList); | 357 __ PushList(kAllCpuRegistersList); |
| 353 ASSERT(kFpuRegisterSize == 2 * kWordSize); | 358 ASSERT(kFpuRegisterSize == 2 * kWordSize); |
| 354 __ vstmd(DB_W, SP, D0, static_cast<DRegister>(kNumberOfDRegisters - 1)); | 359 __ vstmd(DB_W, SP, D0, static_cast<DRegister>(kNumberOfDRegisters - 1)); |
| 355 | 360 |
| 356 __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. | 361 __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. |
| 357 __ ReserveAlignedFrameSpace(0); | 362 __ ReserveAlignedFrameSpace(0); |
| 358 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 363 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
| 359 // Result (R0) is stack-size (FP - SP) in bytes, incl. the return address. | 364 // Result (R0) is stack-size (FP - SP) in bytes, incl. the return address. |
| 360 | 365 |
| 361 if (preserve_result) { | 366 if (preserve_result) { |
| 362 // Restore result into R1 temporarily. | 367 // Restore result into R1 temporarily. |
| 363 __ ldr(R1, Address(FP, saved_r0_offset_from_fp * kWordSize)); | 368 __ ldr(R1, Address(FP, saved_r0_offset_from_fp * kWordSize)); |
| 364 } | 369 } |
| 365 | 370 |
| 366 __ LeaveFrame((1 << FP) | (1 << LR)); | 371 __ LeaveStubFrame(); // Restores FP and LR from stack. |
| 367 __ sub(SP, FP, ShifterOperand(R0)); | 372 __ sub(SP, FP, ShifterOperand(R0)); |
| 368 | 373 |
| 369 __ EnterFrame((1 << FP) | (1 << LR), 0); | 374 __ EnterStubFrame(); |
| 370 __ mov(R0, ShifterOperand(SP)); // Get last FP address. | 375 __ mov(R0, ShifterOperand(SP)); // Get last FP address. |
| 371 if (preserve_result) { | 376 if (preserve_result) { |
| 372 __ Push(R1); // Preserve result. | 377 __ Push(R1); // Preserve result. |
| 373 } | 378 } |
| 374 __ ReserveAlignedFrameSpace(0); | 379 __ ReserveAlignedFrameSpace(0); |
| 375 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. | 380 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. |
| 376 // Result (R0) is our FP. | 381 // Result (R0) is our FP. |
| 377 if (preserve_result) { | 382 if (preserve_result) { |
| 378 // Restore result into R1. | 383 // Restore result into R1. |
| 379 __ ldr(R1, Address(FP, -1 * kWordSize)); | 384 __ ldr(R1, Address(FP, -1 * kWordSize)); |
| 380 } | 385 } |
| 381 // Code above cannot cause GC. | 386 // Code above cannot cause GC. |
| 382 __ LeaveFrame((1 << FP) | (1 << LR)); | 387 __ LeaveStubFrame(); |
| 383 __ mov(FP, ShifterOperand(R0)); | 388 __ mov(FP, ShifterOperand(R0)); |
| 384 | 389 |
| 385 // Frame is fully rewritten at this point and it is safe to perform a GC. | 390 // Frame is fully rewritten at this point and it is safe to perform a GC. |
| 386 // Materialize any objects that were deferred by FillFrame because they | 391 // Materialize any objects that were deferred by FillFrame because they |
| 387 // require allocation. | 392 // require allocation. |
| 388 __ EnterStubFrame(); | 393 __ EnterStubFrame(); |
| 389 if (preserve_result) { | 394 if (preserve_result) { |
| 390 __ Push(R1); // Preserve result, it will be GC-d here. | 395 __ Push(R1); // Preserve result, it will be GC-d here. |
| 391 } | 396 } |
| 392 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); | 397 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); |
| 393 if (preserve_result) { | 398 if (preserve_result) { |
| 394 __ Pop(R0); // Restore result. | 399 __ Pop(R0); // Restore result. |
| 395 } | 400 } |
| 396 __ LeaveStubFrame(); | 401 __ LeaveStubFrame(); |
| 397 __ Ret(); | 402 __ Ret(); |
| 398 } | 403 } |
| 399 | 404 |
| 400 | 405 |
| 401 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { | 406 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
| 402 __ Unimplemented("DeoptimizeLazy stub"); | 407 // Correct return address to point just after the call that is being |
| 408 // deoptimized. |
| 409 __ AddImmediate(LR, -CallPattern::kFixedLengthInBytes); |
| 410 GenerateDeoptimizationSequence(assembler, true); // Preserve R0. |
| 403 } | 411 } |
| 404 | 412 |
| 405 | 413 |
| 406 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 414 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 407 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. | 415 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. |
| 408 } | 416 } |
| 409 | 417 |
| 410 | 418 |
| 411 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 419 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 412 __ Unimplemented("MegamorphicMiss stub"); | 420 __ Unimplemented("MegamorphicMiss stub"); |
| (...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1902 __ Bind(&reference_compare); | 1910 __ Bind(&reference_compare); |
| 1903 __ cmp(left, ShifterOperand(right)); | 1911 __ cmp(left, ShifterOperand(right)); |
| 1904 __ Bind(&done); | 1912 __ Bind(&done); |
| 1905 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1913 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 1906 __ Ret(); | 1914 __ Ret(); |
| 1907 } | 1915 } |
| 1908 | 1916 |
| 1909 } // namespace dart | 1917 } // namespace dart |
| 1910 | 1918 |
| 1911 #endif // defined TARGET_ARCH_ARM | 1919 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |