| 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 "platform/assert.h" | 5 #include "platform/assert.h" |
| 6 #include "vm/class_finalizer.h" | 6 #include "vm/class_finalizer.h" |
| 7 #include "vm/code_patcher.h" | 7 #include "vm/code_patcher.h" |
| 8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/safepoint.h" | 11 #include "vm/safepoint.h" |
| 12 #include "vm/symbols.h" | 12 #include "vm/symbols.h" |
| 13 #include "vm/thread_pool.h" | 13 #include "vm/thread_pool.h" |
| 14 #include "vm/unit_test.h" | 14 #include "vm/unit_test.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 VM_TEST_CASE(CompileScript) { | 18 VM_TEST_CASE(CompileScript) { |
| 19 const char* kScriptChars = | 19 const char* kScriptChars = |
| 20 "class A {\n" | 20 "class A {\n" |
| 21 " static foo() { return 42; }\n" | 21 " static foo() { return 42; }\n" |
| 22 "}\n"; | 22 "}\n"; |
| 23 String& url = String::Handle(String::New("dart-test:CompileScript")); | 23 String& url = String::Handle(String::New("dart-test:CompileScript")); |
| 24 String& source = String::Handle(String::New(kScriptChars)); | 24 String& source = String::Handle(String::New(kScriptChars)); |
| 25 Script& script = Script::Handle(Script::New(url, | 25 Script& script = |
| 26 source, | 26 Script::Handle(Script::New(url, source, RawScript::kScriptTag)); |
| 27 RawScript::kScriptTag)); | |
| 28 Library& lib = Library::Handle(Library::CoreLibrary()); | 27 Library& lib = Library::Handle(Library::CoreLibrary()); |
| 29 EXPECT(CompilerTest::TestCompileScript(lib, script)); | 28 EXPECT(CompilerTest::TestCompileScript(lib, script)); |
| 30 } | 29 } |
| 31 | 30 |
| 32 | 31 |
| 33 VM_TEST_CASE(CompileFunction) { | 32 VM_TEST_CASE(CompileFunction) { |
| 34 const char* kScriptChars = | 33 const char* kScriptChars = |
| 35 "class A {\n" | 34 "class A {\n" |
| 36 " static foo() { return 42; }\n" | 35 " static foo() { return 42; }\n" |
| 37 " static moo() {\n" | 36 " static moo() {\n" |
| 38 " // A.foo();\n" | 37 " // A.foo();\n" |
| 39 " }\n" | 38 " }\n" |
| 40 "}\n"; | 39 "}\n"; |
| 41 String& url = String::Handle(String::New("dart-test:CompileFunction")); | 40 String& url = String::Handle(String::New("dart-test:CompileFunction")); |
| 42 String& source = String::Handle(String::New(kScriptChars)); | 41 String& source = String::Handle(String::New(kScriptChars)); |
| 43 Script& script = Script::Handle(Script::New(url, | 42 Script& script = |
| 44 source, | 43 Script::Handle(Script::New(url, source, RawScript::kScriptTag)); |
| 45 RawScript::kScriptTag)); | |
| 46 Library& lib = Library::Handle(Library::CoreLibrary()); | 44 Library& lib = Library::Handle(Library::CoreLibrary()); |
| 47 EXPECT(CompilerTest::TestCompileScript(lib, script)); | 45 EXPECT(CompilerTest::TestCompileScript(lib, script)); |
| 48 EXPECT(ClassFinalizer::ProcessPendingClasses()); | 46 EXPECT(ClassFinalizer::ProcessPendingClasses()); |
| 49 Class& cls = Class::Handle( | 47 Class& cls = |
| 50 lib.LookupClass(String::Handle(Symbols::New(thread, "A")))); | 48 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A")))); |
| 51 EXPECT(!cls.IsNull()); | 49 EXPECT(!cls.IsNull()); |
| 52 String& function_foo_name = String::Handle(String::New("foo")); | 50 String& function_foo_name = String::Handle(String::New("foo")); |
| 53 Function& function_foo = | 51 Function& function_foo = |
| 54 Function::Handle(cls.LookupStaticFunction(function_foo_name)); | 52 Function::Handle(cls.LookupStaticFunction(function_foo_name)); |
| 55 EXPECT(!function_foo.IsNull()); | 53 EXPECT(!function_foo.IsNull()); |
| 56 String& function_source = String::Handle(function_foo.GetSource()); | 54 String& function_source = String::Handle(function_foo.GetSource()); |
| 57 EXPECT_STREQ("static foo() { return 42; }", function_source.ToCString()); | 55 EXPECT_STREQ("static foo() { return 42; }", function_source.ToCString()); |
| 58 EXPECT(CompilerTest::TestCompileFunction(function_foo)); | 56 EXPECT(CompilerTest::TestCompileFunction(function_foo)); |
| 59 EXPECT(function_foo.HasCode()); | 57 EXPECT(function_foo.HasCode()); |
| 60 | 58 |
| 61 String& function_moo_name = String::Handle(String::New("moo")); | 59 String& function_moo_name = String::Handle(String::New("moo")); |
| 62 Function& function_moo = | 60 Function& function_moo = |
| 63 Function::Handle(cls.LookupStaticFunction(function_moo_name)); | 61 Function::Handle(cls.LookupStaticFunction(function_moo_name)); |
| 64 EXPECT(!function_moo.IsNull()); | 62 EXPECT(!function_moo.IsNull()); |
| 65 | 63 |
| 66 EXPECT(CompilerTest::TestCompileFunction(function_moo)); | 64 EXPECT(CompilerTest::TestCompileFunction(function_moo)); |
| 67 EXPECT(function_moo.HasCode()); | 65 EXPECT(function_moo.HasCode()); |
| 68 function_source = function_moo.GetSource(); | 66 function_source = function_moo.GetSource(); |
| 69 EXPECT_STREQ("static moo() {\n // A.foo();\n }", | 67 EXPECT_STREQ("static moo() {\n // A.foo();\n }", |
| 70 function_source.ToCString()); | 68 function_source.ToCString()); |
| 71 } | 69 } |
| 72 | 70 |
| 73 | 71 |
| 74 VM_TEST_CASE(CompileFunctionOnHelperThread) { | 72 VM_TEST_CASE(CompileFunctionOnHelperThread) { |
| 75 // Create a simple function and compile it without optimization. | 73 // Create a simple function and compile it without optimization. |
| 76 const char* kScriptChars = | 74 const char* kScriptChars = |
| 77 "class A {\n" | 75 "class A {\n" |
| 78 " static foo() { return 42; }\n" | 76 " static foo() { return 42; }\n" |
| 79 "}\n"; | 77 "}\n"; |
| 80 String& url = | 78 String& url = |
| 81 String::Handle(String::New("dart-test:CompileFunctionOnHelperThread")); | 79 String::Handle(String::New("dart-test:CompileFunctionOnHelperThread")); |
| 82 String& source = String::Handle(String::New(kScriptChars)); | 80 String& source = String::Handle(String::New(kScriptChars)); |
| 83 Script& script = Script::Handle(Script::New(url, | 81 Script& script = |
| 84 source, | 82 Script::Handle(Script::New(url, source, RawScript::kScriptTag)); |
| 85 RawScript::kScriptTag)); | |
| 86 Library& lib = Library::Handle(Library::CoreLibrary()); | 83 Library& lib = Library::Handle(Library::CoreLibrary()); |
| 87 EXPECT(CompilerTest::TestCompileScript(lib, script)); | 84 EXPECT(CompilerTest::TestCompileScript(lib, script)); |
| 88 EXPECT(ClassFinalizer::ProcessPendingClasses()); | 85 EXPECT(ClassFinalizer::ProcessPendingClasses()); |
| 89 Class& cls = Class::Handle( | 86 Class& cls = |
| 90 lib.LookupClass(String::Handle(Symbols::New(thread, "A")))); | 87 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A")))); |
| 91 EXPECT(!cls.IsNull()); | 88 EXPECT(!cls.IsNull()); |
| 92 String& function_foo_name = String::Handle(String::New("foo")); | 89 String& function_foo_name = String::Handle(String::New("foo")); |
| 93 Function& func = | 90 Function& func = |
| 94 Function::Handle(cls.LookupStaticFunction(function_foo_name)); | 91 Function::Handle(cls.LookupStaticFunction(function_foo_name)); |
| 95 EXPECT(!func.HasCode()); | 92 EXPECT(!func.HasCode()); |
| 96 CompilerTest::TestCompileFunction(func); | 93 CompilerTest::TestCompileFunction(func); |
| 97 EXPECT(func.HasCode()); | 94 EXPECT(func.HasCode()); |
| 98 EXPECT(!func.HasOptimizedCode()); | 95 EXPECT(!func.HasOptimizedCode()); |
| 99 #if !defined(PRODUCT) | 96 #if !defined(PRODUCT) |
| 100 // Constant in product mode. | 97 // Constant in product mode. |
| 101 FLAG_background_compilation = true; | 98 FLAG_background_compilation = true; |
| 102 #endif | 99 #endif |
| 103 BackgroundCompiler::EnsureInit(thread); | 100 BackgroundCompiler::EnsureInit(thread); |
| 104 Isolate* isolate = thread->isolate(); | 101 Isolate* isolate = thread->isolate(); |
| 105 ASSERT(isolate->background_compiler() != NULL); | 102 ASSERT(isolate->background_compiler() != NULL); |
| 106 isolate->background_compiler()->CompileOptimized(func); | 103 isolate->background_compiler()->CompileOptimized(func); |
| 107 Monitor* m = new Monitor(); | 104 Monitor* m = new Monitor(); |
| 108 MonitorLocker ml(m); | 105 MonitorLocker ml(m); |
| 109 while (!func.HasOptimizedCode()) { | 106 while (!func.HasOptimizedCode()) { |
| 110 ml.WaitWithSafepointCheck(thread, 1); | 107 ml.WaitWithSafepointCheck(thread, 1); |
| 111 } | 108 } |
| 112 BackgroundCompiler::Stop(isolate); | 109 BackgroundCompiler::Stop(isolate); |
| 113 } | 110 } |
| 114 | 111 |
| 115 | 112 |
| 116 TEST_CASE(RegenerateAllocStubs) { | 113 TEST_CASE(RegenerateAllocStubs) { |
| 117 const char* kScriptChars = | 114 const char* kScriptChars = |
| 118 "class A {\n" | 115 "class A {\n" |
| 119 "}\n" | 116 "}\n" |
| 120 "unOpt() => new A(); \n" | 117 "unOpt() => new A(); \n" |
| 121 "optIt() => new A(); \n" | 118 "optIt() => new A(); \n" |
| 122 "A main() {\n" | 119 "A main() {\n" |
| 123 " return unOpt();\n" | 120 " return unOpt();\n" |
| 124 "}\n"; | 121 "}\n"; |
| 125 | 122 |
| 126 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 123 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 127 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 124 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 128 EXPECT_VALID(result); | 125 EXPECT_VALID(result); |
| 129 RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib)); | 126 RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib)); |
| 130 Library& lib_handle = Library::ZoneHandle(raw_library); | 127 Library& lib_handle = Library::ZoneHandle(raw_library); |
| 131 Class& cls = Class::Handle( | 128 Class& cls = Class::Handle( |
| 132 lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A")))); | 129 lib_handle.LookupClass(String::Handle(Symbols::New(thread, "A")))); |
| 133 EXPECT(!cls.IsNull()); | 130 EXPECT(!cls.IsNull()); |
| 134 | 131 |
| 135 Zone* zone = thread->zone(); | 132 Zone* zone = thread->zone(); |
| 136 const Code& stub = Code::Handle(zone, | 133 const Code& stub = |
| 137 StubCode::GetAllocationStubForClass(cls)); | 134 Code::Handle(zone, StubCode::GetAllocationStubForClass(cls)); |
| 138 Class& owner = Class::Handle(); | 135 Class& owner = Class::Handle(); |
| 139 owner ^= stub.owner(); | 136 owner ^= stub.owner(); |
| 140 owner.DisableAllocationStub(); | 137 owner.DisableAllocationStub(); |
| 141 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 138 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 142 EXPECT_VALID(result); | 139 EXPECT_VALID(result); |
| 143 | 140 |
| 144 owner.DisableAllocationStub(); | 141 owner.DisableAllocationStub(); |
| 145 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 142 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 146 EXPECT_VALID(result); | 143 EXPECT_VALID(result); |
| 147 | 144 |
| 148 owner.DisableAllocationStub(); | 145 owner.DisableAllocationStub(); |
| 149 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 146 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 150 EXPECT_VALID(result); | 147 EXPECT_VALID(result); |
| 151 } | 148 } |
| 152 | 149 |
| 153 | 150 |
| 154 TEST_CASE(EvalExpression) { | 151 TEST_CASE(EvalExpression) { |
| 155 const char* kScriptChars = | 152 const char* kScriptChars = |
| 156 "int ten = 2 * 5; \n" | 153 "int ten = 2 * 5; \n" |
| 157 "get dot => '.'; \n" | 154 "get dot => '.'; \n" |
| 158 "class A { \n" | 155 "class A { \n" |
| 159 " var apa = 'Herr Nilsson'; \n" | 156 " var apa = 'Herr Nilsson'; \n" |
| 160 " calc(x) => '${x*ten}'; \n" | 157 " calc(x) => '${x*ten}'; \n" |
| 161 "} \n" | 158 "} \n" |
| 162 "makeObj() => new A(); \n"; | 159 "makeObj() => new A(); \n"; |
| 163 | 160 |
| 164 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 161 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
| 165 Dart_Handle obj_handle = | 162 Dart_Handle obj_handle = |
| 166 Dart_Invoke(lib, Dart_NewStringFromCString("makeObj"), 0, NULL); | 163 Dart_Invoke(lib, Dart_NewStringFromCString("makeObj"), 0, NULL); |
| 167 EXPECT(!Dart_IsNull(obj_handle)); | 164 EXPECT(!Dart_IsNull(obj_handle)); |
| 168 EXPECT(!Dart_IsError(obj_handle)); | 165 EXPECT(!Dart_IsError(obj_handle)); |
| 169 TransitionNativeToVM transition(thread); | 166 TransitionNativeToVM transition(thread); |
| 170 const Object& obj = Object::Handle(Api::UnwrapHandle(obj_handle)); | 167 const Object& obj = Object::Handle(Api::UnwrapHandle(obj_handle)); |
| 171 EXPECT(!obj.IsNull()); | 168 EXPECT(!obj.IsNull()); |
| 172 EXPECT(obj.IsInstance()); | 169 EXPECT(obj.IsInstance()); |
| 173 | 170 |
| 174 String& expr_text = String::Handle(); | 171 String& expr_text = String::Handle(); |
| 175 expr_text = String::New("apa + ' ${calc(10)}' + dot"); | 172 expr_text = String::New("apa + ' ${calc(10)}' + dot"); |
| 176 Object& val = Object::Handle(); | 173 Object& val = Object::Handle(); |
| 177 const Class& receiver_cls = Class::Handle(obj.clazz()); | 174 const Class& receiver_cls = Class::Handle(obj.clazz()); |
| 178 val = Instance::Cast(obj).Evaluate(receiver_cls, | 175 val = Instance::Cast(obj).Evaluate( |
| 179 expr_text, | 176 receiver_cls, expr_text, Array::empty_array(), Array::empty_array()); |
| 180 Array::empty_array(), | |
| 181 Array::empty_array()); | |
| 182 EXPECT(!val.IsNull()); | 177 EXPECT(!val.IsNull()); |
| 183 EXPECT(!val.IsError()); | 178 EXPECT(!val.IsError()); |
| 184 EXPECT(val.IsString()); | 179 EXPECT(val.IsString()); |
| 185 EXPECT_STREQ("Herr Nilsson 100.", val.ToCString()); | 180 EXPECT_STREQ("Herr Nilsson 100.", val.ToCString()); |
| 186 } | 181 } |
| 187 | 182 |
| 188 | 183 |
| 189 VM_TEST_CASE(EvalExpressionWithLazyCompile) { | 184 VM_TEST_CASE(EvalExpressionWithLazyCompile) { |
| 190 Library& lib = Library::Handle(Library::CoreLibrary()); | 185 Library& lib = Library::Handle(Library::CoreLibrary()); |
| 191 | 186 |
| 192 const String& expression = String::Handle(String::New( | 187 const String& expression = String::Handle( |
| 193 "(){ return (){ return (){ return 3 + 4; }(); }(); }()")); | 188 String::New("(){ return (){ return (){ return 3 + 4; }(); }(); }()")); |
| 194 Object& val = Object::Handle(); | 189 Object& val = Object::Handle(); |
| 195 val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array()); | 190 val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array()); |
| 196 | 191 |
| 197 EXPECT(!val.IsNull()); | 192 EXPECT(!val.IsNull()); |
| 198 EXPECT(!val.IsError()); | 193 EXPECT(!val.IsError()); |
| 199 EXPECT(val.IsInteger()); | 194 EXPECT(val.IsInteger()); |
| 200 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value()); | 195 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value()); |
| 201 } | 196 } |
| 202 | 197 |
| 203 | 198 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 223 EXPECT(val.IsInteger()); | 218 EXPECT(val.IsInteger()); |
| 224 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value()); | 219 EXPECT_EQ(7, Integer::Cast(val).AsInt64Value()); |
| 225 | 220 |
| 226 intptr_t final_class_table_size = | 221 intptr_t final_class_table_size = |
| 227 Isolate::Current()->class_table()->NumCids(); | 222 Isolate::Current()->class_table()->NumCids(); |
| 228 // Eval should not eat into this non-renewable resource. | 223 // Eval should not eat into this non-renewable resource. |
| 229 EXPECT_EQ(initial_class_table_size, final_class_table_size); | 224 EXPECT_EQ(initial_class_table_size, final_class_table_size); |
| 230 } | 225 } |
| 231 | 226 |
| 232 } // namespace dart | 227 } // namespace dart |
| OLD | NEW |