| 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 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 // Prefinalized classes have a VM internal representation and no Dart fields. | 1919 // Prefinalized classes have a VM internal representation and no Dart fields. |
| 1919 // Their instance size is precomputed and field offsets are known. | 1920 // Their instance size is precomputed and field offsets are known. |
| 1920 if (!is_prefinalized()) { | 1921 if (!is_prefinalized()) { |
| 1921 // Compute offsets of instance fields and instance size. | 1922 // Compute offsets of instance fields and instance size. |
| 1922 CalculateFieldOffsets(); | 1923 CalculateFieldOffsets(); |
| 1923 } | 1924 } |
| 1924 set_is_finalized(); | 1925 set_is_finalized(); |
| 1925 } | 1926 } |
| 1926 | 1927 |
| 1927 | 1928 |
| 1928 static const char* FormatPatchError(const char* format, const Object& obj) { | 1929 static RawError* FormatError(const Error& prev_error, |
| 1929 const char* msg = obj.ToCString(); | 1930 const Script& script, |
| 1930 intptr_t len = OS::SNPrint(NULL, 0, format, msg) + 1; | 1931 intptr_t token_pos, |
| 1931 char* result = Isolate::Current()->current_zone()->Alloc<char>(len); | 1932 const char* format, ...) { |
| 1932 OS::SNPrint(result, len, format, msg); | 1933 va_list args; |
| 1933 return result; | 1934 va_start(args, format); |
| 1935 if (prev_error.IsNull()) { |
| 1936 return Parser::FormatError(script, token_pos, "Error", format, args); |
| 1937 } else { |
| 1938 return Parser::FormatErrorWithAppend(prev_error, script, token_pos, |
| 1939 "Error", format, args); |
| 1940 } |
| 1934 } | 1941 } |
| 1935 | 1942 |
| 1936 | 1943 |
| 1937 // Apply the members from the patch class to the original class. | 1944 // Apply the members from the patch class to the original class. |
| 1938 const char* Class::ApplyPatch(const Class& patch) const { | 1945 bool Class::ApplyPatch(const Class& patch, Error* error) const { |
| 1946 ASSERT(error != NULL); |
| 1939 ASSERT(!is_finalized()); | 1947 ASSERT(!is_finalized()); |
| 1940 // Shared handles used during the iteration. | 1948 // Shared handles used during the iteration. |
| 1941 String& member_name = String::Handle(); | 1949 String& member_name = String::Handle(); |
| 1942 | 1950 |
| 1943 const PatchClass& patch_class = | 1951 const PatchClass& patch_class = |
| 1944 PatchClass::Handle(PatchClass::New(*this, patch)); | 1952 PatchClass::Handle(PatchClass::New(*this, patch)); |
| 1945 | 1953 |
| 1946 Array& orig_list = Array::Handle(functions()); | 1954 Array& orig_list = Array::Handle(functions()); |
| 1947 intptr_t orig_len = orig_list.Length(); | 1955 intptr_t orig_len = orig_list.Length(); |
| 1948 Array& patch_list = Array::Handle(patch.functions()); | 1956 Array& patch_list = Array::Handle(patch.functions()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1968 member_name ^= orig_func.name(); | 1976 member_name ^= orig_func.name(); |
| 1969 func = patch.LookupFunction(member_name); | 1977 func = patch.LookupFunction(member_name); |
| 1970 if (func.IsNull()) { | 1978 if (func.IsNull()) { |
| 1971 // Non-patched function is preserved, all patched functions are added in | 1979 // Non-patched function is preserved, all patched functions are added in |
| 1972 // the loop below. | 1980 // the loop below. |
| 1973 // However, an implicitly created constructor should not be preserved if | 1981 // However, an implicitly created constructor should not be preserved if |
| 1974 // the patch provides a constructor or a factory. Wait for now. | 1982 // the patch provides a constructor or a factory. Wait for now. |
| 1975 if (orig_func.raw() != orig_implicit_ctor.raw()) { | 1983 if (orig_func.raw() != orig_implicit_ctor.raw()) { |
| 1976 new_functions.Add(orig_func); | 1984 new_functions.Add(orig_func); |
| 1977 } | 1985 } |
| 1978 } else if (!func.HasCompatibleParametersWith(orig_func) && | 1986 } else if (func.UserVisibleSignature() != |
| 1979 !(func.IsFactory() && orig_func.IsConstructor() && | 1987 orig_func.UserVisibleSignature()) { |
| 1980 (func.num_fixed_parameters() + 1 == | 1988 // Compare user visible signatures to ignore different implicit parameters |
| 1981 orig_func.num_fixed_parameters()))) { | 1989 // when patching a constructor with a factory. |
| 1982 return FormatPatchError("mismatched parameters: %s", member_name); | 1990 *error = FormatError(*error, // No previous error. |
| 1991 Script::Handle(patch.script()), func.token_pos(), |
| 1992 "signature mismatch: '%s'", member_name.ToCString()); |
| 1993 return false; |
| 1983 } | 1994 } |
| 1984 } | 1995 } |
| 1985 for (intptr_t i = 0; i < patch_len; i++) { | 1996 for (intptr_t i = 0; i < patch_len; i++) { |
| 1986 func ^= patch_list.At(i); | 1997 func ^= patch_list.At(i); |
| 1987 if (func.IsConstructor() || func.IsFactory()) { | 1998 if (func.IsConstructor() || func.IsFactory()) { |
| 1988 // Do not preserve the original implicit constructor, if any. | 1999 // Do not preserve the original implicit constructor, if any. |
| 1989 orig_implicit_ctor = Function::null(); | 2000 orig_implicit_ctor = Function::null(); |
| 1990 } | 2001 } |
| 1991 func.set_owner(patch_class); | 2002 func.set_owner(patch_class); |
| 1992 new_functions.Add(func); | 2003 new_functions.Add(func); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2010 new_list = Array::New(patch_len + orig_len); | 2021 new_list = Array::New(patch_len + orig_len); |
| 2011 for (intptr_t i = 0; i < patch_len; i++) { | 2022 for (intptr_t i = 0; i < patch_len; i++) { |
| 2012 field ^= patch_list.At(i); | 2023 field ^= patch_list.At(i); |
| 2013 field.set_owner(*this); | 2024 field.set_owner(*this); |
| 2014 member_name = field.name(); | 2025 member_name = field.name(); |
| 2015 // TODO(iposva): Verify non-public fields only. | 2026 // TODO(iposva): Verify non-public fields only. |
| 2016 | 2027 |
| 2017 // Verify no duplicate additions. | 2028 // Verify no duplicate additions. |
| 2018 orig_field ^= LookupField(member_name); | 2029 orig_field ^= LookupField(member_name); |
| 2019 if (!orig_field.IsNull()) { | 2030 if (!orig_field.IsNull()) { |
| 2020 return FormatPatchError("duplicate field: %s", member_name); | 2031 *error = FormatError(*error, // No previous error. |
| 2032 Script::Handle(patch.script()), field.token_pos(), |
| 2033 "duplicate field: %s", member_name.ToCString()); |
| 2034 return false; |
| 2021 } | 2035 } |
| 2022 new_list.SetAt(i, field); | 2036 new_list.SetAt(i, field); |
| 2023 } | 2037 } |
| 2024 for (intptr_t i = 0; i < orig_len; i++) { | 2038 for (intptr_t i = 0; i < orig_len; i++) { |
| 2025 field ^= orig_list.At(i); | 2039 field ^= orig_list.At(i); |
| 2026 new_list.SetAt(patch_len + i, field); | 2040 new_list.SetAt(patch_len + i, field); |
| 2027 } | 2041 } |
| 2028 SetFields(new_list); | 2042 SetFields(new_list); |
| 2029 | 2043 |
| 2030 // The functions and fields in the patch class are no longer needed. | 2044 // The functions and fields in the patch class are no longer needed. |
| 2031 patch.SetFunctions(Object::empty_array()); | 2045 patch.SetFunctions(Object::empty_array()); |
| 2032 patch.SetFields(Object::empty_array()); | 2046 patch.SetFields(Object::empty_array()); |
| 2033 return NULL; | 2047 return true; |
| 2034 } | 2048 } |
| 2035 | 2049 |
| 2036 | 2050 |
| 2037 // Ensure that top level parsing of the class has been done. | 2051 // Ensure that top level parsing of the class has been done. |
| 2038 RawError* Class::EnsureIsFinalized(Isolate* isolate) const { | 2052 RawError* Class::EnsureIsFinalized(Isolate* isolate) const { |
| 2039 // Finalized classes have already been parsed. | 2053 // Finalized classes have already been parsed. |
| 2040 if (is_finalized()) { | 2054 if (is_finalized()) { |
| 2041 return Error::null(); | 2055 return Error::null(); |
| 2042 } | 2056 } |
| 2043 ASSERT(isolate != NULL); | 2057 ASSERT(isolate != NULL); |
| (...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3131 } | 3145 } |
| 3132 type_class = type.type_class(); | 3146 type_class = type.type_class(); |
| 3133 if (!type_class.IsDynamicClass()) { | 3147 if (!type_class.IsDynamicClass()) { |
| 3134 return false; | 3148 return false; |
| 3135 } | 3149 } |
| 3136 } | 3150 } |
| 3137 return true; | 3151 return true; |
| 3138 } | 3152 } |
| 3139 | 3153 |
| 3140 | 3154 |
| 3141 static RawError* FormatError(const Error& prev_error, | |
| 3142 const Script& script, | |
| 3143 intptr_t token_pos, | |
| 3144 const char* format, ...) { | |
| 3145 va_list args; | |
| 3146 va_start(args, format); | |
| 3147 if (prev_error.IsNull()) { | |
| 3148 return Parser::FormatError(script, token_pos, "Error", format, args); | |
| 3149 } else { | |
| 3150 return Parser::FormatErrorWithAppend(prev_error, script, token_pos, | |
| 3151 "Error", format, args); | |
| 3152 } | |
| 3153 } | |
| 3154 | |
| 3155 | |
| 3156 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind, | 3155 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind, |
| 3157 const AbstractTypeArguments& other, | 3156 const AbstractTypeArguments& other, |
| 3158 intptr_t len, | 3157 intptr_t len, |
| 3159 Error* malformed_error) const { | 3158 Error* malformed_error) const { |
| 3160 ASSERT(Length() >= len); | 3159 ASSERT(Length() >= len); |
| 3161 ASSERT(!other.IsNull()); | 3160 ASSERT(!other.IsNull()); |
| 3162 ASSERT(other.Length() >= len); | 3161 ASSERT(other.Length() >= len); |
| 3163 AbstractType& type = AbstractType::Handle(); | 3162 AbstractType& type = AbstractType::Handle(); |
| 3164 AbstractType& other_type = AbstractType::Handle(); | 3163 AbstractType& other_type = AbstractType::Handle(); |
| 3165 for (intptr_t i = 0; i < len; i++) { | 3164 for (intptr_t i = 0; i < len; i++) { |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4365 } | 4364 } |
| 4366 | 4365 |
| 4367 | 4366 |
| 4368 const char* Function::ToFullyQualifiedCString() const { | 4367 const char* Function::ToFullyQualifiedCString() const { |
| 4369 char* chars = NULL; | 4368 char* chars = NULL; |
| 4370 ConstructFunctionFullyQualifiedCString(*this, &chars, 0); | 4369 ConstructFunctionFullyQualifiedCString(*this, &chars, 0); |
| 4371 return chars; | 4370 return chars; |
| 4372 } | 4371 } |
| 4373 | 4372 |
| 4374 | 4373 |
| 4375 bool Function::HasCompatibleParametersWith(const Function& other) const { | 4374 bool Function::HasCompatibleParametersWith(const Function& other, |
| 4376 const intptr_t num_fixed_params = num_fixed_parameters(); | 4375 Error* error) const { |
| 4377 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); | 4376 ASSERT(FLAG_error_on_bad_override); |
| 4378 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 4377 // Check that this function's signature type is a subtype of the other |
| 4379 const intptr_t other_num_opt_pos_params = | 4378 // function's signature type. |
| 4380 other.NumOptionalPositionalParameters(); | 4379 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(), |
| 4381 // A generative constructor may be compared to a redirecting factory and be | 4380 other, Object::null_abstract_type_arguments(), error)) { |
| 4382 // compatible although it has an additional phase parameter. | 4381 // For more informative error reporting, use the location of the other |
| 4383 const intptr_t num_ignored_params = | 4382 // function here, since the caller will use the location of this function. |
| 4384 (other.IsRedirectingFactory() && IsConstructor()) ? 1 : 0; | 4383 *error = FormatError( |
| 4385 // The default values of optional parameters can differ. | 4384 *error, // A malformed error if non null. |
| 4386 // This function requires the same arguments or less and accepts the same | 4385 Script::Handle(other.script()), |
| 4387 // arguments or more. | 4386 other.token_pos(), |
| 4388 if (((num_fixed_params - num_ignored_params) > other_num_fixed_params) || | 4387 "signature type '%s' of function '%s' is not a subtype of signature " |
| 4389 ((num_fixed_params - num_ignored_params) + num_opt_pos_params < | 4388 "type '%s' of function '%s'", |
| 4390 other_num_fixed_params + other_num_opt_pos_params)) { | 4389 String::Handle(UserVisibleSignature()).ToCString(), |
| 4390 String::Handle(UserVisibleName()).ToCString(), |
| 4391 String::Handle(other.UserVisibleSignature()).ToCString(), |
| 4392 String::Handle(other.UserVisibleName()).ToCString()); |
| 4391 return false; | 4393 return false; |
| 4392 } | 4394 } |
| 4395 // We should also check that if the other function explicitly specifies a |
| 4396 // default value for a formal parameter, this function does not specify a |
| 4397 // different default value for the same parameter. However, this check is not |
| 4398 // possible in the current implementation, because the default parameter |
| 4399 // values are not stored in the Function object, but discarded after a |
| 4400 // function is compiled. |
| 4393 return true; | 4401 return true; |
| 4394 } | 4402 } |
| 4395 | 4403 |
| 4396 | 4404 |
| 4397 // If test_kind == kIsSubtypeOf, checks if the type of the specified parameter | 4405 // If test_kind == kIsSubtypeOf, checks if the type of the specified parameter |
| 4398 // of this function is a subtype or a supertype of the type of the specified | 4406 // of this function is a subtype or a supertype of the type of the specified |
| 4399 // parameter of the other function. | 4407 // parameter of the other function. |
| 4400 // If test_kind == kIsMoreSpecificThan, checks if the type of the specified | 4408 // If test_kind == kIsMoreSpecificThan, checks if the type of the specified |
| 4401 // parameter of this function is more specific than the type of the specified | 4409 // parameter of this function is more specific than the type of the specified |
| 4402 // parameter of the other function. | 4410 // parameter of the other function. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4452 const intptr_t num_fixed_params = num_fixed_parameters(); | 4460 const intptr_t num_fixed_params = num_fixed_parameters(); |
| 4453 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); | 4461 const intptr_t num_opt_pos_params = NumOptionalPositionalParameters(); |
| 4454 const intptr_t num_opt_named_params = NumOptionalNamedParameters(); | 4462 const intptr_t num_opt_named_params = NumOptionalNamedParameters(); |
| 4455 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 4463 const intptr_t other_num_fixed_params = other.num_fixed_parameters(); |
| 4456 const intptr_t other_num_opt_pos_params = | 4464 const intptr_t other_num_opt_pos_params = |
| 4457 other.NumOptionalPositionalParameters(); | 4465 other.NumOptionalPositionalParameters(); |
| 4458 const intptr_t other_num_opt_named_params = | 4466 const intptr_t other_num_opt_named_params = |
| 4459 other.NumOptionalNamedParameters(); | 4467 other.NumOptionalNamedParameters(); |
| 4460 // This function requires the same arguments or less and accepts the same | 4468 // This function requires the same arguments or less and accepts the same |
| 4461 // arguments or more. | 4469 // arguments or more. |
| 4462 if ((num_fixed_params > other_num_fixed_params) || | 4470 // A generative constructor may be compared to a redirecting factory and be |
| 4463 (num_fixed_params + num_opt_pos_params < | 4471 // compatible although it has an additional phase parameter. |
| 4464 other_num_fixed_params + other_num_opt_pos_params) || | 4472 // More generally, we can ignore implicit parameters. |
| 4473 const intptr_t num_ignored_params = NumImplicitParameters(); |
| 4474 const intptr_t other_num_ignored_params = other.NumImplicitParameters(); |
| 4475 if (((num_fixed_params - num_ignored_params) > |
| 4476 (other_num_fixed_params - other_num_ignored_params)) || |
| 4477 ((num_fixed_params - num_ignored_params + num_opt_pos_params) < |
| 4478 (other_num_fixed_params - other_num_ignored_params + |
| 4479 other_num_opt_pos_params)) || |
| 4465 (num_opt_named_params < other_num_opt_named_params)) { | 4480 (num_opt_named_params < other_num_opt_named_params)) { |
| 4466 return false; | 4481 return false; |
| 4467 } | 4482 } |
| 4468 // Check the result type. | 4483 // Check the result type. |
| 4469 AbstractType& other_res_type = AbstractType::Handle(other.result_type()); | 4484 AbstractType& other_res_type = AbstractType::Handle(other.result_type()); |
| 4470 if (!other_res_type.IsInstantiated()) { | 4485 if (!other_res_type.IsInstantiated()) { |
| 4471 other_res_type = other_res_type.InstantiateFrom(other_type_arguments, | 4486 other_res_type = other_res_type.InstantiateFrom(other_type_arguments, |
| 4472 malformed_error); | 4487 malformed_error); |
| 4473 ASSERT((malformed_error == NULL) || malformed_error->IsNull()); | 4488 ASSERT((malformed_error == NULL) || malformed_error->IsNull()); |
| 4474 } | 4489 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4487 return false; | 4502 return false; |
| 4488 } | 4503 } |
| 4489 } else { | 4504 } else { |
| 4490 ASSERT(test_kind == kIsMoreSpecificThan); | 4505 ASSERT(test_kind == kIsMoreSpecificThan); |
| 4491 if (!res_type.IsMoreSpecificThan(other_res_type, malformed_error)) { | 4506 if (!res_type.IsMoreSpecificThan(other_res_type, malformed_error)) { |
| 4492 return false; | 4507 return false; |
| 4493 } | 4508 } |
| 4494 } | 4509 } |
| 4495 } | 4510 } |
| 4496 // Check the types of fixed and optional positional parameters. | 4511 // Check the types of fixed and optional positional parameters. |
| 4497 for (intptr_t i = 0; | 4512 for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params + |
| 4498 i < other_num_fixed_params + other_num_opt_pos_params; i++) { | 4513 other_num_opt_pos_params); i++) { |
| 4499 if (!TestParameterType(test_kind, | 4514 if (!TestParameterType(test_kind, |
| 4500 i, i, type_arguments, other, other_type_arguments, | 4515 i + num_ignored_params, i + other_num_ignored_params, |
| 4516 type_arguments, other, other_type_arguments, |
| 4501 malformed_error)) { | 4517 malformed_error)) { |
| 4502 return false; | 4518 return false; |
| 4503 } | 4519 } |
| 4504 } | 4520 } |
| 4505 // Check the names and types of optional named parameters. | 4521 // Check the names and types of optional named parameters. |
| 4506 if (other_num_opt_named_params == 0) { | 4522 if (other_num_opt_named_params == 0) { |
| 4507 return true; | 4523 return true; |
| 4508 } | 4524 } |
| 4509 // Check that for each optional named parameter of type T of the other | 4525 // Check that for each optional named parameter of type T of the other |
| 4510 // function type, there exists an optional named parameter of this function | 4526 // function type, there exists an optional named parameter of this function |
| (...skipping 10099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14610 } | 14626 } |
| 14611 | 14627 |
| 14612 | 14628 |
| 14613 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 14629 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 14614 stream->OpenObject(); | 14630 stream->OpenObject(); |
| 14615 stream->CloseObject(); | 14631 stream->CloseObject(); |
| 14616 } | 14632 } |
| 14617 | 14633 |
| 14618 | 14634 |
| 14619 } // namespace dart | 14635 } // namespace dart |
| OLD | NEW |