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); |
zra
2017/06/08 03:10:30
Is memchr() portable?
rmacnak
2017/06/08 22:15:09
I think so, but it uses a length that would need t
| |
61 if (comma1 == NULL) break; | 79 if (comma1 == NULL) break; |
zra
2017/06/08 03:10:30
Curly braces for single-line ifs.
rmacnak
2017/06/08 22:15:09
Done.
| |
62 *comma1 = 0; | 80 *comma1 = 0; |
63 char* cls_name = comma1 + 1; | 81 char* cls_name = comma1 + 1; |
64 char* comma2 = strchr(cls_name, ','); | 82 char* comma2 = FindCharacter(cls_name, ',', limit); |
65 if (comma2 == NULL) break; | 83 if (comma2 == NULL) break; |
66 *comma2 = 0; | 84 *comma2 = 0; |
67 char* func_name = comma2 + 1; | 85 char* func_name = comma2 + 1; |
68 char* newline = strchr(func_name, '\n'); | 86 char* newline = FindCharacter(func_name, '\n', limit); |
69 if (newline == NULL) break; | 87 if (newline == NULL) break; |
70 *newline = 0; | 88 *newline = 0; |
71 error_ = CompileTriple(uri, cls_name, func_name); | 89 error_ = CompileTriple(uri, cls_name, func_name); |
72 if (error_.IsError()) { | 90 if (error_.IsError()) { |
73 return error_.raw(); | 91 return error_.raw(); |
74 } | 92 } |
75 cursor = newline + 1; | 93 cursor = newline + 1; |
76 } | 94 } |
77 | 95 |
78 // Next, compile common dispatchers. These aren't found with the normal | 96 // Next, compile common dispatchers. These aren't found with the normal |
79 // lookup above because they have irregular lookup that depends on the | 97 // lookup above because they have irregular lookup that depends on the |
80 // arguments descriptor (e.g. call() versus call(x)). | 98 // arguments descriptor (e.g. call() versus call(x)). |
81 const Class& closure_class = | 99 const Class& closure_class = |
82 Class::Handle(zone_, thread_->isolate()->object_store()->closure_class()); | 100 Class::Handle(zone_, thread_->isolate()->object_store()->closure_class()); |
83 Array& arguments_descriptor = Array::Handle(zone_); | 101 Array& arguments_descriptor = Array::Handle(zone_); |
84 Function& dispatcher = Function::Handle(zone_); | 102 Function& dispatcher = Function::Handle(zone_); |
85 for (intptr_t argc = 1; argc <= 4; argc++) { | 103 for (intptr_t argc = 1; argc <= 4; argc++) { |
86 const intptr_t kTypeArgsLen = 0; | 104 const intptr_t kTypeArgsLen = 0; |
87 arguments_descriptor = ArgumentsDescriptor::New(kTypeArgsLen, argc); | 105 arguments_descriptor = ArgumentsDescriptor::New(kTypeArgsLen, argc); |
88 dispatcher = closure_class.GetInvocationDispatcher( | 106 dispatcher = closure_class.GetInvocationDispatcher( |
89 Symbols::Call(), arguments_descriptor, | 107 Symbols::Call(), arguments_descriptor, |
90 RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */); | 108 RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */); |
91 error_ = CompileFunction(dispatcher); | 109 error_ = CompileFunction(dispatcher); |
92 if (error_.IsError()) { | 110 if (error_.IsError()) { |
93 return error_.raw(); | 111 return error_.raw(); |
94 } | 112 } |
95 } | 113 } |
96 | 114 |
97 // Finally, compile closures in all compiled functions. | 115 // Finally, compile closures in all compiled functions. Compiling inner |
116 // functions can cause inner inner functions to be registered, so iterate | |
117 // to a fixed point. | |
98 const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle( | 118 const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle( |
99 zone_, thread_->isolate()->object_store()->closure_functions()); | 119 zone_, thread_->isolate()->object_store()->closure_functions()); |
100 for (intptr_t i = 0; i < closure_functions.Length(); i++) { | 120 intptr_t previous_length = 0; |
101 function_ ^= closure_functions.At(i); | 121 while (closure_functions.Length() != previous_length) { |
102 function2_ = function_.parent_function(); | 122 previous_length = closure_functions.Length(); |
103 if (function2_.HasCode()) { | 123 for (intptr_t i = 0; i < closure_functions.Length(); i++) { |
zra
2017/06/08 03:10:30
How is closure_functions modified by CompileFuncti
rmacnak
2017/06/08 22:15:09
CompileFunction may append to this list, since we
| |
104 error_ = CompileFunction(function_); | 124 function_ ^= closure_functions.At(i); |
105 if (error_.IsError()) { | 125 function2_ = function_.parent_function(); |
106 return error_.raw(); | 126 if (function2_.HasCode()) { |
127 error_ = CompileFunction(function_); | |
128 if (error_.IsError()) { | |
129 return error_.raw(); | |
130 } | |
107 } | 131 } |
108 } | 132 } |
109 } | 133 } |
110 | 134 |
111 return Object::null(); | 135 return Object::null(); |
112 } | 136 } |
113 | 137 |
114 | 138 |
115 RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr, | 139 RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr, |
zra
2017/06/08 03:10:30
A comment about the algorithm used for the fuzzy m
rmacnak
2017/06/08 22:15:09
Added
| |
116 const char* cls_cstr, | 140 const char* cls_cstr, |
117 const char* func_cstr) { | 141 const char* func_cstr) { |
118 uri_ = Symbols::New(thread_, uri_cstr); | 142 uri_ = Symbols::New(thread_, uri_cstr); |
119 class_name_ = Symbols::New(thread_, cls_cstr); | 143 class_name_ = Symbols::New(thread_, cls_cstr); |
120 function_name_ = Symbols::New(thread_, func_cstr); | 144 function_name_ = Symbols::New(thread_, func_cstr); |
121 | 145 |
122 if (function_name_.Equals("_getMainClosure")) { | 146 if (function_name_.Equals("_getMainClosure")) { |
123 // The scheme for invoking main relies on compiling _getMainClosure after | 147 // The scheme for invoking main relies on compiling _getMainClosure after |
124 // synthetically importing the root library. | 148 // synthetically importing the root library. |
125 return Object::null(); | 149 return Object::null(); |
(...skipping 25 matching lines...) Expand all Loading... | |
151 return Object::null(); | 175 return Object::null(); |
152 } | 176 } |
153 | 177 |
154 error_ = cls_.EnsureIsFinalized(thread_); | 178 error_ = cls_.EnsureIsFinalized(thread_); |
155 if (error_.IsError()) { | 179 if (error_.IsError()) { |
156 return error_.raw(); | 180 return error_.raw(); |
157 } | 181 } |
158 | 182 |
159 function_ = cls_.LookupFunctionAllowPrivate(function_name_); | 183 function_ = cls_.LookupFunctionAllowPrivate(function_name_); |
160 field_ = cls_.LookupFieldAllowPrivate(function_name_); | 184 field_ = cls_.LookupFieldAllowPrivate(function_name_); |
161 if (field_.IsNull() && is_getter) { | 185 if (function_.IsNull() && is_getter) { |
162 // Maybe this is a tear off. | 186 // Maybe this was a tear off. |
163 add_closure = true; | 187 add_closure = true; |
164 function_name2_ = Field::NameFromGetter(function_name_); | 188 function_name2_ = Field::NameFromGetter(function_name_); |
165 function_ = cls_.LookupFunctionAllowPrivate(function_name2_); | 189 function_ = cls_.LookupFunctionAllowPrivate(function_name2_); |
166 field_ = cls_.LookupFieldAllowPrivate(function_name2_); | 190 field_ = cls_.LookupFieldAllowPrivate(function_name2_); |
167 if (!function_.IsNull() && !function_.is_static()) { | 191 if (!function_.IsNull() && !function_.is_static()) { |
168 // Maybe this was a method extractor. | 192 // Maybe this was a method extractor. |
169 function2_ = | 193 function2_ = |
170 Resolver::ResolveDynamicAnyArgs(zone_, cls_, function_name_); | 194 Resolver::ResolveDynamicAnyArgs(zone_, cls_, function_name_); |
171 if (!function2_.IsNull()) { | 195 if (!function2_.IsNull()) { |
172 error_ = CompileFunction(function2_); | 196 error_ = CompileFunction(function2_); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 } else { | 243 } else { |
220 Thread* thread = Thread::Current(); | 244 Thread* thread = Thread::Current(); |
221 const Error& error = Error::Handle(thread->sticky_error()); | 245 const Error& error = Error::Handle(thread->sticky_error()); |
222 thread->clear_sticky_error(); | 246 thread->clear_sticky_error(); |
223 return error.raw(); | 247 return error.raw(); |
224 } | 248 } |
225 return Object::null(); | 249 return Object::null(); |
226 } | 250 } |
227 | 251 |
228 } // namespace dart | 252 } // namespace dart |
OLD | NEW |