Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: src/compiler.cc

Issue 10700188: Introduce an OptimizingCompiler class, responsible for maintaining the state needed to run Cranksha… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 return false; 158 return false;
159 #endif 159 #endif
160 } 160 }
161 161
162 162
163 static bool AlwaysFullCompiler(Isolate* isolate) { 163 static bool AlwaysFullCompiler(Isolate* isolate) {
164 return FLAG_always_full_compiler || IsDebuggerActive(isolate); 164 return FLAG_always_full_compiler || IsDebuggerActive(isolate);
165 } 165 }
166 166
167 167
168 static void FinishOptimization(Handle<JSFunction> function, int64_t start) { 168 void OptimizingCompiler::RecordOptimizationStats() {
169 Handle<JSFunction> function = info()->closure();
169 int opt_count = function->shared()->opt_count(); 170 int opt_count = function->shared()->opt_count();
170 function->shared()->set_opt_count(opt_count + 1); 171 function->shared()->set_opt_count(opt_count + 1);
171 double ms = static_cast<double>(OS::Ticks() - start) / 1000; 172 double ms_creategraph =
173 static_cast<double>(time_taken_to_create_graph_) / 1000;
174 double ms_optimize = static_cast<double>(time_taken_to_optimize_) / 1000;
175 double ms_codegen = static_cast<double>(time_taken_to_codegen_) / 1000;
172 if (FLAG_trace_opt) { 176 if (FLAG_trace_opt) {
173 PrintF("[optimizing: "); 177 PrintF("[optimizing: ");
174 function->PrintName(); 178 function->PrintName();
175 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function)); 179 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
176 PrintF(" - took %0.3f ms]\n", ms); 180 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
181 ms_codegen);
177 } 182 }
178 if (FLAG_trace_opt_stats) { 183 if (FLAG_trace_opt_stats) {
179 static double compilation_time = 0.0; 184 static double compilation_time = 0.0;
180 static int compiled_functions = 0; 185 static int compiled_functions = 0;
181 static int code_size = 0; 186 static int code_size = 0;
182 187
183 compilation_time += ms; 188 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
184 compiled_functions++; 189 compiled_functions++;
185 code_size += function->shared()->SourceSize(); 190 code_size += function->shared()->SourceSize();
186 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", 191 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
187 compiled_functions, 192 compiled_functions,
188 code_size, 193 code_size,
189 compilation_time); 194 compilation_time);
190 } 195 }
191 } 196 }
192 197
193 198
199 // A return value of true indicates the compilation pipeline is still
200 // going, not necessarily that we optimized the code.
194 static bool MakeCrankshaftCode(CompilationInfo* info) { 201 static bool MakeCrankshaftCode(CompilationInfo* info) {
202 OptimizingCompiler compiler(info);
203 OptimizingCompiler::Status status = compiler.CreateGraph();
204
205 if (status == OptimizingCompiler::SUCCEEDED) {
206 status = compiler.OptimizeGraph();
207 } else {
208 return status != OptimizingCompiler::FAILED;
209 }
210
211 if (status == OptimizingCompiler::SUCCEEDED) {
212 status = compiler.GenerateAndInstallCode();
213 }
214 return status != OptimizingCompiler::FAILED;
215 }
216
217
218 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
195 ASSERT(V8::UseCrankshaft()); 219 ASSERT(V8::UseCrankshaft());
196 ASSERT(info->IsOptimizing()); 220 ASSERT(info()->IsOptimizing());
197 ASSERT(!info->IsCompilingForDebugging()); 221 ASSERT(!info()->IsCompilingForDebugging());
198 222
199 // We should never arrive here if there is not code object on the 223 // We should never arrive here if there is no code object on the
200 // shared function object. 224 // shared function object.
201 Handle<Code> code(info->shared_info()->code()); 225 Handle<Code> code(info()->shared_info()->code());
202 ASSERT(code->kind() == Code::FUNCTION); 226 ASSERT(code->kind() == Code::FUNCTION);
203 227
204 // We should never arrive here if optimization has been disabled on the 228 // We should never arrive here if optimization has been disabled on the
205 // shared function info. 229 // shared function info.
206 ASSERT(!info->shared_info()->optimization_disabled()); 230 ASSERT(!info()->shared_info()->optimization_disabled());
207 231
208 // Fall back to using the full code generator if it's not possible 232 // Fall back to using the full code generator if it's not possible
209 // to use the Hydrogen-based optimizing compiler. We already have 233 // to use the Hydrogen-based optimizing compiler. We already have
210 // generated code for this from the shared function object. 234 // generated code for this from the shared function object.
211 if (AlwaysFullCompiler(info->isolate())) { 235 if (AlwaysFullCompiler(info()->isolate())) {
212 info->SetCode(code); 236 info()->SetCode(code);
213 return true; 237 return SetLastStatus(BAILED_OUT);
214 } 238 }
215 239
216 // Limit the number of times we re-compile a functions with 240 // Limit the number of times we re-compile a functions with
217 // the optimizing compiler. 241 // the optimizing compiler.
218 const int kMaxOptCount = 242 const int kMaxOptCount =
219 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000; 243 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
220 if (info->shared_info()->opt_count() > kMaxOptCount) { 244 if (info()->shared_info()->opt_count() > kMaxOptCount) {
221 info->AbortOptimization(); 245 return AbortOptimization();
danno 2012/07/16 15:05:02 Is this really equivalent to what was here before?
sanjoy 2012/07/17 08:09:39 Modified this part to make the logic clearer.
222 info->shared_info()->DisableOptimization();
223 // True indicates the compilation pipeline is still going, not
224 // necessarily that we optimized the code.
225 return true;
226 } 246 }
227 247
228 // Due to an encoding limit on LUnallocated operands in the Lithium 248 // Due to an encoding limit on LUnallocated operands in the Lithium
229 // language, we cannot optimize functions with too many formal parameters 249 // language, we cannot optimize functions with too many formal parameters
230 // or perform on-stack replacement for function with too many 250 // or perform on-stack replacement for function with too many
231 // stack-allocated local variables. 251 // stack-allocated local variables.
232 // 252 //
233 // The encoding is as a signed value, with parameters and receiver using 253 // The encoding is as a signed value, with parameters and receiver using
234 // the negative indices and locals the non-negative ones. 254 // the negative indices and locals the non-negative ones.
235 const int parameter_limit = -LUnallocated::kMinFixedIndex; 255 const int parameter_limit = -LUnallocated::kMinFixedIndex;
236 const int locals_limit = LUnallocated::kMaxFixedIndex; 256 const int locals_limit = LUnallocated::kMaxFixedIndex;
237 Scope* scope = info->scope(); 257 Scope* scope = info()->scope();
238 if ((scope->num_parameters() + 1) > parameter_limit || 258 if ((scope->num_parameters() + 1) > parameter_limit ||
239 (info->osr_ast_id() != AstNode::kNoNumber && 259 (info()->osr_ast_id() != AstNode::kNoNumber &&
240 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) { 260 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
241 info->AbortOptimization(); 261 return AbortOptimization();
danno 2012/07/16 15:05:02 Ditto.
sanjoy 2012/07/17 08:09:39 Ditto.
242 info->shared_info()->DisableOptimization();
243 // True indicates the compilation pipeline is still going, not
244 // necessarily that we optimized the code.
245 return true;
246 } 262 }
247 263
248 // Take --hydrogen-filter into account. 264 // Take --hydrogen-filter into account.
249 Handle<String> name = info->function()->debug_name(); 265 Handle<String> name = info()->function()->debug_name();
250 if (*FLAG_hydrogen_filter != '\0') { 266 if (*FLAG_hydrogen_filter != '\0') {
251 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); 267 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
252 if ((filter[0] == '-' 268 if ((filter[0] == '-'
253 && name->IsEqualTo(filter.SubVector(1, filter.length()))) 269 && name->IsEqualTo(filter.SubVector(1, filter.length())))
254 || (filter[0] != '-' && !name->IsEqualTo(filter))) { 270 || (filter[0] != '-' && !name->IsEqualTo(filter))) {
255 info->SetCode(code); 271 info()->SetCode(code);
256 return true; 272 return SetLastStatus(BAILED_OUT);
257 } 273 }
258 } 274 }
259 275
260 // Recompile the unoptimized version of the code if the current version 276 // Recompile the unoptimized version of the code if the current version
261 // doesn't have deoptimization support. Alternatively, we may decide to 277 // doesn't have deoptimization support. Alternatively, we may decide to
262 // run the full code generator to get a baseline for the compile-time 278 // run the full code generator to get a baseline for the compile-time
263 // performance of the hydrogen-based compiler. 279 // performance of the hydrogen-based compiler.
264 int64_t start = OS::Ticks(); 280 Timer t(this, &time_taken_to_create_graph_);
265 bool should_recompile = !info->shared_info()->has_deoptimization_support(); 281 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
266 if (should_recompile || FLAG_hydrogen_stats) { 282 if (should_recompile || FLAG_hydrogen_stats) {
267 HPhase phase(HPhase::kFullCodeGen); 283 HPhase phase(HPhase::kFullCodeGen);
268 CompilationInfoWithZone unoptimized(info->shared_info()); 284 CompilationInfoWithZone unoptimized(info()->shared_info());
269 // Note that we use the same AST that we will use for generating the 285 // Note that we use the same AST that we will use for generating the
270 // optimized code. 286 // optimized code.
271 unoptimized.SetFunction(info->function()); 287 unoptimized.SetFunction(info()->function());
272 unoptimized.SetScope(info->scope()); 288 unoptimized.SetScope(info()->scope());
273 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); 289 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
274 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); 290 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
275 if (should_recompile) { 291 if (should_recompile) {
276 if (!succeeded) return false; 292 if (!succeeded) return FAILED;
277 Handle<SharedFunctionInfo> shared = info->shared_info(); 293 Handle<SharedFunctionInfo> shared = info()->shared_info();
278 shared->EnableDeoptimizationSupport(*unoptimized.code()); 294 shared->EnableDeoptimizationSupport(*unoptimized.code());
279 // The existing unoptimized code was replaced with the new one. 295 // The existing unoptimized code was replaced with the new one.
280 Compiler::RecordFunctionCompilation( 296 Compiler::RecordFunctionCompilation(
281 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); 297 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
282 } 298 }
283 } 299 }
284 300
285 // Check that the unoptimized, shared code is ready for 301 // Check that the unoptimized, shared code is ready for
286 // optimizations. When using the always_opt flag we disregard the 302 // optimizations. When using the always_opt flag we disregard the
287 // optimizable marker in the code object and optimize anyway. This 303 // optimizable marker in the code object and optimize anyway. This
288 // is safe as long as the unoptimized code has deoptimization 304 // is safe as long as the unoptimized code has deoptimization
289 // support. 305 // support.
290 ASSERT(FLAG_always_opt || code->optimizable()); 306 ASSERT(FLAG_always_opt || code->optimizable());
291 ASSERT(info->shared_info()->has_deoptimization_support()); 307 ASSERT(info()->shared_info()->has_deoptimization_support());
292 308
293 if (FLAG_trace_hydrogen) { 309 if (FLAG_trace_hydrogen) {
294 PrintF("-----------------------------------------------------------\n"); 310 PrintF("-----------------------------------------------------------\n");
295 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); 311 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
296 HTracer::Instance()->TraceCompilation(info->function()); 312 HTracer::Instance()->TraceCompilation(info()->function());
313 }
314 Handle<Context> global_context(
315 info()->closure()->context()->global_context());
316 oracle_ = new(info()->zone()) TypeFeedbackOracle(
317 code, global_context, info()->isolate(), info()->zone());
318 graph_builder_ = new(info()->zone()) HGraphBuilder(info(), oracle_);
319 HPhase phase(HPhase::kTotal);
320 is_inline_bailout_ = graph_builder_->inline_bailout();
321 graph_ = graph_builder_->CreateGraph();
322
323 if (info()->isolate()->has_pending_exception()) {
324 info()->SetCode(Handle<Code>::null());
325 return SetLastStatus(FAILED);
326 }
327 if (graph_ == NULL) {
328 return AbortOptimization();
297 } 329 }
298 330
299 Handle<Context> global_context(info->closure()->context()->global_context()); 331 return SUCCEEDED;
300 TypeFeedbackOracle oracle(code, global_context, info->isolate(), 332 }
301 info->zone());
302 HGraphBuilder builder(info, &oracle);
303 HPhase phase(HPhase::kTotal);
304 HGraph* graph = builder.CreateGraph();
305 if (info->isolate()->has_pending_exception()) {
306 info->SetCode(Handle<Code>::null());
307 return false;
308 }
309 333
310 if (graph != NULL) { 334 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
311 SmartArrayPointer<char> bailout_reason; 335 Timer t(this, &time_taken_to_optimize_);
312 if (!graph->Optimize(&bailout_reason)) { 336 ASSERT(graph_ != NULL);
313 if (!bailout_reason.is_empty()) builder.Bailout(*bailout_reason); 337 SmartArrayPointer<char> bailout_reason;
314 } else { 338 if (!graph_->Optimize(&bailout_reason)) {
315 LChunk* chunk = LChunk::NewChunk(graph); 339 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
316 if (chunk != NULL) { 340 return AbortOptimization();
317 Handle<Code> optimized_code = chunk->Codegen(); 341 } else {
318 if (!optimized_code.is_null()) { 342 chunk_ = LChunk::NewChunk(graph_);
319 info->SetCode(optimized_code); 343 if (chunk_ == NULL) {
320 FinishOptimization(info->closure(), start); 344 return AbortOptimization();
321 return true;
322 }
323 }
324 } 345 }
325 } 346 }
326 347 return SUCCEEDED;
327 // Keep using the shared code.
328 info->AbortOptimization();
329 if (!builder.inline_bailout()) {
330 // Mark the shared code as unoptimizable unless it was an inlined
331 // function that bailed out.
332 info->shared_info()->DisableOptimization();
333 }
334 // True indicates the compilation pipeline is still going, not necessarily
335 // that we optimized the code.
336 return true;
337 } 348 }
338 349
339 350
351 OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
352 Timer timer(this, &time_taken_to_codegen_);
353 ASSERT(chunk_ != NULL);
354 ASSERT(graph_ != NULL);
355 Handle<Code> optimized_code = chunk_->Codegen();
356 if (optimized_code.is_null()) return AbortOptimization();
357 info()->SetCode(optimized_code);
358 RecordOptimizationStats();
359 return SUCCEEDED;
360 }
361
362
340 static bool GenerateCode(CompilationInfo* info) { 363 static bool GenerateCode(CompilationInfo* info) {
341 bool is_optimizing = V8::UseCrankshaft() && 364 bool is_optimizing = V8::UseCrankshaft() &&
342 !info->IsCompilingForDebugging() && 365 !info->IsCompilingForDebugging() &&
343 info->IsOptimizing(); 366 info->IsOptimizing();
344 if (is_optimizing) { 367 if (is_optimizing) {
345 return MakeCrankshaftCode(info); 368 return MakeCrankshaftCode(info);
346 } else { 369 } else {
347 if (info->IsOptimizing()) { 370 if (info->IsOptimizing()) {
348 // Have the CompilationInfo decide if the compilation should be 371 // Have the CompilationInfo decide if the compilation should be
349 // BASE or NONOPT. 372 // BASE or NONOPT.
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 } 901 }
879 } 902 }
880 903
881 GDBJIT(AddCode(Handle<String>(shared->DebugName()), 904 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
882 Handle<Script>(info->script()), 905 Handle<Script>(info->script()),
883 Handle<Code>(info->code()), 906 Handle<Code>(info->code()),
884 info)); 907 info));
885 } 908 }
886 909
887 } } // namespace v8::internal 910 } } // namespace v8::internal
OLDNEW
« src/compiler.h ('K') | « src/compiler.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698