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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed comments Created 5 years, 3 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/block_scheduler.cc ('k') | runtime/vm/code_patcher.h » ('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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 if (!target_function.HasCode()) { 667 if (!target_function.HasCode()) {
668 const Error& error = 668 const Error& error =
669 Error::Handle(Compiler::CompileFunction(thread, target_function)); 669 Error::Handle(Compiler::CompileFunction(thread, target_function));
670 if (!error.IsNull()) { 670 if (!error.IsNull()) {
671 Exceptions::PropagateError(error); 671 Exceptions::PropagateError(error);
672 } 672 }
673 } 673 }
674 const Code& target_code = Code::Handle(target_function.CurrentCode()); 674 const Code& target_code = Code::Handle(target_function.CurrentCode());
675 // Before patching verify that we are not repeatedly patching to the same 675 // Before patching verify that we are not repeatedly patching to the same
676 // target. 676 // target.
677 ASSERT(target_code.EntryPoint() != 677 ASSERT(target_code.raw() !=
678 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); 678 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code));
679 const Instructions& instrs = 679 CodePatcher::PatchStaticCallAt(caller_frame->pc(),
680 Instructions::Handle(caller_code.instructions()); 680 caller_code,
681 { 681 target_code);
682 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); 682 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
683 CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code,
684 target_code.EntryPoint());
685 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
686 }
687 if (FLAG_trace_patching) { 683 if (FLAG_trace_patching) {
688 OS::PrintErr("PatchStaticCall: patching caller pc %#" Px "" 684 OS::PrintErr("PatchStaticCall: patching caller pc %#" Px ""
689 " to '%s' new entry point %#" Px " (%s)\n", 685 " to '%s' new entry point %#" Px " (%s)\n",
690 caller_frame->pc(), 686 caller_frame->pc(),
691 target_function.ToFullyQualifiedCString(), 687 target_function.ToFullyQualifiedCString(),
692 target_code.EntryPoint(), 688 target_code.EntryPoint(),
693 target_code.is_optimized() ? "optimized" : "unoptimized"); 689 target_code.is_optimized() ? "optimized" : "unoptimized");
694 } 690 }
695 arguments.SetReturn(target_code); 691 arguments.SetReturn(target_code);
696 } 692 }
697 693
698 694
699 // Result of an invoke may be an unhandled exception, in which case we 695 // Result of an invoke may be an unhandled exception, in which case we
700 // rethrow it. 696 // rethrow it.
701 static void CheckResultError(const Object& result) { 697 static void CheckResultError(const Object& result) {
702 if (result.IsError()) { 698 if (result.IsError()) {
703 Exceptions::PropagateError(Error::Cast(result)); 699 Exceptions::PropagateError(Error::Cast(result));
704 } 700 }
705 } 701 }
706 702
707 703
708 // Gets called from debug stub when code reaches a breakpoint 704 // Gets called from debug stub when code reaches a breakpoint
709 // set on a runtime stub call. 705 // set on a runtime stub call.
710 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { 706 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
711 DartFrameIterator iterator; 707 DartFrameIterator iterator;
712 StackFrame* caller_frame = iterator.NextFrame(); 708 StackFrame* caller_frame = iterator.NextFrame();
713 ASSERT(caller_frame != NULL); 709 ASSERT(caller_frame != NULL);
714 uword orig_stub = 710 const Code& orig_stub = Code::Handle(
715 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()); 711 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()));
716 isolate->debugger()->SignalBpReached(); 712 isolate->debugger()->SignalBpReached();
717 ASSERT((orig_stub & kSmiTagMask) == kSmiTag); 713 arguments.SetReturn(orig_stub);
718 arguments.SetReturn(Smi::Handle(reinterpret_cast<RawSmi*>(orig_stub)));
719 } 714 }
720 715
721 716
722 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { 717 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) {
723 isolate->debugger()->DebuggerStepCallback(); 718 isolate->debugger()->DebuggerStepCallback();
724 } 719 }
725 720
726 721
727 // An instance call of the form o.f(...) could not be resolved. Check if 722 // An instance call of the form o.f(...) could not be resolved. Check if
728 // there is a getter with the same name. If so, invoke it. If the value is 723 // there is a getter with the same name. If so, invoke it. If the value is
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 // The current code will not be changed in the case that the compiler 1428 // The current code will not be changed in the case that the compiler
1434 // bailed out during OSR compilation. 1429 // bailed out during OSR compilation.
1435 if (optimized_code.raw() != original_code.raw()) { 1430 if (optimized_code.raw() != original_code.raw()) {
1436 // The OSR code does not work for calling the function, so restore the 1431 // The OSR code does not work for calling the function, so restore the
1437 // unoptimized code. Patch the stack frame to return into the OSR 1432 // unoptimized code. Patch the stack frame to return into the OSR
1438 // code. 1433 // code.
1439 uword optimized_entry = 1434 uword optimized_entry =
1440 Instructions::Handle(optimized_code.instructions()).EntryPoint(); 1435 Instructions::Handle(optimized_code.instructions()).EntryPoint();
1441 function.AttachCode(original_code); 1436 function.AttachCode(original_code);
1442 frame->set_pc(optimized_entry); 1437 frame->set_pc(optimized_entry);
1438 frame->set_pc_marker(optimized_code.raw());
1443 } 1439 }
1444 } 1440 }
1445 } 1441 }
1446 1442
1447 1443
1448 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { 1444 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) {
1449 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); 1445 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0));
1450 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); 1446 const Function& function = Function::CheckedHandle(arguments.ArgAt(1));
1451 DartFrameIterator iterator; 1447 DartFrameIterator iterator;
1452 StackFrame* frame = iterator.NextFrame(); 1448 StackFrame* frame = iterator.NextFrame();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 isolate, Compiler::CompileFunction(thread, target_function)); 1516 isolate, Compiler::CompileFunction(thread, target_function));
1521 if (!error.IsNull()) { 1517 if (!error.IsNull()) {
1522 Exceptions::PropagateError(error); 1518 Exceptions::PropagateError(error);
1523 } 1519 }
1524 } 1520 }
1525 ASSERT(target_function.HasCode()); 1521 ASSERT(target_function.HasCode());
1526 ASSERT(target_function.raw() == target_code.function()); 1522 ASSERT(target_function.raw() == target_code.function());
1527 1523
1528 const Code& current_target_code = Code::Handle( 1524 const Code& current_target_code = Code::Handle(
1529 isolate, target_function.CurrentCode()); 1525 isolate, target_function.CurrentCode());
1530 const Instructions& instrs = Instructions::Handle( 1526 CodePatcher::PatchStaticCallAt(frame->pc(),
1531 isolate, caller_code.instructions()); 1527 caller_code,
1532 { 1528 current_target_code);
1533 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); 1529 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
1534 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code,
1535 current_target_code.EntryPoint());
1536 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
1537 }
1538 if (FLAG_trace_patching) { 1530 if (FLAG_trace_patching) {
1539 OS::PrintErr("FixCallersTarget: caller %#" Px " " 1531 OS::PrintErr("FixCallersTarget: caller %#" Px " "
1540 "target '%s' %#" Px " -> %#" Px "\n", 1532 "target '%s' %#" Px " -> %#" Px "\n",
1541 frame->pc(), 1533 frame->pc(),
1542 target_function.ToFullyQualifiedCString(), 1534 target_function.ToFullyQualifiedCString(),
1543 target_code.EntryPoint(), 1535 target_code.EntryPoint(),
1544 current_target_code.EntryPoint()); 1536 current_target_code.EntryPoint());
1545 } 1537 }
1546 arguments.SetReturn(current_target_code); 1538 arguments.SetReturn(current_target_code);
1547 } 1539 }
1548 1540
1549 1541
1550 // The caller tried to allocate an instance via an invalidated allocation 1542 // The caller tried to allocate an instance via an invalidated allocation
1551 // stub. 1543 // stub.
1552 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { 1544 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) {
1553 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); 1545 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames);
1554 StackFrame* frame = iterator.NextFrame(); 1546 StackFrame* frame = iterator.NextFrame();
1555 ASSERT(frame != NULL); 1547 ASSERT(frame != NULL);
1556 while (frame->IsStubFrame() || frame->IsExitFrame()) { 1548 while (frame->IsStubFrame() || frame->IsExitFrame()) {
1557 frame = iterator.NextFrame(); 1549 frame = iterator.NextFrame();
1558 ASSERT(frame != NULL); 1550 ASSERT(frame != NULL);
1559 } 1551 }
1560 if (frame->IsEntryFrame()) { 1552 if (frame->IsEntryFrame()) {
1561 // There must be a valid Dart frame. 1553 // There must be a valid Dart frame.
1562 UNREACHABLE(); 1554 UNREACHABLE();
1563 } 1555 }
1564 ASSERT(frame->IsDartFrame()); 1556 ASSERT(frame->IsDartFrame());
1565 const Code& caller_code = Code::Handle(isolate, frame->LookupDartCode()); 1557 const Code& caller_code = Code::Handle(isolate, frame->LookupDartCode());
1566 ASSERT(!caller_code.IsNull()); 1558 ASSERT(!caller_code.IsNull());
1567 const uword target = 1559 const Code& stub = Code::Handle(
1568 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code); 1560 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code));
1569 const Code& stub = Code::Handle(isolate, Code::LookupCode(target));
1570 Class& alloc_class = Class::ZoneHandle(zone); 1561 Class& alloc_class = Class::ZoneHandle(zone);
1571 alloc_class ^= stub.owner(); 1562 alloc_class ^= stub.owner();
1572 Code& alloc_stub = Code::Handle(isolate, alloc_class.allocation_stub()); 1563 Code& alloc_stub = Code::Handle(isolate, alloc_class.allocation_stub());
1573 if (alloc_stub.IsNull()) { 1564 if (alloc_stub.IsNull()) {
1574 alloc_stub = StubCode::GetAllocationStubForClass(alloc_class); 1565 alloc_stub = StubCode::GetAllocationStubForClass(alloc_class);
1575 ASSERT(!CodePatcher::IsEntryPatched(alloc_stub)); 1566 ASSERT(!CodePatcher::IsEntryPatched(alloc_stub));
1576 } 1567 }
1577 const Instructions& instrs = 1568 CodePatcher::PatchStaticCallAt(frame->pc(),
1578 Instructions::Handle(isolate, caller_code.instructions()); 1569 caller_code,
1579 { 1570 alloc_stub);
1580 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); 1571 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub);
1581 CodePatcher::PatchStaticCallAt(frame->pc(),
1582 caller_code,
1583 alloc_stub.EntryPoint());
1584 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub);
1585 }
1586 if (FLAG_trace_patching) { 1572 if (FLAG_trace_patching) {
1587 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " 1573 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s "
1588 " -> %#" Px "\n", 1574 " -> %#" Px "\n",
1589 frame->pc(), 1575 frame->pc(),
1590 alloc_class.ToCString(), 1576 alloc_class.ToCString(),
1591 alloc_stub.EntryPoint()); 1577 alloc_stub.EntryPoint());
1592 } 1578 }
1593 arguments.SetReturn(alloc_stub); 1579 arguments.SetReturn(alloc_stub);
1594 } 1580 }
1595 1581
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 function.SwitchToUnoptimizedCode(); 1615 function.SwitchToUnoptimizedCode();
1630 } 1616 }
1631 // Patch call site (lazy deoptimization is quite rare, patching it twice 1617 // Patch call site (lazy deoptimization is quite rare, patching it twice
1632 // is not a performance issue). 1618 // is not a performance issue).
1633 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); 1619 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc();
1634 ASSERT(lazy_deopt_jump != 0); 1620 ASSERT(lazy_deopt_jump != 0);
1635 const Instructions& instrs = 1621 const Instructions& instrs =
1636 Instructions::Handle(zone, optimized_code.instructions()); 1622 Instructions::Handle(zone, optimized_code.instructions());
1637 { 1623 {
1638 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); 1624 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size());
1639 CodePatcher::InsertCallAt(pc, lazy_deopt_jump); 1625 CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump);
1640 } 1626 }
1641 if (FLAG_trace_patching) { 1627 if (FLAG_trace_patching) {
1642 const String& name = String::Handle(function.name()); 1628 const String& name = String::Handle(function.name());
1643 OS::PrintErr("InsertCallAt: %" Px " to %" Px " for %s\n", pc, 1629 OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc,
1644 lazy_deopt_jump, name.ToCString()); 1630 lazy_deopt_jump, name.ToCString());
1645 } 1631 }
1646 // Mark code as dead (do not GC its embedded objects). 1632 // Mark code as dead (do not GC its embedded objects).
1647 optimized_code.set_is_alive(false); 1633 optimized_code.set_is_alive(false);
1648 } 1634 }
1649 1635
1650 1636
1651 // Currently checks only that all optimized frames have kDeoptIndex 1637 // Currently checks only that all optimized frames have kDeoptIndex
1652 // and unoptimized code has the kDeoptAfter. 1638 // and unoptimized code has the kDeoptAfter.
1653 void DeoptimizeFunctionsOnStack() { 1639 void DeoptimizeFunctionsOnStack() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 *reinterpret_cast<intptr_t*>(saved_registers_address); 1672 *reinterpret_cast<intptr_t*>(saved_registers_address);
1687 saved_registers_address += kWordSize; 1673 saved_registers_address += kWordSize;
1688 } 1674 }
1689 *cpu_registers = cpu_registers_copy; 1675 *cpu_registers = cpu_registers_copy;
1690 } 1676 }
1691 1677
1692 1678
1693 // Copies saved registers and caller's frame into temporary buffers. 1679 // Copies saved registers and caller's frame into temporary buffers.
1694 // Returns the stack size of unoptimized frame. 1680 // Returns the stack size of unoptimized frame.
1695 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 1681 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1696 1, uword saved_registers_address) { 1682 2,
1683 uword saved_registers_address,
1684 uword is_lazy_deopt) {
1697 Thread* thread = Thread::Current(); 1685 Thread* thread = Thread::Current();
1698 Isolate* isolate = thread->isolate(); 1686 Isolate* isolate = thread->isolate();
1699 StackZone zone(thread); 1687 StackZone zone(thread);
1700 HANDLESCOPE(thread); 1688 HANDLESCOPE(thread);
1701 1689
1702 // All registers have been saved below last-fp as if they were locals. 1690 // All registers have been saved below last-fp as if they were locals.
1703 const uword last_fp = saved_registers_address 1691 const uword last_fp = saved_registers_address
1704 + (kNumberOfCpuRegisters * kWordSize) 1692 + (kNumberOfCpuRegisters * kWordSize)
1705 + (kNumberOfFpuRegisters * kFpuRegisterSize) 1693 + (kNumberOfFpuRegisters * kFpuRegisterSize)
1706 - ((kFirstLocalSlotFromFp + 1) * kWordSize); 1694 - ((kFirstLocalSlotFromFp + 1) * kWordSize);
1707 1695
1708 // Get optimized code and frame that need to be deoptimized. 1696 // Get optimized code and frame that need to be deoptimized.
1709 DartFrameIterator iterator(last_fp); 1697 DartFrameIterator iterator(last_fp);
1710 StackFrame* caller_frame = iterator.NextFrame(); 1698 StackFrame* caller_frame = iterator.NextFrame();
1711 ASSERT(caller_frame != NULL); 1699 ASSERT(caller_frame != NULL);
1712 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1700 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1713 ASSERT(optimized_code.is_optimized()); 1701 ASSERT(optimized_code.is_optimized());
1714 1702
1715 // Copy the saved registers from the stack. 1703 // Copy the saved registers from the stack.
1716 fpu_register_t* fpu_registers; 1704 fpu_register_t* fpu_registers;
1717 intptr_t* cpu_registers; 1705 intptr_t* cpu_registers;
1718 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); 1706 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers);
1719 1707
1720 // Create the DeoptContext. 1708 // Create the DeoptContext.
1721 DeoptContext* deopt_context = 1709 DeoptContext* deopt_context =
1722 new DeoptContext(caller_frame, optimized_code, 1710 new DeoptContext(caller_frame,
1711 optimized_code,
1723 DeoptContext::kDestIsOriginalFrame, 1712 DeoptContext::kDestIsOriginalFrame,
1724 fpu_registers, cpu_registers); 1713 fpu_registers,
1714 cpu_registers,
1715 is_lazy_deopt != 0);
1725 isolate->set_deopt_context(deopt_context); 1716 isolate->set_deopt_context(deopt_context);
1726 1717
1727 // Stack size (FP - SP) in bytes. 1718 // Stack size (FP - SP) in bytes.
1728 return deopt_context->DestStackAdjustment() * kWordSize; 1719 return deopt_context->DestStackAdjustment() * kWordSize;
1729 } 1720 }
1730 END_LEAF_RUNTIME_ENTRY 1721 END_LEAF_RUNTIME_ENTRY
1731 1722
1732 1723
1733 // The stack has been adjusted to fit all values for unoptimized frame. 1724 // The stack has been adjusted to fit all values for unoptimized frame.
1734 // Fill the unoptimized frame. 1725 // Fill the unoptimized frame.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 const intptr_t elm_size = old_data.ElementSizeInBytes(); 1846 const intptr_t elm_size = old_data.ElementSizeInBytes();
1856 const TypedData& new_data = 1847 const TypedData& new_data =
1857 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); 1848 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld));
1858 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); 1849 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size);
1859 typed_data_cell.SetAt(0, new_data); 1850 typed_data_cell.SetAt(0, new_data);
1860 arguments.SetReturn(new_data); 1851 arguments.SetReturn(new_data);
1861 } 1852 }
1862 1853
1863 1854
1864 } // namespace dart 1855 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/block_scheduler.cc ('k') | runtime/vm/code_patcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698