Chromium Code Reviews| 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 RawClass* Object::type_parameter_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 61 RawClass* Object::type_parameter_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 62 RawClass* Object::instantiated_type_class_ = | 62 RawClass* Object::instantiated_type_class_ = |
| 63 reinterpret_cast<RawClass*>(RAW_NULL); | 63 reinterpret_cast<RawClass*>(RAW_NULL); |
| 64 RawClass* Object::abstract_type_arguments_class_ = | 64 RawClass* Object::abstract_type_arguments_class_ = |
| 65 reinterpret_cast<RawClass*>(RAW_NULL); | 65 reinterpret_cast<RawClass*>(RAW_NULL); |
| 66 RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 66 RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 67 RawClass* Object::instantiated_type_arguments_class_ = | 67 RawClass* Object::instantiated_type_arguments_class_ = |
| 68 reinterpret_cast<RawClass*>(RAW_NULL); | 68 reinterpret_cast<RawClass*>(RAW_NULL); |
| 69 RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 69 RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 70 RawClass* Object::field_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 70 RawClass* Object::field_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 71 RawClass* Object::literal_token_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | |
| 71 RawClass* Object::token_stream_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 72 RawClass* Object::token_stream_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 72 RawClass* Object::script_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 73 RawClass* Object::script_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 73 RawClass* Object::library_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 74 RawClass* Object::library_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 74 RawClass* Object::library_prefix_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 75 RawClass* Object::library_prefix_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 75 RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 76 RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 76 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 77 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 77 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL); | 78 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
| 78 RawClass* Object::var_descriptors_class_ = | 79 RawClass* Object::var_descriptors_class_ = |
| 79 reinterpret_cast<RawClass*>(RAW_NULL); | 80 reinterpret_cast<RawClass*>(RAW_NULL); |
| 80 RawClass* Object::exception_handlers_class_ = | 81 RawClass* Object::exception_handlers_class_ = |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 110 } else if (raw_class == abstract_type_arguments_class()) { | 111 } else if (raw_class == abstract_type_arguments_class()) { |
| 111 return kAbstractTypeArgumentsClass; | 112 return kAbstractTypeArgumentsClass; |
| 112 } else if (raw_class == type_arguments_class()) { | 113 } else if (raw_class == type_arguments_class()) { |
| 113 return kTypeArgumentsClass; | 114 return kTypeArgumentsClass; |
| 114 } else if (raw_class == instantiated_type_arguments_class()) { | 115 } else if (raw_class == instantiated_type_arguments_class()) { |
| 115 return kInstantiatedTypeArgumentsClass; | 116 return kInstantiatedTypeArgumentsClass; |
| 116 } else if (raw_class == function_class()) { | 117 } else if (raw_class == function_class()) { |
| 117 return kFunctionClass; | 118 return kFunctionClass; |
| 118 } else if (raw_class == field_class()) { | 119 } else if (raw_class == field_class()) { |
| 119 return kFieldClass; | 120 return kFieldClass; |
| 121 } else if (raw_class == literal_token_class()) { | |
| 122 return kLiteralTokenClass; | |
| 120 } else if (raw_class == token_stream_class()) { | 123 } else if (raw_class == token_stream_class()) { |
| 121 return kTokenStreamClass; | 124 return kTokenStreamClass; |
| 122 } else if (raw_class == script_class()) { | 125 } else if (raw_class == script_class()) { |
| 123 return kScriptClass; | 126 return kScriptClass; |
| 124 } else if (raw_class == library_class()) { | 127 } else if (raw_class == library_class()) { |
| 125 return kLibraryClass; | 128 return kLibraryClass; |
| 126 } else if (raw_class == library_prefix_class()) { | 129 } else if (raw_class == library_prefix_class()) { |
| 127 return kLibraryPrefixClass; | 130 return kLibraryPrefixClass; |
| 128 } else if (raw_class == code_class()) { | 131 } else if (raw_class == code_class()) { |
| 129 return kCodeClass; | 132 return kCodeClass; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 163 case kUnresolvedClassClass: return unresolved_class_class(); | 166 case kUnresolvedClassClass: return unresolved_class_class(); |
| 164 case kTypeClass: return type_class(); | 167 case kTypeClass: return type_class(); |
| 165 case kTypeParameterClass: return type_parameter_class(); | 168 case kTypeParameterClass: return type_parameter_class(); |
| 166 case kInstantiatedTypeClass: return instantiated_type_class(); | 169 case kInstantiatedTypeClass: return instantiated_type_class(); |
| 167 case kAbstractTypeArgumentsClass: return abstract_type_arguments_class(); | 170 case kAbstractTypeArgumentsClass: return abstract_type_arguments_class(); |
| 168 case kTypeArgumentsClass: return type_arguments_class(); | 171 case kTypeArgumentsClass: return type_arguments_class(); |
| 169 case kInstantiatedTypeArgumentsClass: | 172 case kInstantiatedTypeArgumentsClass: |
| 170 return instantiated_type_arguments_class(); | 173 return instantiated_type_arguments_class(); |
| 171 case kFunctionClass: return function_class(); | 174 case kFunctionClass: return function_class(); |
| 172 case kFieldClass: return field_class(); | 175 case kFieldClass: return field_class(); |
| 176 case kLiteralTokenClass: return literal_token_class(); | |
| 173 case kTokenStreamClass: return token_stream_class(); | 177 case kTokenStreamClass: return token_stream_class(); |
| 174 case kScriptClass: return script_class(); | 178 case kScriptClass: return script_class(); |
| 175 case kLibraryClass: return library_class(); | 179 case kLibraryClass: return library_class(); |
| 176 case kLibraryPrefixClass: return library_prefix_class(); | 180 case kLibraryPrefixClass: return library_prefix_class(); |
| 177 case kCodeClass: return code_class(); | 181 case kCodeClass: return code_class(); |
| 178 case kInstructionsClass: return instructions_class(); | 182 case kInstructionsClass: return instructions_class(); |
| 179 case kPcDescriptorsClass: return pc_descriptors_class(); | 183 case kPcDescriptorsClass: return pc_descriptors_class(); |
| 180 case kLocalVarDescriptorsClass: return var_descriptors_class(); | 184 case kLocalVarDescriptorsClass: return var_descriptors_class(); |
| 181 case kExceptionHandlersClass: return exception_handlers_class(); | 185 case kExceptionHandlersClass: return exception_handlers_class(); |
| 182 case kContextClass: return context_class(); | 186 case kContextClass: return context_class(); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 | 330 |
| 327 cls = Class::New<InstantiatedTypeArguments>(); | 331 cls = Class::New<InstantiatedTypeArguments>(); |
| 328 instantiated_type_arguments_class_ = cls.raw(); | 332 instantiated_type_arguments_class_ = cls.raw(); |
| 329 | 333 |
| 330 cls = Class::New<Function>(); | 334 cls = Class::New<Function>(); |
| 331 function_class_ = cls.raw(); | 335 function_class_ = cls.raw(); |
| 332 | 336 |
| 333 cls = Class::New<Field>(); | 337 cls = Class::New<Field>(); |
| 334 field_class_ = cls.raw(); | 338 field_class_ = cls.raw(); |
| 335 | 339 |
| 340 cls = Class::New<LiteralToken>(); | |
| 341 literal_token_class_ = cls.raw(); | |
| 342 | |
| 336 cls = Class::New<TokenStream>(); | 343 cls = Class::New<TokenStream>(); |
| 337 token_stream_class_ = cls.raw(); | 344 token_stream_class_ = cls.raw(); |
| 338 | 345 |
| 339 cls = Class::New<Script>(); | 346 cls = Class::New<Script>(); |
| 340 script_class_ = cls.raw(); | 347 script_class_ = cls.raw(); |
| 341 | 348 |
| 342 cls = Class::New<Library>(); | 349 cls = Class::New<Library>(); |
| 343 library_class_ = cls.raw(); | 350 library_class_ = cls.raw(); |
| 344 | 351 |
| 345 cls = Class::New<LibraryPrefix>(); | 352 cls = Class::New<LibraryPrefix>(); |
| (...skipping 3379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3725 const char* cls_name = String::Handle(cls.Name()).ToCString(); | 3732 const char* cls_name = String::Handle(cls.Name()).ToCString(); |
| 3726 intptr_t len = | 3733 intptr_t len = |
| 3727 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1) + 1; | 3734 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1) + 1; |
| 3728 char* chars = reinterpret_cast<char*>( | 3735 char* chars = reinterpret_cast<char*>( |
| 3729 Isolate::Current()->current_zone()->Allocate(len)); | 3736 Isolate::Current()->current_zone()->Allocate(len)); |
| 3730 OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1); | 3737 OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1); |
| 3731 return chars; | 3738 return chars; |
| 3732 } | 3739 } |
| 3733 | 3740 |
| 3734 | 3741 |
| 3742 void LiteralToken::set_literal(const String& literal) const { | |
| 3743 StorePointer(&raw_ptr()->literal_, literal.raw()); | |
| 3744 } | |
| 3745 | |
| 3746 | |
| 3747 void LiteralToken::set_value(const Object& value) const { | |
| 3748 StorePointer(&raw_ptr()->value_, value.raw()); | |
| 3749 } | |
| 3750 | |
| 3751 | |
| 3752 RawLiteralToken* LiteralToken::Canonicalize() const { | |
| 3753 const String& literal_value = String::Handle(literal()); | |
| 3754 return NewCanonical(kind(), literal_value); | |
| 3755 } | |
| 3756 | |
| 3757 | |
| 3758 RawLiteralToken* LiteralToken::New() { | |
| 3759 const Class& cls = Class::Handle(Object::literal_token_class()); | |
| 3760 RawObject* raw = Object::Allocate(cls, | |
| 3761 LiteralToken::InstanceSize(), | |
| 3762 Heap::kOld); | |
| 3763 return reinterpret_cast<RawLiteralToken*>(raw); | |
| 3764 } | |
| 3765 | |
| 3766 | |
| 3767 RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) { | |
| 3768 const LiteralToken& result = LiteralToken::Handle(LiteralToken::New()); | |
| 3769 result.set_kind(kind); | |
| 3770 result.set_literal(literal); | |
| 3771 if (kind == Token::kINTEGER) { | |
| 3772 const Integer& value = Integer::Handle(Integer::New(literal)); | |
| 3773 result.set_value(value); | |
| 3774 } else if (kind == Token::kDOUBLE) { | |
| 3775 const Double& value = Double::Handle(Double::NewCanonical(literal)); | |
| 3776 result.set_value(value); | |
| 3777 } else { | |
| 3778 ASSERT(Token::NeedsLiteralToken(kind)); | |
| 3779 result.set_value(literal); | |
| 3780 } | |
| 3781 return result.raw(); | |
| 3782 } | |
| 3783 | |
| 3784 | |
| 3785 RawLiteralToken* LiteralToken::NewCanonical(Token::Kind kind, | |
| 3786 const String& literal) { | |
| 3787 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 3788 Array& canonical_list = | |
| 3789 Array::Handle(object_store->literal_tokens_canonical_list()); | |
| 3790 const intptr_t canonical_list_len = | |
| 3791 canonical_list.IsNull() ? 0 : canonical_list.Length(); | |
| 3792 | |
| 3793 // Linear search to see whether this value is already present in the | |
| 3794 // list of canonicalized literal tokens. | |
| 3795 intptr_t index = 0; | |
| 3796 LiteralToken& canonical_value = LiteralToken::Handle(); | |
| 3797 String& literal_value = String::Handle(); | |
| 3798 while (index < canonical_list_len) { | |
|
hausner
2012/02/25 00:41:57
This linear search might become a bottleneck once
siva
2012/02/28 19:57:31
I removed this canonicalization step, the literal
| |
| 3799 canonical_value ^= canonical_list.At(index); | |
| 3800 if (canonical_value.IsNull()) { | |
| 3801 break; | |
| 3802 } | |
| 3803 if ((canonical_value.kind() == kind)) { | |
| 3804 literal_value = canonical_value.literal(); | |
| 3805 if (literal_value.Equals(literal, 0, literal.Length())) { | |
|
hausner
2012/02/25 00:41:57
As discussed in person: no need to call Equals, yo
siva
2012/02/28 19:57:31
This code has been removed.
On 2012/02/25 00:41:5
| |
| 3806 return canonical_value.raw(); | |
| 3807 } | |
| 3808 } | |
| 3809 index++; | |
| 3810 } | |
| 3811 // The value needs to be added to the canonical list. | |
| 3812 // Grow the list if it is full. | |
| 3813 canonical_value = LiteralToken::New(kind, literal); | |
| 3814 if (index >= canonical_list_len) { | |
| 3815 const intptr_t new_length = canonical_list_len + 4; | |
| 3816 canonical_list = Array::Grow(canonical_list, new_length, Heap::kOld); | |
| 3817 object_store->set_literal_tokens_canonical_list(canonical_list); | |
| 3818 } | |
| 3819 canonical_list.SetAt(index, canonical_value); | |
| 3820 canonical_value.SetCanonical(); | |
| 3821 return canonical_value.raw(); | |
| 3822 } | |
| 3823 | |
| 3824 | |
| 3825 const char* LiteralToken::ToCString() const { | |
| 3826 const String& token = String::Handle(literal()); | |
| 3827 return token.ToCString(); | |
| 3828 } | |
| 3829 | |
| 3830 | |
| 3735 void TokenStream::SetLength(intptr_t value) const { | 3831 void TokenStream::SetLength(intptr_t value) const { |
| 3736 raw_ptr()->length_ = Smi::New(value); | 3832 raw_ptr()->length_ = Smi::New(value); |
| 3737 } | 3833 } |
| 3738 | 3834 |
| 3739 | 3835 |
| 3740 void TokenStream::SetTokenAt(intptr_t index, | 3836 void TokenStream::SetTokenAt(intptr_t index, |
| 3741 Token::Kind kind, | 3837 Token::Kind kind, |
| 3742 const String& literal) { | 3838 const String& literal) { |
| 3743 *(SmiAddr(index, RawTokenStream::kKindEntry)) = Smi::New(kind); | 3839 if (kind == Token::kIDENT) { |
| 3744 StorePointer(EntryAddr(index, RawTokenStream::kLiteralEntry), | 3840 if (FLAG_compiler_stats) { |
| 3745 reinterpret_cast<RawObject*>(literal.raw())); | 3841 CompilerStats::num_ident_tokens_total += 1; |
| 3842 } | |
| 3843 StorePointer(EntryAddr(index, RawTokenStream::kTokenEntry), | |
| 3844 reinterpret_cast<RawObject*>(literal.raw())); | |
| 3845 } else if (Token::NeedsLiteralToken(kind)) { | |
| 3846 if (FLAG_compiler_stats) { | |
| 3847 CompilerStats::num_literal_tokens_total += 1; | |
| 3848 } | |
| 3849 StorePointer( | |
| 3850 EntryAddr(index, RawTokenStream::kTokenEntry), | |
| 3851 reinterpret_cast<RawObject*>(LiteralToken::NewCanonical(kind, | |
| 3852 literal))); | |
| 3853 } else { | |
| 3854 ASSERT(kind < Token::kNumTokens); | |
| 3855 *(SmiAddr(index, RawTokenStream::kTokenEntry)) = Smi::New(kind); | |
| 3856 } | |
| 3857 } | |
| 3858 | |
| 3859 | |
| 3860 void TokenStream::SetTokenAt(intptr_t index, const Object& token) { | |
| 3861 StorePointer(EntryAddr(index, RawTokenStream::kTokenEntry), token.raw()); | |
| 3862 } | |
| 3863 | |
| 3864 | |
| 3865 RawObject* TokenStream::TokenAt(intptr_t index) const { | |
| 3866 return *EntryAddr(index, RawTokenStream::kTokenEntry); | |
| 3867 } | |
| 3868 | |
| 3869 | |
| 3870 RawString* TokenStream::LiteralAt(intptr_t index) const { | |
| 3871 const Object& obj = Object::Handle(TokenAt(index)); | |
| 3872 if (obj.IsString()) { | |
| 3873 return reinterpret_cast<RawString*>(obj.raw()); | |
| 3874 } else if (obj.IsSmi()) { | |
| 3875 Token::Kind kind = static_cast<Token::Kind>( | |
| 3876 Smi::Value(reinterpret_cast<RawSmi*>(obj.raw()))); | |
| 3877 ASSERT(kind < Token::kNumTokens); | |
| 3878 if (Token::IsPseudoKeyword(kind) || Token::IsKeyword(kind)) { | |
| 3879 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 3880 String& str = String::Handle(); | |
| 3881 str ^= object_store->GetKeywordSymbol(kind - Token::kFirstKeyword); | |
| 3882 ASSERT(!str.IsNull()); | |
| 3883 return str.raw(); | |
| 3884 } | |
| 3885 return String::NewSymbol(Token::Str(kind)); | |
| 3886 } else { | |
| 3887 LiteralToken& token = LiteralToken::Handle(); | |
| 3888 token ^= obj.raw(); // Must be a literal token. | |
| 3889 return token.literal(); | |
| 3890 } | |
| 3746 } | 3891 } |
| 3747 | 3892 |
| 3748 | 3893 |
| 3749 RawTokenStream* TokenStream::New(intptr_t len) { | 3894 RawTokenStream* TokenStream::New(intptr_t len) { |
| 3750 const Class& token_stream_class = Class::Handle(Object::token_stream_class()); | 3895 const Class& token_stream_class = Class::Handle(Object::token_stream_class()); |
| 3751 TokenStream& result = TokenStream::Handle(); | 3896 TokenStream& result = TokenStream::Handle(); |
| 3752 { | 3897 { |
| 3753 RawObject* raw = Object::Allocate(token_stream_class, | 3898 RawObject* raw = Object::Allocate(token_stream_class, |
| 3754 TokenStream::InstanceSize(len), | 3899 TokenStream::InstanceSize(len), |
| 3755 Heap::kOld); | 3900 Heap::kOld); |
| 3756 NoGCScope no_gc; | 3901 NoGCScope no_gc; |
| 3757 result ^= raw; | 3902 result ^= raw; |
| 3758 result.SetLength(len); | 3903 result.SetLength(len); |
| 3759 } | 3904 } |
| 3760 return result.raw(); | 3905 return result.raw(); |
| 3761 } | 3906 } |
| 3762 | 3907 |
| 3763 | 3908 |
| 3764 RawTokenStream* TokenStream::New(const Scanner::GrowableTokenStream& tokens) { | 3909 RawTokenStream* TokenStream::New(const Scanner::GrowableTokenStream& tokens) { |
| 3765 intptr_t len = tokens.length(); | 3910 intptr_t len = tokens.length(); |
| 3766 | 3911 |
| 3767 TokenStream& result = TokenStream::Handle(New(len)); | 3912 TokenStream& result = TokenStream::Handle(New(len)); |
| 3768 // Copy the relevant data out of the scanner's token stream. | 3913 // Copy the relevant data out of the scanner's token stream. |
| 3914 const String& empty_literal = String::Handle(); | |
| 3769 for (intptr_t i = 0; i < len; i++) { | 3915 for (intptr_t i = 0; i < len; i++) { |
| 3770 Scanner::TokenDescriptor token = tokens[i]; | 3916 Scanner::TokenDescriptor token = tokens[i]; |
| 3771 if (token.literal != NULL) { | 3917 if (token.literal != NULL) { |
| 3772 result.SetTokenAt(i, token.kind, *(token.literal)); | 3918 result.SetTokenAt(i, token.kind, *(token.literal)); |
| 3773 } else { | 3919 } else { |
| 3774 result.SetTokenAt(i, token.kind, String::Handle()); | 3920 result.SetTokenAt(i, token.kind, empty_literal); |
| 3775 } | 3921 } |
| 3776 } | 3922 } |
| 3777 return result.raw(); | 3923 return result.raw(); |
| 3778 } | 3924 } |
| 3779 | 3925 |
| 3780 | 3926 |
| 3781 const char* TokenStream::ToCString() const { | 3927 const char* TokenStream::ToCString() const { |
| 3782 return "TokenStream"; | 3928 return "TokenStream"; |
| 3783 } | 3929 } |
| 3784 | 3930 |
| (...skipping 4517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8302 result.set_num_args_tested(num_args_tested); | 8448 result.set_num_args_tested(num_args_tested); |
| 8303 // Number of array elements in one test entry (num_args_tested + 1) | 8449 // Number of array elements in one test entry (num_args_tested + 1) |
| 8304 intptr_t len = num_args_tested + 1; | 8450 intptr_t len = num_args_tested + 1; |
| 8305 // IC data array must be null terminated (sentinel entry). | 8451 // IC data array must be null terminated (sentinel entry). |
| 8306 Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); | 8452 Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); |
| 8307 result.set_ic_data(ic_data); | 8453 result.set_ic_data(ic_data); |
| 8308 return result.raw(); | 8454 return result.raw(); |
| 8309 } | 8455 } |
| 8310 | 8456 |
| 8311 } // namespace dart | 8457 } // namespace dart |
| OLD | NEW |