OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_macros.h" | 7 #include "vm/assembler_macros.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 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 &num_named_arguments, | 751 &num_named_arguments, |
752 &target); | 752 &target); |
753 ASSERT(function_name.IsSymbol()); | 753 ASSERT(function_name.IsSymbol()); |
754 Class& receiver_class = Class::Handle(); | 754 Class& receiver_class = Class::Handle(); |
755 if (receiver.IsNull()) { | 755 if (receiver.IsNull()) { |
756 // TODO(srdjan): Clarify behavior of null objects. | 756 // TODO(srdjan): Clarify behavior of null objects. |
757 receiver_class = isolate->object_store()->object_class(); | 757 receiver_class = isolate->object_store()->object_class(); |
758 } else { | 758 } else { |
759 receiver_class = receiver.clazz(); | 759 receiver_class = receiver.clazz(); |
760 } | 760 } |
761 FunctionsCache functions_cache(receiver_class); | |
762 Code& code = Code::Handle(); | |
763 code = functions_cache.LookupCode(function_name, | |
764 num_arguments, | |
765 num_named_arguments); | |
766 if (!code.IsNull()) { | |
767 // Function's code found in the cache. | |
768 return code.raw(); | |
769 } | |
770 | 761 |
771 Function& function = Function::Handle(); | 762 Function& function = Function::Handle(); |
772 function = Resolver::ResolveDynamic(receiver, | 763 function = Resolver::ResolveDynamic(receiver, |
773 function_name, | 764 function_name, |
774 num_arguments, | 765 num_arguments, |
775 num_named_arguments); | 766 num_named_arguments); |
776 if (function.IsNull()) { | 767 if (function.IsNull()) { |
777 return Code::null(); | 768 return Code::null(); |
778 } else { | 769 } else { |
779 if (!function.HasCode()) { | 770 if (!function.HasCode()) { |
780 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 771 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
781 if (!error.IsNull()) { | 772 if (!error.IsNull()) { |
782 Exceptions::PropagateError(error); | 773 Exceptions::PropagateError(error); |
783 } | 774 } |
784 } | 775 } |
785 functions_cache.AddCompiledFunction(function, | |
786 num_arguments, | |
787 num_named_arguments); | |
788 return function.CurrentCode(); | 776 return function.CurrentCode(); |
789 } | 777 } |
790 } | 778 } |
791 | 779 |
792 | 780 |
793 // Result of an invoke may be an unhandled exception, in which case we | 781 // Result of an invoke may be an unhandled exception, in which case we |
794 // rethrow it. | 782 // rethrow it. |
795 static void CheckResultError(const Object& result) { | 783 static void CheckResultError(const Object& result) { |
796 if (result.IsError()) { | 784 if (result.IsError()) { |
797 Exceptions::PropagateError(Error::Cast(result)); | 785 Exceptions::PropagateError(Error::Cast(result)); |
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 // classes have been collected. | 1613 // classes have been collected. |
1626 function.set_usage_counter(0); | 1614 function.set_usage_counter(0); |
1627 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1615 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
1628 | 1616 |
1629 if (function.HasOptimizedCode()) { | 1617 if (function.HasOptimizedCode()) { |
1630 function.SwitchToUnoptimizedCode(); | 1618 function.SwitchToUnoptimizedCode(); |
1631 } | 1619 } |
1632 } | 1620 } |
1633 END_LEAF_RUNTIME_ENTRY | 1621 END_LEAF_RUNTIME_ENTRY |
1634 | 1622 |
1635 | |
1636 // We are entering function name for a valid argument count. | |
1637 void FunctionsCache::EnterFunctionAt(int i, | |
1638 const Array& cache, | |
1639 const Function& function, | |
1640 int num_arguments, | |
1641 int num_named_arguments) { | |
1642 ASSERT((i % kNumEntries) == 0); | |
1643 ASSERT(function.AreValidArgumentCounts(num_arguments, | |
1644 num_named_arguments, | |
1645 NULL)); | |
1646 cache.SetAt(i + FunctionsCache::kFunctionName, | |
1647 String::Handle(function.name())); | |
1648 cache.SetAt(i + FunctionsCache::kArgCount, | |
1649 Smi::Handle(Smi::New(num_arguments))); | |
1650 cache.SetAt(i + FunctionsCache::kNamedArgCount, | |
1651 Smi::Handle(Smi::New(num_named_arguments))); | |
1652 cache.SetAt(i + FunctionsCache::kFunction, function); | |
1653 } | |
1654 | |
1655 | |
1656 void FunctionsCache::AddCompiledFunction(const Function& function, | |
1657 int num_arguments, | |
1658 int num_named_arguments) { | |
1659 // TODO(srdjan): Evaluate if populating the function cache is needed. | |
1660 // It is turned off currently because we do not populate code objects | |
1661 // in snapshot and hence end up in an inconsistent state as function | |
1662 // cache is populated but there are no code objects. | |
1663 #if 0 | |
1664 ASSERT(function.HasCode()); | |
1665 Array& cache = Array::Handle(class_.functions_cache()); | |
1666 if (cache.IsNull()) { | |
1667 class_.InitFunctionsCache(); | |
1668 cache = class_.functions_cache(); | |
1669 } | |
1670 // Search for first free slot. Last entry is always NULL object. | |
1671 for (intptr_t i = 0; i < (cache.Length() - kNumEntries); i += kNumEntries) { | |
1672 if (Object::Handle(cache.At(i)).IsNull()) { | |
1673 EnterFunctionAt(i, | |
1674 cache, | |
1675 function, | |
1676 num_arguments, | |
1677 num_named_arguments); | |
1678 return; | |
1679 } | |
1680 } | |
1681 intptr_t ix = cache.Length() - kNumEntries; | |
1682 // Grow by 8 entries. | |
1683 cache = Array::Grow(cache, cache.Length() + (8 * kNumEntries)); | |
1684 class_.set_functions_cache(cache); | |
1685 EnterFunctionAt(ix, | |
1686 cache, | |
1687 function, | |
1688 num_arguments, | |
1689 num_named_arguments); | |
1690 #endif | |
1691 } | |
1692 | |
1693 | |
1694 // Only the number of named arguments is checked, but not the actual names. | |
1695 RawCode* FunctionsCache::LookupCode(const String& function_name, | |
1696 int num_arguments, | |
1697 int num_named_arguments) { | |
1698 const Array& cache = Array::Handle(class_.functions_cache()); | |
1699 if (cache.IsNull()) { | |
1700 return Code::null(); // Functions cache has not been populated yet. | |
1701 } | |
1702 String& test_name = String::Handle(); | |
1703 for (intptr_t i = 0; i < cache.Length(); i += kNumEntries) { | |
1704 test_name ^= cache.At(i + FunctionsCache::kFunctionName); | |
1705 if (test_name.IsNull()) { | |
1706 // Found NULL, no more entries to check, abort lookup. | |
1707 return Code::null(); | |
1708 } | |
1709 if (function_name.Equals(test_name)) { | |
1710 Smi& smi = Smi::Handle(); | |
1711 smi ^= cache.At(i + FunctionsCache::kArgCount); | |
1712 if (num_arguments == smi.Value()) { | |
1713 smi ^= cache.At(i + FunctionsCache::kNamedArgCount); | |
1714 if (num_named_arguments == smi.Value()) { | |
1715 Function& result = Function::Handle(); | |
1716 result ^= cache.At(i + FunctionsCache::kFunction); | |
1717 ASSERT(!result.IsNull()); | |
1718 ASSERT(result.HasCode()); | |
1719 return result.CurrentCode(); | |
1720 } | |
1721 } | |
1722 } | |
1723 } | |
1724 // The cache is null terminated, therefore the loop above should never | |
1725 // terminate by itself. | |
1726 UNREACHABLE(); | |
1727 return Code::null(); | |
1728 } | |
1729 | |
1730 } // namespace dart | 1623 } // namespace dart |
OLD | NEW |