| 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/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" | 10 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 Handle<String> source; | 45 Handle<String> source; |
| 46 if (maybe_resource) { | 46 if (maybe_resource) { |
| 47 source = isolate->factory() | 47 source = isolate->factory() |
| 48 ->NewExternalStringFromOneByte(maybe_resource) | 48 ->NewExternalStringFromOneByte(maybe_resource) |
| 49 .ToHandleChecked(); | 49 .ToHandleChecked(); |
| 50 } else { | 50 } else { |
| 51 source = isolate->factory()->NewStringFromAsciiChecked(test_script); | 51 source = isolate->factory()->NewStringFromAsciiChecked(test_script); |
| 52 } | 52 } |
| 53 Handle<Script> script = isolate->factory()->NewScript(source); | 53 Handle<Script> script = isolate->factory()->NewScript(source); |
| 54 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( | 54 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( |
| 55 isolate->factory()->NewStringFromAsciiChecked("f"), MaybeHandle<Code>(), | 55 isolate->factory()->NewStringFromAsciiChecked("f"), |
| 56 false); | 56 isolate->builtins()->CompileLazy(), false); |
| 57 SharedFunctionInfo::SetScript(shared, script); | 57 SharedFunctionInfo::SetScript(shared, script); |
| 58 shared->set_end_position(source->length()); | 58 shared->set_end_position(source->length()); |
| 59 Handle<JSFunction> function = | 59 Handle<JSFunction> function = |
| 60 isolate->factory()->NewFunctionFromSharedFunctionInfo( | 60 isolate->factory()->NewFunctionFromSharedFunctionInfo( |
| 61 shared, handle(isolate->context(), isolate)); | 61 shared, handle(isolate->context(), isolate)); |
| 62 return scope.CloseAndEscape(function); | 62 return scope.CloseAndEscape(function); |
| 63 } | 63 } |
| 64 | 64 |
| 65 Handle<Object> RunJS(v8::Isolate* isolate, const char* script) { |
| 66 return Utils::OpenHandle( |
| 67 *v8::Script::Compile( |
| 68 isolate->GetCurrentContext(), |
| 69 v8::String::NewFromUtf8(isolate, script, v8::NewStringType::kNormal) |
| 70 .ToLocalChecked()) |
| 71 .ToLocalChecked() |
| 72 ->Run(isolate->GetCurrentContext()) |
| 73 .ToLocalChecked()); |
| 74 } |
| 75 |
| 65 } // namespace | 76 } // namespace |
| 66 | 77 |
| 67 TEST_F(CompilerDispatcherJobTest, Construct) { | 78 TEST_F(CompilerDispatcherJobTest, Construct) { |
| 68 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 79 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| 69 i_isolate(), CreateFunction(i_isolate(), nullptr), FLAG_stack_size)); | 80 i_isolate(), CreateFunction(i_isolate(), nullptr), FLAG_stack_size)); |
| 70 } | 81 } |
| 71 | 82 |
| 72 TEST_F(CompilerDispatcherJobTest, CanParseOnBackgroundThread) { | 83 TEST_F(CompilerDispatcherJobTest, CanParseOnBackgroundThread) { |
| 73 { | 84 { |
| 74 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 85 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 86 TEST_F(CompilerDispatcherJobTest, StateTransitions) { | 97 TEST_F(CompilerDispatcherJobTest, StateTransitions) { |
| 87 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 98 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| 88 i_isolate(), CreateFunction(i_isolate(), nullptr), FLAG_stack_size)); | 99 i_isolate(), CreateFunction(i_isolate(), nullptr), FLAG_stack_size)); |
| 89 | 100 |
| 90 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 101 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 91 job->PrepareToParseOnMainThread(); | 102 job->PrepareToParseOnMainThread(); |
| 92 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse); | 103 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToParse); |
| 93 job->Parse(); | 104 job->Parse(); |
| 94 ASSERT_TRUE(job->status() == CompileJobStatus::kParsed); | 105 ASSERT_TRUE(job->status() == CompileJobStatus::kParsed); |
| 95 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); | 106 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); |
| 107 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyse); |
| 108 ASSERT_TRUE(job->PrepareToCompileOnMainThread()); |
| 96 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); | 109 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); |
| 110 job->Compile(); |
| 111 ASSERT_TRUE(job->status() == CompileJobStatus::kCompiled); |
| 112 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); |
| 113 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); |
| 97 job->ResetOnMainThread(); | 114 job->ResetOnMainThread(); |
| 98 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 115 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 99 } | 116 } |
| 100 | 117 |
| 101 TEST_F(CompilerDispatcherJobTest, SyntaxError) { | 118 TEST_F(CompilerDispatcherJobTest, SyntaxError) { |
| 102 ScriptResource script("^^^", strlen("^^^")); | 119 ScriptResource script("^^^", strlen("^^^")); |
| 103 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( | 120 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| 104 i_isolate(), CreateFunction(i_isolate(), &script), FLAG_stack_size)); | 121 i_isolate(), CreateFunction(i_isolate(), &script), FLAG_stack_size)); |
| 105 | 122 |
| 106 job->PrepareToParseOnMainThread(); | 123 job->PrepareToParseOnMainThread(); |
| 107 job->Parse(); | 124 job->Parse(); |
| 108 ASSERT_FALSE(job->FinalizeParsingOnMainThread()); | 125 ASSERT_FALSE(job->FinalizeParsingOnMainThread()); |
| 109 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); | 126 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
| 110 ASSERT_TRUE(i_isolate()->has_pending_exception()); | 127 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
| 111 | 128 |
| 112 i_isolate()->clear_pending_exception(); | 129 i_isolate()->clear_pending_exception(); |
| 113 | 130 |
| 114 job->ResetOnMainThread(); | 131 job->ResetOnMainThread(); |
| 115 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 132 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 116 } | 133 } |
| 117 | 134 |
| 118 TEST_F(CompilerDispatcherJobTest, ScopeChain) { | 135 TEST_F(CompilerDispatcherJobTest, ScopeChain) { |
| 119 const char script[] = | 136 const char script[] = |
| 120 "function g() { var g = 1; function f(x) { return x * g }; return f; } " | 137 "function g() { var g = 1; function f(x) { return x * g }; return f; } " |
| 121 "g();"; | 138 "g();"; |
| 122 Handle<JSFunction> f = Handle<JSFunction>::cast(Utils::OpenHandle( | 139 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); |
| 123 *v8::Script::Compile(isolate()->GetCurrentContext(), | |
| 124 v8::String::NewFromUtf8(isolate(), script, | |
| 125 v8::NewStringType::kNormal) | |
| 126 .ToLocalChecked()) | |
| 127 .ToLocalChecked() | |
| 128 ->Run(isolate()->GetCurrentContext()) | |
| 129 .ToLocalChecked())); | |
| 130 | 140 |
| 131 std::unique_ptr<CompilerDispatcherJob> job( | 141 std::unique_ptr<CompilerDispatcherJob> job( |
| 132 new CompilerDispatcherJob(i_isolate(), f, FLAG_stack_size)); | 142 new CompilerDispatcherJob(i_isolate(), f, FLAG_stack_size)); |
| 133 | 143 |
| 134 job->PrepareToParseOnMainThread(); | 144 job->PrepareToParseOnMainThread(); |
| 135 job->Parse(); | 145 job->Parse(); |
| 136 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); | 146 ASSERT_TRUE(job->FinalizeParsingOnMainThread()); |
| 137 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile); | 147 ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyse); |
| 138 | 148 |
| 139 const AstRawString* var_x = | 149 const AstRawString* var_x = |
| 140 job->parse_info_->ast_value_factory()->GetOneByteString("x"); | 150 job->parse_info_->ast_value_factory()->GetOneByteString("x"); |
| 141 Variable* var = job->parse_info_->literal()->scope()->Lookup(var_x); | 151 Variable* var = job->parse_info_->literal()->scope()->Lookup(var_x); |
| 142 ASSERT_TRUE(var); | 152 ASSERT_TRUE(var); |
| 143 ASSERT_TRUE(var->IsUnallocated()); | 153 ASSERT_TRUE(var->IsUnallocated()); |
| 144 | 154 |
| 145 const AstRawString* var_g = | 155 const AstRawString* var_g = |
| 146 job->parse_info_->ast_value_factory()->GetOneByteString("g"); | 156 job->parse_info_->ast_value_factory()->GetOneByteString("g"); |
| 147 var = job->parse_info_->literal()->scope()->Lookup(var_g); | 157 var = job->parse_info_->literal()->scope()->Lookup(var_g); |
| 148 ASSERT_TRUE(var); | 158 ASSERT_TRUE(var); |
| 149 ASSERT_TRUE(var->IsContextSlot()); | 159 ASSERT_TRUE(var->IsContextSlot()); |
| 150 | 160 |
| 151 job->ResetOnMainThread(); | 161 job->ResetOnMainThread(); |
| 152 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); | 162 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 153 } | 163 } |
| 154 | 164 |
| 165 TEST_F(CompilerDispatcherJobTest, CompileAndRun) { |
| 166 const char script[] = |
| 167 "function g() {\n" |
| 168 " f = function(a) {\n" |
| 169 " for (var i = 0; i < 3; i++) { a += 20; }\n" |
| 170 " return a;\n" |
| 171 " }\n" |
| 172 " return f;\n" |
| 173 "}\n" |
| 174 "g();"; |
| 175 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); |
| 176 std::unique_ptr<CompilerDispatcherJob> job( |
| 177 new CompilerDispatcherJob(i_isolate(), f, FLAG_stack_size)); |
| 178 |
| 179 job->PrepareToParseOnMainThread(); |
| 180 job->Parse(); |
| 181 job->FinalizeParsingOnMainThread(); |
| 182 job->PrepareToCompileOnMainThread(); |
| 183 job->Compile(); |
| 184 ASSERT_TRUE(job->FinalizeCompilingOnMainThread()); |
| 185 ASSERT_TRUE(job->status() == CompileJobStatus::kDone); |
| 186 |
| 187 Smi* value = Smi::cast(*RunJS(isolate(), "f(100);")); |
| 188 ASSERT_TRUE(value == Smi::FromInt(160)); |
| 189 |
| 190 job->ResetOnMainThread(); |
| 191 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 192 } |
| 193 |
| 194 TEST_F(CompilerDispatcherJobTest, CompileFailureToPrepare) { |
| 195 std::string raw_script("() { var a = "); |
| 196 for (int i = 0; i < 100000; i++) { |
| 197 raw_script += "'x' + "; |
| 198 } |
| 199 raw_script += " 'x'; }"; |
| 200 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); |
| 201 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| 202 i_isolate(), CreateFunction(i_isolate(), &script), 100)); |
| 203 |
| 204 job->PrepareToParseOnMainThread(); |
| 205 job->Parse(); |
| 206 job->FinalizeParsingOnMainThread(); |
| 207 ASSERT_FALSE(job->PrepareToCompileOnMainThread()); |
| 208 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
| 209 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
| 210 |
| 211 i_isolate()->clear_pending_exception(); |
| 212 job->ResetOnMainThread(); |
| 213 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 214 } |
| 215 |
| 216 TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) { |
| 217 std::string raw_script("() { var a = "); |
| 218 for (int i = 0; i < 1000; i++) { |
| 219 raw_script += "'x' + "; |
| 220 } |
| 221 raw_script += " 'x'; }"; |
| 222 ScriptResource script(raw_script.c_str(), strlen(raw_script.c_str())); |
| 223 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( |
| 224 i_isolate(), CreateFunction(i_isolate(), &script), 100)); |
| 225 |
| 226 job->PrepareToParseOnMainThread(); |
| 227 job->Parse(); |
| 228 job->FinalizeParsingOnMainThread(); |
| 229 job->PrepareToCompileOnMainThread(); |
| 230 job->Compile(); |
| 231 ASSERT_FALSE(job->FinalizeCompilingOnMainThread()); |
| 232 ASSERT_TRUE(job->status() == CompileJobStatus::kFailed); |
| 233 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
| 234 |
| 235 i_isolate()->clear_pending_exception(); |
| 236 job->ResetOnMainThread(); |
| 237 ASSERT_TRUE(job->status() == CompileJobStatus::kInitial); |
| 238 } |
| 239 |
| 155 } // namespace internal | 240 } // namespace internal |
| 156 } // namespace v8 | 241 } // namespace v8 |
| OLD | NEW |