| 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 |