| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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/kernel_reader.h" | 5 #include "vm/kernel_reader.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
| 10 #include "vm/kernel_binary.h" | 10 #include "vm/kernel_binary.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 | 122 |
| 123 KernelReader::KernelReader(Program* program) | 123 KernelReader::KernelReader(Program* program) |
| 124 : program_(program), | 124 : program_(program), |
| 125 thread_(dart::Thread::Current()), | 125 thread_(dart::Thread::Current()), |
| 126 zone_(thread_->zone()), | 126 zone_(thread_->zone()), |
| 127 isolate_(thread_->isolate()), | 127 isolate_(thread_->isolate()), |
| 128 scripts_(Array::ZoneHandle(zone_)), | 128 scripts_(Array::ZoneHandle(zone_)), |
| 129 translation_helper_(this, thread_), | 129 translation_helper_(this, thread_), |
| 130 builder_(&translation_helper_, | 130 builder_(&translation_helper_, |
| 131 zone_, | 131 zone_, |
| 132 program_->libraries()[0]->kernel_data(), | 132 program_->kernel_data(), |
| 133 program_->libraries()[0]->kernel_data_size()) { | 133 program_->kernel_data_size()) { |
| 134 T.active_class_ = &active_class_; | 134 T.active_class_ = &active_class_; |
| 135 T.finalize_ = false; | 135 T.finalize_ = false; |
| 136 | 136 |
| 137 intptr_t source_file_count = program->source_table().size(); | 137 scripts_ = Array::New(builder_.SourceTableSize(), Heap::kOld); |
| 138 scripts_ = Array::New(source_file_count, Heap::kOld); | |
| 139 | |
| 140 // We need at least one library to get access to the binary. | |
| 141 ASSERT(program->libraries().length() > 0); | |
| 142 Library* library = program->libraries()[0]; | |
| 143 Reader reader(library->kernel_data(), library->kernel_data_size()); | |
| 144 | 138 |
| 145 // Copy the Kernel string offsets out of the binary and into the VM's heap. | 139 // Copy the Kernel string offsets out of the binary and into the VM's heap. |
| 146 ASSERT(program->string_table_offset() >= 0); | 140 ASSERT(program->string_table_offset() >= 0); |
| 141 Reader reader(program->kernel_data(), program->kernel_data_size()); |
| 147 reader.set_offset(program->string_table_offset()); | 142 reader.set_offset(program->string_table_offset()); |
| 148 intptr_t count = reader.ReadUInt() + 1; | 143 intptr_t count = reader.ReadUInt() + 1; |
| 149 TypedData& offsets = TypedData::Handle( | 144 TypedData& offsets = TypedData::Handle( |
| 150 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld)); | 145 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld)); |
| 151 offsets.SetUint32(0, 0); | 146 offsets.SetUint32(0, 0); |
| 152 intptr_t end_offset = 0; | 147 intptr_t end_offset = 0; |
| 153 for (intptr_t i = 1; i < count; ++i) { | 148 for (intptr_t i = 1; i < count; ++i) { |
| 154 end_offset = reader.ReadUInt(); | 149 end_offset = reader.ReadUInt(); |
| 155 offsets.SetUint32(i << 2, end_offset); | 150 offsets.SetUint32(i << 2, end_offset); |
| 156 } | 151 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 175 | 170 |
| 176 H.SetStringOffsets(offsets); | 171 H.SetStringOffsets(offsets); |
| 177 H.SetStringData(data); | 172 H.SetStringData(data); |
| 178 H.SetCanonicalNames(names); | 173 H.SetCanonicalNames(names); |
| 179 } | 174 } |
| 180 | 175 |
| 181 | 176 |
| 182 Object& KernelReader::ReadProgram() { | 177 Object& KernelReader::ReadProgram() { |
| 183 LongJumpScope jump; | 178 LongJumpScope jump; |
| 184 if (setjmp(*jump.Set()) == 0) { | 179 if (setjmp(*jump.Set()) == 0) { |
| 185 intptr_t length = program_->libraries().length(); | 180 intptr_t length = program_->library_count(); |
| 186 for (intptr_t i = 0; i < length; i++) { | 181 for (intptr_t i = 0; i < length; i++) { |
| 187 Library* kernel_library = program_->libraries()[i]; | 182 ReadLibrary(library_offset(i)); |
| 188 ReadLibrary(kernel_library->kernel_offset()); | |
| 189 } | 183 } |
| 190 | 184 |
| 191 for (intptr_t i = 0; i < length; i++) { | 185 for (intptr_t i = 0; i < length; i++) { |
| 192 dart::Library& library = | 186 dart::Library& library = LookupLibrary(library_canonical_name(i)); |
| 193 LookupLibrary(program_->libraries()[i]->canonical_name()); | |
| 194 if (!library.Loaded()) library.SetLoaded(); | 187 if (!library.Loaded()) library.SetLoaded(); |
| 195 } | 188 } |
| 196 | 189 |
| 197 if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) { | 190 if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) { |
| 198 // If 'main' is not found return a null library, this is the case | 191 // If 'main' is not found return a null library, this is the case |
| 199 // when bootstrapping is in progress. | 192 // when bootstrapping is in progress. |
| 200 NameIndex main = program_->main_method(); | 193 NameIndex main = program_->main_method(); |
| 201 if (main == -1) { | 194 if (main == -1) { |
| 202 return dart::Library::Handle(Z); | 195 return dart::Library::Handle(Z); |
| 203 } | 196 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 215 // In both cases sticky error would be set. | 208 // In both cases sticky error would be set. |
| 216 Error& error = Error::Handle(Z); | 209 Error& error = Error::Handle(Z); |
| 217 error = thread_->sticky_error(); | 210 error = thread_->sticky_error(); |
| 218 thread_->clear_sticky_error(); | 211 thread_->clear_sticky_error(); |
| 219 return error; | 212 return error; |
| 220 } | 213 } |
| 221 | 214 |
| 222 | 215 |
| 223 void KernelReader::ReadLibrary(intptr_t kernel_offset) { | 216 void KernelReader::ReadLibrary(intptr_t kernel_offset) { |
| 224 builder_.SetOffset(kernel_offset); | 217 builder_.SetOffset(kernel_offset); |
| 218 LibraryHelper library_helper(&builder_); |
| 219 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName); |
| 220 dart::Library& library = LookupLibrary(library_helper.canonical_name_); |
| 221 if (library.Loaded()) return; |
| 225 | 222 |
| 226 int flags = builder_.ReadFlags(); | 223 library_helper.ReadUntilIncluding(LibraryHelper::kName); |
| 227 ASSERT(flags == 0); // external libraries not supported | 224 library.SetName(H.DartSymbol(library_helper.name_index_)); |
| 228 | |
| 229 NameIndex canonical_name = | |
| 230 builder_.ReadCanonicalNameReference(); // read canonical name. | |
| 231 dart::Library& library = LookupLibrary(canonical_name); | |
| 232 if (library.Loaded()) return; | |
| 233 StringIndex name = builder_.ReadStringReference(); // read name. | |
| 234 library.SetName(H.DartSymbol(name)); | |
| 235 | 225 |
| 236 // The bootstrapper will take care of creating the native wrapper classes, but | 226 // The bootstrapper will take care of creating the native wrapper classes, but |
| 237 // we will add the synthetic constructors to them here. | 227 // we will add the synthetic constructors to them here. |
| 238 if (library.name() == | 228 if (library.name() == |
| 239 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { | 229 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { |
| 240 ASSERT(library.LoadInProgress()); | 230 ASSERT(library.LoadInProgress()); |
| 241 } else { | 231 } else { |
| 242 library.SetLoadInProgress(); | 232 library.SetLoadInProgress(); |
| 243 } | 233 } |
| 244 // Setup toplevel class (which contains library fields/procedures). | 234 // Setup toplevel class (which contains library fields/procedures). |
| 245 | 235 |
| 246 StringIndex import_uri_index = H.CanonicalNameString(canonical_name); | 236 StringIndex import_uri_index = |
| 247 intptr_t source_uri_index = builder_.ReadUInt(); // read source uri index. | 237 H.CanonicalNameString(library_helper.canonical_name_); |
| 238 library_helper.ReadUntilIncluding(LibraryHelper::kSourceUriIndex); |
| 239 Script& script = ScriptAt(library_helper.source_uri_index_, import_uri_index); |
| 248 | 240 |
| 249 Script& script = ScriptAt(source_uri_index, import_uri_index); | |
| 250 dart::Class& toplevel_class = dart::Class::Handle( | 241 dart::Class& toplevel_class = dart::Class::Handle( |
| 251 Z, dart::Class::New(library, Symbols::TopLevel(), script, | 242 Z, dart::Class::New(library, Symbols::TopLevel(), script, |
| 252 TokenPosition::kNoSource)); | 243 TokenPosition::kNoSource)); |
| 253 toplevel_class.set_is_cycle_free(); | 244 toplevel_class.set_is_cycle_free(); |
| 254 library.set_toplevel_class(toplevel_class); | 245 library.set_toplevel_class(toplevel_class); |
| 255 | 246 |
| 256 intptr_t annotation_count = builder_.ReadUInt(); // read list length. | |
| 257 for (intptr_t i = 0; i < annotation_count; ++i) { | |
| 258 builder_.SkipExpression(); // read ith annotation expression. | |
| 259 } | |
| 260 | |
| 261 intptr_t dependency_count = builder_.ReadUInt(); // read list length. | |
| 262 for (intptr_t i = 0; i < dependency_count; ++i) { | |
| 263 builder_.ReadFlags(); // read flags. | |
| 264 annotation_count = builder_.ReadUInt(); // read list length. | |
| 265 for (intptr_t i = 0; i < annotation_count; ++i) { | |
| 266 builder_.SkipExpression(); // read ith annotation expression. | |
| 267 } | |
| 268 builder_.ReadCanonicalNameReference(); // read target_reference. | |
| 269 builder_.ReadStringReference(); // read name_index. | |
| 270 intptr_t combinator_count = builder_.ReadListLength(); // read list length. | |
| 271 for (intptr_t i = 0; i < combinator_count; ++i) { | |
| 272 builder_.ReadBool(); // read is_show. | |
| 273 intptr_t name_count = builder_.ReadUInt(); // read list length. | |
| 274 for (intptr_t j = 0; j < name_count; ++j) { | |
| 275 builder_.ReadUInt(); // read ith entry of name_indices. | |
| 276 } | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 // Skip typedefs. | |
| 281 intptr_t typedef_count = builder_.ReadListLength(); // read list length. | |
| 282 for (intptr_t i = 0; i < typedef_count; i++) { | |
| 283 builder_.SkipCanonicalNameReference(); // read canonical name. | |
| 284 builder_.ReadPosition(); // read position. | |
| 285 builder_.SkipStringReference(); // read name index. | |
| 286 builder_.ReadUInt(); // read source_uri_index. | |
| 287 builder_.SkipListOfDartTypes(); // read type parameters. | |
| 288 builder_.SkipDartType(); // read type. | |
| 289 } | |
| 290 | |
| 291 const GrowableObjectArray& classes = | 247 const GrowableObjectArray& classes = |
| 292 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()); | 248 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()); |
| 293 | 249 |
| 250 library_helper.ReadUntilExcluding(LibraryHelper::kClasses); |
| 251 |
| 294 // Load all classes. | 252 // Load all classes. |
| 295 int class_count = builder_.ReadListLength(); // read list length. | 253 int class_count = builder_.ReadListLength(); // read list length. |
| 296 for (intptr_t i = 0; i < class_count; ++i) { | 254 for (intptr_t i = 0; i < class_count; ++i) { |
| 297 classes.Add(ReadClass(library, toplevel_class), Heap::kOld); | 255 classes.Add(ReadClass(library, toplevel_class), Heap::kOld); |
| 298 } | 256 } |
| 299 | 257 |
| 300 fields_.Clear(); | 258 fields_.Clear(); |
| 301 functions_.Clear(); | 259 functions_.Clear(); |
| 302 ActiveClassScope active_class_scope(&active_class_, 0, -1, &toplevel_class); | 260 ActiveClassScope active_class_scope(&active_class_, 0, -1, &toplevel_class); |
| 303 // Load toplevel fields. | 261 // Load toplevel fields. |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 intptr_t source_uri_index) { | 680 intptr_t source_uri_index) { |
| 723 Script& correct_script = ScriptAt(source_uri_index); | 681 Script& correct_script = ScriptAt(source_uri_index); |
| 724 if (klass.script() != correct_script.raw()) { | 682 if (klass.script() != correct_script.raw()) { |
| 725 // TODO(jensj): We could probably cache this so we don't create | 683 // TODO(jensj): We could probably cache this so we don't create |
| 726 // new PatchClasses all the time | 684 // new PatchClasses all the time |
| 727 return PatchClass::ZoneHandle(Z, PatchClass::New(klass, correct_script)); | 685 return PatchClass::ZoneHandle(Z, PatchClass::New(klass, correct_script)); |
| 728 } | 686 } |
| 729 return klass; | 687 return klass; |
| 730 } | 688 } |
| 731 | 689 |
| 732 static int LowestFirst(const intptr_t* a, const intptr_t* b) { | |
| 733 return *a - *b; | |
| 734 } | |
| 735 | |
| 736 /** | |
| 737 * If index exists as sublist in list, sort the sublist from lowest to highest, | |
| 738 * then copy it, as Smis and without duplicates, | |
| 739 * to a new Array in Heap::kOld which is returned. | |
| 740 * Note that the source list is both sorted and de-duplicated as well, but will | |
| 741 * possibly contain duplicate and unsorted data at the end. | |
| 742 * Otherwise (when sublist doesn't exist in list) return new empty array. | |
| 743 */ | |
| 744 static RawArray* AsSortedDuplicateFreeArray( | |
| 745 intptr_t index, | |
| 746 MallocGrowableArray<MallocGrowableArray<intptr_t>*>* list) { | |
| 747 if ((index < list->length()) && (list->At(index)->length() > 0)) { | |
| 748 MallocGrowableArray<intptr_t>* source = list->At(index); | |
| 749 source->Sort(LowestFirst); | |
| 750 | |
| 751 intptr_t size = source->length(); | |
| 752 intptr_t last = 0; | |
| 753 for (intptr_t current = 1; current < size; ++current) { | |
| 754 if (source->At(last) != source->At(current)) { | |
| 755 (*source)[++last] = source->At(current); | |
| 756 } | |
| 757 } | |
| 758 Array& array_object = Array::Handle(); | |
| 759 array_object = Array::New(last + 1, Heap::kOld); | |
| 760 Smi& smi_value = Smi::Handle(); | |
| 761 for (intptr_t i = 0; i <= last; ++i) { | |
| 762 smi_value = Smi::New(source->At(i)); | |
| 763 array_object.SetAt(i, smi_value); | |
| 764 } | |
| 765 return array_object.raw(); | |
| 766 } else { | |
| 767 return Array::New(0); | |
| 768 } | |
| 769 } | |
| 770 | |
| 771 Script& KernelReader::ScriptAt(intptr_t index, StringIndex import_uri) { | 690 Script& KernelReader::ScriptAt(intptr_t index, StringIndex import_uri) { |
| 772 Script& script = Script::ZoneHandle(Z); | 691 Script& script = Script::ZoneHandle(Z); |
| 773 script ^= scripts_.At(index); | 692 script ^= scripts_.At(index); |
| 774 if (script.IsNull()) { | 693 if (script.IsNull()) { |
| 775 // Create script with correct uri(s). | 694 // Create script with correct uri(s). |
| 776 uint8_t* uri_buffer = program_->source_table().UriFor(index); | 695 dart::String& uri_string = builder_.SourceTableUriFor(index); |
| 777 intptr_t uri_size = program_->source_table().UriSizeFor(index); | |
| 778 dart::String& uri_string = H.DartString(uri_buffer, uri_size, Heap::kOld); | |
| 779 dart::String& import_uri_string = | 696 dart::String& import_uri_string = |
| 780 import_uri == -1 ? uri_string : H.DartString(import_uri, Heap::kOld); | 697 import_uri == -1 ? uri_string : H.DartString(import_uri, Heap::kOld); |
| 781 uint8_t* source_buffer = program_->source_table().SourceCodeFor(index); | 698 script = Script::New(import_uri_string, uri_string, |
| 782 intptr_t source_size = program_->source_table().SourceCodeSizeFor(index); | 699 String::Handle(String::null()), RawScript::kKernelTag); |
| 783 dart::String& source_code = | 700 script.set_kernel_data(program_->kernel_data()); |
| 784 H.DartString(source_buffer, source_size, Heap::kOld); | 701 script.set_kernel_data_size(program_->kernel_data_size()); |
| 785 script = Script::New(import_uri_string, uri_string, source_code, | 702 script.set_kernel_script_index(index); |
| 786 RawScript::kKernelTag); | |
| 787 script.set_kernel_data(program_->libraries()[0]->kernel_data()); | |
| 788 script.set_kernel_data_size(program_->libraries()[0]->kernel_data_size()); | |
| 789 script.set_kernel_string_offsets(H.string_offsets()); | 703 script.set_kernel_string_offsets(H.string_offsets()); |
| 790 script.set_kernel_string_data(H.string_data()); | 704 script.set_kernel_string_data(H.string_data()); |
| 791 script.set_kernel_canonical_names(H.canonical_names()); | 705 script.set_kernel_canonical_names(H.canonical_names()); |
| 792 scripts_.SetAt(index, script); | 706 scripts_.SetAt(index, script); |
| 793 | 707 |
| 794 // Create line_starts array for the script. | 708 script.set_line_starts(Array::Handle(Array::null())); |
| 795 intptr_t* line_starts = program_->source_table().LineStartsFor(index); | 709 script.set_debug_positions(Array::Handle(Array::null())); |
| 796 intptr_t line_count = program_->source_table().LineCountFor(index); | 710 script.set_yield_positions(Array::Handle(Array::null())); |
| 797 Array& array_object = Array::Handle(Z, Array::New(line_count, Heap::kOld)); | |
| 798 Smi& value = Smi::Handle(Z); | |
| 799 for (intptr_t i = 0; i < line_count; ++i) { | |
| 800 value = Smi::New(line_starts[i]); | |
| 801 array_object.SetAt(i, value); | |
| 802 } | |
| 803 script.set_line_starts(array_object); | |
| 804 | |
| 805 // Create tokens_seen array for the script. | |
| 806 array_object = | |
| 807 AsSortedDuplicateFreeArray(index, &program_->valid_token_positions); | |
| 808 script.set_debug_positions(array_object); | |
| 809 | |
| 810 // Create yield_positions array for the script. | |
| 811 array_object = | |
| 812 AsSortedDuplicateFreeArray(index, &program_->yield_token_positions); | |
| 813 script.set_yield_positions(array_object); | |
| 814 } | 711 } |
| 815 return script; | 712 return script; |
| 816 } | 713 } |
| 817 | 714 |
| 818 void KernelReader::GenerateFieldAccessors(const dart::Class& klass, | 715 void KernelReader::GenerateFieldAccessors(const dart::Class& klass, |
| 819 const dart::Field& field, | 716 const dart::Field& field, |
| 820 FieldHelper* field_helper, | 717 FieldHelper* field_helper, |
| 821 intptr_t field_offset) { | 718 intptr_t field_offset) { |
| 822 Tag tag = builder_.PeekTag(); | 719 Tag tag = builder_.PeekTag(); |
| 823 if (field_helper->IsStatic() && tag == kNothing) { | 720 if (field_helper->IsStatic() && tag == kNothing) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 setter.set_is_debuggable(false); | 797 setter.set_is_debuggable(false); |
| 901 SetupFieldAccessorFunction(klass, setter); | 798 SetupFieldAccessorFunction(klass, setter); |
| 902 } | 799 } |
| 903 } | 800 } |
| 904 | 801 |
| 905 | 802 |
| 906 void KernelReader::SetupFieldAccessorFunction(const dart::Class& klass, | 803 void KernelReader::SetupFieldAccessorFunction(const dart::Class& klass, |
| 907 const dart::Function& function) { | 804 const dart::Function& function) { |
| 908 bool is_setter = function.IsImplicitSetterFunction(); | 805 bool is_setter = function.IsImplicitSetterFunction(); |
| 909 bool is_method = !function.IsStaticFunction(); | 806 bool is_method = !function.IsStaticFunction(); |
| 910 intptr_t num_parameters = (is_method ? 1 : 0) + (is_setter ? 1 : 0); | 807 intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0); |
| 911 | 808 |
| 912 function.SetNumOptionalParameters(0, false); | 809 function.SetNumOptionalParameters(0, false); |
| 913 function.set_num_fixed_parameters(num_parameters); | 810 function.set_num_fixed_parameters(parameter_count); |
| 914 function.set_parameter_types( | 811 function.set_parameter_types( |
| 915 Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); | 812 Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
| 916 function.set_parameter_names( | 813 function.set_parameter_names( |
| 917 Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); | 814 Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
| 918 | 815 |
| 919 intptr_t pos = 0; | 816 intptr_t pos = 0; |
| 920 if (is_method) { | 817 if (is_method) { |
| 921 function.SetParameterTypeAt(pos, T.ReceiverType(klass)); | 818 function.SetParameterTypeAt(pos, T.ReceiverType(klass)); |
| 922 function.SetParameterNameAt(pos, Symbols::This()); | 819 function.SetParameterNameAt(pos, Symbols::This()); |
| 923 pos++; | 820 pos++; |
| 924 } | 821 } |
| 925 if (is_setter) { | 822 if (is_setter) { |
| 926 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); | 823 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 927 function.SetParameterNameAt(pos, Symbols::Value()); | 824 function.SetParameterNameAt(pos, Symbols::Value()); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 initializer_fun.set_is_debuggable(false); | 906 initializer_fun.set_is_debuggable(false); |
| 1010 initializer_fun.set_is_reflectable(false); | 907 initializer_fun.set_is_reflectable(false); |
| 1011 initializer_fun.set_is_inlinable(false); | 908 initializer_fun.set_is_inlinable(false); |
| 1012 return new (zone) ParsedFunction(thread, initializer_fun); | 909 return new (zone) ParsedFunction(thread, initializer_fun); |
| 1013 } | 910 } |
| 1014 | 911 |
| 1015 | 912 |
| 1016 } // namespace kernel | 913 } // namespace kernel |
| 1017 } // namespace dart | 914 } // namespace dart |
| 1018 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 915 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |