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 |