| 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 |