| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include <stdio.h> |
| |
| #include "vm/unit_test.h" |
| |
| #include "bin/builtin.h" |
| #include "bin/dartutils.h" |
| |
| #include "vm/assembler.h" |
| #include "vm/ast_printer.h" |
| #include "vm/compiler.h" |
| #include "vm/dart_api_impl.h" |
| #include "vm/disassembler.h" |
| #include "vm/parser.h" |
| #include "vm/symbols.h" |
| #include "vm/virtual_memory.h" |
| |
| using dart::bin::Builtin; |
| using dart::bin::DartUtils; |
| |
| namespace dart { |
| |
| DECLARE_FLAG(bool, disassemble); |
| |
| |
| TestCaseBase* TestCaseBase::first_ = NULL; |
| TestCaseBase* TestCaseBase::tail_ = NULL; |
| |
| |
| TestCaseBase::TestCaseBase(const char* name) : next_(NULL), name_(name) { |
| if (first_ == NULL) { |
| first_ = this; |
| } else { |
| tail_->next_ = this; |
| } |
| tail_ = this; |
| } |
| |
| |
| void TestCaseBase::RunAll() { |
| TestCaseBase* test = first_; |
| while (test != NULL) { |
| test->RunTest(); |
| test = test->next_; |
| } |
| } |
| |
| |
| static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url) { |
| if (!Dart_IsLibrary(library)) { |
| return Dart_Error("not a library"); |
| } |
| if (!Dart_IsString(url)) { |
| return Dart_Error("url is not a string"); |
| } |
| const char* url_chars = NULL; |
| Dart_Handle result = Dart_StringToCString(url, &url_chars); |
| if (Dart_IsError(result)) { |
| return Dart_Error("accessing url characters failed"); |
| } |
| bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_chars); |
| if (tag == kCanonicalizeUrl) { |
| // If this is a Dart Scheme URL then it is not modified as it will be |
| // handled by the VM internally. |
| if (is_dart_scheme_url) { |
| return url; |
| } |
| Dart_Handle builtin_lib = |
| Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); |
| DART_CHECK_VALID(builtin_lib); |
| return DartUtils::CanonicalizeURL(NULL, library, url_chars); |
| } |
| if (is_dart_scheme_url) { |
| ASSERT(tag == kImportTag); |
| // Handle imports of other built-in libraries present in the SDK. |
| if (DartUtils::IsDartIOLibURL(url_chars)) { |
| return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary); |
| } else if (DartUtils::IsDartBuiltinLibURL(url_chars)) { |
| return Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); |
| } else { |
| return Dart_Error("Do not know how to load '%s'", url_chars); |
| } |
| } |
| return DartUtils::LoadSource(NULL, |
| library, |
| url, |
| tag, |
| url_chars); |
| } |
| |
| |
| Dart_Handle TestCase::LoadTestScript(const char* script, |
| Dart_NativeEntryResolver resolver) { |
| Dart_Handle url = NewString(TestCase::url()); |
| Dart_Handle source = NewString(script); |
| Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); |
| EXPECT_VALID(result); |
| EXPECT_VALID(result); |
| Dart_Handle lib = Dart_LoadScript(url, source, 0, 0); |
| DART_CHECK_VALID(lib); |
| result = Dart_SetNativeResolver(lib, resolver); |
| DART_CHECK_VALID(result); |
| return lib; |
| } |
| |
| |
| Dart_Handle TestCase::lib() { |
| Dart_Handle url = NewString(TestCase::url()); |
| Dart_Handle lib = Dart_LookupLibrary(url); |
| DART_CHECK_VALID(lib); |
| ASSERT(Dart_IsLibrary(lib)); |
| return lib; |
| } |
| |
| |
| Dart_Handle TestCase::library_handler(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url) { |
| if (tag == kCanonicalizeUrl) { |
| return url; |
| } |
| return Api::Success(Isolate::Current()); |
| } |
| |
| |
| void AssemblerTest::Assemble() { |
| const String& function_name = String::ZoneHandle(Symbols::New(name_)); |
| const Class& cls = Class::ZoneHandle( |
| Class::New(function_name, Script::Handle(), Scanner::kDummyTokenIndex)); |
| Function& function = Function::ZoneHandle( |
| Function::New(function_name, RawFunction::kRegularFunction, |
| true, false, false, false, cls, 0)); |
| code_ = Code::FinalizeCode(function, assembler_); |
| if (FLAG_disassemble) { |
| OS::Print("Code for test '%s' {\n", name_); |
| const Instructions& instructions = |
| Instructions::Handle(code_.instructions()); |
| uword start = instructions.EntryPoint(); |
| Disassembler::Disassemble(start, start + assembler_->CodeSize()); |
| OS::Print("}\n"); |
| } |
| const Instructions& instructions = Instructions::Handle(code_.instructions()); |
| entry_ = instructions.EntryPoint(); |
| } |
| |
| |
| CodeGenTest::CodeGenTest(const char* name) |
| : function_(Function::ZoneHandle()), |
| node_sequence_(new SequenceNode(Scanner::kDummyTokenIndex, |
| new LocalScope(NULL, 0, 0))), |
| default_parameter_values_(Array::ZoneHandle()) { |
| ASSERT(name != NULL); |
| const String& function_name = String::ZoneHandle(Symbols::New(name)); |
| // Add function to a class and that class to the class dictionary so that |
| // frame walking can be used. |
| const Class& cls = Class::ZoneHandle( |
| Class::New(function_name, Script::Handle(), Scanner::kDummyTokenIndex)); |
| function_ = Function::New( |
| function_name, RawFunction::kRegularFunction, |
| true, false, false, false, cls, 0); |
| function_.set_result_type(Type::Handle(Type::DynamicType())); |
| const Array& functions = Array::Handle(Array::New(1)); |
| functions.SetAt(0, function_); |
| cls.SetFunctions(functions); |
| Library& lib = Library::Handle(Library::CoreLibrary()); |
| lib.AddClass(cls); |
| } |
| |
| |
| void CodeGenTest::Compile() { |
| ParsedFunction* parsed_function = new ParsedFunction(function_); |
| parsed_function->SetNodeSequence(node_sequence_); |
| parsed_function->set_instantiator(NULL); |
| parsed_function->set_default_parameter_values(default_parameter_values_); |
| parsed_function->set_expression_temp_var( |
| ParsedFunction::CreateExpressionTempVar(0)); |
| node_sequence_->scope()->AddVariable(parsed_function->expression_temp_var()); |
| parsed_function->AllocateVariables(); |
| const Error& error = |
| Error::Handle(Compiler::CompileParsedFunction(*parsed_function)); |
| EXPECT(error.IsNull()); |
| } |
| |
| |
| LocalVariable* CodeGenTest::CreateTempConstVariable(const char* name_part) { |
| char name[64]; |
| OS::SNPrint(name, 64, ":%s", name_part); |
| LocalVariable* temp = |
| new LocalVariable(0, |
| String::ZoneHandle(Symbols::New(name)), |
| Type::ZoneHandle(Type::DynamicType())); |
| temp->set_is_final(); |
| node_sequence_->scope()->AddVariable(temp); |
| return temp; |
| } |
| |
| |
| bool CompilerTest::TestCompileScript(const Library& library, |
| const Script& script) { |
| Isolate* isolate = Isolate::Current(); |
| ASSERT(isolate != NULL); |
| const Error& error = Error::Handle(Compiler::Compile(library, script)); |
| return error.IsNull(); |
| } |
| |
| |
| bool CompilerTest::TestCompileFunction(const Function& function) { |
| Isolate* isolate = Isolate::Current(); |
| ASSERT(isolate != NULL); |
| ASSERT(ClassFinalizer::AllClassesFinalized()); |
| const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| return error.IsNull(); |
| } |
| |
| } // namespace dart |