| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/precompiler.h" | 5 #include "vm/precompiler.h" |
| 6 | 6 |
| 7 #include "vm/cha.h" | 7 #include "vm/cha.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/hash_table.h" | 10 #include "vm/hash_table.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 Precompiler::Precompiler(Thread* thread, bool reset_fields) : | 56 Precompiler::Precompiler(Thread* thread, bool reset_fields) : |
| 57 thread_(thread), | 57 thread_(thread), |
| 58 zone_(thread->zone()), | 58 zone_(thread->zone()), |
| 59 isolate_(thread->isolate()), | 59 isolate_(thread->isolate()), |
| 60 reset_fields_(reset_fields), | 60 reset_fields_(reset_fields), |
| 61 changed_(false), | 61 changed_(false), |
| 62 function_count_(0), | 62 function_count_(0), |
| 63 class_count_(0), | 63 class_count_(0), |
| 64 selector_count_(0), | 64 selector_count_(0), |
| 65 dropped_function_count_(0), | 65 dropped_function_count_(0), |
| 66 dropped_field_count_(0), |
| 66 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), | 67 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), |
| 67 pending_functions_( | 68 pending_functions_( |
| 68 GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), | 69 GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), |
| 69 sent_selectors_(), | 70 sent_selectors_(), |
| 70 enqueued_functions_(), | 71 enqueued_functions_(), |
| 71 error_(Error::Handle(Z)) { | 72 error_(Error::Handle(Z)) { |
| 72 } | 73 } |
| 73 | 74 |
| 74 | 75 |
| 75 void Precompiler::DoCompileAll( | 76 void Precompiler::DoCompileAll( |
| (...skipping 28 matching lines...) Expand all Loading... |
| 104 | 105 |
| 105 // Start with the allocations and invocations that happen from C++. | 106 // Start with the allocations and invocations that happen from C++. |
| 106 AddRoots(embedder_entry_points); | 107 AddRoots(embedder_entry_points); |
| 107 | 108 |
| 108 // Compile newly found targets and add their callees until we reach a fixed | 109 // Compile newly found targets and add their callees until we reach a fixed |
| 109 // point. | 110 // point. |
| 110 Iterate(); | 111 Iterate(); |
| 111 } | 112 } |
| 112 | 113 |
| 113 DropUncompiledFunctions(); | 114 DropUncompiledFunctions(); |
| 115 DropFields(); |
| 114 | 116 |
| 115 // TODO(rmacnak): DropEmptyClasses(); | 117 // TODO(rmacnak): DropEmptyClasses(); |
| 116 | 118 |
| 117 BindStaticCalls(); | 119 BindStaticCalls(); |
| 118 | 120 |
| 119 DedupStackmaps(); | 121 DedupStackmaps(); |
| 120 | 122 |
| 121 if (FLAG_trace_precompiler) { | 123 if (FLAG_trace_precompiler) { |
| 122 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," | 124 THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types," |
| 123 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n", | 125 " %" Pd " dynamic selectors.\n Dropped %" Pd " functions, %" Pd |
| 126 " fields.\n", |
| 124 function_count_, | 127 function_count_, |
| 125 class_count_, | 128 class_count_, |
| 126 selector_count_, | 129 selector_count_, |
| 127 dropped_function_count_); | 130 dropped_function_count_, |
| 131 dropped_field_count_); |
| 128 } | 132 } |
| 129 | 133 |
| 130 I->set_compilation_allowed(false); | 134 I->set_compilation_allowed(false); |
| 131 } | 135 } |
| 132 | 136 |
| 133 | 137 |
| 134 void Precompiler::ClearAllCode() { | 138 void Precompiler::ClearAllCode() { |
| 135 class ClearCodeFunctionVisitor : public FunctionVisitor { | 139 class ClearCodeFunctionVisitor : public FunctionVisitor { |
| 136 void VisitFunction(const Function& function) { | 140 void VisitFunction(const Function& function) { |
| 137 function.ClearCode(); | 141 function.ClearCode(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 kIllegalCid | 223 kIllegalCid |
| 220 }; | 224 }; |
| 221 | 225 |
| 222 Class& cls = Class::Handle(Z); | 226 Class& cls = Class::Handle(Z); |
| 223 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { | 227 for (intptr_t i = 0; kExternallyAllocatedCids[i] != kIllegalCid; i++) { |
| 224 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); | 228 cls = isolate()->class_table()->At(kExternallyAllocatedCids[i]); |
| 225 AddInstantiatedClass(cls); | 229 AddInstantiatedClass(cls); |
| 226 } | 230 } |
| 227 | 231 |
| 228 Dart_QualifiedFunctionName vm_entry_points[] = { | 232 Dart_QualifiedFunctionName vm_entry_points[] = { |
| 233 // Functions |
| 229 { "dart:async", "::", "_setScheduleImmediateClosure" }, | 234 { "dart:async", "::", "_setScheduleImmediateClosure" }, |
| 230 { "dart:core", "::", "_completeDeferredLoads"}, | 235 { "dart:core", "::", "_completeDeferredLoads"}, |
| 231 { "dart:core", "AbstractClassInstantiationError", | 236 { "dart:core", "AbstractClassInstantiationError", |
| 232 "AbstractClassInstantiationError._create" }, | 237 "AbstractClassInstantiationError._create" }, |
| 233 { "dart:core", "ArgumentError", "ArgumentError." }, | 238 { "dart:core", "ArgumentError", "ArgumentError." }, |
| 234 { "dart:core", "CyclicInitializationError", | 239 { "dart:core", "CyclicInitializationError", |
| 235 "CyclicInitializationError." }, | 240 "CyclicInitializationError." }, |
| 236 { "dart:core", "FallThroughError", "FallThroughError._create" }, | 241 { "dart:core", "FallThroughError", "FallThroughError._create" }, |
| 237 { "dart:core", "FormatException", "FormatException." }, | 242 { "dart:core", "FormatException", "FormatException." }, |
| 238 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, | 243 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 257 { "dart:isolate", "::", "_startMainIsolate" }, | 262 { "dart:isolate", "::", "_startMainIsolate" }, |
| 258 { "dart:isolate", "_RawReceivePortImpl", "_handleMessage" }, | 263 { "dart:isolate", "_RawReceivePortImpl", "_handleMessage" }, |
| 259 { "dart:isolate", "_RawReceivePortImpl", "_lookupHandler" }, | 264 { "dart:isolate", "_RawReceivePortImpl", "_lookupHandler" }, |
| 260 { "dart:isolate", "_SendPortImpl", "send" }, | 265 { "dart:isolate", "_SendPortImpl", "send" }, |
| 261 { "dart:typed_data", "ByteData", "ByteData." }, | 266 { "dart:typed_data", "ByteData", "ByteData." }, |
| 262 { "dart:typed_data", "ByteData", "ByteData._view" }, | 267 { "dart:typed_data", "ByteData", "ByteData._view" }, |
| 263 { "dart:typed_data", "_ByteBuffer", "_ByteBuffer._New" }, | 268 { "dart:typed_data", "_ByteBuffer", "_ByteBuffer._New" }, |
| 264 { "dart:_vmservice", "::", "_registerIsolate" }, | 269 { "dart:_vmservice", "::", "_registerIsolate" }, |
| 265 { "dart:_vmservice", "::", "boot" }, | 270 { "dart:_vmservice", "::", "boot" }, |
| 266 { "dart:developer", "Metrics", "_printMetrics" }, | 271 { "dart:developer", "Metrics", "_printMetrics" }, |
| 272 // Fields |
| 273 { "dart:core", "Error", "_stackTrace" }, |
| 274 { "dart:math", "_Random", "_state" }, |
| 267 { NULL, NULL, NULL } // Must be terminated with NULL entries. | 275 { NULL, NULL, NULL } // Must be terminated with NULL entries. |
| 268 }; | 276 }; |
| 269 | 277 |
| 270 AddEntryPoints(vm_entry_points); | 278 AddEntryPoints(vm_entry_points); |
| 271 AddEntryPoints(embedder_entry_points); | 279 AddEntryPoints(embedder_entry_points); |
| 272 } | 280 } |
| 273 | 281 |
| 274 | 282 |
| 275 void Precompiler::AddEntryPoints(Dart_QualifiedFunctionName entry_points[]) { | 283 void Precompiler::AddEntryPoints(Dart_QualifiedFunctionName entry_points[]) { |
| 276 Library& lib = Library::Handle(Z); | 284 Library& lib = Library::Handle(Z); |
| 277 Class& cls = Class::Handle(Z); | 285 Class& cls = Class::Handle(Z); |
| 278 Function& func = Function::Handle(Z); | 286 Function& func = Function::Handle(Z); |
| 287 Field& field = Field::Handle(Z); |
| 279 String& library_uri = String::Handle(Z); | 288 String& library_uri = String::Handle(Z); |
| 280 String& class_name = String::Handle(Z); | 289 String& class_name = String::Handle(Z); |
| 281 String& function_name = String::Handle(Z); | 290 String& function_name = String::Handle(Z); |
| 282 | 291 |
| 283 for (intptr_t i = 0; entry_points[i].library_uri != NULL; i++) { | 292 for (intptr_t i = 0; entry_points[i].library_uri != NULL; i++) { |
| 284 library_uri = Symbols::New(entry_points[i].library_uri); | 293 library_uri = Symbols::New(entry_points[i].library_uri); |
| 285 class_name = Symbols::New(entry_points[i].class_name); | 294 class_name = Symbols::New(entry_points[i].class_name); |
| 286 function_name = Symbols::New(entry_points[i].function_name); | 295 function_name = Symbols::New(entry_points[i].function_name); |
| 287 | 296 |
| 288 lib = Library::LookupLibrary(library_uri); | 297 lib = Library::LookupLibrary(library_uri); |
| 289 if (lib.IsNull()) { | 298 if (lib.IsNull()) { |
| 290 if (FLAG_trace_precompiler) { | 299 if (FLAG_trace_precompiler) { |
| 291 THR_Print("WARNING: Missing %s\n", entry_points[i].library_uri); | 300 THR_Print("WARNING: Missing %s\n", entry_points[i].library_uri); |
| 292 } | 301 } |
| 293 continue; | 302 continue; |
| 294 } | 303 } |
| 295 | 304 |
| 296 if (class_name.raw() == Symbols::TopLevel().raw()) { | 305 if (class_name.raw() == Symbols::TopLevel().raw()) { |
| 297 func = lib.LookupFunctionAllowPrivate(function_name); | 306 func = lib.LookupFunctionAllowPrivate(function_name); |
| 307 field = lib.LookupFieldAllowPrivate(function_name); |
| 298 } else { | 308 } else { |
| 299 cls = lib.LookupClassAllowPrivate(class_name); | 309 cls = lib.LookupClassAllowPrivate(class_name); |
| 300 if (cls.IsNull()) { | 310 if (cls.IsNull()) { |
| 301 if (FLAG_trace_precompiler) { | 311 if (FLAG_trace_precompiler) { |
| 302 THR_Print("WARNING: Missing %s %s\n", | 312 THR_Print("WARNING: Missing %s %s\n", |
| 303 entry_points[i].library_uri, | 313 entry_points[i].library_uri, |
| 304 entry_points[i].class_name); | 314 entry_points[i].class_name); |
| 305 } | 315 } |
| 306 continue; | 316 continue; |
| 307 } | 317 } |
| 308 | 318 |
| 309 ASSERT(!cls.IsNull()); | 319 ASSERT(!cls.IsNull()); |
| 310 func = cls.LookupFunctionAllowPrivate(function_name); | 320 func = cls.LookupFunctionAllowPrivate(function_name); |
| 321 field = cls.LookupField(function_name); |
| 311 } | 322 } |
| 312 | 323 |
| 313 if (func.IsNull()) { | 324 if (func.IsNull() && field.IsNull()) { |
| 314 if (FLAG_trace_precompiler) { | 325 if (FLAG_trace_precompiler) { |
| 315 THR_Print("WARNING: Missing %s %s %s\n", | 326 THR_Print("WARNING: Missing %s %s %s\n", |
| 316 entry_points[i].library_uri, | 327 entry_points[i].library_uri, |
| 317 entry_points[i].class_name, | 328 entry_points[i].class_name, |
| 318 entry_points[i].function_name); | 329 entry_points[i].function_name); |
| 319 } | 330 } |
| 320 continue; | |
| 321 } | 331 } |
| 322 | 332 |
| 323 AddFunction(func); | 333 if (!func.IsNull()) { |
| 324 if (func.IsGenerativeConstructor()) { | 334 AddFunction(func); |
| 325 // Allocation stubs are referenced from the call site of the constructor, | 335 if (func.IsGenerativeConstructor()) { |
| 326 // not in the constructor itself. So compiling the constructor isn't | 336 // Allocation stubs are referenced from the call site of the |
| 327 // enough for us to discover the class is instantiated if the class isn't | 337 // constructor, not in the constructor itself. So compiling the |
| 328 // otherwise instantiated from Dart code and only instantiated from C++. | 338 // constructor isn't enough for us to discover the class is |
| 329 AddInstantiatedClass(cls); | 339 // instantiated if the class isn't otherwise instantiated from Dart |
| 340 // code and only instantiated from C++. |
| 341 AddInstantiatedClass(cls); |
| 342 } |
| 343 } |
| 344 if (!field.IsNull()) { |
| 345 AddField(field); |
| 330 } | 346 } |
| 331 } | 347 } |
| 332 } | 348 } |
| 333 | 349 |
| 334 | 350 |
| 335 void Precompiler::Iterate() { | 351 void Precompiler::Iterate() { |
| 336 Function& function = Function::Handle(Z); | 352 Function& function = Function::Handle(Z); |
| 337 | 353 |
| 338 while (changed_) { | 354 while (changed_) { |
| 339 changed_ = false; | 355 changed_ = false; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 const Function& dispatcher = Function::Handle(Z, | 535 const Function& dispatcher = Function::Handle(Z, |
| 520 cache_class.GetInvocationDispatcher(Symbols::Call(), | 536 cache_class.GetInvocationDispatcher(Symbols::Call(), |
| 521 arguments_descriptor, | 537 arguments_descriptor, |
| 522 RawFunction::kInvokeFieldDispatcher, | 538 RawFunction::kInvokeFieldDispatcher, |
| 523 true /* create_if_absent */)); | 539 true /* create_if_absent */)); |
| 524 AddFunction(dispatcher); | 540 AddFunction(dispatcher); |
| 525 } | 541 } |
| 526 | 542 |
| 527 | 543 |
| 528 void Precompiler::AddField(const Field& field) { | 544 void Precompiler::AddField(const Field& field) { |
| 545 fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.raw())); |
| 546 |
| 529 if (field.is_static()) { | 547 if (field.is_static()) { |
| 530 const Object& value = Object::Handle(Z, field.StaticValue()); | 548 const Object& value = Object::Handle(Z, field.StaticValue()); |
| 531 if (value.IsInstance()) { | 549 if (value.IsInstance()) { |
| 532 AddConstObject(Instance::Cast(value)); | 550 AddConstObject(Instance::Cast(value)); |
| 533 } | 551 } |
| 534 | 552 |
| 535 if (field.has_initializer()) { | 553 if (field.has_initializer()) { |
| 536 // Should not be in the middle of initialization while precompiling. | 554 // Should not be in the middle of initialization while precompiling. |
| 537 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 555 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| 538 | 556 |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 function.DropUncompiledImplicitClosureFunction(); | 918 function.DropUncompiledImplicitClosureFunction(); |
| 901 } else { | 919 } else { |
| 902 dropped_function_count_++; | 920 dropped_function_count_++; |
| 903 if (FLAG_trace_precompiler) { | 921 if (FLAG_trace_precompiler) { |
| 904 THR_Print("Precompilation dropping %s\n", | 922 THR_Print("Precompilation dropping %s\n", |
| 905 function.ToLibNamePrefixedQualifiedCString()); | 923 function.ToLibNamePrefixedQualifiedCString()); |
| 906 } | 924 } |
| 907 } | 925 } |
| 908 } | 926 } |
| 909 | 927 |
| 910 functions = Array::New(retained_functions.Length(), Heap::kOld); | 928 if (retained_functions.Length() > 0) { |
| 911 for (intptr_t j = 0; j < retained_functions.Length(); j++) { | 929 functions = Array::MakeArray(retained_functions); |
| 912 function ^= retained_functions.At(j); | 930 cls.SetFunctions(functions); |
| 913 functions.SetAt(j, function); | 931 } else { |
| 932 cls.SetFunctions(Object::empty_array()); |
| 914 } | 933 } |
| 915 cls.SetFunctions(functions); | |
| 916 } | 934 } |
| 917 } | 935 } |
| 918 | 936 |
| 919 closures = isolate()->object_store()->closure_functions(); | 937 closures = isolate()->object_store()->closure_functions(); |
| 920 retained_functions = GrowableObjectArray::New(); | 938 retained_functions = GrowableObjectArray::New(); |
| 921 for (intptr_t j = 0; j < closures.Length(); j++) { | 939 for (intptr_t j = 0; j < closures.Length(); j++) { |
| 922 function ^= closures.At(j); | 940 function ^= closures.At(j); |
| 923 if (function.HasCode()) { | 941 if (function.HasCode()) { |
| 924 retained_functions.Add(function); | 942 retained_functions.Add(function); |
| 925 } else { | 943 } else { |
| 926 dropped_function_count_++; | 944 dropped_function_count_++; |
| 927 if (FLAG_trace_precompiler) { | 945 if (FLAG_trace_precompiler) { |
| 928 THR_Print("Precompilation dropping %s\n", | 946 THR_Print("Precompilation dropping %s\n", |
| 929 function.ToLibNamePrefixedQualifiedCString()); | 947 function.ToLibNamePrefixedQualifiedCString()); |
| 930 } | 948 } |
| 931 } | 949 } |
| 932 } | 950 } |
| 933 isolate()->object_store()->set_closure_functions(retained_functions); | 951 isolate()->object_store()->set_closure_functions(retained_functions); |
| 934 } | 952 } |
| 935 | 953 |
| 936 | 954 |
| 955 void Precompiler::DropFields() { |
| 956 Library& lib = Library::Handle(Z); |
| 957 Class& cls = Class::Handle(Z); |
| 958 Array& fields = Array::Handle(Z); |
| 959 Field& field = Field::Handle(Z); |
| 960 GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z); |
| 961 |
| 962 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 963 lib ^= libraries_.At(i); |
| 964 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 965 while (it.HasNext()) { |
| 966 cls = it.GetNextClass(); |
| 967 if (cls.IsDynamicClass()) { |
| 968 continue; // class 'dynamic' is in the read-only VM isolate. |
| 969 } |
| 970 |
| 971 fields = cls.fields(); |
| 972 retained_fields = GrowableObjectArray::New(); |
| 973 for (intptr_t j = 0; j < fields.Length(); j++) { |
| 974 field ^= fields.At(j); |
| 975 bool drop = fields_to_retain_.Lookup(&field) == NULL; |
| 976 if (drop) { |
| 977 dropped_field_count_++; |
| 978 if (FLAG_trace_precompiler) { |
| 979 THR_Print("Precompilation dropping %s\n", |
| 980 field.ToCString()); |
| 981 } |
| 982 } else { |
| 983 retained_fields.Add(field); |
| 984 } |
| 985 } |
| 986 |
| 987 if (retained_fields.Length() > 0) { |
| 988 fields = Array::MakeArray(retained_fields); |
| 989 cls.SetFields(fields); |
| 990 } else { |
| 991 cls.SetFields(Object::empty_array()); |
| 992 } |
| 993 } |
| 994 } |
| 995 } |
| 996 |
| 997 |
| 937 void Precompiler::BindStaticCalls() { | 998 void Precompiler::BindStaticCalls() { |
| 938 class BindStaticCallsVisitor : public FunctionVisitor { | 999 class BindStaticCallsVisitor : public FunctionVisitor { |
| 939 public: | 1000 public: |
| 940 explicit BindStaticCallsVisitor(Zone* zone) : | 1001 explicit BindStaticCallsVisitor(Zone* zone) : |
| 941 code_(Code::Handle(zone)), | 1002 code_(Code::Handle(zone)), |
| 942 table_(Array::Handle(zone)), | 1003 table_(Array::Handle(zone)), |
| 943 pc_offset_(Smi::Handle(zone)), | 1004 pc_offset_(Smi::Handle(zone)), |
| 944 target_(Function::Handle(zone)), | 1005 target_(Function::Handle(zone)), |
| 945 target_code_(Code::Handle(zone)) { | 1006 target_code_(Code::Handle(zone)) { |
| 946 } | 1007 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 cls = it.GetNextClass(); | 1202 cls = it.GetNextClass(); |
| 1142 if (cls.IsDynamicClass()) { | 1203 if (cls.IsDynamicClass()) { |
| 1143 continue; // class 'dynamic' is in the read-only VM isolate. | 1204 continue; // class 'dynamic' is in the read-only VM isolate. |
| 1144 } | 1205 } |
| 1145 cls.set_is_allocated(false); | 1206 cls.set_is_allocated(false); |
| 1146 } | 1207 } |
| 1147 } | 1208 } |
| 1148 } | 1209 } |
| 1149 | 1210 |
| 1150 } // namespace dart | 1211 } // namespace dart |
| OLD | NEW |