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

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

Issue 2374273002: Fix a throw returning to a frame marked for lazy deopt that captures the stacktrace. (Closed)
Patch Set: . Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code.h ('k') | runtime/vm/stub_code_arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_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/cpu.h" 10 #include "vm/cpu.h"
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 COMPILE_ASSERT(PP < CODE_REG); 420 COMPILE_ASSERT(PP < CODE_REG);
421 COMPILE_ASSERT(CODE_REG < FP); 421 COMPILE_ASSERT(CODE_REG < FP);
422 COMPILE_ASSERT(FP < IP); 422 COMPILE_ASSERT(FP < IP);
423 __ EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << IP), 0); 423 __ EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << IP), 0);
424 __ LoadPoolPointer(); 424 __ LoadPoolPointer();
425 425
426 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry 426 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
427 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. 427 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
428 const intptr_t saved_result_slot_from_fp = 428 const intptr_t saved_result_slot_from_fp =
429 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); 429 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
430 const intptr_t saved_exception_slot_from_fp =
431 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
432 const intptr_t saved_stacktrace_slot_from_fp =
433 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R1);
430 // Result in R0 is preserved as part of pushing all registers below. 434 // Result in R0 is preserved as part of pushing all registers below.
431 435
432 // Push registers in their enumeration order: lowest register number at 436 // Push registers in their enumeration order: lowest register number at
433 // lowest address. 437 // lowest address.
434 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) { 438 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
435 if (i == CODE_REG) { 439 if (i == CODE_REG) {
436 // Save the original value of CODE_REG pushed before invoking this stub 440 // Save the original value of CODE_REG pushed before invoking this stub
437 // instead of the value used to call this stub. 441 // instead of the value used to call this stub.
438 __ ldr(IP, Address(FP, kCallerSpSlotFromFp * kWordSize)); 442 __ ldr(IP, Address(FP, kCallerSpSlotFromFp * kWordSize));
439 __ Push(IP); 443 __ Push(IP);
(...skipping 12 matching lines...) Expand all
452 __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16); 456 __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16);
453 __ vstmd(DB_W, SP, D0, 16); 457 __ vstmd(DB_W, SP, D0, 16);
454 } else { 458 } else {
455 __ vstmd(DB_W, SP, D0, kNumberOfDRegisters); 459 __ vstmd(DB_W, SP, D0, kNumberOfDRegisters);
456 } 460 }
457 } else { 461 } else {
458 __ AddImmediate(SP, SP, -kNumberOfFpuRegisters * kFpuRegisterSize); 462 __ AddImmediate(SP, SP, -kNumberOfFpuRegisters * kFpuRegisterSize);
459 } 463 }
460 464
461 __ mov(R0, Operand(SP)); // Pass address of saved registers block. 465 __ mov(R0, Operand(SP)); // Pass address of saved registers block.
462 __ mov(R1, Operand(kind == kLazyDeopt ? 1 : 0)); 466 bool is_lazy = (kind == kLazyDeoptFromReturn) ||
467 (kind == kLazyDeoptFromThrow);
468 __ mov(R1, Operand(is_lazy ? 1 : 0));
463 __ ReserveAlignedFrameSpace(0); 469 __ ReserveAlignedFrameSpace(0);
464 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 470 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
465 // Result (R0) is stack-size (FP - SP) in bytes. 471 // Result (R0) is stack-size (FP - SP) in bytes.
466 472
467 const bool preserve_result = (kind == kLazyDeopt); 473 if (kind == kLazyDeoptFromReturn) {
468 if (preserve_result) {
469 // Restore result into R1 temporarily. 474 // Restore result into R1 temporarily.
470 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); 475 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize));
476 } else if (kind == kLazyDeoptFromThrow) {
477 // Restore result into R1 temporarily.
478 __ ldr(R1, Address(FP, saved_exception_slot_from_fp * kWordSize));
479 __ ldr(R2, Address(FP, saved_stacktrace_slot_from_fp * kWordSize));
471 } 480 }
472 481
473 __ RestoreCodePointer(); 482 __ RestoreCodePointer();
474 __ LeaveDartFrame(); 483 __ LeaveDartFrame();
475 __ sub(SP, FP, Operand(R0)); 484 __ sub(SP, FP, Operand(R0));
476 485
477 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 486 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
478 // is no need to set the correct PC marker or load PP, since they get patched. 487 // is no need to set the correct PC marker or load PP, since they get patched.
479 __ EnterStubFrame(); 488 __ EnterStubFrame();
480 __ mov(R0, Operand(FP)); // Get last FP address. 489 __ mov(R0, Operand(FP)); // Get last FP address.
481 if (preserve_result) { 490 if (kind == kLazyDeoptFromReturn) {
482 __ Push(R1); // Preserve result as first local. 491 __ Push(R1); // Preserve result as first local.
492 } else if (kind == kLazyDeoptFromThrow) {
493 __ Push(R1); // Preserve exception as first local.
494 __ Push(R2); // Preserve stacktrace as second local.
483 } 495 }
484 __ ReserveAlignedFrameSpace(0); 496 __ ReserveAlignedFrameSpace(0);
485 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in R0. 497 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in R0.
486 if (preserve_result) { 498 if (kind == kLazyDeoptFromReturn) {
487 // Restore result into R1. 499 // Restore result into R1.
488 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); 500 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
501 } else if (kind == kLazyDeoptFromThrow) {
502 // Restore result into R1.
503 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
504 __ ldr(R2, Address(FP, (kFirstLocalSlotFromFp - 1) * kWordSize));
489 } 505 }
490 // Code above cannot cause GC. 506 // Code above cannot cause GC.
491 __ RestoreCodePointer(); 507 __ RestoreCodePointer();
492 __ LeaveStubFrame(); 508 __ LeaveStubFrame();
493 509
494 // Frame is fully rewritten at this point and it is safe to perform a GC. 510 // Frame is fully rewritten at this point and it is safe to perform a GC.
495 // Materialize any objects that were deferred by FillFrame because they 511 // Materialize any objects that were deferred by FillFrame because they
496 // require allocation. 512 // require allocation.
497 // Enter stub frame with loading PP. The caller's PP is not materialized yet. 513 // Enter stub frame with loading PP. The caller's PP is not materialized yet.
498 __ EnterStubFrame(); 514 __ EnterStubFrame();
499 if (preserve_result) { 515 if (kind == kLazyDeoptFromReturn) {
500 __ Push(R1); // Preserve result, it will be GC-d here. 516 __ Push(R1); // Preserve result, it will be GC-d here.
517 } else if (kind == kLazyDeoptFromThrow) {
518 __ Push(R1); // Preserve exception, it will be GC-d here.
519 __ Push(R2); // Preserve stacktrace, it will be GC-d here.
501 } 520 }
502 __ PushObject(Smi::ZoneHandle()); // Space for the result. 521 __ PushObject(Smi::ZoneHandle()); // Space for the result.
503 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); 522 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
504 // Result tells stub how many bytes to remove from the expression stack 523 // Result tells stub how many bytes to remove from the expression stack
505 // of the bottom-most frame. They were used as materialization arguments. 524 // of the bottom-most frame. They were used as materialization arguments.
506 __ Pop(R1); 525 __ Pop(R1);
507 if (preserve_result) { 526 if (kind == kLazyDeoptFromReturn) {
508 __ Pop(R0); // Restore result. 527 __ Pop(R0); // Restore result.
528 } else if (kind == kLazyDeoptFromThrow) {
529 __ Pop(R1); // Restore stacktrace.
530 __ Pop(R0); // Restore exception.
509 } 531 }
510 __ LeaveStubFrame(); 532 __ LeaveStubFrame();
511 // Remove materialization arguments. 533 // Remove materialization arguments.
512 __ add(SP, SP, Operand(R1, ASR, kSmiTagSize)); 534 __ add(SP, SP, Operand(R1, ASR, kSmiTagSize));
513 __ Ret(); 535 __ Ret();
514 } 536 }
515 537
516 538
517 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 539 // LR: return address + call-instruction-size
540 // R0: result, must be preserved
541 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
518 // Correct return address to point just after the call that is being 542 // Correct return address to point just after the call that is being
519 // deoptimized. 543 // deoptimized.
520 __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes()); 544 __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes());
521 // Push zap value instead of CODE_REG for lazy deopt. 545 // Push zap value instead of CODE_REG for lazy deopt.
522 __ LoadImmediate(IP, 0xf1f1f1f1); 546 __ LoadImmediate(IP, 0xf1f1f1f1);
523 __ Push(IP); 547 __ Push(IP);
524 GenerateDeoptimizationSequence(assembler, kLazyDeopt); 548 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
525 } 549 }
526 550
527 551
552 // LR: return address + call-instruction-size
553 // R0: exception, must be preserved
554 // R1: stacktrace, must be preserved
555 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
556 // Correct return address to point just after the call that is being
557 // deoptimized.
558 __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes());
559 // Push zap value instead of CODE_REG for lazy deopt.
560 __ LoadImmediate(IP, 0xf1f1f1f1);
561 __ Push(IP);
562 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
563 }
564
565
528 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 566 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
529 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 567 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
530 } 568 }
531 569
532 570
533 static void GenerateDispatcherCode(Assembler* assembler, 571 static void GenerateDispatcherCode(Assembler* assembler,
534 Label* call_target_function) { 572 Label* call_target_function) {
535 __ Comment("NoSuchMethodDispatch"); 573 __ Comment("NoSuchMethodDispatch");
536 // When lazily generated invocation dispatchers are disabled, the 574 // When lazily generated invocation dispatchers are disabled, the
537 // miss-handler may return null. 575 // miss-handler may return null.
(...skipping 1680 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 } 2256 }
2219 2257
2220 2258
2221 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2259 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2222 __ bkpt(0); 2260 __ bkpt(0);
2223 } 2261 }
2224 2262
2225 } // namespace dart 2263 } // namespace dart
2226 2264
2227 #endif // defined TARGET_ARCH_ARM 2265 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/stub_code.h ('k') | runtime/vm/stub_code_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698