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

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

Issue 3007603002: [VM generic function reification] Support generic functions in Invocation class. (Closed)
Patch Set: address review comment Created 3 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/native_entry.h ('k') | runtime/vm/object.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) 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 #ifndef RUNTIME_VM_OBJECT_H_ 5 #ifndef RUNTIME_VM_OBJECT_H_
6 #define RUNTIME_VM_OBJECT_H_ 6 #define RUNTIME_VM_OBJECT_H_
7 7
8 #include "include/dart_api.h" 8 #include "include/dart_api.h"
9 #include "platform/assert.h" 9 #include "platform/assert.h"
10 #include "platform/utils.h" 10 #include "platform/utils.h"
(...skipping 1564 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 friend class Class; 1575 friend class Class;
1576 }; 1576 };
1577 1577
1578 // Classification of type genericity according to type parameter owners. 1578 // Classification of type genericity according to type parameter owners.
1579 enum Genericity { 1579 enum Genericity {
1580 kAny, // Consider type params of current class and functions. 1580 kAny, // Consider type params of current class and functions.
1581 kCurrentClass, // Consider type params of current class only. 1581 kCurrentClass, // Consider type params of current class only.
1582 kFunctions, // Consider type params of current and parent functions. 1582 kFunctions, // Consider type params of current and parent functions.
1583 }; 1583 };
1584 1584
1585 // A TypeArguments is an array of AbstractType.
1586 class TypeArguments : public Object {
1587 public:
1588 // We use 30 bits for the hash code so hashes in a snapshot taken on a
1589 // 64-bit architecture stay in Smi range when loaded on a 32-bit
1590 // architecture.
1591 static const intptr_t kHashBits = 30;
1592
1593 intptr_t Length() const;
1594 RawAbstractType* TypeAt(intptr_t index) const;
1595 static intptr_t type_at_offset(intptr_t index) {
1596 return OFFSET_OF_RETURNED_VALUE(RawTypeArguments, types) +
1597 index * kWordSize;
1598 }
1599 void SetTypeAt(intptr_t index, const AbstractType& value) const;
1600
1601 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
1602 RawString* Name() const { return SubvectorName(0, Length(), kInternalName); }
1603
1604 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
1605 // Names of internal classes are mapped to their public interfaces.
1606 RawString* UserVisibleName() const {
1607 return SubvectorName(0, Length(), kUserVisibleName);
1608 }
1609
1610 // Check if the subvector of length 'len' starting at 'from_index' of this
1611 // type argument vector consists solely of DynamicType.
1612 bool IsRaw(intptr_t from_index, intptr_t len) const {
1613 return IsDynamicTypes(false, from_index, len);
1614 }
1615
1616 // Check if this type argument vector would consist solely of DynamicType if
1617 // it was instantiated from both a raw (null) instantiator typearguments and
1618 // a raw (null) function type arguments, i.e. consider each class type
1619 // parameter and function type parameters as it would be first instantiated
1620 // from a vector of dynamic types.
1621 // Consider only a prefix of length 'len'.
1622 bool IsRawWhenInstantiatedFromRaw(intptr_t len) const {
1623 return IsDynamicTypes(true, 0, len);
1624 }
1625
1626 // Check the subtype relationship, considering only a subvector of length
1627 // 'len' starting at 'from_index'.
1628 bool IsSubtypeOf(const TypeArguments& other,
1629 intptr_t from_index,
1630 intptr_t len,
1631 Error* bound_error,
1632 TrailPtr bound_trail,
1633 Heap::Space space) const {
1634 return TypeTest(kIsSubtypeOf, other, from_index, len, bound_error,
1635 bound_trail, space);
1636 }
1637
1638 // Check the 'more specific' relationship, considering only a subvector of
1639 // length 'len' starting at 'from_index'.
1640 bool IsMoreSpecificThan(const TypeArguments& other,
1641 intptr_t from_index,
1642 intptr_t len,
1643 Error* bound_error,
1644 TrailPtr bound_trail,
1645 Heap::Space space) const {
1646 return TypeTest(kIsMoreSpecificThan, other, from_index, len, bound_error,
1647 bound_trail, space);
1648 }
1649
1650 // Check if the vectors are equal (they may be null).
1651 bool Equals(const TypeArguments& other) const {
1652 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length());
1653 }
1654
1655 bool IsEquivalent(const TypeArguments& other, TrailPtr trail = NULL) const {
1656 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length(), trail);
1657 }
1658 bool IsSubvectorEquivalent(const TypeArguments& other,
1659 intptr_t from_index,
1660 intptr_t len,
1661 TrailPtr trail = NULL) const;
1662
1663 // Check if the vector is instantiated (it must not be null).
1664 bool IsInstantiated(Genericity genericity = kAny,
1665 intptr_t num_free_fun_type_params = kMaxInt32,
1666 TrailPtr trail = NULL) const {
1667 return IsSubvectorInstantiated(0, Length(), genericity,
1668 num_free_fun_type_params, trail);
1669 }
1670 bool IsSubvectorInstantiated(intptr_t from_index,
1671 intptr_t len,
1672 Genericity genericity = kAny,
1673 intptr_t num_free_fun_type_params = kMaxInt32,
1674 TrailPtr trail = NULL) const;
1675 bool IsUninstantiatedIdentity() const;
1676 bool CanShareInstantiatorTypeArguments(const Class& instantiator_class) const;
1677
1678 // Return true if all types of this vector are respectively, resolved,
1679 // finalized, or bounded.
1680 bool IsResolved() const;
1681 bool IsFinalized() const;
1682 bool IsBounded() const;
1683
1684 // Return true if this vector contains a recursive type argument.
1685 bool IsRecursive() const;
1686
1687 // Set the scope of this type argument vector to the given function.
1688 void SetScopeFunction(const Function& function) const;
1689
1690 // Clone this type argument vector and clone all unfinalized type arguments.
1691 // Finalized type arguments are shared.
1692 RawTypeArguments* CloneUnfinalized() const;
1693
1694 // Clone this type argument vector and clone all uninstantiated type
1695 // arguments, changing the class owner of type parameters.
1696 // Instantiated type arguments are shared.
1697 RawTypeArguments* CloneUninstantiated(const Class& new_owner,
1698 TrailPtr trail = NULL) const;
1699
1700 // Canonicalize only if instantiated, otherwise returns 'this'.
1701 RawTypeArguments* Canonicalize(TrailPtr trail = NULL) const;
1702
1703 // Returns a formatted list of occurring type arguments with their URI.
1704 RawString* EnumerateURIs() const;
1705
1706 // Return 'this' if this type argument vector is instantiated, i.e. if it does
1707 // not refer to type parameters. Otherwise, return a new type argument vector
1708 // where each reference to a type parameter is replaced with the corresponding
1709 // type from the various type argument vectors (class instantiator, function,
1710 // or parent functions via the current context).
1711 // If bound_error is not NULL, it may be set to reflect a bound error.
1712 RawTypeArguments* InstantiateFrom(
1713 const TypeArguments& instantiator_type_arguments,
1714 const TypeArguments& function_type_arguments,
1715 Error* bound_error,
1716 TrailPtr instantiation_trail,
1717 TrailPtr bound_trail,
1718 Heap::Space space) const;
1719
1720 // Runtime instantiation with canonicalization. Not to be used during type
1721 // finalization at compile time.
1722 RawTypeArguments* InstantiateAndCanonicalizeFrom(
1723 const TypeArguments& instantiator_type_arguments,
1724 const TypeArguments& function_type_arguments,
1725 Error* bound_error) const;
1726
1727 // Return true if this type argument vector has cached instantiations.
1728 bool HasInstantiations() const;
1729
1730 // Return the number of cached instantiations for this type argument vector.
1731 intptr_t NumInstantiations() const;
1732
1733 static intptr_t instantiations_offset() {
1734 return OFFSET_OF(RawTypeArguments, instantiations_);
1735 }
1736
1737 static const intptr_t kBytesPerElement = kWordSize;
1738 static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
1739
1740 static intptr_t InstanceSize() {
1741 ASSERT(sizeof(RawTypeArguments) ==
1742 OFFSET_OF_RETURNED_VALUE(RawTypeArguments, types));
1743 return 0;
1744 }
1745
1746 static intptr_t InstanceSize(intptr_t len) {
1747 // Ensure that the types() is not adding to the object size, which includes
1748 // 3 fields: instantiations_, length_ and hash_.
1749 ASSERT(sizeof(RawTypeArguments) ==
1750 (sizeof(RawObject) + (kNumFields * kWordSize)));
1751 ASSERT(0 <= len && len <= kMaxElements);
1752 return RoundedAllocationSize(sizeof(RawTypeArguments) +
1753 (len * kBytesPerElement));
1754 }
1755
1756 intptr_t Hash() const;
1757
1758 static RawTypeArguments* New(intptr_t len, Heap::Space space = Heap::kOld);
1759
1760 private:
1761 intptr_t ComputeHash() const;
1762 void SetHash(intptr_t value) const;
1763
1764 // Check if the subvector of length 'len' starting at 'from_index' of this
1765 // type argument vector consists solely of DynamicType.
1766 // If raw_instantiated is true, consider each class type parameter to be first
1767 // instantiated from a vector of dynamic types.
1768 bool IsDynamicTypes(bool raw_instantiated,
1769 intptr_t from_index,
1770 intptr_t len) const;
1771
1772 // Check the subtype or 'more specific' relationship, considering only a
1773 // subvector of length 'len' starting at 'from_index'.
1774 bool TypeTest(TypeTestKind test_kind,
1775 const TypeArguments& other,
1776 intptr_t from_index,
1777 intptr_t len,
1778 Error* bound_error,
1779 TrailPtr bound_trail,
1780 Heap::Space space) const;
1781
1782 // Return the internal or public name of a subvector of this type argument
1783 // vector, e.g. "<T, dynamic, List<T>, int>".
1784 RawString* SubvectorName(intptr_t from_index,
1785 intptr_t len,
1786 NameVisibility name_visibility) const;
1787
1788 RawArray* instantiations() const;
1789 void set_instantiations(const Array& value) const;
1790 RawAbstractType* const* TypeAddr(intptr_t index) const;
1791 void SetLength(intptr_t value) const;
1792 // Number of fields in the raw object=3 (instantiations_, length_ and hash_).
1793 static const int kNumFields = 3;
1794
1795 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, Object);
1796 friend class AbstractType;
1797 friend class Class;
1798 friend class ClearTypeHashVisitor;
1799 friend class Object;
1800 };
1801
1802 class PatchClass : public Object { 1585 class PatchClass : public Object {
1803 public: 1586 public:
1804 RawClass* patched_class() const { return raw_ptr()->patched_class_; } 1587 RawClass* patched_class() const { return raw_ptr()->patched_class_; }
1805 RawClass* origin_class() const { return raw_ptr()->origin_class_; } 1588 RawClass* origin_class() const { return raw_ptr()->origin_class_; }
1806 RawScript* script() const { return raw_ptr()->script_; } 1589 RawScript* script() const { return raw_ptr()->script_; }
1807 1590
1808 static intptr_t InstanceSize() { 1591 static intptr_t InstanceSize() {
1809 return RoundedAllocationSize(sizeof(RawPatchClass)); 1592 return RoundedAllocationSize(sizeof(RawPatchClass));
1810 } 1593 }
1811 static bool IsInFullSnapshot(RawPatchClass* cls) { 1594 static bool IsInFullSnapshot(RawPatchClass* cls) {
(...skipping 3907 matching lines...) Expand 10 before | Expand all | Expand 10 after
5719 void set_num_imports(intptr_t value) const; 5502 void set_num_imports(intptr_t value) const;
5720 void set_importer(const Library& value) const; 5503 void set_importer(const Library& value) const;
5721 void set_is_loaded() const; 5504 void set_is_loaded() const;
5722 5505
5723 static RawLibraryPrefix* New(); 5506 static RawLibraryPrefix* New();
5724 5507
5725 FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Instance); 5508 FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Instance);
5726 friend class Class; 5509 friend class Class;
5727 }; 5510 };
5728 5511
5512 // A TypeArguments is an array of AbstractType.
5513 class TypeArguments : public Instance {
5514 public:
5515 // We use 30 bits for the hash code so hashes in a snapshot taken on a
5516 // 64-bit architecture stay in Smi range when loaded on a 32-bit
5517 // architecture.
5518 static const intptr_t kHashBits = 30;
5519
5520 intptr_t Length() const;
5521 RawAbstractType* TypeAt(intptr_t index) const;
5522 static intptr_t type_at_offset(intptr_t index) {
5523 return OFFSET_OF_RETURNED_VALUE(RawTypeArguments, types) +
5524 index * kWordSize;
5525 }
5526 void SetTypeAt(intptr_t index, const AbstractType& value) const;
5527
5528 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
5529 RawString* Name() const { return SubvectorName(0, Length(), kInternalName); }
5530
5531 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
5532 // Names of internal classes are mapped to their public interfaces.
5533 RawString* UserVisibleName() const {
5534 return SubvectorName(0, Length(), kUserVisibleName);
5535 }
5536
5537 // Check if the subvector of length 'len' starting at 'from_index' of this
5538 // type argument vector consists solely of DynamicType.
5539 bool IsRaw(intptr_t from_index, intptr_t len) const {
5540 return IsDynamicTypes(false, from_index, len);
5541 }
5542
5543 // Check if this type argument vector would consist solely of DynamicType if
5544 // it was instantiated from both a raw (null) instantiator typearguments and
5545 // a raw (null) function type arguments, i.e. consider each class type
5546 // parameter and function type parameters as it would be first instantiated
5547 // from a vector of dynamic types.
5548 // Consider only a prefix of length 'len'.
5549 bool IsRawWhenInstantiatedFromRaw(intptr_t len) const {
5550 return IsDynamicTypes(true, 0, len);
5551 }
5552
5553 // Check the subtype relationship, considering only a subvector of length
5554 // 'len' starting at 'from_index'.
5555 bool IsSubtypeOf(const TypeArguments& other,
5556 intptr_t from_index,
5557 intptr_t len,
5558 Error* bound_error,
5559 TrailPtr bound_trail,
5560 Heap::Space space) const {
5561 return TypeTest(kIsSubtypeOf, other, from_index, len, bound_error,
5562 bound_trail, space);
5563 }
5564
5565 // Check the 'more specific' relationship, considering only a subvector of
5566 // length 'len' starting at 'from_index'.
5567 bool IsMoreSpecificThan(const TypeArguments& other,
5568 intptr_t from_index,
5569 intptr_t len,
5570 Error* bound_error,
5571 TrailPtr bound_trail,
5572 Heap::Space space) const {
5573 return TypeTest(kIsMoreSpecificThan, other, from_index, len, bound_error,
5574 bound_trail, space);
5575 }
5576
5577 // Check if the vectors are equal (they may be null).
5578 bool Equals(const TypeArguments& other) const {
5579 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length());
5580 }
5581
5582 bool IsEquivalent(const TypeArguments& other, TrailPtr trail = NULL) const {
5583 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length(), trail);
5584 }
5585 bool IsSubvectorEquivalent(const TypeArguments& other,
5586 intptr_t from_index,
5587 intptr_t len,
5588 TrailPtr trail = NULL) const;
5589
5590 // Check if the vector is instantiated (it must not be null).
5591 bool IsInstantiated(Genericity genericity = kAny,
5592 intptr_t num_free_fun_type_params = kMaxInt32,
5593 TrailPtr trail = NULL) const {
5594 return IsSubvectorInstantiated(0, Length(), genericity,
5595 num_free_fun_type_params, trail);
5596 }
5597 bool IsSubvectorInstantiated(intptr_t from_index,
5598 intptr_t len,
5599 Genericity genericity = kAny,
5600 intptr_t num_free_fun_type_params = kMaxInt32,
5601 TrailPtr trail = NULL) const;
5602 bool IsUninstantiatedIdentity() const;
5603 bool CanShareInstantiatorTypeArguments(const Class& instantiator_class) const;
5604
5605 // Return true if all types of this vector are respectively, resolved,
5606 // finalized, or bounded.
5607 bool IsResolved() const;
5608 bool IsFinalized() const;
5609 bool IsBounded() const;
5610
5611 // Return true if this vector contains a recursive type argument.
5612 bool IsRecursive() const;
5613
5614 // Set the scope of this type argument vector to the given function.
5615 void SetScopeFunction(const Function& function) const;
5616
5617 // Clone this type argument vector and clone all unfinalized type arguments.
5618 // Finalized type arguments are shared.
5619 RawTypeArguments* CloneUnfinalized() const;
5620
5621 // Clone this type argument vector and clone all uninstantiated type
5622 // arguments, changing the class owner of type parameters.
5623 // Instantiated type arguments are shared.
5624 RawTypeArguments* CloneUninstantiated(const Class& new_owner,
5625 TrailPtr trail = NULL) const;
5626
5627 // Canonicalize only if instantiated, otherwise returns 'this'.
5628 RawTypeArguments* Canonicalize(TrailPtr trail = NULL) const;
5629
5630 // Returns a formatted list of occurring type arguments with their URI.
5631 RawString* EnumerateURIs() const;
5632
5633 // Return 'this' if this type argument vector is instantiated, i.e. if it does
5634 // not refer to type parameters. Otherwise, return a new type argument vector
5635 // where each reference to a type parameter is replaced with the corresponding
5636 // type from the various type argument vectors (class instantiator, function,
5637 // or parent functions via the current context).
5638 // If bound_error is not NULL, it may be set to reflect a bound error.
5639 RawTypeArguments* InstantiateFrom(
5640 const TypeArguments& instantiator_type_arguments,
5641 const TypeArguments& function_type_arguments,
5642 Error* bound_error,
5643 TrailPtr instantiation_trail,
5644 TrailPtr bound_trail,
5645 Heap::Space space) const;
5646
5647 // Runtime instantiation with canonicalization. Not to be used during type
5648 // finalization at compile time.
5649 RawTypeArguments* InstantiateAndCanonicalizeFrom(
5650 const TypeArguments& instantiator_type_arguments,
5651 const TypeArguments& function_type_arguments,
5652 Error* bound_error) const;
5653
5654 // Return true if this type argument vector has cached instantiations.
5655 bool HasInstantiations() const;
5656
5657 // Return the number of cached instantiations for this type argument vector.
5658 intptr_t NumInstantiations() const;
5659
5660 static intptr_t instantiations_offset() {
5661 return OFFSET_OF(RawTypeArguments, instantiations_);
5662 }
5663
5664 static const intptr_t kBytesPerElement = kWordSize;
5665 static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
5666
5667 static intptr_t InstanceSize() {
5668 ASSERT(sizeof(RawTypeArguments) ==
5669 OFFSET_OF_RETURNED_VALUE(RawTypeArguments, types));
5670 return 0;
5671 }
5672
5673 static intptr_t InstanceSize(intptr_t len) {
5674 // Ensure that the types() is not adding to the object size, which includes
5675 // 3 fields: instantiations_, length_ and hash_.
5676 ASSERT(sizeof(RawTypeArguments) ==
5677 (sizeof(RawObject) + (kNumFields * kWordSize)));
5678 ASSERT(0 <= len && len <= kMaxElements);
5679 return RoundedAllocationSize(sizeof(RawTypeArguments) +
5680 (len * kBytesPerElement));
5681 }
5682
5683 intptr_t Hash() const;
5684
5685 static RawTypeArguments* New(intptr_t len, Heap::Space space = Heap::kOld);
5686
5687 private:
5688 intptr_t ComputeHash() const;
5689 void SetHash(intptr_t value) const;
5690
5691 // Check if the subvector of length 'len' starting at 'from_index' of this
5692 // type argument vector consists solely of DynamicType.
5693 // If raw_instantiated is true, consider each class type parameter to be first
5694 // instantiated from a vector of dynamic types.
5695 bool IsDynamicTypes(bool raw_instantiated,
5696 intptr_t from_index,
5697 intptr_t len) const;
5698
5699 // Check the subtype or 'more specific' relationship, considering only a
5700 // subvector of length 'len' starting at 'from_index'.
5701 bool TypeTest(TypeTestKind test_kind,
5702 const TypeArguments& other,
5703 intptr_t from_index,
5704 intptr_t len,
5705 Error* bound_error,
5706 TrailPtr bound_trail,
5707 Heap::Space space) const;
5708
5709 // Return the internal or public name of a subvector of this type argument
5710 // vector, e.g. "<T, dynamic, List<T>, int>".
5711 RawString* SubvectorName(intptr_t from_index,
5712 intptr_t len,
5713 NameVisibility name_visibility) const;
5714
5715 RawArray* instantiations() const;
5716 void set_instantiations(const Array& value) const;
5717 RawAbstractType* const* TypeAddr(intptr_t index) const;
5718 void SetLength(intptr_t value) const;
5719 // Number of fields in the raw object=3 (instantiations_, length_ and hash_).
5720 static const int kNumFields = 3;
5721
5722 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, Instance);
5723 friend class AbstractType;
5724 friend class Class;
5725 friend class ClearTypeHashVisitor;
5726 friend class Object;
5727 };
5728
5729 // AbstractType is an abstract superclass. 5729 // AbstractType is an abstract superclass.
5730 // Subclasses of AbstractType are Type and TypeParameter. 5730 // Subclasses of AbstractType are Type and TypeParameter.
5731 class AbstractType : public Instance { 5731 class AbstractType : public Instance {
5732 public: 5732 public:
5733 // We use 30 bits for the hash code so hashes in a snapshot taken on a 5733 // We use 30 bits for the hash code so hashes in a snapshot taken on a
5734 // 64-bit architecture stay in Smi range when loaded on a 32-bit 5734 // 64-bit architecture stay in Smi range when loaded on a 32-bit
5735 // architecture. 5735 // architecture.
5736 static const intptr_t kHashBits = 30; 5736 static const intptr_t kHashBits = 30;
5737 5737
5738 virtual bool IsFinalized() const; 5738 virtual bool IsFinalized() const;
(...skipping 3266 matching lines...) Expand 10 before | Expand all | Expand 10 after
9005 9005
9006 inline void TypeArguments::SetHash(intptr_t value) const { 9006 inline void TypeArguments::SetHash(intptr_t value) const {
9007 // This is only safe because we create a new Smi, which does not cause 9007 // This is only safe because we create a new Smi, which does not cause
9008 // heap allocation. 9008 // heap allocation.
9009 StoreSmi(&raw_ptr()->hash_, Smi::New(value)); 9009 StoreSmi(&raw_ptr()->hash_, Smi::New(value));
9010 } 9010 }
9011 9011
9012 } // namespace dart 9012 } // namespace dart
9013 9013
9014 #endif // RUNTIME_VM_OBJECT_H_ 9014 #endif // RUNTIME_VM_OBJECT_H_
OLDNEW
« no previous file with comments | « runtime/vm/native_entry.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698