OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "include/v8.h" | 7 #include "include/v8.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
11 #include "src/base/platform/semaphore.h" | 11 #include "src/base/platform/semaphore.h" |
12 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" | 12 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
| 13 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" |
13 #include "src/flags.h" | 14 #include "src/flags.h" |
14 #include "src/isolate-inl.h" | 15 #include "src/isolate-inl.h" |
15 #include "src/parsing/parse-info.h" | 16 #include "src/parsing/parse-info.h" |
16 #include "src/v8.h" | 17 #include "src/v8.h" |
| 18 #include "test/unittests/compiler-dispatcher/compiler-dispatcher-helper.h" |
17 #include "test/unittests/test-utils.h" | 19 #include "test/unittests/test-utils.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
19 | 21 |
20 namespace v8 { | 22 namespace v8 { |
21 namespace internal { | 23 namespace internal { |
22 | 24 |
23 typedef TestWithContext CompilerDispatcherJobTest; | 25 class CompilerDispatcherJobTest : public TestWithContext { |
| 26 public: |
| 27 CompilerDispatcherJobTest() : tracer_(i_isolate()) {} |
| 28 ~CompilerDispatcherJobTest() override {} |
24 | 29 |
25 class IgnitionCompilerDispatcherJobTest : public TestWithContext { | 30 CompilerDispatcherTracer* tracer() { return &tracer_; } |
| 31 |
| 32 private: |
| 33 CompilerDispatcherTracer tracer_; |
| 34 |
| 35 DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherJobTest); |
| 36 }; |
| 37 |
| 38 class IgnitionCompilerDispatcherJobTest : public CompilerDispatcherJobTest { |
26 public: | 39 public: |
27 IgnitionCompilerDispatcherJobTest() {} | 40 IgnitionCompilerDispatcherJobTest() {} |
28 ~IgnitionCompilerDispatcherJobTest() override {} | 41 ~IgnitionCompilerDispatcherJobTest() override {} |
29 | 42 |
30 static void SetUpTestCase() { | 43 static void SetUpTestCase() { |
31 old_flag_ = i::FLAG_ignition; | 44 old_flag_ = i::FLAG_ignition; |
32 i::FLAG_ignition = true; | 45 i::FLAG_ignition = true; |
33 i::FLAG_never_compact = true; | 46 i::FLAG_never_compact = true; |
34 TestWithContext::SetUpTestCase(); | 47 TestWithContext::SetUpTestCase(); |
35 } | 48 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( | 96 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( |
84 isolate->factory()->NewStringFromAsciiChecked("f"), | 97 isolate->factory()->NewStringFromAsciiChecked("f"), |
85 isolate->builtins()->CompileLazy(), false); | 98 isolate->builtins()->CompileLazy(), false); |
86 shared->set_end_position(source->length()); | 99 shared->set_end_position(source->length()); |
87 shared->set_outer_scope_info(ScopeInfo::Empty(isolate)); | 100 shared->set_outer_scope_info(ScopeInfo::Empty(isolate)); |
88 shared->set_function_literal_id(1); | 101 shared->set_function_literal_id(1); |
89 SharedFunctionInfo::SetScript(shared, script); | 102 SharedFunctionInfo::SetScript(shared, script); |
90 return scope.CloseAndEscape(shared); | 103 return scope.CloseAndEscape(shared); |
91 } | 104 } |
92 | 105 |
93 Handle<Object> RunJS(v8::Isolate* isolate, const char* script) { | |
94 return Utils::OpenHandle( | |
95 *v8::Script::Compile( | |
96 isolate->GetCurrentContext(), | |
97 v8::String::NewFromUtf8(isolate, script, v8::NewStringType::kNormal) | |
98 .ToLocalChecked()) | |
99 .ToLocalChecked() | |
100 ->Run(isolate->GetCurrentContext()) | |
101 .ToLocalChecked()); | |
102 } | |
103 | |
104 } // namespace | 106 } // namespace |
105 | 107 |
106 TEST_F(CompilerDispatcherJobTest, Construct) { | 108 TEST_F(CompilerDispatcherJobTest, Construct) { |
107 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 109 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
108 i_isolate(), CreateSharedFunctionInfo(i_isolate(), nullptr), | 110 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), nullptr), |
109 FLAG_stack_size)); | 111 FLAG_stack_size)); |
110 } | 112 } |
111 | 113 |
112 TEST_F(CompilerDispatcherJobTest, CanParseOnBackgroundThread) { | 114 TEST_F(CompilerDispatcherJobTest, CanParseOnBackgroundThread) { |
113 { | 115 { |
114 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 116 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
115 i_isolate(), CreateSharedFunctionInfo(i_isolate(), nullptr), | 117 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), nullptr), |
116 FLAG_stack_size)); | 118 FLAG_stack_size)); |
117 ASSERT_FALSE(job->can_parse_on_background_thread()); | 119 ASSERT_FALSE(job->can_parse_on_background_thread()); |
118 } | 120 } |
119 { | 121 { |
120 ScriptResource script(test_script, strlen(test_script)); | 122 ScriptResource script(test_script, strlen(test_script)); |
121 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 123 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
122 i_isolate(), CreateSharedFunctionInfo(i_isolate(), &script), | 124 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), |
123 FLAG_stack_size)); | 125 FLAG_stack_size)); |
124 ASSERT_TRUE(job->can_parse_on_background_thread()); | 126 ASSERT_TRUE(job->can_parse_on_background_thread()); |
125 } | 127 } |
126 } | 128 } |
127 | 129 |
128 TEST_F(CompilerDispatcherJobTest, StateTransitions) { | 130 TEST_F(CompilerDispatcherJobTest, StateTransitions) { |
129 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 131 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
130 i_isolate(), CreateSharedFunctionInfo(i_isolate(), nullptr), | 132 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), nullptr), |
131 FLAG_stack_size)); | 133 FLAG_stack_size)); |
132 | 134 |
133 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 135 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
134 job->PrepareToParseOnMainThread(); | 136 job->PrepareToParseOnMainThread(); |
135 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse); | 137 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse); |
136 job->Parse(); | 138 job->Parse(); |
137 ASSERT_TRUE(job->status() == CompileJobStatus::kParsed); | 139 ASSERT_TRUE(job->status() == CompileJobStatus::kParsed); |
138 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); | 140 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); |
139 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyse); | 141 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyse); |
140 ASSERT_TRUE(job->PrepareToCompileOnMainThread()); | 142 ASSERT_TRUE(job->PrepareToCompileOnMainThread()); |
141 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); | 143 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); |
142 job->Compile(); | 144 job->Compile(); |
143 ASSERT_TRUE(job->status() == CompileJobStatus::kCompiled); | 145 ASSERT_TRUE(job->status() == CompileJobStatus::kCompiled); |
144 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); | 146 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); |
145 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); | 147 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); |
146 job->ResetOnMainThread(); | 148 job->ResetOnMainThread(); |
147 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 149 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
148 } | 150 } |
149 | 151 |
150 TEST_F(CompilerDispatcherJobTest, SyntaxError) { | 152 TEST_F(CompilerDispatcherJobTest, SyntaxError) { |
151 ScriptResource script("^^^", strlen("^^^")); | 153 ScriptResource script("^^^", strlen("^^^")); |
152 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 154 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
153 i_isolate(), CreateSharedFunctionInfo(i_isolate(), &script), | 155 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), |
154 FLAG_stack_size)); | 156 FLAG_stack_size)); |
155 | 157 |
156 job->PrepareToParseOnMainThread(); | 158 job->PrepareToParseOnMainThread(); |
157 job->Parse(); | 159 job->Parse(); |
158 ASSERT_FALSE(job->FinalizeParsingOnMainThread()); | 160 ASSERT_FALSE(job->FinalizeParsingOnMainThread()); |
159 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); | 161 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
160 ASSERT_TRUE(i_isolate()->has_pending_exception()); | 162 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
161 | 163 |
162 i_isolate()->clear_pending_exception(); | 164 i_isolate()->clear_pending_exception(); |
163 | 165 |
164 job->ResetOnMainThread(); | 166 job->ResetOnMainThread(); |
165 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 167 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
166 } | 168 } |
167 | 169 |
168 TEST_F(CompilerDispatcherJobTest, ScopeChain) { | 170 TEST_F(CompilerDispatcherJobTest, ScopeChain) { |
169 const char script[] = | 171 const char script[] = |
170 "function g() { var y = 1; function f(x) { return x * y }; return f; } " | 172 "function g() { var y = 1; function f(x) { return x * y }; return f; } " |
171 "g();"; | 173 "g();"; |
172 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 174 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); |
173 | 175 |
174 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 176 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
175 i_isolate(), handle(f->shared()), FLAG_stack_size)); | 177 i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size)); |
176 | 178 |
177 job->PrepareToParseOnMainThread(); | 179 job->PrepareToParseOnMainThread(); |
178 job->Parse(); | 180 job->Parse(); |
179 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); | 181 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); |
180 ASSERT_TRUE(job->PrepareToCompileOnMainThread()); | 182 ASSERT_TRUE(job->PrepareToCompileOnMainThread()); |
181 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); | 183 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); |
182 | 184 |
183 const AstRawString* var_x = | 185 const AstRawString* var_x = |
184 job->parse_info_->ast_value_factory()->GetOneByteString("x"); | 186 job->parse_info_->ast_value_factory()->GetOneByteString("x"); |
185 Variable* var = job->parse_info_->literal()->scope()->Lookup(var_x); | 187 Variable* var = job->parse_info_->literal()->scope()->Lookup(var_x); |
(...skipping 15 matching lines...) Expand all Loading... |
201 "function g() {\n" | 203 "function g() {\n" |
202 " f = function(a) {\n" | 204 " f = function(a) {\n" |
203 " for (var i = 0; i < 3; i++) { a += 20; }\n" | 205 " for (var i = 0; i < 3; i++) { a += 20; }\n" |
204 " return a;\n" | 206 " return a;\n" |
205 " }\n" | 207 " }\n" |
206 " return f;\n" | 208 " return f;\n" |
207 "}\n" | 209 "}\n" |
208 "g();"; | 210 "g();"; |
209 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 211 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); |
210 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 212 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
211 i_isolate(), handle(f->shared()), FLAG_stack_size)); | 213 i_isolate(), tracer(), handle(f->shared()), FLAG_stack_size)); |
212 | 214 |
213 job->PrepareToParseOnMainThread(); | 215 job->PrepareToParseOnMainThread(); |
214 job->Parse(); | 216 job->Parse(); |
215 job->FinalizeParsingOnMainThread(); | 217 job->FinalizeParsingOnMainThread(); |
216 job->PrepareToCompileOnMainThread(); | 218 job->PrepareToCompileOnMainThread(); |
217 job->Compile(); | 219 job->Compile(); |
218 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); | 220 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); |
219 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); | 221 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); |
220 | 222 |
221 Smi* value = Smi::cast(*RunJS(isolate(), "f(100);")); | 223 Smi* value = Smi::cast(*RunJS(isolate(), "f(100);")); |
222 ASSERT_TRUE(value == Smi::FromInt(160)); | 224 ASSERT_TRUE(value == Smi::FromInt(160)); |
223 | 225 |
224 job->ResetOnMainThread(); | 226 job->ResetOnMainThread(); |
225 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 227 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
226 } | 228 } |
227 | 229 |
228 TEST_F(CompilerDispatcherJobTest, CompileFailureToPrepare) { | 230 TEST_F(CompilerDispatcherJobTest, CompileFailureToPrepare) { |
229 std::string raw_script("() { var a = "); | 231 std::string raw_script("() { var a = "); |
230 for (int i = 0; i < 100000; i++) { | 232 for (int i = 0; i < 100000; i++) { |
231 raw_script += "'x' + "; | 233 raw_script += "'x' + "; |
232 } | 234 } |
233 raw_script += " 'x'; }"; | 235 raw_script += " 'x'; }"; |
234 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); | 236 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); |
235 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 237 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
236 i_isolate(), CreateSharedFunctionInfo(i_isolate(), &script), 100)); | 238 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), |
| 239 100)); |
237 | 240 |
238 job->PrepareToParseOnMainThread(); | 241 job->PrepareToParseOnMainThread(); |
239 job->Parse(); | 242 job->Parse(); |
240 job->FinalizeParsingOnMainThread(); | 243 job->FinalizeParsingOnMainThread(); |
241 ASSERT_FALSE(job->PrepareToCompileOnMainThread()); | 244 ASSERT_FALSE(job->PrepareToCompileOnMainThread()); |
242 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); | 245 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
243 ASSERT_TRUE(i_isolate()->has_pending_exception()); | 246 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
244 | 247 |
245 i_isolate()->clear_pending_exception(); | 248 i_isolate()->clear_pending_exception(); |
246 job->ResetOnMainThread(); | 249 job->ResetOnMainThread(); |
247 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 250 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
248 } | 251 } |
249 | 252 |
250 TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) { | 253 TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) { |
251 std::string raw_script("() { var a = "); | 254 std::string raw_script("() { var a = "); |
252 for (int i = 0; i < 1000; i++) { | 255 for (int i = 0; i < 1000; i++) { |
253 raw_script += "'x' + "; | 256 raw_script += "'x' + "; |
254 } | 257 } |
255 raw_script += " 'x'; }"; | 258 raw_script += " 'x'; }"; |
256 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); | 259 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); |
257 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 260 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
258 i_isolate(), CreateSharedFunctionInfo(i_isolate(), &script), 50)); | 261 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), |
| 262 50)); |
259 | 263 |
260 job->PrepareToParseOnMainThread(); | 264 job->PrepareToParseOnMainThread(); |
261 job->Parse(); | 265 job->Parse(); |
262 job->FinalizeParsingOnMainThread(); | 266 job->FinalizeParsingOnMainThread(); |
263 job->PrepareToCompileOnMainThread(); | 267 job->PrepareToCompileOnMainThread(); |
264 job->Compile(); | 268 job->Compile(); |
265 ASSERT_FALSE(job->FinalizeCompilingOnMainThread()); | 269 ASSERT_FALSE(job->FinalizeCompilingOnMainThread()); |
266 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); | 270 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
267 ASSERT_TRUE(i_isolate()->has_pending_exception()); | 271 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
268 | 272 |
(...skipping 22 matching lines...) Expand all Loading... |
291 TEST_F(IgnitionCompilerDispatcherJobTest, CompileOnBackgroundThread) { | 295 TEST_F(IgnitionCompilerDispatcherJobTest, CompileOnBackgroundThread) { |
292 const char* raw_script = | 296 const char* raw_script = |
293 "(a, b) {\n" | 297 "(a, b) {\n" |
294 " var c = a + b;\n" | 298 " var c = a + b;\n" |
295 " function bar() { return b }\n" | 299 " function bar() { return b }\n" |
296 " var d = { foo: 100, bar : bar() }\n" | 300 " var d = { foo: 100, bar : bar() }\n" |
297 " return bar;" | 301 " return bar;" |
298 "}"; | 302 "}"; |
299 ScriptResource script(raw_script, strlen(raw_script)); | 303 ScriptResource script(raw_script, strlen(raw_script)); |
300 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 304 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
301 i_isolate(), CreateSharedFunctionInfo(i_isolate(), &script), 100)); | 305 i_isolate(), tracer(), CreateSharedFunctionInfo(i_isolate(), &script), |
| 306 100)); |
302 | 307 |
303 job->PrepareToParseOnMainThread(); | 308 job->PrepareToParseOnMainThread(); |
304 job->Parse(); | 309 job->Parse(); |
305 job->FinalizeParsingOnMainThread(); | 310 job->FinalizeParsingOnMainThread(); |
306 job->PrepareToCompileOnMainThread(); | 311 job->PrepareToCompileOnMainThread(); |
307 ASSERT_TRUE(job->can_compile_on_background_thread()); | 312 ASSERT_TRUE(job->can_compile_on_background_thread()); |
308 | 313 |
309 base::Semaphore semaphore(0); | 314 base::Semaphore semaphore(0); |
310 CompileTask* background_task = new CompileTask(job.get(), &semaphore); | 315 CompileTask* background_task = new CompileTask(job.get(), &semaphore); |
311 V8::GetCurrentPlatform()->CallOnBackgroundThread(background_task, | 316 V8::GetCurrentPlatform()->CallOnBackgroundThread(background_task, |
312 Platform::kShortRunningTask); | 317 Platform::kShortRunningTask); |
313 semaphore.Wait(); | 318 semaphore.Wait(); |
314 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); | 319 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); |
315 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); | 320 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); |
316 | 321 |
317 job->ResetOnMainThread(); | 322 job->ResetOnMainThread(); |
318 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 323 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
319 } | 324 } |
320 | 325 |
321 } // namespace internal | 326 } // namespace internal |
322 } // namespace v8 | 327 } // namespace v8 |
OLD | NEW |