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 |