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

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: 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 OptimizingCompiler::Status OptimizingCompiler::InnerCreateHGraph() {
169 int opt_count = function->shared()->opt_count(); 169 ASSERT(V8::UseCrankshaft());
170 function->shared()->set_opt_count(opt_count + 1); 170 ASSERT(info()->IsOptimizing());
171 double ms = static_cast<double>(OS::Ticks() - start) / 1000; 171 ASSERT(!info()->IsCompilingForDebugging());
172 if (FLAG_trace_opt) {
173 PrintF("[optimizing: ");
174 function->PrintName();
175 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
176 PrintF(" - took %0.3f ms]\n", ms);
177 }
178 if (FLAG_trace_opt_stats) {
179 static double compilation_time = 0.0;
180 static int compiled_functions = 0;
181 static int code_size = 0;
182 172
183 compilation_time += ms; 173 // We should never arrive here if there is no code object on the
184 compiled_functions++;
185 code_size += function->shared()->SourceSize();
186 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
187 compiled_functions,
188 code_size,
189 compilation_time);
190 }
191 }
192
193
194 static bool MakeCrankshaftCode(CompilationInfo* info) {
195 ASSERT(V8::UseCrankshaft());
196 ASSERT(info->IsOptimizing());
197 ASSERT(!info->IsCompilingForDebugging());
198
199 // We should never arrive here if there is not code object on the
200 // shared function object. 174 // shared function object.
201 Handle<Code> code(info->shared_info()->code()); 175 Handle<Code> code(info()->shared_info()->code());
202 ASSERT(code->kind() == Code::FUNCTION); 176 ASSERT(code->kind() == Code::FUNCTION);
203 177
204 // We should never arrive here if optimization has been disabled on the 178 // We should never arrive here if optimization has been disabled on the
205 // shared function info. 179 // shared function info.
206 ASSERT(!info->shared_info()->optimization_disabled()); 180 ASSERT(!info()->shared_info()->optimization_disabled());
207 181
208 // Fall back to using the full code generator if it's not possible 182 // Fall back to using the full code generator if it's not possible
209 // to use the Hydrogen-based optimizing compiler. We already have 183 // to use the Hydrogen-based optimizing compiler. We already have
210 // generated code for this from the shared function object. 184 // generated code for this from the shared function object.
211 if (AlwaysFullCompiler(info->isolate())) { 185 if (AlwaysFullCompiler(info()->isolate())) {
212 info->SetCode(code); 186 info()->SetCode(code);
213 return true; 187 return BAILED_OUT;
214 } 188 }
215 189
216 // Limit the number of times we re-compile a functions with 190 // Limit the number of times we re-compile a functions with
217 // the optimizing compiler. 191 // the optimizing compiler.
218 const int kMaxOptCount = 192 const int kMaxOptCount =
219 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000; 193 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
220 if (info->shared_info()->opt_count() > kMaxOptCount) { 194 if (info()->shared_info()->opt_count() > kMaxOptCount) {
221 info->AbortOptimization(); 195 info()->AbortOptimization();
222 info->shared_info()->DisableOptimization(); 196 info()->shared_info()->DisableOptimization();
223 // True indicates the compilation pipeline is still going, not 197 return BAILED_OUT;
224 // necessarily that we optimized the code.
225 return true;
226 } 198 }
227 199
228 // Due to an encoding limit on LUnallocated operands in the Lithium 200 // Due to an encoding limit on LUnallocated operands in the Lithium
229 // language, we cannot optimize functions with too many formal parameters 201 // language, we cannot optimize functions with too many formal parameters
230 // or perform on-stack replacement for function with too many 202 // or perform on-stack replacement for function with too many
231 // stack-allocated local variables. 203 // stack-allocated local variables.
232 // 204 //
233 // The encoding is as a signed value, with parameters and receiver using 205 // The encoding is as a signed value, with parameters and receiver using
234 // the negative indices and locals the non-negative ones. 206 // the negative indices and locals the non-negative ones.
235 const int parameter_limit = -LUnallocated::kMinFixedIndex; 207 const int parameter_limit = -LUnallocated::kMinFixedIndex;
236 const int locals_limit = LUnallocated::kMaxFixedIndex; 208 const int locals_limit = LUnallocated::kMaxFixedIndex;
237 Scope* scope = info->scope(); 209 Scope* scope = info()->scope();
238 if ((scope->num_parameters() + 1) > parameter_limit || 210 if ((scope->num_parameters() + 1) > parameter_limit ||
239 (info->osr_ast_id() != AstNode::kNoNumber && 211 (info()->osr_ast_id() != AstNode::kNoNumber &&
240 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) { 212 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
241 info->AbortOptimization(); 213 info()->AbortOptimization();
242 info->shared_info()->DisableOptimization(); 214 info()->shared_info()->DisableOptimization();
243 // True indicates the compilation pipeline is still going, not 215 return BAILED_OUT;
244 // necessarily that we optimized the code.
245 return true;
246 } 216 }
247 217
248 // Take --hydrogen-filter into account. 218 // Take --hydrogen-filter into account.
249 Handle<String> name = info->function()->debug_name(); 219 Handle<String> name = info()->function()->debug_name();
250 if (*FLAG_hydrogen_filter != '\0') { 220 if (*FLAG_hydrogen_filter != '\0') {
251 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); 221 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
252 if ((filter[0] == '-' 222 if ((filter[0] == '-'
253 && name->IsEqualTo(filter.SubVector(1, filter.length()))) 223 && name->IsEqualTo(filter.SubVector(1, filter.length())))
254 || (filter[0] != '-' && !name->IsEqualTo(filter))) { 224 || (filter[0] != '-' && !name->IsEqualTo(filter))) {
255 info->SetCode(code); 225 info()->SetCode(code);
256 return true; 226 return BAILED_OUT;
257 } 227 }
258 } 228 }
259 229
230 Timer t(this);
danno 2012/07/16 12:19:09 nit: Move this down after the comment so diff is c
sanjoy 2012/07/16 13:46:46 Done.
260 // Recompile the unoptimized version of the code if the current version 231 // Recompile the unoptimized version of the code if the current version
261 // doesn't have deoptimization support. Alternatively, we may decide to 232 // doesn't have deoptimization support. Alternatively, we may decide to
262 // run the full code generator to get a baseline for the compile-time 233 // run the full code generator to get a baseline for the compile-time
263 // performance of the hydrogen-based compiler. 234 // performance of the hydrogen-based compiler.
264 int64_t start = OS::Ticks(); 235 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
265 bool should_recompile = !info->shared_info()->has_deoptimization_support();
266 if (should_recompile || FLAG_hydrogen_stats) { 236 if (should_recompile || FLAG_hydrogen_stats) {
267 HPhase phase(HPhase::kFullCodeGen); 237 HPhase phase(HPhase::kFullCodeGen);
268 CompilationInfoWithZone unoptimized(info->shared_info()); 238 CompilationInfoWithZone unoptimized(info()->shared_info());
269 // Note that we use the same AST that we will use for generating the 239 // Note that we use the same AST that we will use for generating the
270 // optimized code. 240 // optimized code.
271 unoptimized.SetFunction(info->function()); 241 unoptimized.SetFunction(info()->function());
272 unoptimized.SetScope(info->scope()); 242 unoptimized.SetScope(info()->scope());
273 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); 243 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
274 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); 244 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
275 if (should_recompile) { 245 if (should_recompile) {
276 if (!succeeded) return false; 246 if (!succeeded) return FAILED;
277 Handle<SharedFunctionInfo> shared = info->shared_info(); 247 Handle<SharedFunctionInfo> shared = info()->shared_info();
278 shared->EnableDeoptimizationSupport(*unoptimized.code()); 248 shared->EnableDeoptimizationSupport(*unoptimized.code());
279 // The existing unoptimized code was replaced with the new one. 249 // The existing unoptimized code was replaced with the new one.
280 Compiler::RecordFunctionCompilation( 250 Compiler::RecordFunctionCompilation(
281 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); 251 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
282 } 252 }
283 } 253 }
284 254
285 // Check that the unoptimized, shared code is ready for 255 // Check that the unoptimized, shared code is ready for
286 // optimizations. When using the always_opt flag we disregard the 256 // optimizations. When using the always_opt flag we disregard the
287 // optimizable marker in the code object and optimize anyway. This 257 // optimizable marker in the code object and optimize anyway. This
288 // is safe as long as the unoptimized code has deoptimization 258 // is safe as long as the unoptimized code has deoptimization
289 // support. 259 // support.
290 ASSERT(FLAG_always_opt || code->optimizable()); 260 ASSERT(FLAG_always_opt || code->optimizable());
291 ASSERT(info->shared_info()->has_deoptimization_support()); 261 ASSERT(info()->shared_info()->has_deoptimization_support());
292 262
293 if (FLAG_trace_hydrogen) { 263 if (FLAG_trace_hydrogen) {
294 PrintF("-----------------------------------------------------------\n"); 264 PrintF("-----------------------------------------------------------\n");
295 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); 265 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
296 HTracer::Instance()->TraceCompilation(info->function()); 266 HTracer::Instance()->TraceCompilation(info()->function());
267 }
268 Handle<Context> global_context(
danno 2012/07/16 12:19:09 This fits on one line like in the original, no?
sanjoy 2012/07/16 13:46:46 No, because I had to replace `info' with `info()'.
269 info()->closure()->context()->global_context());
270 oracle_ = new(info()->zone()) TypeFeedbackOracle(
271 code, global_context, info()->isolate(), info()->zone());
272 graph_builder_ = new(info()->zone()) HGraphBuilder(info(), oracle_);
273 HPhase phase(HPhase::kTotal);
274 graph_ = graph_builder_->CreateGraph();
275 is_inline_bailout_ = graph_builder_->inline_bailout();
276
277 if (info()->isolate()->has_pending_exception()) {
278 info()->SetCode(Handle<Code>::null());
279 return FAILED;
297 } 280 }
298 281
danno 2012/07/16 12:19:09 Don't add a line here, please keep original white
sanjoy 2012/07/16 13:46:46 Done.
sanjoy 2012/07/16 13:46:46 Done.
299 Handle<Context> global_context(info->closure()->context()->global_context()); 282 if (graph_ == NULL) {
300 TypeFeedbackOracle oracle(code, global_context, info->isolate(), 283 AbortCrankshaft();
301 info->zone()); 284 return BAILED_OUT;
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 } 285 }
309 286
310 if (graph != NULL) { 287 return SUCCEEDED;
311 SmartArrayPointer<char> bailout_reason; 288 }
312 if (!graph->Optimize(&bailout_reason)) { 289
313 if (!bailout_reason.is_empty()) builder.Bailout(*bailout_reason); 290 OptimizingCompiler::Status OptimizingCompiler::InnerOptimizeHGraph() {
314 } else { 291 Timer t(this);
315 LChunk* chunk = LChunk::NewChunk(graph); 292 ASSERT(graph_ != NULL);
316 if (chunk != NULL) { 293 SmartArrayPointer<char> bailout_reason;
317 Handle<Code> optimized_code = chunk->Codegen(); 294 if (!graph_->Optimize(&bailout_reason)) {
318 if (!optimized_code.is_null()) { 295 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
319 info->SetCode(optimized_code); 296 AbortCrankshaft();
320 FinishOptimization(info->closure(), start); 297 return BAILED_OUT;
danno 2012/07/16 12:19:09 How about AbortCrankshaft just returns a Optimizin
321 return true; 298 } else {
322 } 299 chunk_ = LChunk::NewChunk(graph_);
323 }
324 }
325 } 300 }
326 301 if (chunk_ == NULL) {
danno 2012/07/16 12:19:09 Why will chunk ever be null? It seems like the onl
sanjoy 2012/07/16 13:46:46 Done.
327 // Keep using the shared code. 302 AbortCrankshaft();
328 info->AbortOptimization(); 303 return BAILED_OUT;
329 if (!builder.inline_bailout()) { 304 } else {
330 // Mark the shared code as unoptimizable unless it was an inlined 305 return SUCCEEDED;
331 // function that bailed out.
332 info->shared_info()->DisableOptimization();
333 } 306 }
334 // True indicates the compilation pipeline is still going, not necessarily
335 // that we optimized the code.
336 return true;
337 } 307 }
338 308
339 309
310 OptimizingCompiler::Status OptimizingCompiler::InnerGenerateAndInstallCode() {
311 Timer timer(this);
312 ASSERT(chunk_ != NULL);
313 ASSERT(graph_ != NULL);
314 Handle<Code> optimized_code = chunk_->Codegen();
315 if (optimized_code.is_null()) {
316 AbortCrankshaft();
317 return BAILED_OUT;
318 }
319 info()->SetCode(optimized_code);
320 return SUCCEEDED;
321 }
322
323
324 void OptimizingCompiler::RecordOptimizationStats() {
danno 2012/07/16 12:19:09 Can you please move this back up to where FinishOp
sanjoy 2012/07/16 13:46:46 Done.
325 Handle<JSFunction> function = info()->closure();
326 int opt_count = function->shared()->opt_count();
327 function->shared()->set_opt_count(opt_count + 1);
328 double ms = static_cast<double>(total_time_taken_) / 1000;
329 if (FLAG_trace_opt) {
330 PrintF("[optimizing: ");
331 function->PrintName();
332 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
333 PrintF(" - took %0.3f ms]\n", ms);
334 }
335 if (FLAG_trace_opt_stats) {
336 static double compilation_time = 0.0;
337 static int compiled_functions = 0;
338 static int code_size = 0;
339
340 compilation_time += ms;
341 compiled_functions++;
342 code_size += function->shared()->SourceSize();
343 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
344 compiled_functions,
345 code_size,
346 compilation_time);
347 }
348 }
349
350 // A return value of true indicates the compilation pipeline is still
351 // going, not necessarily that we optimized the code.
352 static bool MakeCrankshaftCode(CompilationInfo* info) {
danno 2012/07/16 12:19:09 Can you please move this up where MakeCrankshaftCo
sanjoy 2012/07/16 13:46:46 Done.
353 OptimizingCompiler compiler(info);
354 OptimizingCompiler::Status status = compiler.CreateHGraph();
355
356 if (status == OptimizingCompiler::SUCCEEDED) {
357 status = compiler.OptimizeHGraph();
358 } else {
359 return status != OptimizingCompiler::FAILED;
360 }
361
362 if (status == OptimizingCompiler::SUCCEEDED) {
363 status = compiler.GenerateAndInstallCode();
364 }
365 return status != OptimizingCompiler::FAILED;
366 }
367
368
340 static bool GenerateCode(CompilationInfo* info) { 369 static bool GenerateCode(CompilationInfo* info) {
341 bool is_optimizing = V8::UseCrankshaft() && 370 bool is_optimizing = V8::UseCrankshaft() &&
342 !info->IsCompilingForDebugging() && 371 !info->IsCompilingForDebugging() &&
343 info->IsOptimizing(); 372 info->IsOptimizing();
344 if (is_optimizing) { 373 if (is_optimizing) {
345 return MakeCrankshaftCode(info); 374 return MakeCrankshaftCode(info);
346 } else { 375 } else {
347 if (info->IsOptimizing()) { 376 if (info->IsOptimizing()) {
348 // Have the CompilationInfo decide if the compilation should be 377 // Have the CompilationInfo decide if the compilation should be
349 // BASE or NONOPT. 378 // BASE or NONOPT.
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 } 907 }
879 } 908 }
880 909
881 GDBJIT(AddCode(Handle<String>(shared->DebugName()), 910 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
882 Handle<Script>(info->script()), 911 Handle<Script>(info->script()),
883 Handle<Code>(info->code()), 912 Handle<Code>(info->code()),
884 info)); 913 info));
885 } 914 }
886 915
887 } } // namespace v8::internal 916 } } // 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