OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/unit_test.h" | 5 #include "vm/unit_test.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include "bin/builtin.h" | 9 #include "bin/builtin.h" |
10 #include "bin/dartutils.h" | 10 #include "bin/dartutils.h" |
11 #include "bin/isolate_data.h" | 11 #include "bin/isolate_data.h" |
12 | 12 |
13 #include "platform/globals.h" | 13 #include "platform/globals.h" |
14 | 14 |
15 #include "vm/assembler.h" | 15 #include "vm/assembler.h" |
16 #include "vm/ast_printer.h" | 16 #include "vm/ast_printer.h" |
17 #include "vm/compiler.h" | 17 #include "vm/compiler.h" |
18 #include "vm/dart_api_impl.h" | 18 #include "vm/dart_api_impl.h" |
19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
| 20 #include "vm/isolate_reload.h" |
20 #include "vm/parser.h" | 21 #include "vm/parser.h" |
21 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
22 #include "vm/thread.h" | 23 #include "vm/thread.h" |
23 #include "vm/virtual_memory.h" | 24 #include "vm/virtual_memory.h" |
24 | 25 |
25 using dart::bin::Builtin; | 26 using dart::bin::Builtin; |
26 using dart::bin::DartUtils; | 27 using dart::bin::DartUtils; |
27 | 28 |
28 namespace dart { | 29 namespace dart { |
29 | 30 |
(...skipping 29 matching lines...) Expand all Loading... |
59 OS::Print("Creation of isolate failed '%s'\n", err); | 60 OS::Print("Creation of isolate failed '%s'\n", err); |
60 free(err); | 61 free(err); |
61 } | 62 } |
62 EXPECT(isolate != NULL); | 63 EXPECT(isolate != NULL); |
63 return isolate; | 64 return isolate; |
64 } | 65 } |
65 | 66 |
66 | 67 |
67 static const char* kPackageScheme = "package:"; | 68 static const char* kPackageScheme = "package:"; |
68 | 69 |
| 70 |
69 static bool IsPackageSchemeURL(const char* url_name) { | 71 static bool IsPackageSchemeURL(const char* url_name) { |
70 static const intptr_t kPackageSchemeLen = strlen(kPackageScheme); | 72 static const intptr_t kPackageSchemeLen = strlen(kPackageScheme); |
71 return (strncmp(url_name, kPackageScheme, kPackageSchemeLen) == 0); | 73 return (strncmp(url_name, kPackageScheme, kPackageSchemeLen) == 0); |
72 } | 74 } |
73 | 75 |
| 76 |
| 77 static bool IsImportableTestLib(const char* url_name) { |
| 78 const char* kImportTestLibUri = "importable_test_lib"; |
| 79 static const intptr_t kImportTestLibUriLen = strlen(kImportTestLibUri); |
| 80 return (strncmp(url_name, kImportTestLibUri, kImportTestLibUriLen) == 0); |
| 81 } |
| 82 |
| 83 |
| 84 static Dart_Handle ImportableTestLibSource() { |
| 85 const char* kScript = |
| 86 "importedFunc() => 'a';\n" |
| 87 "importedIntFunc() => 4;\n" |
| 88 "class ImportedMixin {\n" |
| 89 " mixinFunc() => 'mixin';\n" |
| 90 "}\n"; |
| 91 return DartUtils::NewString(kScript); |
| 92 } |
| 93 |
| 94 |
| 95 static bool IsIsolateReloadTestLib(const char* url_name) { |
| 96 const char* kIsolateReloadTestLibUri = "isolate_reload_test_helper"; |
| 97 static const intptr_t kIsolateReloadTestLibUriLen = |
| 98 strlen(kIsolateReloadTestLibUri); |
| 99 return (strncmp(url_name, |
| 100 kIsolateReloadTestLibUri, |
| 101 kIsolateReloadTestLibUriLen) == 0); |
| 102 } |
| 103 |
| 104 |
| 105 #ifndef PRODUCT |
| 106 static Dart_Handle IsolateReloadTestLibSource() { |
| 107 // Special library with one function. |
| 108 return DartUtils::NewString("void reloadTest() native 'Reload_Test';\n"); |
| 109 } |
| 110 |
| 111 |
| 112 static void ReloadTest(Dart_NativeArguments native_args) { |
| 113 DART_CHECK_VALID(TestCase::TriggerReload()); |
| 114 } |
| 115 |
| 116 |
| 117 static Dart_NativeFunction IsolateReloadTestNativeResolver( |
| 118 Dart_Handle name, |
| 119 int num_of_arguments, |
| 120 bool* auto_setup_scope) { |
| 121 return ReloadTest; |
| 122 } |
| 123 #endif // !PRODUCT |
| 124 |
| 125 |
74 static Dart_Handle ResolvePackageUri(const char* uri_chars) { | 126 static Dart_Handle ResolvePackageUri(const char* uri_chars) { |
75 const int kNumArgs = 1; | 127 const int kNumArgs = 1; |
76 Dart_Handle dart_args[kNumArgs]; | 128 Dart_Handle dart_args[kNumArgs]; |
77 dart_args[0] = DartUtils::NewString(uri_chars); | 129 dart_args[0] = DartUtils::NewString(uri_chars); |
78 return Dart_Invoke(DartUtils::BuiltinLib(), | 130 return Dart_Invoke(DartUtils::BuiltinLib(), |
79 DartUtils::NewString("_filePathFromUri"), | 131 DartUtils::NewString("_filePathFromUri"), |
80 kNumArgs, | 132 kNumArgs, |
81 dart_args); | 133 dart_args); |
82 } | 134 } |
83 | 135 |
| 136 |
| 137 static ThreadLocalKey script_reload_key = kUnsetThreadLocalKey; |
| 138 |
84 static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, | 139 static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
85 Dart_Handle library, | 140 Dart_Handle library, |
86 Dart_Handle url) { | 141 Dart_Handle url) { |
| 142 if (tag == Dart_kScriptTag) { |
| 143 // Reload request. |
| 144 ASSERT(script_reload_key != kUnsetThreadLocalKey); |
| 145 const char* script_source = |
| 146 reinterpret_cast<const char*>( |
| 147 OSThread::GetThreadLocal(script_reload_key)); |
| 148 ASSERT(script_source != NULL); |
| 149 OSThread::SetThreadLocal(script_reload_key, NULL); |
| 150 return Dart_LoadScript(url, |
| 151 NewString(script_source), |
| 152 0, |
| 153 0); |
| 154 } |
87 if (!Dart_IsLibrary(library)) { | 155 if (!Dart_IsLibrary(library)) { |
88 return Dart_NewApiError("not a library"); | 156 return Dart_NewApiError("not a library"); |
89 } | 157 } |
90 if (!Dart_IsString(url)) { | 158 if (!Dart_IsString(url)) { |
91 return Dart_NewApiError("url is not a string"); | 159 return Dart_NewApiError("url is not a string"); |
92 } | 160 } |
93 const char* url_chars = NULL; | 161 const char* url_chars = NULL; |
94 Dart_Handle result = Dart_StringToCString(url, &url_chars); | 162 Dart_Handle result = Dart_StringToCString(url, &url_chars); |
95 if (Dart_IsError(result)) { | 163 if (Dart_IsError(result)) { |
96 return Dart_NewApiError("accessing url characters failed"); | 164 return Dart_NewApiError("accessing url characters failed"); |
97 } | 165 } |
98 Dart_Handle library_url = Dart_LibraryUrl(library); | 166 Dart_Handle library_url = Dart_LibraryUrl(library); |
99 const char* library_url_string = NULL; | 167 const char* library_url_string = NULL; |
100 result = Dart_StringToCString(library_url, &library_url_string); | 168 result = Dart_StringToCString(library_url, &library_url_string); |
101 if (Dart_IsError(result)) { | 169 if (Dart_IsError(result)) { |
102 return result; | 170 return result; |
103 } | 171 } |
104 | 172 |
105 bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_chars); | 173 bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_chars); |
106 bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string); | 174 bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string); |
107 if (tag == Dart_kCanonicalizeUrl) { | 175 if (tag == Dart_kCanonicalizeUrl) { |
| 176 // Already canonicalized. |
| 177 if (IsImportableTestLib(url_chars) || IsIsolateReloadTestLib(url_chars)) { |
| 178 return url; |
| 179 } |
108 // If this is a Dart Scheme URL then it is not modified as it will be | 180 // If this is a Dart Scheme URL then it is not modified as it will be |
109 // handled by the VM internally. | 181 // handled by the VM internally. |
110 if (is_dart_scheme_url || is_io_library) { | 182 if (is_dart_scheme_url || is_io_library) { |
111 return url; | 183 return url; |
112 } | 184 } |
113 | 185 |
114 Dart_Handle library_url = Dart_LibraryUrl(library); | 186 Dart_Handle library_url = Dart_LibraryUrl(library); |
115 if (Dart_IsError(library_url)) { | 187 if (Dart_IsError(library_url)) { |
116 return library_url; | 188 return library_url; |
117 } | 189 } |
118 return DartUtils::ResolveUri(library_url, url); | 190 return DartUtils::ResolveUri(library_url, url); |
119 } | 191 } |
120 if (is_dart_scheme_url) { | 192 if (is_dart_scheme_url) { |
121 ASSERT(tag == Dart_kImportTag); | 193 ASSERT(tag == Dart_kImportTag); |
122 // Handle imports of other built-in libraries present in the SDK. | 194 // Handle imports of other built-in libraries present in the SDK. |
123 if (DartUtils::IsDartIOLibURL(url_chars)) { | 195 if (DartUtils::IsDartIOLibURL(url_chars)) { |
124 return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary); | 196 return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary); |
125 } else if (DartUtils::IsDartBuiltinLibURL(url_chars)) { | 197 } else if (DartUtils::IsDartBuiltinLibURL(url_chars)) { |
126 return Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); | 198 return Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); |
127 } else { | 199 } else { |
128 return DartUtils::NewError("Do not know how to load '%s'", url_chars); | 200 return DartUtils::NewError("Do not know how to load '%s'", url_chars); |
129 } | 201 } |
130 } | 202 } |
| 203 if (IsImportableTestLib(url_chars)) { |
| 204 return Dart_LoadLibrary(url, ImportableTestLibSource(), 0, 0); |
| 205 } |
| 206 NOT_IN_PRODUCT( |
| 207 if (IsIsolateReloadTestLib(url_chars)) { |
| 208 Dart_Handle library = |
| 209 Dart_LoadLibrary(url, IsolateReloadTestLibSource(), 0, 0); |
| 210 DART_CHECK_VALID(library); |
| 211 Dart_SetNativeResolver(library, IsolateReloadTestNativeResolver, 0); |
| 212 return library; |
| 213 }) |
131 if (is_io_library) { | 214 if (is_io_library) { |
132 ASSERT(tag == Dart_kSourceTag); | 215 ASSERT(tag == Dart_kSourceTag); |
133 return Dart_LoadSource(library, | 216 return Dart_LoadSource(library, |
134 url, | 217 url, |
135 Builtin::PartSource(Builtin::kIOLibrary, | 218 Builtin::PartSource(Builtin::kIOLibrary, |
136 url_chars), | 219 url_chars), |
137 0, 0); | 220 0, 0); |
138 } | 221 } |
139 if (IsPackageSchemeURL(url_chars)) { | 222 if (IsPackageSchemeURL(url_chars)) { |
140 Dart_Handle resolved_uri = ResolvePackageUri(url_chars); | 223 Dart_Handle resolved_uri = ResolvePackageUri(url_chars); |
(...skipping 29 matching lines...) Expand all Loading... |
170 result = Dart_SetNativeResolver(lib, resolver, NULL); | 253 result = Dart_SetNativeResolver(lib, resolver, NULL); |
171 DART_CHECK_VALID(result); | 254 DART_CHECK_VALID(result); |
172 if (finalize_classes) { | 255 if (finalize_classes) { |
173 result = Dart_FinalizeLoading(false); | 256 result = Dart_FinalizeLoading(false); |
174 DART_CHECK_VALID(result); | 257 DART_CHECK_VALID(result); |
175 } | 258 } |
176 return lib; | 259 return lib; |
177 } | 260 } |
178 | 261 |
179 | 262 |
| 263 #ifndef PRODUCT |
| 264 |
| 265 |
| 266 void TestCase::SetReloadTestScript(const char* script) { |
| 267 if (script_reload_key == kUnsetThreadLocalKey) { |
| 268 script_reload_key = OSThread::CreateThreadLocal(); |
| 269 } |
| 270 ASSERT(script_reload_key != kUnsetThreadLocalKey); |
| 271 ASSERT(OSThread::GetThreadLocal(script_reload_key) == 0); |
| 272 // Store the new script in TLS. |
| 273 OSThread::SetThreadLocal(script_reload_key, reinterpret_cast<uword>(script)); |
| 274 } |
| 275 |
| 276 |
| 277 Dart_Handle TestCase::TriggerReload() { |
| 278 Isolate* isolate = Isolate::Current(); |
| 279 |
| 280 { |
| 281 TransitionNativeToVM transition(Thread::Current()); |
| 282 isolate->ReloadSources(/* test_mode = */ true); |
| 283 } |
| 284 |
| 285 return Dart_FinalizeLoading(false); |
| 286 } |
| 287 |
| 288 |
| 289 Dart_Handle TestCase::GetReloadErrorOrRootLibrary() { |
| 290 Isolate* isolate = Isolate::Current(); |
| 291 |
| 292 if (isolate->reload_context() != NULL) { |
| 293 // We should only have a reload context hanging around if an error occurred. |
| 294 ASSERT(isolate->reload_context()->has_error()); |
| 295 // Return a handle to the error. |
| 296 return Api::NewHandle(Thread::Current(), |
| 297 isolate->reload_context()->error()); |
| 298 } |
| 299 return Dart_RootLibrary(); |
| 300 } |
| 301 |
| 302 |
| 303 Dart_Handle TestCase::ReloadTestScript(const char* script) { |
| 304 SetReloadTestScript(script); |
| 305 |
| 306 Dart_Handle result = TriggerReload(); |
| 307 if (Dart_IsError(result)) { |
| 308 return result; |
| 309 } |
| 310 |
| 311 return GetReloadErrorOrRootLibrary(); |
| 312 } |
| 313 |
| 314 |
| 315 #endif // !PRODUCT |
| 316 |
| 317 |
180 Dart_Handle TestCase::LoadCoreTestScript(const char* script, | 318 Dart_Handle TestCase::LoadCoreTestScript(const char* script, |
181 Dart_NativeEntryResolver resolver) { | 319 Dart_NativeEntryResolver resolver) { |
182 return LoadTestScript(script, resolver, CORELIB_TEST_URI); | 320 return LoadTestScript(script, resolver, CORELIB_TEST_URI); |
183 } | 321 } |
184 | 322 |
185 | 323 |
186 Dart_Handle TestCase::lib() { | 324 Dart_Handle TestCase::lib() { |
187 Dart_Handle url = NewString(TestCase::url()); | 325 Dart_Handle url = NewString(TestCase::url()); |
188 Dart_Handle lib = Dart_LookupLibrary(url); | 326 Dart_Handle lib = Dart_LookupLibrary(url); |
189 DART_CHECK_VALID(lib); | 327 DART_CHECK_VALID(lib); |
(...skipping 22 matching lines...) Expand all Loading... |
212 Symbols::New(Thread::Current(), name_)); | 350 Symbols::New(Thread::Current(), name_)); |
213 | 351 |
214 // We make a dummy script so that exception objects can be composed for | 352 // We make a dummy script so that exception objects can be composed for |
215 // assembler instructions that do runtime calls, in particular on DBC. | 353 // assembler instructions that do runtime calls, in particular on DBC. |
216 const char* kDummyScript = "assembler_test_dummy_function() {}"; | 354 const char* kDummyScript = "assembler_test_dummy_function() {}"; |
217 const Script& script = Script::Handle(Script::New( | 355 const Script& script = Script::Handle(Script::New( |
218 function_name, | 356 function_name, |
219 String::Handle(String::New(kDummyScript)), | 357 String::Handle(String::New(kDummyScript)), |
220 RawScript::kSourceTag)); | 358 RawScript::kSourceTag)); |
221 script.Tokenize(String::Handle()); | 359 script.Tokenize(String::Handle()); |
222 | 360 const Library& lib = Library::Handle(Library::CoreLibrary()); |
223 const Class& cls = Class::ZoneHandle( | 361 const Class& cls = Class::ZoneHandle( |
224 Class::New(function_name, | 362 Class::New(lib, |
| 363 function_name, |
225 script, | 364 script, |
226 TokenPosition::kMinSource)); | 365 TokenPosition::kMinSource)); |
227 const Library& lib = Library::ZoneHandle(Library::New(function_name)); | |
228 cls.set_library(lib); | |
229 Function& function = Function::ZoneHandle( | 366 Function& function = Function::ZoneHandle( |
230 Function::New(function_name, RawFunction::kRegularFunction, | 367 Function::New(function_name, RawFunction::kRegularFunction, |
231 true, false, false, false, false, cls, | 368 true, false, false, false, false, cls, |
232 TokenPosition::kMinSource)); | 369 TokenPosition::kMinSource)); |
233 code_ = Code::FinalizeCode(function, assembler_); | 370 code_ = Code::FinalizeCode(function, assembler_); |
234 code_.set_owner(function); | 371 code_.set_owner(function); |
235 code_.set_exception_handlers(Object::empty_exception_handlers()); | 372 code_.set_exception_handlers(Object::empty_exception_handlers()); |
236 if (FLAG_disassemble) { | 373 if (FLAG_disassemble) { |
237 OS::Print("Code for test '%s' {\n", name_); | 374 OS::Print("Code for test '%s' {\n", name_); |
238 const Instructions& instructions = | 375 const Instructions& instructions = |
239 Instructions::Handle(code_.instructions()); | 376 Instructions::Handle(code_.instructions()); |
240 uword start = instructions.EntryPoint(); | 377 uword start = instructions.EntryPoint(); |
241 Disassembler::Disassemble(start, start + assembler_->CodeSize()); | 378 Disassembler::Disassemble(start, start + assembler_->CodeSize()); |
242 OS::Print("}\n"); | 379 OS::Print("}\n"); |
243 } | 380 } |
244 } | 381 } |
245 | 382 |
246 | 383 |
247 CodeGenTest::CodeGenTest(const char* name) | 384 CodeGenTest::CodeGenTest(const char* name) |
248 : function_(Function::ZoneHandle()), | 385 : function_(Function::ZoneHandle()), |
249 node_sequence_(new SequenceNode(TokenPosition::kMinSource, | 386 node_sequence_(new SequenceNode(TokenPosition::kMinSource, |
250 new LocalScope(NULL, 0, 0))), | 387 new LocalScope(NULL, 0, 0))), |
251 default_parameter_values_(new ZoneGrowableArray<const Instance*> ()) { | 388 default_parameter_values_(new ZoneGrowableArray<const Instance*> ()) { |
252 ASSERT(name != NULL); | 389 ASSERT(name != NULL); |
253 const String& function_name = String::ZoneHandle( | 390 const String& function_name = String::ZoneHandle( |
254 Symbols::New(Thread::Current(), name)); | 391 Symbols::New(Thread::Current(), name)); |
255 // Add function to a class and that class to the class dictionary so that | 392 // Add function to a class and that class to the class dictionary so that |
256 // frame walking can be used. | 393 // frame walking can be used. |
| 394 Library& lib = Library::Handle(Library::CoreLibrary()); |
257 const Class& cls = Class::ZoneHandle( | 395 const Class& cls = Class::ZoneHandle( |
258 Class::New(function_name, Script::Handle(), | 396 Class::New(lib, function_name, Script::Handle(), |
259 TokenPosition::kMinSource)); | 397 TokenPosition::kMinSource)); |
260 function_ = Function::New( | 398 function_ = Function::New( |
261 function_name, RawFunction::kRegularFunction, | 399 function_name, RawFunction::kRegularFunction, |
262 true, false, false, false, false, cls, TokenPosition::kMinSource); | 400 true, false, false, false, false, cls, TokenPosition::kMinSource); |
263 function_.set_result_type(Type::Handle(Type::DynamicType())); | 401 function_.set_result_type(Type::Handle(Type::DynamicType())); |
264 const Array& functions = Array::Handle(Array::New(1)); | 402 const Array& functions = Array::Handle(Array::New(1)); |
265 functions.SetAt(0, function_); | 403 functions.SetAt(0, function_); |
266 cls.SetFunctions(functions); | 404 cls.SetFunctions(functions); |
267 Library& lib = Library::Handle(Library::CoreLibrary()); | |
268 lib.AddClass(cls); | 405 lib.AddClass(cls); |
269 } | 406 } |
270 | 407 |
271 | 408 |
272 void CodeGenTest::Compile() { | 409 void CodeGenTest::Compile() { |
273 if (function_.HasCode()) return; | 410 if (function_.HasCode()) return; |
274 ParsedFunction* parsed_function = | 411 ParsedFunction* parsed_function = |
275 new ParsedFunction(Thread::Current(), function_); | 412 new ParsedFunction(Thread::Current(), function_); |
276 parsed_function->SetNodeSequence(node_sequence_); | 413 parsed_function->SetNodeSequence(node_sequence_); |
277 parsed_function->set_instantiator(NULL); | 414 parsed_function->set_instantiator(NULL); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 } | 461 } |
325 // Copy the remainder of in to out. | 462 // Copy the remainder of in to out. |
326 while (*in != '\0') { | 463 while (*in != '\0') { |
327 *out++ = *in++; | 464 *out++ = *in++; |
328 } | 465 } |
329 *out = '\0'; | 466 *out = '\0'; |
330 } | 467 } |
331 | 468 |
332 | 469 |
333 } // namespace dart | 470 } // namespace dart |
OLD | NEW |