| Index: runtime/vm/compilation_trace.cc
|
| diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
|
| index f972dfa1f9d86aadd048a4543f7b1a5ac302014c..2fd2cf0b7b0c079733bfc470adfb2c1177bcc630 100644
|
| --- a/runtime/vm/compilation_trace.cc
|
| +++ b/runtime/vm/compilation_trace.cc
|
| @@ -22,6 +22,11 @@ CompilationTraceSaver::CompilationTraceSaver(Zone* zone)
|
|
|
| void CompilationTraceSaver::Visit(const Function& function) {
|
| if (!function.HasCode()) {
|
| + return; // Not compiled.
|
| + }
|
| + if (function.parent_function() != Function::null()) {
|
| + // Lookup works poorly for local functions. We compile all local functions
|
| + // in a compiled function instead.
|
| return;
|
| }
|
|
|
| @@ -52,21 +57,40 @@ CompilationTraceLoader::CompilationTraceLoader(Thread* thread)
|
| error_(Object::Handle(zone_)) {}
|
|
|
|
|
| -RawObject* CompilationTraceLoader::CompileTrace(char* buffer) {
|
| +static char* FindCharacter(char* str, char goal, char* limit) {
|
| + while (str < limit) {
|
| + if (*str == goal) {
|
| + return str;
|
| + }
|
| + str++;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +RawObject* CompilationTraceLoader::CompileTrace(uint8_t* buffer,
|
| + intptr_t size) {
|
| // First compile functions named in the trace.
|
| - char* cursor = buffer;
|
| - while (cursor != NULL) {
|
| + char* cursor = reinterpret_cast<char*>(buffer);
|
| + char* limit = cursor + size;
|
| + while (cursor < limit) {
|
| char* uri = cursor;
|
| - char* comma1 = strchr(uri, ',');
|
| - if (comma1 == NULL) break;
|
| + char* comma1 = FindCharacter(uri, ',', limit);
|
| + if (comma1 == NULL) {
|
| + break;
|
| + }
|
| *comma1 = 0;
|
| char* cls_name = comma1 + 1;
|
| - char* comma2 = strchr(cls_name, ',');
|
| - if (comma2 == NULL) break;
|
| + char* comma2 = FindCharacter(cls_name, ',', limit);
|
| + if (comma2 == NULL) {
|
| + break;
|
| + }
|
| *comma2 = 0;
|
| char* func_name = comma2 + 1;
|
| - char* newline = strchr(func_name, '\n');
|
| - if (newline == NULL) break;
|
| + char* newline = FindCharacter(func_name, '\n', limit);
|
| + if (newline == NULL) {
|
| + break;
|
| + }
|
| *newline = 0;
|
| error_ = CompileTriple(uri, cls_name, func_name);
|
| if (error_.IsError()) {
|
| @@ -94,7 +118,8 @@ RawObject* CompilationTraceLoader::CompileTrace(char* buffer) {
|
| }
|
| }
|
|
|
| - // Finally, compile closures in all compiled functions.
|
| + // Finally, compile closures in all compiled functions. Don't cache the
|
| + // length since compiling may append to this list.
|
| const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle(
|
| zone_, thread_->isolate()->object_store()->closure_functions());
|
| for (intptr_t i = 0; i < closure_functions.Length(); i++) {
|
| @@ -112,6 +137,16 @@ RawObject* CompilationTraceLoader::CompileTrace(char* buffer) {
|
| }
|
|
|
|
|
| +// Use a fuzzy match to find the right function to compile. This allows a
|
| +// compilation trace to remain mostly valid in the face of program changes, and
|
| +// deals with implicit/dispatcher functions that don't have proper names.
|
| +// - Ignore private name mangling
|
| +// - If looking for a getter and we only have the corresponding regular method,
|
| +// compile the regular method, create its implicit closure and compile that.
|
| +// - If looking for a regular method and we only have the corresponding getter,
|
| +// compile the getter, create its method extractor and compile that.
|
| +// - If looking for a getter and we only have a const field, evaluate the const
|
| +// field.
|
| RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr,
|
| const char* cls_cstr,
|
| const char* func_cstr) {
|
| @@ -158,8 +193,8 @@ RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr,
|
|
|
| function_ = cls_.LookupFunctionAllowPrivate(function_name_);
|
| field_ = cls_.LookupFieldAllowPrivate(function_name_);
|
| - if (field_.IsNull() && is_getter) {
|
| - // Maybe this is a tear off.
|
| + if (function_.IsNull() && is_getter) {
|
| + // Maybe this was a tear off.
|
| add_closure = true;
|
| function_name2_ = Field::NameFromGetter(function_name_);
|
| function_ = cls_.LookupFunctionAllowPrivate(function_name2_);
|
|
|