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

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

Issue 18097004: Support fast noSuchMethod dispatch for any number of arguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: reformatting Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
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/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1485 void Class::InitEmptyFields() { 1485 void Class::InitEmptyFields() {
1486 if (Object::empty_array().raw() == Array::null()) { 1486 if (Object::empty_array().raw() == Array::null()) {
1487 // The empty array has not been initialized yet. 1487 // The empty array has not been initialized yet.
1488 return; 1488 return;
1489 } 1489 }
1490 StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw()); 1490 StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw());
1491 StorePointer(&raw_ptr()->constants_, Object::empty_array().raw()); 1491 StorePointer(&raw_ptr()->constants_, Object::empty_array().raw());
1492 StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw()); 1492 StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw());
1493 StorePointer(&raw_ptr()->functions_, Object::empty_array().raw()); 1493 StorePointer(&raw_ptr()->functions_, Object::empty_array().raw());
1494 StorePointer(&raw_ptr()->fields_, Object::empty_array().raw()); 1494 StorePointer(&raw_ptr()->fields_, Object::empty_array().raw());
1495 StorePointer(&raw_ptr()->no_such_method_cache_, Object::empty_array().raw());
1495 } 1496 }
1496 1497
1497 1498
1498 bool Class::HasInstanceFields() const { 1499 bool Class::HasInstanceFields() const {
1499 const Array& field_array = Array::Handle(fields()); 1500 const Array& field_array = Array::Handle(fields());
1500 Field& field = Field::Handle(); 1501 Field& field = Field::Handle();
1501 for (intptr_t i = 0; i < field_array.Length(); ++i) { 1502 for (intptr_t i = 0; i < field_array.Length(); ++i) {
1502 field ^= field_array.At(i); 1503 field ^= field_array.At(i);
1503 if (!field.is_static()) { 1504 if (!field.is_static()) {
1504 return true; 1505 return true;
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 ASSERT(field.Offset() == 0); 1742 ASSERT(field.Offset() == 0);
1742 field.SetOffset(offset); 1743 field.SetOffset(offset);
1743 offset += kWordSize; 1744 offset += kWordSize;
1744 } 1745 }
1745 } 1746 }
1746 set_instance_size(RoundedAllocationSize(offset)); 1747 set_instance_size(RoundedAllocationSize(offset));
1747 set_next_field_offset(offset); 1748 set_next_field_offset(offset);
1748 } 1749 }
1749 1750
1750 1751
1752 RawFunction* Class::GetNoSuchMethodDispatcher(const String& target_name,
1753 const Array& args_desc) const {
1754 enum {
1755 kNameIndex = 0,
1756 kArgsDescIndex,
1757 kFunctionIndex,
1758 kEntrySize
1759 };
1760
1761 Function& dispatcher = Function::Handle();
1762 Array& cache = Array::Handle(no_such_method_cache());
1763 ASSERT(!cache.IsNull());
1764 String& name = String::Handle();
1765 Array& desc = Array::Handle();
1766 intptr_t i = 0;
1767 for (; i < cache.Length(); i += kEntrySize) {
1768 name ^= cache.At(i + kNameIndex);
1769 if (name.IsNull()) break; // Reached last entry.
srdjan 2013/07/09 15:20:28 WHy do you terminate on name being null AND on cac
Florian Schneider 2013/07/10 09:06:00 When growing by more than 1 element, the cache arr
1770 if (!name.Equals(target_name)) continue;
1771 desc ^= cache.At(i + kArgsDescIndex);
1772 if (desc.raw() != args_desc.raw()) continue;
1773 // Found match.
1774 dispatcher ^= cache.At(i + kFunctionIndex);
1775 ASSERT(dispatcher.IsFunction());
1776 break;
srdjan 2013/07/09 15:20:28 I believe this is simpler: if (desc.raw() == args_
Florian Schneider 2013/07/10 09:06:00 Done.
1777 }
1778
1779 if (dispatcher.IsNull()) {
1780 if (i == cache.Length()) {
1781 // Allocate new larger cache.
1782 intptr_t new_len = cache.Length() == 0 ? kEntrySize : cache.Length() * 2;
srdjan 2013/07/09 15:35:40 Is it necessary to grow that aggressively? I would
Florian Schneider 2013/07/10 09:06:00 I don't think it matters, For the common case of f
1783 cache ^= Array::Grow(cache, new_len);
1784 set_no_such_method_cache(cache);
1785 }
1786 dispatcher ^= CreateNoSuchMethodDispatcher(target_name, args_desc);
1787 cache.SetAt(i + kNameIndex, target_name);
1788 cache.SetAt(i + kArgsDescIndex, args_desc);
1789 cache.SetAt(i + kFunctionIndex, dispatcher);
1790 }
1791 return dispatcher.raw();
1792 }
1793
1794
1795 RawFunction* Class::CreateNoSuchMethodDispatcher(const String& target_name,
1796 const Array& args_desc) const {
1797 Function& invocation = Function::Handle(
1798 Function::New(String::Handle(Symbols::New(target_name)),
1799 RawFunction::kNoSuchMethodDispatcher,
1800 false, // Not static.
1801 false, // Not const.
1802 false, // Not abstract.
1803 false, // Not external.
1804 *this,
1805 0)); // No token position.
1806 ArgumentsDescriptor desc(args_desc);
1807 const intptr_t num_parameters = desc.Count();
1808 invocation.set_num_fixed_parameters(num_parameters);
1809 invocation.SetNumOptionalParameters(0, true);
1810 invocation.set_parameter_types(Array::Handle(Array::New(num_parameters,
1811 Heap::kOld)));
1812 invocation.set_parameter_names(Array::Handle(Array::New(num_parameters,
1813 Heap::kOld)));
1814 // Receiver.
1815 invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType()));
1816 invocation.SetParameterNameAt(0, Symbols::This());
1817 // Remaining parameters.
1818 for (intptr_t i = 1; i < num_parameters; i++) {
1819 invocation.SetParameterTypeAt(i, Type::Handle(Type::DynamicType()));
1820 char name[64];
1821 OS::SNPrint(name, 64, ":p%"Pd, i);
1822 invocation.SetParameterNameAt(i, String::Handle(Symbols::New(name)));
1823 }
1824 invocation.set_result_type(Type::Handle(Type::DynamicType()));
1825 invocation.set_is_visible(false); // Not visible in stack trace.
1826 invocation.set_saved_args_desc(args_desc);
1827
1828 return invocation.raw();
1829 }
1830
1831
1832 RawArray* Class::no_such_method_cache() const {
1833 return raw_ptr()->no_such_method_cache_;
1834 }
1835
1836
1837 void Class::set_no_such_method_cache(const Array& cache) const {
1838 StorePointer(&raw_ptr()->no_such_method_cache_, cache.raw());
1839 }
1840
1841
1751 void Class::Finalize() const { 1842 void Class::Finalize() const {
1752 ASSERT(!is_finalized()); 1843 ASSERT(!is_finalized());
1753 // Prefinalized classes have a VM internal representation and no Dart fields. 1844 // Prefinalized classes have a VM internal representation and no Dart fields.
1754 // Their instance size is precomputed and field offsets are known. 1845 // Their instance size is precomputed and field offsets are known.
1755 if (!is_prefinalized()) { 1846 if (!is_prefinalized()) {
1756 // Compute offsets of instance fields and instance size. 1847 // Compute offsets of instance fields and instance size.
1757 CalculateFieldOffsets(); 1848 CalculateFieldOffsets();
1758 } 1849 }
1759 set_is_finalized(); 1850 set_is_finalized();
1760 } 1851 }
(...skipping 1787 matching lines...) Expand 10 before | Expand all | Expand 10 after
3548 } 3639 }
3549 3640
3550 3641
3551 void Function::set_extracted_method_closure(const Function& value) const { 3642 void Function::set_extracted_method_closure(const Function& value) const {
3552 ASSERT(kind() == RawFunction::kMethodExtractor); 3643 ASSERT(kind() == RawFunction::kMethodExtractor);
3553 ASSERT(raw_ptr()->data_ == Object::null()); 3644 ASSERT(raw_ptr()->data_ == Object::null());
3554 set_data(value); 3645 set_data(value);
3555 } 3646 }
3556 3647
3557 3648
3649 RawArray* Function::saved_args_desc() const {
3650 ASSERT(kind() == RawFunction::kNoSuchMethodDispatcher);
3651 const Object& obj = Object::Handle(raw_ptr()->data_);
3652 ASSERT(obj.IsArray());
3653 return Array::Cast(obj).raw();
3654 }
3655
3656
3657 void Function::set_saved_args_desc(const Array& value) const {
3658 ASSERT(kind() == RawFunction::kNoSuchMethodDispatcher);
3659 ASSERT(raw_ptr()->data_ == Object::null());
3660 set_data(value);
3661 }
3662
3663
3558 RawFunction* Function::parent_function() const { 3664 RawFunction* Function::parent_function() const {
3559 if (IsClosureFunction()) { 3665 if (IsClosureFunction()) {
3560 const Object& obj = Object::Handle(raw_ptr()->data_); 3666 const Object& obj = Object::Handle(raw_ptr()->data_);
3561 ASSERT(!obj.IsNull()); 3667 ASSERT(!obj.IsNull());
3562 return ClosureData::Cast(obj).parent_function(); 3668 return ClosureData::Cast(obj).parent_function();
3563 } 3669 }
3564 return Function::null(); 3670 return Function::null();
3565 } 3671 }
3566 3672
3567 3673
(...skipping 10097 matching lines...) Expand 10 before | Expand all | Expand 10 after
13665 space); 13771 space);
13666 return reinterpret_cast<RawWeakProperty*>(raw); 13772 return reinterpret_cast<RawWeakProperty*>(raw);
13667 } 13773 }
13668 13774
13669 13775
13670 const char* WeakProperty::ToCString() const { 13776 const char* WeakProperty::ToCString() const {
13671 return "_WeakProperty"; 13777 return "_WeakProperty";
13672 } 13778 }
13673 13779
13674 } // namespace dart 13780 } // namespace dart
OLDNEW
« runtime/vm/code_generator.cc ('K') | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698