| 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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 // frame contains all values on stack. | 324 // frame contains all values on stack. |
| 325 // Deoptimization occurs in following steps: | 325 // Deoptimization occurs in following steps: |
| 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 PP | <- TOS |
| 335 // +------------------+ |
| 336 // | Saved FP | <- FP of stub |
| 335 // +------------------+ | 337 // +------------------+ |
| 336 // | Saved LR | (deoptimization point) | 338 // | Saved LR | (deoptimization point) |
| 337 // +------------------+ | 339 // +------------------+ |
| 338 // | stub pc marker | (necessary to keep constant offset SP - Saved LR. | 340 // | PC marker | |
| 339 // +------------------+ | 341 // +------------------+ |
| 340 // | optimized frame | <- SP of optimized code | 342 // | ... | <- SP of optimized frame |
| 341 // | ... | | |
| 342 // | 343 // |
| 343 // Parts of the code cannot GC, part of the code can GC. | 344 // Parts of the code cannot GC, part of the code can GC. |
| 344 static void GenerateDeoptimizationSequence(Assembler* assembler, | 345 static void GenerateDeoptimizationSequence(Assembler* assembler, |
| 345 bool preserve_result) { | 346 bool preserve_result) { |
| 346 __ EnterStubFrame(); // Do not save pp (implicit saved regs to fp offset). | 347 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 348 // is no need to set the correct PC marker or load PP, since they get patched. |
| 349 __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); |
| 347 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 350 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 348 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 351 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 349 const intptr_t saved_r0_offset_from_fp = -(kNumberOfCpuRegisters - R0); | 352 const intptr_t saved_result_slot_from_fp = |
| 353 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); |
| 350 // Result in R0 is preserved as part of pushing all registers below. | 354 // Result in R0 is preserved as part of pushing all registers below. |
| 351 | 355 |
| 352 // TODO(regis): Should we align the stack before pushing the fpu registers? | 356 // 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. | 357 // If we do, saved_r0_offset_from_fp is not constant anymore. |
| 354 | 358 |
| 355 // Push registers in their enumeration order: lowest register number at | 359 // Push registers in their enumeration order: lowest register number at |
| 356 // lowest address. | 360 // lowest address. |
| 357 __ PushList(kAllCpuRegistersList); | 361 __ PushList(kAllCpuRegistersList); |
| 358 ASSERT(kFpuRegisterSize == 2 * kWordSize); | 362 ASSERT(kFpuRegisterSize == 2 * kWordSize); |
| 359 __ vstmd(DB_W, SP, D0, static_cast<DRegister>(kNumberOfDRegisters - 1)); | 363 __ vstmd(DB_W, SP, D0, static_cast<DRegister>(kNumberOfDRegisters - 1)); |
| 360 | 364 |
| 361 __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. | 365 __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. |
| 362 __ ReserveAlignedFrameSpace(0); | 366 __ ReserveAlignedFrameSpace(0); |
| 363 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 367 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
| 364 // Result (R0) is stack-size (FP - SP) in bytes, incl. the return address. | 368 // Result (R0) is stack-size (FP - SP) in bytes. |
| 365 | 369 |
| 366 if (preserve_result) { | 370 if (preserve_result) { |
| 367 // Restore result into R1 temporarily. | 371 // Restore result into R1 temporarily. |
| 368 __ ldr(R1, Address(FP, saved_r0_offset_from_fp * kWordSize)); | 372 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); |
| 369 } | 373 } |
| 370 | 374 |
| 371 __ LeaveStubFrame(); // Restores FP and LR from stack. | 375 __ LeaveDartFrame(); |
| 372 __ sub(SP, FP, ShifterOperand(R0)); | 376 __ sub(SP, FP, ShifterOperand(R0)); |
| 373 | 377 |
| 374 __ EnterStubFrame(); | 378 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
| 375 __ mov(R0, ShifterOperand(SP)); // Get last FP address. | 379 // is no need to set the correct PC marker or load PP, since they get patched. |
| 380 __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); |
| 381 __ mov(R0, ShifterOperand(FP)); // Get last FP address. |
| 376 if (preserve_result) { | 382 if (preserve_result) { |
| 377 __ Push(R1); // Preserve result. | 383 __ Push(R1); // Preserve result as first local. |
| 378 } | 384 } |
| 379 __ ReserveAlignedFrameSpace(0); | 385 __ ReserveAlignedFrameSpace(0); |
| 380 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. | 386 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); // Pass last FP in R0. |
| 381 // Result (R0) is our FP. | |
| 382 if (preserve_result) { | 387 if (preserve_result) { |
| 383 // Restore result into R1. | 388 // Restore result into R1. |
| 384 __ ldr(R1, Address(FP, -1 * kWordSize)); | 389 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
| 385 } | 390 } |
| 386 // Code above cannot cause GC. | 391 // Code above cannot cause GC. |
| 387 __ LeaveStubFrame(); | 392 __ LeaveDartFrame(); |
| 388 __ mov(FP, ShifterOperand(R0)); | |
| 389 | 393 |
| 390 // Frame is fully rewritten at this point and it is safe to perform a GC. | 394 // Frame is fully rewritten at this point and it is safe to perform a GC. |
| 391 // Materialize any objects that were deferred by FillFrame because they | 395 // Materialize any objects that were deferred by FillFrame because they |
| 392 // require allocation. | 396 // require allocation. |
| 393 __ EnterStubFrame(); | 397 __ EnterStubFrame(); |
| 394 if (preserve_result) { | 398 if (preserve_result) { |
| 395 __ Push(R1); // Preserve result, it will be GC-d here. | 399 __ Push(R1); // Preserve result, it will be GC-d here. |
| 396 } | 400 } |
| 397 __ PushObject(Smi::ZoneHandle()); // Space for the result. | 401 __ PushObject(Smi::ZoneHandle()); // Space for the result. |
| 398 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); | 402 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry); |
| (...skipping 1538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1937 __ Bind(&reference_compare); | 1941 __ Bind(&reference_compare); |
| 1938 __ cmp(left, ShifterOperand(right)); | 1942 __ cmp(left, ShifterOperand(right)); |
| 1939 __ Bind(&done); | 1943 __ Bind(&done); |
| 1940 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1944 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 1941 __ Ret(); | 1945 __ Ret(); |
| 1942 } | 1946 } |
| 1943 | 1947 |
| 1944 } // namespace dart | 1948 } // namespace dart |
| 1945 | 1949 |
| 1946 #endif // defined TARGET_ARCH_ARM | 1950 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |