| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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/compilation_trace.h" | 5 #include "vm/compilation_trace.h" |
| 6 | 6 |
| 7 #include "vm/longjump.h" | 7 #include "vm/longjump.h" |
| 8 #include "vm/object_store.h" | 8 #include "vm/object_store.h" |
| 9 #include "vm/resolver.h" | 9 #include "vm/resolver.h" |
| 10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 CompilationTraceSaver::CompilationTraceSaver(Zone* zone) | 14 CompilationTraceSaver::CompilationTraceSaver(Zone* zone) |
| 15 : buf_(zone, 4 * KB), | 15 : buf_(zone, 4 * KB), |
| 16 func_name_(String::Handle(zone)), | 16 func_name_(String::Handle(zone)), |
| 17 cls_(Class::Handle(zone)), | 17 cls_(Class::Handle(zone)), |
| 18 cls_name_(String::Handle(zone)), | 18 cls_name_(String::Handle(zone)), |
| 19 lib_(Library::Handle(zone)), | 19 lib_(Library::Handle(zone)), |
| 20 uri_(String::Handle(zone)) {} | 20 uri_(String::Handle(zone)) {} |
| 21 | 21 |
| 22 | 22 |
| 23 void CompilationTraceSaver::Visit(const Function& function) { | 23 void CompilationTraceSaver::Visit(const Function& function) { |
| 24 if (!function.HasCode()) { | 24 if (!function.HasCode()) { |
| 25 return; // Not compiled. |
| 26 } |
| 27 if (function.parent_function() != Function::null()) { |
| 28 // Lookup works poorly for local functions. We compile all local functions |
| 29 // in a compiled function instead. |
| 25 return; | 30 return; |
| 26 } | 31 } |
| 27 | 32 |
| 28 func_name_ = function.name(); | 33 func_name_ = function.name(); |
| 29 func_name_ = String::RemovePrivateKey(func_name_); | 34 func_name_ = String::RemovePrivateKey(func_name_); |
| 30 cls_ = function.Owner(); | 35 cls_ = function.Owner(); |
| 31 cls_name_ = cls_.Name(); | 36 cls_name_ = cls_.Name(); |
| 32 cls_name_ = String::RemovePrivateKey(cls_name_); | 37 cls_name_ = String::RemovePrivateKey(cls_name_); |
| 33 lib_ = cls_.library(); | 38 lib_ = cls_.library(); |
| 34 uri_ = lib_.url(); | 39 uri_ = lib_.url(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 45 function_name_(String::Handle(zone_)), | 50 function_name_(String::Handle(zone_)), |
| 46 function_name2_(String::Handle(zone_)), | 51 function_name2_(String::Handle(zone_)), |
| 47 lib_(Library::Handle(zone_)), | 52 lib_(Library::Handle(zone_)), |
| 48 cls_(Class::Handle(zone_)), | 53 cls_(Class::Handle(zone_)), |
| 49 function_(Function::Handle(zone_)), | 54 function_(Function::Handle(zone_)), |
| 50 function2_(Function::Handle(zone_)), | 55 function2_(Function::Handle(zone_)), |
| 51 field_(Field::Handle(zone_)), | 56 field_(Field::Handle(zone_)), |
| 52 error_(Object::Handle(zone_)) {} | 57 error_(Object::Handle(zone_)) {} |
| 53 | 58 |
| 54 | 59 |
| 55 RawObject* CompilationTraceLoader::CompileTrace(char* buffer) { | 60 static char* FindCharacter(char* str, char goal, char* limit) { |
| 61 while (str < limit) { |
| 62 if (*str == goal) { |
| 63 return str; |
| 64 } |
| 65 str++; |
| 66 } |
| 67 return NULL; |
| 68 } |
| 69 |
| 70 |
| 71 RawObject* CompilationTraceLoader::CompileTrace(uint8_t* buffer, |
| 72 intptr_t size) { |
| 56 // First compile functions named in the trace. | 73 // First compile functions named in the trace. |
| 57 char* cursor = buffer; | 74 char* cursor = reinterpret_cast<char*>(buffer); |
| 58 while (cursor != NULL) { | 75 char* limit = cursor + size; |
| 76 while (cursor < limit) { |
| 59 char* uri = cursor; | 77 char* uri = cursor; |
| 60 char* comma1 = strchr(uri, ','); | 78 char* comma1 = FindCharacter(uri, ',', limit); |
| 61 if (comma1 == NULL) break; | 79 if (comma1 == NULL) { |
| 80 break; |
| 81 } |
| 62 *comma1 = 0; | 82 *comma1 = 0; |
| 63 char* cls_name = comma1 + 1; | 83 char* cls_name = comma1 + 1; |
| 64 char* comma2 = strchr(cls_name, ','); | 84 char* comma2 = FindCharacter(cls_name, ',', limit); |
| 65 if (comma2 == NULL) break; | 85 if (comma2 == NULL) { |
| 86 break; |
| 87 } |
| 66 *comma2 = 0; | 88 *comma2 = 0; |
| 67 char* func_name = comma2 + 1; | 89 char* func_name = comma2 + 1; |
| 68 char* newline = strchr(func_name, '\n'); | 90 char* newline = FindCharacter(func_name, '\n', limit); |
| 69 if (newline == NULL) break; | 91 if (newline == NULL) { |
| 92 break; |
| 93 } |
| 70 *newline = 0; | 94 *newline = 0; |
| 71 error_ = CompileTriple(uri, cls_name, func_name); | 95 error_ = CompileTriple(uri, cls_name, func_name); |
| 72 if (error_.IsError()) { | 96 if (error_.IsError()) { |
| 73 return error_.raw(); | 97 return error_.raw(); |
| 74 } | 98 } |
| 75 cursor = newline + 1; | 99 cursor = newline + 1; |
| 76 } | 100 } |
| 77 | 101 |
| 78 // Next, compile common dispatchers. These aren't found with the normal | 102 // Next, compile common dispatchers. These aren't found with the normal |
| 79 // lookup above because they have irregular lookup that depends on the | 103 // lookup above because they have irregular lookup that depends on the |
| 80 // arguments descriptor (e.g. call() versus call(x)). | 104 // arguments descriptor (e.g. call() versus call(x)). |
| 81 const Class& closure_class = | 105 const Class& closure_class = |
| 82 Class::Handle(zone_, thread_->isolate()->object_store()->closure_class()); | 106 Class::Handle(zone_, thread_->isolate()->object_store()->closure_class()); |
| 83 Array& arguments_descriptor = Array::Handle(zone_); | 107 Array& arguments_descriptor = Array::Handle(zone_); |
| 84 Function& dispatcher = Function::Handle(zone_); | 108 Function& dispatcher = Function::Handle(zone_); |
| 85 for (intptr_t argc = 1; argc <= 4; argc++) { | 109 for (intptr_t argc = 1; argc <= 4; argc++) { |
| 86 const intptr_t kTypeArgsLen = 0; | 110 const intptr_t kTypeArgsLen = 0; |
| 87 arguments_descriptor = ArgumentsDescriptor::New(kTypeArgsLen, argc); | 111 arguments_descriptor = ArgumentsDescriptor::New(kTypeArgsLen, argc); |
| 88 dispatcher = closure_class.GetInvocationDispatcher( | 112 dispatcher = closure_class.GetInvocationDispatcher( |
| 89 Symbols::Call(), arguments_descriptor, | 113 Symbols::Call(), arguments_descriptor, |
| 90 RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */); | 114 RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */); |
| 91 error_ = CompileFunction(dispatcher); | 115 error_ = CompileFunction(dispatcher); |
| 92 if (error_.IsError()) { | 116 if (error_.IsError()) { |
| 93 return error_.raw(); | 117 return error_.raw(); |
| 94 } | 118 } |
| 95 } | 119 } |
| 96 | 120 |
| 97 // Finally, compile closures in all compiled functions. | 121 // Finally, compile closures in all compiled functions. Don't cache the |
| 122 // length since compiling may append to this list. |
| 98 const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle( | 123 const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle( |
| 99 zone_, thread_->isolate()->object_store()->closure_functions()); | 124 zone_, thread_->isolate()->object_store()->closure_functions()); |
| 100 for (intptr_t i = 0; i < closure_functions.Length(); i++) { | 125 for (intptr_t i = 0; i < closure_functions.Length(); i++) { |
| 101 function_ ^= closure_functions.At(i); | 126 function_ ^= closure_functions.At(i); |
| 102 function2_ = function_.parent_function(); | 127 function2_ = function_.parent_function(); |
| 103 if (function2_.HasCode()) { | 128 if (function2_.HasCode()) { |
| 104 error_ = CompileFunction(function_); | 129 error_ = CompileFunction(function_); |
| 105 if (error_.IsError()) { | 130 if (error_.IsError()) { |
| 106 return error_.raw(); | 131 return error_.raw(); |
| 107 } | 132 } |
| 108 } | 133 } |
| 109 } | 134 } |
| 110 | 135 |
| 111 return Object::null(); | 136 return Object::null(); |
| 112 } | 137 } |
| 113 | 138 |
| 114 | 139 |
| 140 // Use a fuzzy match to find the right function to compile. This allows a |
| 141 // compilation trace to remain mostly valid in the face of program changes, and |
| 142 // deals with implicit/dispatcher functions that don't have proper names. |
| 143 // - Ignore private name mangling |
| 144 // - If looking for a getter and we only have the corresponding regular method, |
| 145 // compile the regular method, create its implicit closure and compile that. |
| 146 // - If looking for a regular method and we only have the corresponding getter, |
| 147 // compile the getter, create its method extractor and compile that. |
| 148 // - If looking for a getter and we only have a const field, evaluate the const |
| 149 // field. |
| 115 RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr, | 150 RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr, |
| 116 const char* cls_cstr, | 151 const char* cls_cstr, |
| 117 const char* func_cstr) { | 152 const char* func_cstr) { |
| 118 uri_ = Symbols::New(thread_, uri_cstr); | 153 uri_ = Symbols::New(thread_, uri_cstr); |
| 119 class_name_ = Symbols::New(thread_, cls_cstr); | 154 class_name_ = Symbols::New(thread_, cls_cstr); |
| 120 function_name_ = Symbols::New(thread_, func_cstr); | 155 function_name_ = Symbols::New(thread_, func_cstr); |
| 121 | 156 |
| 122 if (function_name_.Equals("_getMainClosure")) { | 157 if (function_name_.Equals("_getMainClosure")) { |
| 123 // The scheme for invoking main relies on compiling _getMainClosure after | 158 // The scheme for invoking main relies on compiling _getMainClosure after |
| 124 // synthetically importing the root library. | 159 // synthetically importing the root library. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 151 return Object::null(); | 186 return Object::null(); |
| 152 } | 187 } |
| 153 | 188 |
| 154 error_ = cls_.EnsureIsFinalized(thread_); | 189 error_ = cls_.EnsureIsFinalized(thread_); |
| 155 if (error_.IsError()) { | 190 if (error_.IsError()) { |
| 156 return error_.raw(); | 191 return error_.raw(); |
| 157 } | 192 } |
| 158 | 193 |
| 159 function_ = cls_.LookupFunctionAllowPrivate(function_name_); | 194 function_ = cls_.LookupFunctionAllowPrivate(function_name_); |
| 160 field_ = cls_.LookupFieldAllowPrivate(function_name_); | 195 field_ = cls_.LookupFieldAllowPrivate(function_name_); |
| 161 if (field_.IsNull() && is_getter) { | 196 if (function_.IsNull() && is_getter) { |
| 162 // Maybe this is a tear off. | 197 // Maybe this was a tear off. |
| 163 add_closure = true; | 198 add_closure = true; |
| 164 function_name2_ = Field::NameFromGetter(function_name_); | 199 function_name2_ = Field::NameFromGetter(function_name_); |
| 165 function_ = cls_.LookupFunctionAllowPrivate(function_name2_); | 200 function_ = cls_.LookupFunctionAllowPrivate(function_name2_); |
| 166 field_ = cls_.LookupFieldAllowPrivate(function_name2_); | 201 field_ = cls_.LookupFieldAllowPrivate(function_name2_); |
| 167 if (!function_.IsNull() && !function_.is_static()) { | 202 if (!function_.IsNull() && !function_.is_static()) { |
| 168 // Maybe this was a method extractor. | 203 // Maybe this was a method extractor. |
| 169 function2_ = | 204 function2_ = |
| 170 Resolver::ResolveDynamicAnyArgs(zone_, cls_, function_name_); | 205 Resolver::ResolveDynamicAnyArgs(zone_, cls_, function_name_); |
| 171 if (!function2_.IsNull()) { | 206 if (!function2_.IsNull()) { |
| 172 error_ = CompileFunction(function2_); | 207 error_ = CompileFunction(function2_); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } else { | 254 } else { |
| 220 Thread* thread = Thread::Current(); | 255 Thread* thread = Thread::Current(); |
| 221 const Error& error = Error::Handle(thread->sticky_error()); | 256 const Error& error = Error::Handle(thread->sticky_error()); |
| 222 thread->clear_sticky_error(); | 257 thread->clear_sticky_error(); |
| 223 return error.raw(); | 258 return error.raw(); |
| 224 } | 259 } |
| 225 return Object::null(); | 260 return Object::null(); |
| 226 } | 261 } |
| 227 | 262 |
| 228 } // namespace dart | 263 } // namespace dart |
| OLD | NEW |