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

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
« no previous file with comments | « src/compiler.h ('k') | src/hydrogen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 return status != OptimizingCompiler::FAILED;
207 }
208 status = compiler.OptimizeGraph();
209 if (status != OptimizingCompiler::SUCCEEDED) {
210 return status != OptimizingCompiler::FAILED;
211 }
212 status = compiler.GenerateAndInstallCode();
213 return status != OptimizingCompiler::FAILED;
214 }
215
216
217 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
195 ASSERT(V8::UseCrankshaft()); 218 ASSERT(V8::UseCrankshaft());
196 ASSERT(info->IsOptimizing()); 219 ASSERT(info()->IsOptimizing());
197 ASSERT(!info->IsCompilingForDebugging()); 220 ASSERT(!info()->IsCompilingForDebugging());
198 221
199 // We should never arrive here if there is not code object on the 222 // We should never arrive here if there is no code object on the
200 // shared function object. 223 // shared function object.
201 Handle<Code> code(info->shared_info()->code()); 224 Handle<Code> code(info()->shared_info()->code());
202 ASSERT(code->kind() == Code::FUNCTION); 225 ASSERT(code->kind() == Code::FUNCTION);
203 226
204 // We should never arrive here if optimization has been disabled on the 227 // We should never arrive here if optimization has been disabled on the
205 // shared function info. 228 // shared function info.
206 ASSERT(!info->shared_info()->optimization_disabled()); 229 ASSERT(!info()->shared_info()->optimization_disabled());
207 230
208 // Fall back to using the full code generator if it's not possible 231 // Fall back to using the full code generator if it's not possible
209 // to use the Hydrogen-based optimizing compiler. We already have 232 // to use the Hydrogen-based optimizing compiler. We already have
210 // generated code for this from the shared function object. 233 // generated code for this from the shared function object.
211 if (AlwaysFullCompiler(info->isolate())) { 234 if (AlwaysFullCompiler(info()->isolate())) {
212 info->SetCode(code); 235 info()->SetCode(code);
213 return true; 236 return SetLastStatus(BAILED_OUT);
214 } 237 }
215 238
216 // Limit the number of times we re-compile a functions with 239 // Limit the number of times we re-compile a functions with
217 // the optimizing compiler. 240 // the optimizing compiler.
218 const int kMaxOptCount = 241 const int kMaxOptCount =
219 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000; 242 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
220 if (info->shared_info()->opt_count() > kMaxOptCount) { 243 if (info()->shared_info()->opt_count() > kMaxOptCount) {
221 info->AbortOptimization(); 244 return AbortOptimization();
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 } 245 }
227 246
228 // Due to an encoding limit on LUnallocated operands in the Lithium 247 // Due to an encoding limit on LUnallocated operands in the Lithium
229 // language, we cannot optimize functions with too many formal parameters 248 // language, we cannot optimize functions with too many formal parameters
230 // or perform on-stack replacement for function with too many 249 // or perform on-stack replacement for function with too many
231 // stack-allocated local variables. 250 // stack-allocated local variables.
232 // 251 //
233 // The encoding is as a signed value, with parameters and receiver using 252 // The encoding is as a signed value, with parameters and receiver using
234 // the negative indices and locals the non-negative ones. 253 // the negative indices and locals the non-negative ones.
235 const int parameter_limit = -LUnallocated::kMinFixedIndex; 254 const int parameter_limit = -LUnallocated::kMinFixedIndex;
236 const int locals_limit = LUnallocated::kMaxFixedIndex; 255 const int locals_limit = LUnallocated::kMaxFixedIndex;
237 Scope* scope = info->scope(); 256 Scope* scope = info()->scope();
238 if ((scope->num_parameters() + 1) > parameter_limit || 257 if ((scope->num_parameters() + 1) > parameter_limit ||
239 (info->osr_ast_id() != AstNode::kNoNumber && 258 (info()->osr_ast_id() != AstNode::kNoNumber &&
240 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) { 259 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
241 info->AbortOptimization(); 260 return AbortOptimization();
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 } 261 }
247 262
248 // Take --hydrogen-filter into account. 263 // Take --hydrogen-filter into account.
249 Handle<String> name = info->function()->debug_name(); 264 Handle<String> name = info()->function()->debug_name();
250 if (*FLAG_hydrogen_filter != '\0') { 265 if (*FLAG_hydrogen_filter != '\0') {
251 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); 266 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
252 if ((filter[0] == '-' 267 if ((filter[0] == '-'
253 && name->IsEqualTo(filter.SubVector(1, filter.length()))) 268 && name->IsEqualTo(filter.SubVector(1, filter.length())))
254 || (filter[0] != '-' && !name->IsEqualTo(filter))) { 269 || (filter[0] != '-' && !name->IsEqualTo(filter))) {
255 info->SetCode(code); 270 info()->SetCode(code);
256 return true; 271 return SetLastStatus(BAILED_OUT);
257 } 272 }
258 } 273 }
259 274
260 // Recompile the unoptimized version of the code if the current version 275 // Recompile the unoptimized version of the code if the current version
261 // doesn't have deoptimization support. Alternatively, we may decide to 276 // doesn't have deoptimization support. Alternatively, we may decide to
262 // run the full code generator to get a baseline for the compile-time 277 // run the full code generator to get a baseline for the compile-time
263 // performance of the hydrogen-based compiler. 278 // performance of the hydrogen-based compiler.
264 int64_t start = OS::Ticks(); 279 Timer t(this, &time_taken_to_create_graph_);
265 bool should_recompile = !info->shared_info()->has_deoptimization_support(); 280 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
266 if (should_recompile || FLAG_hydrogen_stats) { 281 if (should_recompile || FLAG_hydrogen_stats) {
267 HPhase phase(HPhase::kFullCodeGen); 282 HPhase phase(HPhase::kFullCodeGen);
268 CompilationInfoWithZone unoptimized(info->shared_info()); 283 CompilationInfoWithZone unoptimized(info()->shared_info());
269 // Note that we use the same AST that we will use for generating the 284 // Note that we use the same AST that we will use for generating the
270 // optimized code. 285 // optimized code.
271 unoptimized.SetFunction(info->function()); 286 unoptimized.SetFunction(info()->function());
272 unoptimized.SetScope(info->scope()); 287 unoptimized.SetScope(info()->scope());
273 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); 288 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
274 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); 289 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
275 if (should_recompile) { 290 if (should_recompile) {
276 if (!succeeded) return false; 291 if (!succeeded) return SetLastStatus(FAILED);
277 Handle<SharedFunctionInfo> shared = info->shared_info(); 292 Handle<SharedFunctionInfo> shared = info()->shared_info();
278 shared->EnableDeoptimizationSupport(*unoptimized.code()); 293 shared->EnableDeoptimizationSupport(*unoptimized.code());
279 // The existing unoptimized code was replaced with the new one. 294 // The existing unoptimized code was replaced with the new one.
280 Compiler::RecordFunctionCompilation( 295 Compiler::RecordFunctionCompilation(
281 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); 296 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
282 } 297 }
283 } 298 }
284 299
285 // Check that the unoptimized, shared code is ready for 300 // Check that the unoptimized, shared code is ready for
286 // optimizations. When using the always_opt flag we disregard the 301 // optimizations. When using the always_opt flag we disregard the
287 // optimizable marker in the code object and optimize anyway. This 302 // optimizable marker in the code object and optimize anyway. This
288 // is safe as long as the unoptimized code has deoptimization 303 // is safe as long as the unoptimized code has deoptimization
289 // support. 304 // support.
290 ASSERT(FLAG_always_opt || code->optimizable()); 305 ASSERT(FLAG_always_opt || code->optimizable());
291 ASSERT(info->shared_info()->has_deoptimization_support()); 306 ASSERT(info()->shared_info()->has_deoptimization_support());
292 307
293 if (FLAG_trace_hydrogen) { 308 if (FLAG_trace_hydrogen) {
294 PrintF("-----------------------------------------------------------\n"); 309 PrintF("-----------------------------------------------------------\n");
295 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); 310 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
296 HTracer::Instance()->TraceCompilation(info->function()); 311 HTracer::Instance()->TraceCompilation(info()->function());
312 }
313 Handle<Context> global_context(
314 info()->closure()->context()->global_context());
315 oracle_ = new(info()->zone()) TypeFeedbackOracle(
316 code, global_context, info()->isolate(), info()->zone());
317 graph_builder_ = new(info()->zone()) HGraphBuilder(info(), oracle_);
318 HPhase phase(HPhase::kTotal);
319 graph_ = graph_builder_->CreateGraph();
320
321 if (info()->isolate()->has_pending_exception()) {
322 info()->SetCode(Handle<Code>::null());
323 return SetLastStatus(FAILED);
297 } 324 }
298 325
299 Handle<Context> global_context(info->closure()->context()->global_context()); 326 // The function being compiled may have bailed out due to an inline
300 TypeFeedbackOracle oracle(code, global_context, info->isolate(), 327 // candidate bailing out. In such a case, we don't disable
301 info->zone()); 328 // optimization on the shared_info.
302 HGraphBuilder builder(info, &oracle); 329 ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
303 HPhase phase(HPhase::kTotal); 330 if (graph_ == NULL) {
304 HGraph* graph = builder.CreateGraph(); 331 if (graph_builder_->inline_bailout()) {
305 if (info->isolate()->has_pending_exception()) { 332 info_->AbortOptimization();
306 info->SetCode(Handle<Code>::null()); 333 return SetLastStatus(BAILED_OUT);
307 return false;
308 }
309
310 if (graph != NULL) {
311 SmartArrayPointer<char> bailout_reason;
312 if (!graph->Optimize(&bailout_reason)) {
313 if (!bailout_reason.is_empty()) builder.Bailout(*bailout_reason);
314 } else { 334 } else {
315 LChunk* chunk = LChunk::NewChunk(graph); 335 return AbortOptimization();
316 if (chunk != NULL) {
317 Handle<Code> optimized_code = chunk->Codegen();
318 if (!optimized_code.is_null()) {
319 info->SetCode(optimized_code);
320 FinishOptimization(info->closure(), start);
321 return true;
322 }
323 }
324 } 336 }
325 } 337 }
326 338
327 // Keep using the shared code. 339 return SetLastStatus(SUCCEEDED);
328 info->AbortOptimization(); 340 }
329 if (!builder.inline_bailout()) { 341
330 // Mark the shared code as unoptimizable unless it was an inlined 342 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
331 // function that bailed out. 343 ASSERT(last_status_ != FAILED && last_status_ != BAILED_OUT);
332 info->shared_info()->DisableOptimization(); 344 Timer t(this, &time_taken_to_optimize_);
345 ASSERT(graph_ != NULL);
346 SmartArrayPointer<char> bailout_reason;
347 if (!graph_->Optimize(&bailout_reason)) {
348 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
349 return AbortOptimization();
350 } else {
351 chunk_ = LChunk::NewChunk(graph_);
352 if (chunk_ == NULL) {
353 return AbortOptimization();
354 }
333 } 355 }
334 // True indicates the compilation pipeline is still going, not necessarily 356 return SetLastStatus(SUCCEEDED);
335 // that we optimized the code.
336 return true;
337 } 357 }
338 358
339 359
360 OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
361 Timer timer(this, &time_taken_to_codegen_);
362 ASSERT(chunk_ != NULL);
363 ASSERT(graph_ != NULL);
364 Handle<Code> optimized_code = chunk_->Codegen();
365 if (optimized_code.is_null()) return AbortOptimization();
366 info()->SetCode(optimized_code);
367 RecordOptimizationStats();
368 return SetLastStatus(SUCCEEDED);
369 }
370
371
340 static bool GenerateCode(CompilationInfo* info) { 372 static bool GenerateCode(CompilationInfo* info) {
341 bool is_optimizing = V8::UseCrankshaft() && 373 bool is_optimizing = V8::UseCrankshaft() &&
342 !info->IsCompilingForDebugging() && 374 !info->IsCompilingForDebugging() &&
343 info->IsOptimizing(); 375 info->IsOptimizing();
344 if (is_optimizing) { 376 if (is_optimizing) {
345 return MakeCrankshaftCode(info); 377 return MakeCrankshaftCode(info);
346 } else { 378 } else {
347 if (info->IsOptimizing()) { 379 if (info->IsOptimizing()) {
348 // Have the CompilationInfo decide if the compilation should be 380 // Have the CompilationInfo decide if the compilation should be
349 // BASE or NONOPT. 381 // BASE or NONOPT.
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 } 910 }
879 } 911 }
880 912
881 GDBJIT(AddCode(Handle<String>(shared->DebugName()), 913 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
882 Handle<Script>(info->script()), 914 Handle<Script>(info->script()),
883 Handle<Code>(info->code()), 915 Handle<Code>(info->code()),
884 info)); 916 info));
885 } 917 }
886 918
887 } } // namespace v8::internal 919 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698