| 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 "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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 51 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
| 52 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 52 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
| 53 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 53 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
| 54 "Huge method cutoff in unoptimized code size (in bytes)."); | 54 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 55 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, | 55 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, |
| 56 "Throw an exception when the result of an integer calculation will not " | 56 "Throw an exception when the result of an integer calculation will not " |
| 57 "fit into a javascript integer."); | 57 "fit into a javascript integer."); |
| 58 DECLARE_FLAG(bool, trace_compiler); | 58 DECLARE_FLAG(bool, trace_compiler); |
| 59 DECLARE_FLAG(bool, eliminate_type_checks); | 59 DECLARE_FLAG(bool, eliminate_type_checks); |
| 60 DECLARE_FLAG(bool, enable_type_checks); | 60 DECLARE_FLAG(bool, enable_type_checks); |
| 61 DECLARE_FLAG(bool, error_on_bad_override); |
| 61 | 62 |
| 62 static const char* kGetterPrefix = "get:"; | 63 static const char* kGetterPrefix = "get:"; |
| 63 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); | 64 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); |
| 64 static const char* kSetterPrefix = "set:"; | 65 static const char* kSetterPrefix = "set:"; |
| 65 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); | 66 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); |
| 66 | 67 |
| 67 cpp_vtable Object::handle_vtable_ = 0; | 68 cpp_vtable Object::handle_vtable_ = 0; |
| 68 cpp_vtable Object::builtin_vtables_[kNumPredefinedCids] = { 0 }; | 69 cpp_vtable Object::builtin_vtables_[kNumPredefinedCids] = { 0 }; |
| 69 cpp_vtable Smi::handle_vtable_ = 0; | 70 cpp_vtable Smi::handle_vtable_ = 0; |
| 70 | 71 |
| (...skipping 1829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 // Prefinalized classes have a VM internal representation and no Dart fields. | 1901 // Prefinalized classes have a VM internal representation and no Dart fields. |
| 1901 // Their instance size is precomputed and field offsets are known. | 1902 // Their instance size is precomputed and field offsets are known. |
| 1902 if (!is_prefinalized()) { | 1903 if (!is_prefinalized()) { |
| 1903 // Compute offsets of instance fields and instance size. | 1904 // Compute offsets of instance fields and instance size. |
| 1904 CalculateFieldOffsets(); | 1905 CalculateFieldOffsets(); |
| 1905 } | 1906 } |
| 1906 set_is_finalized(); | 1907 set_is_finalized(); |
| 1907 } | 1908 } |
| 1908 | 1909 |
| 1909 | 1910 |
| 1910 static const char* FormatPatchError(const char* format, const Object& obj) { | 1911 static RawError* FormatError(const Error& prev_error, |
| 1911 const char* msg = obj.ToCString(); | 1912 const Script& script, |
| 1912 intptr_t len = OS::SNPrint(NULL, 0, format, msg) + 1; | 1913 intptr_t token_pos, |
| 1913 char* result = Isolate::Current()->current_zone()->Alloc<char>(len); | 1914 const char* format, ...) { |
| 1914 OS::SNPrint(result, len, format, msg); | 1915 va_list args; |
| 1915 return result; | 1916 va_start(args, format); |
| 1917 if (prev_error.IsNull()) { |
| 1918 return Parser::FormatError(script, token_pos, "Error", format, args); |
| 1919 } else { |
| 1920 return Parser::FormatErrorWithAppend(prev_error, script, token_pos, |
| 1921 "Error", format, args); |
| 1922 } |
| 1916 } | 1923 } |
| 1917 | 1924 |
| 1918 | 1925 |
| 1919 // Apply the members from the patch class to the original class. | 1926 // Apply the members from the patch class to the original class. |
| 1920 const char* Class::ApplyPatch(const Class& patch) const { | 1927 bool Class::ApplyPatch(const Class& patch, Error* error) const { |
| 1928 ASSERT(error != NULL); |
| 1921 ASSERT(!is_finalized()); | 1929 ASSERT(!is_finalized()); |
| 1922 // Shared handles used during the iteration. | 1930 // Shared handles used during the iteration. |
| 1923 String& member_name = String::Handle(); | 1931 String& member_name = String::Handle(); |
| 1924 | 1932 |
| 1925 const PatchClass& patch_class = | 1933 const PatchClass& patch_class = |
| 1926 PatchClass::Handle(PatchClass::New(*this, patch)); | 1934 PatchClass::Handle(PatchClass::New(*this, patch)); |
| 1927 | 1935 |
| 1928 Array& orig_list = Array::Handle(functions()); | 1936 Array& orig_list = Array::Handle(functions()); |
| 1929 intptr_t orig_len = orig_list.Length(); | 1937 intptr_t orig_len = orig_list.Length(); |
| 1930 Array& patch_list = Array::Handle(patch.functions()); | 1938 Array& patch_list = Array::Handle(patch.functions()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1950 member_name ^= orig_func.name(); | 1958 member_name ^= orig_func.name(); |
| 1951 func = patch.LookupFunction(member_name); | 1959 func = patch.LookupFunction(member_name); |
| 1952 if (func.IsNull()) { | 1960 if (func.IsNull()) { |
| 1953 // Non-patched function is preserved, all patched functions are added in | 1961 // Non-patched function is preserved, all patched functions are added in |
| 1954 // the loop below. | 1962 // the loop below. |
| 1955 // However, an implicitly created constructor should not be preserved if | 1963 // However, an implicitly created constructor should not be preserved if |
| 1956 // the patch provides a constructor or a factory. Wait for now. | 1964 // the patch provides a constructor or a factory. Wait for now. |
| 1957 if (orig_func.raw() != orig_implicit_ctor.raw()) { | 1965 if (orig_func.raw() != orig_implicit_ctor.raw()) { |
| 1958 new_functions.Add(orig_func); | 1966 new_functions.Add(orig_func); |
| 1959 } | 1967 } |
| 1960 } else if (!func.HasCompatibleParametersWith(orig_func) && | 1968 } else if (func.UserVisibleSignature() != |
| 1961 !(func.IsFactory() && orig_func.IsConstructor() && | 1969 orig_func.UserVisibleSignature()) { |
| 1962 (func.num_fixed_parameters() + 1 == | 1970 // Compare user visible signatures to ignore different implicit parameters |
| 1963 orig_func.num_fixed_parameters()))) { | 1971 // when patching a constructor with a factory. |
| 1964 return FormatPatchError("mismatched parameters: %s", member_name); | 1972 *error = FormatError(*error, // No previous error. |
| 1973 Script::Handle(patch.script()), func.token_pos(), |
| 1974 "signature mismatch: '%s'", member_name.ToCString()); |
| 1975 return false; |
| 1965 } | 1976 } |
| 1966 } | 1977 } |
| 1967 for (intptr_t i = 0; i < patch_len; i++) { | 1978 for (intptr_t i = 0; i < patch_len; i++) { |
| 1968 func ^= patch_list.At(i); | 1979 func ^= patch_list.At(i); |
| 1969 if (func.IsConstructor() || func.IsFactory()) { | 1980 if (func.IsConstructor() || func.IsFactory()) { |
| 1970 // Do not preserve the original implicit constructor, if any. | 1981 // Do not preserve the original implicit constructor, if any. |
| 1971 orig_implicit_ctor = Function::null(); | 1982 orig_implicit_ctor = Function::null(); |
| 1972 } | 1983 } |
| 1973 func.set_owner(patch_class); | 1984 func.set_owner(patch_class); |
| 1974 new_functions.Add(func); | 1985 new_functions.Add(func); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1992 new_list = Array::New(patch_len + orig_len); | 2003 new_list = Array::New(patch_len + orig_len); |
| 1993 for (intptr_t i = 0; i < patch_len; i++) { | 2004 for (intptr_t i = 0; i < patch_len; i++) { |
| 1994 field ^= patch_list.At(i); | 2005 field ^= patch_list.At(i); |
| 1995 field.set_owner(*this); | 2006 field.set_owner(*this); |
| 1996 member_name = field.name(); | 2007 member_name = field.name(); |
| 1997 // TODO(iposva): Verify non-public fields only. | 2008 // TODO(iposva): Verify non-public fields only. |
| 1998 | 2009 |
| 1999 // Verify no duplicate additions. | 2010 // Verify no duplicate additions. |
| 2000 orig_field ^= LookupField(member_name); | 2011 orig_field ^= LookupField(member_name); |
| 2001 if (!orig_field.IsNull()) { | 2012 if (!orig_field.IsNull()) { |
| 2002 return FormatPatchError("duplicate field: %s", member_name); | 2013 *error = FormatError(*error, // No previous error. |
| 2014 Script::Handle(patch.script()), field.token_pos(), |
| 2015 "duplicate field: %s", member_name.ToCString()); |
| 2016 return false; |
| 2003 } | 2017 } |
| 2004 new_list.SetAt(i, field); | 2018 new_list.SetAt(i, field); |
| 2005 } | 2019 } |
| 2006 for (intptr_t i = 0; i < orig_len; i++) { | 2020 for (intptr_t i = 0; i < orig_len; i++) { |
| 2007 field ^= orig_list.At(i); | 2021 field ^= orig_list.At(i); |
| 2008 new_list.SetAt(patch_len + i, field); | 2022 new_list.SetAt(patch_len + i, field); |
| 2009 } | 2023 } |
| 2010 SetFields(new_list); | 2024 SetFields(new_list); |
| 2011 | 2025 |
| 2012 // The functions and fields in the patch class are no longer needed. | 2026 // The functions and fields in the patch class are no longer needed. |
| 2013 patch.SetFunctions(Object::empty_array()); | 2027 patch.SetFunctions(Object::empty_array()); |
| 2014 patch.SetFields(Object::empty_array()); | 2028 patch.SetFields(Object::empty_array()); |
| 2015 return NULL; | 2029 return true; |
| 2016 } | 2030 } |
| 2017 | 2031 |
| 2018 | 2032 |
| 2019 // Ensure that top level parsing of the class has been done. | 2033 // Ensure that top level parsing of the class has been done. |
| 2020 RawError* Class::EnsureIsFinalized(Isolate* isolate) const { | 2034 RawError* Class::EnsureIsFinalized(Isolate* isolate) const { |
| 2021 // Finalized classes have already been parsed. | 2035 // Finalized classes have already been parsed. |
| 2022 if (is_finalized()) { | 2036 if (is_finalized()) { |
| 2023 return Error::null(); | 2037 return Error::null(); |
| 2024 } | 2038 } |
| 2025 ASSERT(isolate != NULL); | 2039 ASSERT(isolate != NULL); |
| (...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3113 } | 3127 } |
| 3114 type_class = type.type_class(); | 3128 type_class = type.type_class(); |
| 3115 if (!type_class.IsDynamicClass()) { | 3129 if (!type_class.IsDynamicClass()) { |
| 3116 return false; | 3130 return false; |
| 3117 } | 3131 } |
| 3118 } | 3132 } |
| 3119 return true; | 3133 return true; |
| 3120 } | 3134 } |
| 3121 | 3135 |
| 3122 | 3136 |
| 3123 static RawError* FormatError(const Error& prev_error, | |
| 3124 const Script& script, | |
| 3125 intptr_t token_pos, | |
| 3126 const char* format, ...) { | |
| 3127 va_list args; | |
| 3128 va_start(args, format); | |
| 3129 if (prev_error.IsNull()) { | |
| 3130 return Parser::FormatError(script, token_pos, "Error", format, args); | |
| 3131 } else { | |
| 3132 return Parser::FormatErrorWithAppend(prev_error, script, token_pos, | |
| 3133 "Error", format, args); | |
| 3134 } | |
| 3135 } | |
| 3136 | |
| 3137 | |
| 3138 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind, | 3137 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind, |
| 3139 const AbstractTypeArguments& other, | 3138 const AbstractTypeArguments& other, |
| 3140 intptr_t len, | 3139 intptr_t len, |
| 3141 Error* malformed_error) const { | 3140 Error* malformed_error) const { |
| 3142 ASSERT(Length() >= len); | 3141 ASSERT(Length() >= len); |
| 3143 ASSERT(!other.IsNull()); | 3142 ASSERT(!other.IsNull()); |
| 3144 ASSERT(other.Length() >= len); | 3143 ASSERT(other.Length() >= len); |
| 3145 AbstractType& type = AbstractType::Handle(); | 3144 AbstractType& type = AbstractType::Handle(); |
| 3146 AbstractType& other_type = AbstractType::Handle(); | 3145 AbstractType& other_type = AbstractType::Handle(); |
| 3147 for (intptr_t i = 0; i < len; i++) { | 3146 for (intptr_t i = 0; i < len; i++) { |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4347 } | 4346 } |
| 4348 | 4347 |
| 4349 | 4348 |
| 4350 const char* Function::ToFullyQualifiedCString() const { | 4349 const char* Function::ToFullyQualifiedCString() const { |
| 4351 char* chars = NULL; | 4350 char* chars = NULL; |
| 4352 ConstructFunctionFullyQualifiedCString(*this, &chars, 0); | 4351 ConstructFunctionFullyQualifiedCString(*this, &chars, 0); |
| 4353 return chars; | 4352 return chars; |
| 4354 } | 4353 } |
| 4355 | 4354 |
| 4356 | 4355 |
| 4357 bool Function::HasCompatibleParametersWith(const Function& other) const { | 4356 bool Function::HasCompatibleParametersWith(const Function& other, |
| 4358 const intptr_t num_fixed_params = num_fixed_parameters(); | 4357 Error* error) const { |
| 4359 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); | 4358 ASSERT(FLAG_error_on_bad_override); |
| 4360 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 4359 // Check that this function's signature type is a subtype of the other |
| 4361 const intptr_t other_num_opt_pos_params = | 4360 // function's signature type. |
| 4362 other.NumOptionalPositionalParameters(); | 4361 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(), |
| 4363 // A generative constructor may be compared to a redirecting factory and be | 4362 other, Object::null_abstract_type_arguments(), error)) { |
| 4364 // compatible although it has an additional phase parameter. | 4363 // For more informative error reporting, use the location of the other |
| 4365 const intptr_t num_ignored_params = | 4364 // function here, since the caller will use the location of this function. |
| 4366 (other.IsRedirectingFactory() && IsConstructor()) ? 1 : 0; | 4365 *error = FormatError( |
| 4367 // The default values of optional parameters can differ. | 4366 *error, // A malformed error if non null. |
| 4368 // This function requires the same arguments or less and accepts the same | 4367 Script::Handle(other.script()), |
| 4369 // arguments or more. | 4368 other.token_pos(), |
| 4370 if (((num_fixed_params - num_ignored_params) > other_num_fixed_params) || | 4369 "signature type '%s' of function '%s' is not a subtype of signature " |
| 4371 ((num_fixed_params - num_ignored_params) + num_opt_pos_params < | 4370 "type '%s' of function '%s'", |
| 4372 other_num_fixed_params + other_num_opt_pos_params)) { | 4371 String::Handle(UserVisibleSignature()).ToCString(), |
| 4372 String::Handle(UserVisibleName()).ToCString(), |
| 4373 String::Handle(other.UserVisibleSignature()).ToCString(), |
| 4374 String::Handle(other.UserVisibleName()).ToCString()); |
| 4373 return false; | 4375 return false; |
| 4374 } | 4376 } |
| 4377 // We should also check that if the other function explicitly specifies a |
| 4378 // default value for a formal parameter, this function does not specify a |
| 4379 // different default value for the same parameter. However, this check is not |
| 4380 // possible in the current implementation, because the default parameter |
| 4381 // values are not stored in the Function object, but discarded after a |
| 4382 // function is compiled. |
| 4375 return true; | 4383 return true; |
| 4376 } | 4384 } |
| 4377 | 4385 |
| 4378 | 4386 |
| 4379 // If test_kind == kIsSubtypeOf, checks if the type of the specified parameter | 4387 // If test_kind == kIsSubtypeOf, checks if the type of the specified parameter |
| 4380 // of this function is a subtype or a supertype of the type of the specified | 4388 // of this function is a subtype or a supertype of the type of the specified |
| 4381 // parameter of the other function. | 4389 // parameter of the other function. |
| 4382 // If test_kind == kIsMoreSpecificThan, checks if the type of the specified | 4390 // If test_kind == kIsMoreSpecificThan, checks if the type of the specified |
| 4383 // parameter of this function is more specific than the type of the specified | 4391 // parameter of this function is more specific than the type of the specified |
| 4384 // parameter of the other function. | 4392 // parameter of the other function. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4434 const intptr_t num_fixed_params = num_fixed_parameters(); | 4442 const intptr_t num_fixed_params = num_fixed_parameters(); |
| 4435 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); | 4443 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); |
| 4436 const intptr_t num_opt_named_params = NumOptionalNamedParameters(); | 4444 const intptr_t num_opt_named_params = NumOptionalNamedParameters(); |
| 4437 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 4445 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); |
| 4438 const intptr_t other_num_opt_pos_params = | 4446 const intptr_t other_num_opt_pos_params = |
| 4439 other.NumOptionalPositionalParameters(); | 4447 other.NumOptionalPositionalParameters(); |
| 4440 const intptr_t other_num_opt_named_params = | 4448 const intptr_t other_num_opt_named_params = |
| 4441 other.NumOptionalNamedParameters(); | 4449 other.NumOptionalNamedParameters(); |
| 4442 // This function requires the same arguments or less and accepts the same | 4450 // This function requires the same arguments or less and accepts the same |
| 4443 // arguments or more. | 4451 // arguments or more. |
| 4444 if ((num_fixed_params > other_num_fixed_params) || | 4452 // A generative constructor may be compared to a redirecting factory and be |
| 4445 (num_fixed_params + num_opt_pos_params < | 4453 // compatible although it has an additional phase parameter. |
| 4446 other_num_fixed_params + other_num_opt_pos_params) || | 4454 // More generally, we can ignore implicit parameters. |
| 4455 const intptr_t num_ignored_params = NumImplicitParameters(); |
| 4456 const intptr_t other_num_ignored_params = other.NumImplicitParameters(); |
| 4457 if (((num_fixed_params - num_ignored_params) > |
| 4458 (other_num_fixed_params - other_num_ignored_params)) || |
| 4459 ((num_fixed_params - num_ignored_params + num_opt_pos_params) < |
| 4460 (other_num_fixed_params - other_num_ignored_params + |
| 4461 other_num_opt_pos_params)) || |
| 4447 (num_opt_named_params < other_num_opt_named_params)) { | 4462 (num_opt_named_params < other_num_opt_named_params)) { |
| 4448 return false; | 4463 return false; |
| 4449 } | 4464 } |
| 4450 // Check the result type. | 4465 // Check the result type. |
| 4451 AbstractType& other_res_type = AbstractType::Handle(other.result_type()); | 4466 AbstractType& other_res_type = AbstractType::Handle(other.result_type()); |
| 4452 if (!other_res_type.IsInstantiated()) { | 4467 if (!other_res_type.IsInstantiated()) { |
| 4453 other_res_type = other_res_type.InstantiateFrom(other_type_arguments, | 4468 other_res_type = other_res_type.InstantiateFrom(other_type_arguments, |
| 4454 malformed_error); | 4469 malformed_error); |
| 4455 ASSERT((malformed_error == NULL) || malformed_error->IsNull()); | 4470 ASSERT((malformed_error == NULL) || malformed_error->IsNull()); |
| 4456 } | 4471 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4469 return false; | 4484 return false; |
| 4470 } | 4485 } |
| 4471 } else { | 4486 } else { |
| 4472 ASSERT(test_kind == kIsMoreSpecificThan); | 4487 ASSERT(test_kind == kIsMoreSpecificThan); |
| 4473 if (!res_type.IsMoreSpecificThan(other_res_type, malformed_error)) { | 4488 if (!res_type.IsMoreSpecificThan(other_res_type, malformed_error)) { |
| 4474 return false; | 4489 return false; |
| 4475 } | 4490 } |
| 4476 } | 4491 } |
| 4477 } | 4492 } |
| 4478 // Check the types of fixed and optional positional parameters. | 4493 // Check the types of fixed and optional positional parameters. |
| 4479 for (intptr_t i = 0; | 4494 for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params + |
| 4480 i < other_num_fixed_params + other_num_opt_pos_params; i++) { | 4495 other_num_opt_pos_params); i++) { |
| 4481 if (!TestParameterType(test_kind, | 4496 if (!TestParameterType(test_kind, |
| 4482 i, i, type_arguments, other, other_type_arguments, | 4497 i + num_ignored_params, i + other_num_ignored_params, |
| 4498 type_arguments, other, other_type_arguments, |
| 4483 malformed_error)) { | 4499 malformed_error)) { |
| 4484 return false; | 4500 return false; |
| 4485 } | 4501 } |
| 4486 } | 4502 } |
| 4487 // Check the names and types of optional named parameters. | 4503 // Check the names and types of optional named parameters. |
| 4488 if (other_num_opt_named_params == 0) { | 4504 if (other_num_opt_named_params == 0) { |
| 4489 return true; | 4505 return true; |
| 4490 } | 4506 } |
| 4491 // Check that for each optional named parameter of type T of the other | 4507 // Check that for each optional named parameter of type T of the other |
| 4492 // function type, there exists an optional named parameter of this function | 4508 // function type, there exists an optional named parameter of this function |
| (...skipping 10093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14586 } | 14602 } |
| 14587 | 14603 |
| 14588 | 14604 |
| 14589 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 14605 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 14590 stream->OpenObject(); | 14606 stream->OpenObject(); |
| 14591 stream->CloseObject(); | 14607 stream->CloseObject(); |
| 14592 } | 14608 } |
| 14593 | 14609 |
| 14594 | 14610 |
| 14595 } // namespace dart | 14611 } // namespace dart |
| OLD | NEW |