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

Side by Side Diff: src/compiler.cc

Issue 110203002: Refactor the compiling pipeline. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: move some code Created 7 years 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 52
53 namespace v8 { 53 namespace v8 {
54 namespace internal { 54 namespace internal {
55 55
56 56
57 CompilationInfo::CompilationInfo(Handle<Script> script, 57 CompilationInfo::CompilationInfo(Handle<Script> script,
58 Zone* zone) 58 Zone* zone)
59 : flags_(LanguageModeField::encode(CLASSIC_MODE)), 59 : flags_(LanguageModeField::encode(CLASSIC_MODE)),
60 script_(script), 60 script_(script),
61 osr_ast_id_(BailoutId::None()), 61 osr_ast_id_(BailoutId::None()),
62 osr_pc_offset_(0),
63 parameter_count_(0) { 62 parameter_count_(0) {
64 Initialize(script->GetIsolate(), BASE, zone); 63 Initialize(script->GetIsolate(), BASE, zone);
65 } 64 }
66 65
67 66
68 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, 67 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
69 Zone* zone) 68 Zone* zone)
70 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), 69 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
71 shared_info_(shared_info), 70 shared_info_(shared_info),
72 script_(Handle<Script>(Script::cast(shared_info->script()))), 71 script_(Handle<Script>(Script::cast(shared_info->script()))),
73 osr_ast_id_(BailoutId::None()), 72 osr_ast_id_(BailoutId::None()),
74 osr_pc_offset_(0),
75 parameter_count_(0) { 73 parameter_count_(0) {
76 Initialize(script_->GetIsolate(), BASE, zone); 74 Initialize(script_->GetIsolate(), BASE, zone);
77 } 75 }
78 76
79 77
80 CompilationInfo::CompilationInfo(Handle<JSFunction> closure, 78 CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
81 Zone* zone) 79 Zone* zone)
82 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), 80 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
83 closure_(closure), 81 closure_(closure),
84 shared_info_(Handle<SharedFunctionInfo>(closure->shared())), 82 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
85 script_(Handle<Script>(Script::cast(shared_info_->script()))), 83 script_(Handle<Script>(Script::cast(shared_info_->script()))),
86 context_(closure->context()), 84 context_(closure->context()),
87 osr_ast_id_(BailoutId::None()), 85 osr_ast_id_(BailoutId::None()),
88 osr_pc_offset_(0),
89 parameter_count_(0) { 86 parameter_count_(0) {
90 Initialize(script_->GetIsolate(), BASE, zone); 87 Initialize(script_->GetIsolate(), BASE, zone);
91 } 88 }
92 89
93 90
94 CompilationInfo::CompilationInfo(HydrogenCodeStub* stub, 91 CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
95 Isolate* isolate, 92 Isolate* isolate,
96 Zone* zone) 93 Zone* zone)
97 : flags_(LanguageModeField::encode(CLASSIC_MODE) | 94 : flags_(LanguageModeField::encode(CLASSIC_MODE) |
98 IsLazy::encode(true)), 95 IsLazy::encode(true)),
99 osr_ast_id_(BailoutId::None()), 96 osr_ast_id_(BailoutId::None()),
100 osr_pc_offset_(0),
101 parameter_count_(0) { 97 parameter_count_(0) {
102 Initialize(isolate, STUB, zone); 98 Initialize(isolate, STUB, zone);
103 code_stub_ = stub; 99 code_stub_ = stub;
104 } 100 }
105 101
106 102
107 void CompilationInfo::Initialize(Isolate* isolate, 103 void CompilationInfo::Initialize(Isolate* isolate,
108 Mode mode, 104 Mode mode,
109 Zone* zone) { 105 Zone* zone) {
110 isolate_ = isolate; 106 isolate_ = isolate;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time. 232 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
237 bool CompilationInfo::ShouldSelfOptimize() { 233 bool CompilationInfo::ShouldSelfOptimize() {
238 return FLAG_crankshaft && 234 return FLAG_crankshaft &&
239 !function()->flags()->Contains(kDontSelfOptimize) && 235 !function()->flags()->Contains(kDontSelfOptimize) &&
240 !function()->dont_optimize() && 236 !function()->dont_optimize() &&
241 function()->scope()->AllowsLazyCompilation() && 237 function()->scope()->AllowsLazyCompilation() &&
242 (shared_info().is_null() || !shared_info()->optimization_disabled()); 238 (shared_info().is_null() || !shared_info()->optimization_disabled());
243 } 239 }
244 240
245 241
246 // Determine whether to use the full compiler for all code. If the flag
247 // --always-full-compiler is specified this is the case. For the virtual frame
248 // based compiler the full compiler is also used if a debugger is connected, as
249 // the code from the full compiler supports mode precise break points. For the
250 // crankshaft adaptive compiler debugging the optimized code is not possible at
251 // all. However crankshaft support recompilation of functions, so in this case
252 // the full compiler need not be be used if a debugger is attached, but only if
253 // break points has actually been set.
254 static bool IsDebuggerActive(Isolate* isolate) {
255 #ifdef ENABLE_DEBUGGER_SUPPORT
256 return isolate->use_crankshaft() ?
257 isolate->debug()->has_break_points() :
258 isolate->debugger()->IsDebuggerActive();
259 #else
260 return false;
261 #endif
262 }
263
264
265 static bool AlwaysFullCompiler(Isolate* isolate) {
266 return FLAG_always_full_compiler || IsDebuggerActive(isolate);
267 }
268
269
270 void RecompileJob::RecordOptimizationStats() {
271 Handle<JSFunction> function = info()->closure();
272 if (!function->IsOptimized()) {
273 // Concurrent recompilation and OSR may race. Increment only once.
274 int opt_count = function->shared()->opt_count();
275 function->shared()->set_opt_count(opt_count + 1);
276 }
277 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
278 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
279 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
280 if (FLAG_trace_opt) {
281 PrintF("[optimizing ");
282 function->ShortPrint();
283 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
284 ms_codegen);
285 }
286 if (FLAG_trace_opt_stats) {
287 static double compilation_time = 0.0;
288 static int compiled_functions = 0;
289 static int code_size = 0;
290
291 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
292 compiled_functions++;
293 code_size += function->shared()->SourceSize();
294 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
295 compiled_functions,
296 code_size,
297 compilation_time);
298 }
299 if (FLAG_hydrogen_stats) {
300 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
301 time_taken_to_optimize_,
302 time_taken_to_codegen_);
303 }
304 }
305
306
307 // A return value of true indicates the compilation pipeline is still
308 // going, not necessarily that we optimized the code.
309 static bool MakeCrankshaftCode(CompilationInfo* info) {
310 RecompileJob job(info);
311 RecompileJob::Status status = job.CreateGraph();
312
313 if (status != RecompileJob::SUCCEEDED) {
314 return status != RecompileJob::FAILED;
315 }
316 status = job.OptimizeGraph();
317 if (status != RecompileJob::SUCCEEDED) {
318 status = job.AbortOptimization();
319 return status != RecompileJob::FAILED;
320 }
321 status = job.GenerateAndInstallCode();
322 return status != RecompileJob::FAILED;
323 }
324
325
326 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { 242 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
327 public: 243 public:
328 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) 244 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
329 : HOptimizedGraphBuilder(info) { 245 : HOptimizedGraphBuilder(info) {
330 } 246 }
331 247
332 #define DEF_VISIT(type) \ 248 #define DEF_VISIT(type) \
333 virtual void Visit##type(type* node) V8_OVERRIDE { \ 249 virtual void Visit##type(type* node) V8_OVERRIDE { \
334 if (node->position() != RelocInfo::kNoPosition) { \ 250 if (node->position() != RelocInfo::kNoPosition) { \
335 SetSourcePosition(node->position()); \ 251 SetSourcePosition(node->position()); \
(...skipping 17 matching lines...) Expand all
353 virtual void Visit##type(type* node) V8_OVERRIDE { \ 269 virtual void Visit##type(type* node) V8_OVERRIDE { \
354 HOptimizedGraphBuilder::Visit##type(node); \ 270 HOptimizedGraphBuilder::Visit##type(node); \
355 } 271 }
356 MODULE_NODE_LIST(DEF_VISIT) 272 MODULE_NODE_LIST(DEF_VISIT)
357 DECLARATION_NODE_LIST(DEF_VISIT) 273 DECLARATION_NODE_LIST(DEF_VISIT)
358 AUXILIARY_NODE_LIST(DEF_VISIT) 274 AUXILIARY_NODE_LIST(DEF_VISIT)
359 #undef DEF_VISIT 275 #undef DEF_VISIT
360 }; 276 };
361 277
362 278
279 // Determine whether to use the full compiler for all code. If the flag
280 // --always-full-compiler is specified this is the case. For the virtual frame
281 // based compiler the full compiler is also used if a debugger is connected, as
282 // the code from the full compiler supports mode precise break points. For the
283 // crankshaft adaptive compiler debugging the optimized code is not possible at
284 // all. However crankshaft support recompilation of functions, so in this case
285 // the full compiler need not be be used if a debugger is attached, but only if
286 // break points has actually been set.
287 static bool IsDebuggerActive(Isolate* isolate) {
288 #ifdef ENABLE_DEBUGGER_SUPPORT
289 return isolate->use_crankshaft() ?
290 isolate->debug()->has_break_points() :
291 isolate->debugger()->IsDebuggerActive();
292 #else
293 return false;
294 #endif
295 }
296
297
363 RecompileJob::Status RecompileJob::CreateGraph() { 298 RecompileJob::Status RecompileJob::CreateGraph() {
364 ASSERT(isolate()->use_crankshaft()); 299 ASSERT(isolate()->use_crankshaft());
365 ASSERT(info()->IsOptimizing()); 300 ASSERT(info()->IsOptimizing());
366 ASSERT(!info()->IsCompilingForDebugging()); 301 ASSERT(!info()->IsCompilingForDebugging());
367 302
368 // We should never arrive here if there is no code object on the 303 // We should never arrive here if there is no code object on the
369 // shared function object. 304 // shared function object.
370 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION); 305 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION);
371 306
372 // We should never arrive here if optimization has been disabled on the 307 // We should never arrive here if optimization has been disabled on the
373 // shared function info. 308 // shared function info.
374 ASSERT(!info()->shared_info()->optimization_disabled()); 309 ASSERT(!info()->shared_info()->optimization_disabled());
375 310
376 // Fall back to using the full code generator if it's not possible 311 // Fall back to using the full code generator if it's not possible
377 // to use the Hydrogen-based optimizing compiler. We already have 312 // to use the Hydrogen-based optimizing compiler. We already have
378 // generated code for this from the shared function object. 313 // generated code for this from the shared function object.
379 if (AlwaysFullCompiler(isolate())) { 314 if (FLAG_always_full_compiler || IsDebuggerActive(isolate())) {
380 info()->AbortOptimization(); 315 return AbortOptimization();
381 return SetLastStatus(BAILED_OUT);
382 } 316 }
383 317
384 // Limit the number of times we re-compile a functions with 318 // Limit the number of times we re-compile a functions with
385 // the optimizing compiler. 319 // the optimizing compiler.
386 const int kMaxOptCount = 320 const int kMaxOptCount =
387 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; 321 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
388 if (info()->opt_count() > kMaxOptCount) { 322 if (info()->opt_count() > kMaxOptCount) {
389 info()->set_bailout_reason(kOptimizedTooManyTimes); 323 info()->set_bailout_reason(kOptimizedTooManyTimes);
390 return AbortOptimization(); 324 return AbortAndDisableOptimization();
391 } 325 }
392 326
393 // Due to an encoding limit on LUnallocated operands in the Lithium 327 // Due to an encoding limit on LUnallocated operands in the Lithium
394 // language, we cannot optimize functions with too many formal parameters 328 // language, we cannot optimize functions with too many formal parameters
395 // or perform on-stack replacement for function with too many 329 // or perform on-stack replacement for function with too many
396 // stack-allocated local variables. 330 // stack-allocated local variables.
397 // 331 //
398 // The encoding is as a signed value, with parameters and receiver using 332 // The encoding is as a signed value, with parameters and receiver using
399 // the negative indices and locals the non-negative ones. 333 // the negative indices and locals the non-negative ones.
400 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; 334 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
401 Scope* scope = info()->scope(); 335 Scope* scope = info()->scope();
402 if ((scope->num_parameters() + 1) > parameter_limit) { 336 if ((scope->num_parameters() + 1) > parameter_limit) {
403 info()->set_bailout_reason(kTooManyParameters); 337 info()->set_bailout_reason(kTooManyParameters);
404 return AbortOptimization(); 338 return AbortAndDisableOptimization();
405 } 339 }
406 340
407 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; 341 const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
408 if (info()->is_osr() && 342 if (info()->is_osr() &&
409 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { 343 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
410 info()->set_bailout_reason(kTooManyParametersLocals); 344 info()->set_bailout_reason(kTooManyParametersLocals);
411 return AbortOptimization(); 345 return AbortAndDisableOptimization();
412 } 346 }
413 347
414 // Take --hydrogen-filter into account. 348 // Take --hydrogen-filter into account.
415 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { 349 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
titzer 2013/12/09 14:49:28 Do we also want to set a bailout reason and disabl
Yang 2013/12/10 11:22:04 Done.
416 info()->AbortOptimization(); 350 return AbortOptimization();
417 return SetLastStatus(BAILED_OUT);
418 } 351 }
419 352
420 // Recompile the unoptimized version of the code if the current version 353 // Recompile the unoptimized version of the code if the current version
421 // doesn't have deoptimization support. Alternatively, we may decide to 354 // doesn't have deoptimization support. Alternatively, we may decide to
422 // run the full code generator to get a baseline for the compile-time 355 // run the full code generator to get a baseline for the compile-time
423 // performance of the hydrogen-based compiler. 356 // performance of the hydrogen-based compiler.
424 bool should_recompile = !info()->shared_info()->has_deoptimization_support(); 357 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
425 if (should_recompile || FLAG_hydrogen_stats) { 358 if (should_recompile || FLAG_hydrogen_stats) {
426 ElapsedTimer timer; 359 ElapsedTimer timer;
427 if (FLAG_hydrogen_stats) { 360 if (FLAG_hydrogen_stats) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 AstTyper::Run(info()); 400 AstTyper::Run(info());
468 401
469 graph_builder_ = FLAG_emit_opt_code_positions 402 graph_builder_ = FLAG_emit_opt_code_positions
470 ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info()) 403 ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info())
471 : new(info()->zone()) HOptimizedGraphBuilder(info()); 404 : new(info()->zone()) HOptimizedGraphBuilder(info());
472 405
473 Timer t(this, &time_taken_to_create_graph_); 406 Timer t(this, &time_taken_to_create_graph_);
474 graph_ = graph_builder_->CreateGraph(); 407 graph_ = graph_builder_->CreateGraph();
475 408
476 if (isolate()->has_pending_exception()) { 409 if (isolate()->has_pending_exception()) {
477 info()->SetCode(Handle<Code>::null());
478 return SetLastStatus(FAILED); 410 return SetLastStatus(FAILED);
479 } 411 }
480 412
481 // The function being compiled may have bailed out due to an inline 413 // The function being compiled may have bailed out due to an inline
482 // candidate bailing out. In such a case, we don't disable 414 // candidate bailing out. In such a case, we don't disable
483 // optimization on the shared_info. 415 // optimization on the shared_info.
484 ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL); 416 ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
485 if (graph_ == NULL) { 417 if (graph_ == NULL) {
486 if (graph_builder_->inline_bailout()) { 418 if (graph_builder_->inline_bailout()) {
487 info_->AbortOptimization(); 419 return AbortOptimization();
488 return SetLastStatus(BAILED_OUT);
489 } else { 420 } else {
490 return AbortOptimization(); 421 return AbortAndDisableOptimization();
491 } 422 }
492 } 423 }
493 424
494 if (info()->HasAbortedDueToDependencyChange()) { 425 if (info()->HasAbortedDueToDependencyChange()) {
495 info_->set_bailout_reason(kBailedOutDueToDependencyChange); 426 info_->set_bailout_reason(kBailedOutDueToDependencyChange);
496 info_->AbortOptimization(); 427 return AbortOptimization();
497 return SetLastStatus(BAILED_OUT);
498 } 428 }
499 429
500 return SetLastStatus(SUCCEEDED); 430 return SetLastStatus(SUCCEEDED);
501 } 431 }
502 432
503 433
504 RecompileJob::Status RecompileJob::OptimizeGraph() { 434 RecompileJob::Status RecompileJob::OptimizeGraph() {
505 DisallowHeapAllocation no_allocation; 435 DisallowHeapAllocation no_allocation;
506 DisallowHandleAllocation no_handles; 436 DisallowHandleAllocation no_handles;
507 DisallowHandleDereference no_deref; 437 DisallowHandleDereference no_deref;
508 DisallowCodeDependencyChange no_dependency_change; 438 DisallowCodeDependencyChange no_dependency_change;
509 439
510 ASSERT(last_status() == SUCCEEDED); 440 ASSERT(last_status() == SUCCEEDED);
511 Timer t(this, &time_taken_to_optimize_); 441 Timer t(this, &time_taken_to_optimize_);
512 ASSERT(graph_ != NULL); 442 ASSERT(graph_ != NULL);
513 BailoutReason bailout_reason = kNoReason; 443 BailoutReason bailout_reason = kNoReason;
514 if (!graph_->Optimize(&bailout_reason)) { 444
515 if (bailout_reason != kNoReason) graph_builder_->Bailout(bailout_reason); 445 if (graph_->Optimize(&bailout_reason)) {
516 return SetLastStatus(BAILED_OUT);
517 } else {
518 chunk_ = LChunk::NewChunk(graph_); 446 chunk_ = LChunk::NewChunk(graph_);
519 if (chunk_ == NULL) { 447 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
520 return SetLastStatus(BAILED_OUT); 448 } else if (bailout_reason != kNoReason) {
521 } 449 graph_builder_->Bailout(bailout_reason);
522 } 450 }
523 return SetLastStatus(SUCCEEDED); 451
452 return AbortOptimization();
524 } 453 }
525 454
526 455
527 RecompileJob::Status RecompileJob::GenerateAndInstallCode() { 456 RecompileJob::Status RecompileJob::GenerateCode() {
528 ASSERT(last_status() == SUCCEEDED); 457 ASSERT(last_status() == SUCCEEDED);
529 ASSERT(!info()->HasAbortedDueToDependencyChange()); 458 ASSERT(!info()->HasAbortedDueToDependencyChange());
530 DisallowCodeDependencyChange no_dependency_change; 459 DisallowCodeDependencyChange no_dependency_change;
531 { // Scope for timer. 460 { // Scope for timer.
532 Timer timer(this, &time_taken_to_codegen_); 461 Timer timer(this, &time_taken_to_codegen_);
533 ASSERT(chunk_ != NULL); 462 ASSERT(chunk_ != NULL);
534 ASSERT(graph_ != NULL); 463 ASSERT(graph_ != NULL);
535 // Deferred handles reference objects that were accessible during 464 // Deferred handles reference objects that were accessible during
536 // graph creation. To make sure that we don't encounter inconsistencies 465 // graph creation. To make sure that we don't encounter inconsistencies
537 // between graph creation and code generation, we disallow accessing 466 // between graph creation and code generation, we disallow accessing
538 // objects through deferred handles during the latter, with exceptions. 467 // objects through deferred handles during the latter, with exceptions.
539 DisallowDeferredHandleDereference no_deferred_handle_deref; 468 DisallowDeferredHandleDereference no_deferred_handle_deref;
540 Handle<Code> optimized_code = chunk_->Codegen(); 469 Handle<Code> optimized_code = chunk_->Codegen();
541 if (optimized_code.is_null()) { 470 if (optimized_code.is_null()) {
542 if (info()->bailout_reason() == kNoReason) { 471 if (info()->bailout_reason() == kNoReason) {
543 info()->set_bailout_reason(kCodeGenerationFailed); 472 info()->set_bailout_reason(kCodeGenerationFailed);
544 } 473 }
545 return AbortOptimization(); 474 return AbortAndDisableOptimization();
546 } 475 }
547 info()->SetCode(optimized_code); 476 info()->SetCode(optimized_code);
548 } 477 }
549 RecordOptimizationStats(); 478 RecordOptimizationStats();
550 // Add to the weak list of optimized code objects. 479 // Add to the weak list of optimized code objects.
551 info()->context()->native_context()->AddOptimizedCode(*info()->code()); 480 info()->context()->native_context()->AddOptimizedCode(*info()->code());
552 return SetLastStatus(SUCCEEDED); 481 return SetLastStatus(SUCCEEDED);
553 } 482 }
554 483
555 484
556 static bool GenerateCode(CompilationInfo* info) { 485 void RecompileJob::RecordOptimizationStats() {
557 bool is_optimizing = info->isolate()->use_crankshaft() && 486 Handle<JSFunction> function = info()->closure();
558 !info->IsCompilingForDebugging() && 487 if (!function->IsOptimized()) {
559 info->IsOptimizing(); 488 // Concurrent recompilation and OSR may race. Increment only once.
560 if (is_optimizing) { 489 int opt_count = function->shared()->opt_count();
561 Logger::TimerEventScope timer( 490 function->shared()->set_opt_count(opt_count + 1);
562 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous); 491 }
563 return MakeCrankshaftCode(info); 492 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
564 } else { 493 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
565 if (info->IsOptimizing()) { 494 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
566 // Have the CompilationInfo decide if the compilation should be 495 if (FLAG_trace_opt) {
567 // BASE or NONOPT. 496 PrintF("[optimizing ");
568 info->DisableOptimization(); 497 function->ShortPrint();
569 } 498 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
570 Logger::TimerEventScope timer( 499 ms_codegen);
571 info->isolate(), Logger::TimerEventScope::v8_compile_full_code); 500 }
572 return FullCodeGenerator::MakeCode(info); 501 if (FLAG_trace_opt_stats) {
502 static double compilation_time = 0.0;
503 static int compiled_functions = 0;
504 static int code_size = 0;
505
506 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
507 compiled_functions++;
508 code_size += function->shared()->SourceSize();
509 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
510 compiled_functions,
511 code_size,
512 compilation_time);
513 }
514 if (FLAG_hydrogen_stats) {
515 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
516 time_taken_to_optimize_,
517 time_taken_to_codegen_);
573 } 518 }
574 } 519 }
575 520
576 521
577 static bool MakeCode(CompilationInfo* info) {
578 // Precondition: code has been parsed. Postcondition: the code field in
579 // the compilation info is set if compilation succeeded.
580 ASSERT(info->function() != NULL);
581 return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
582 }
583
584
585 #ifdef ENABLE_DEBUGGER_SUPPORT
586 bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
587 // Precondition: code has been parsed. Postcondition: the code field in
588 // the compilation info is set if compilation succeeded.
589 bool succeeded = MakeCode(info);
590 if (!info->shared_info().is_null()) {
591 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(),
592 info->zone());
593 info->shared_info()->set_scope_info(*scope_info);
594 }
595 return succeeded;
596 }
597 #endif
598
599
600 static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
601 bool allow_lazy_without_ctx = false) {
602 return LiveEditFunctionTracker::IsActive(info->isolate()) ||
603 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
604 }
605
606
607 // Sets the expected number of properties based on estimate from compiler. 522 // Sets the expected number of properties based on estimate from compiler.
608 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, 523 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
609 int estimate) { 524 int estimate) {
610 // See the comment in SetExpectedNofProperties. 525 // See the comment in SetExpectedNofProperties.
611 if (shared->live_objects_may_exist()) return; 526 if (shared->live_objects_may_exist()) return;
612 527
613 // If no properties are added in the constructor, they are more likely 528 // If no properties are added in the constructor, they are more likely
614 // to be added later. 529 // to be added later.
615 if (estimate == 0) estimate = 2; 530 if (estimate == 0) estimate = 2;
616 531
617 // TODO(yangguo): check whether those heuristics are still up-to-date. 532 // TODO(yangguo): check whether those heuristics are still up-to-date.
618 // We do not shrink objects that go into a snapshot (yet), so we adjust 533 // We do not shrink objects that go into a snapshot (yet), so we adjust
619 // the estimate conservatively. 534 // the estimate conservatively.
620 if (Serializer::enabled()) { 535 if (Serializer::enabled()) {
621 estimate += 2; 536 estimate += 2;
622 } else if (FLAG_clever_optimizations) { 537 } else if (FLAG_clever_optimizations) {
623 // Inobject slack tracking will reclaim redundant inobject space later, 538 // Inobject slack tracking will reclaim redundant inobject space later,
624 // so we can afford to adjust the estimate generously. 539 // so we can afford to adjust the estimate generously.
625 estimate += 8; 540 estimate += 8;
626 } else { 541 } else {
627 estimate += 3; 542 estimate += 3;
628 } 543 }
629 544
630 shared->set_expected_nof_properties(estimate); 545 shared->set_expected_nof_properties(estimate);
631 } 546 }
632 547
633 548
634 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { 549 static void UpdateSharedFunctionInfo(CompilationInfo* info) {
550 // Update the shared function info with the compiled code and the
551 // scope info. Please note, that the order of the shared function
552 // info initialization is important since set_scope_info might
553 // trigger a GC, causing the ASSERT below to be invalid if the code
554 // was flushed. By setting the code object last we avoid this.
555 Handle<SharedFunctionInfo> shared = info->shared_info();
556 Handle<ScopeInfo> scope_info =
557 ScopeInfo::Create(info->scope(), info->zone());
558 shared->set_scope_info(*scope_info);
559
560 Handle<Code> code = info->code();
561 CHECK(code->kind() == Code::FUNCTION);
562 shared->ReplaceCode(*code);
563 if (shared->optimization_disabled()) code->set_optimizable(false);
564
565 // Set the expected number of properties for instances.
566 FunctionLiteral* lit = info->function();
567 int expected = lit->expected_property_count();
568 SetExpectedNofPropertiesFromEstimate(shared, expected);
569
570 // Check the function has compiled code.
571 ASSERT(shared->is_compiled());
572 shared->set_dont_optimize_reason(lit->dont_optimize_reason());
573 shared->set_dont_inline(lit->flags()->Contains(kDontInline));
574 shared->set_ast_node_count(lit->ast_node_count());
575 shared->set_language_mode(lit->language_mode());
576 }
577
578
579 // Sets the function info on a function.
580 // The start_position points to the first '(' character after the function name
581 // in the full script source. When counting characters in the script source the
582 // the first character is number 0 (not 1).
583 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
584 FunctionLiteral* lit,
585 bool is_toplevel,
586 Handle<Script> script) {
587 function_info->set_length(lit->parameter_count());
588 function_info->set_formal_parameter_count(lit->parameter_count());
589 function_info->set_script(*script);
590 function_info->set_function_token_position(lit->function_token_position());
591 function_info->set_start_position(lit->start_position());
592 function_info->set_end_position(lit->end_position());
593 function_info->set_is_expression(lit->is_expression());
594 function_info->set_is_anonymous(lit->is_anonymous());
595 function_info->set_is_toplevel(is_toplevel);
596 function_info->set_inferred_name(*lit->inferred_name());
597 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
598 function_info->set_allows_lazy_compilation_without_context(
599 lit->AllowsLazyCompilationWithoutContext());
600 function_info->set_language_mode(lit->language_mode());
601 function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
602 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
603 function_info->set_ast_node_count(lit->ast_node_count());
604 function_info->set_is_function(lit->is_function());
605 function_info->set_dont_optimize_reason(lit->dont_optimize_reason());
606 function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
607 function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
608 function_info->set_is_generator(lit->is_generator());
609 }
610
611
612 static bool CompileUnoptimizedCode(CompilationInfo* info) {
613 ASSERT(info->function() != NULL);
614 if (!Rewriter::Rewrite(info)) return false;
615 if (!Scope::Analyze(info)) return false;
616 ASSERT(info->scope() != NULL);
617
618 if (!FullCodeGenerator::MakeCode(info)) {
619 Isolate* isolate = info->isolate();
620 if (!isolate->has_pending_exception()) isolate->StackOverflow();
621 return false;
622 }
623 return true;
624 }
625
626
627 static Handle<Code> GetUnoptimizedCodeCommon(CompilationInfo* info) {
628 VMState<COMPILER> state(info->isolate());
629 PostponeInterruptsScope postpone(info->isolate());
630 if (!Parser::Parse(info)) return Handle<Code>::null();
631 LanguageMode language_mode = info->function()->language_mode();
632 info->SetLanguageMode(language_mode);
633
634 if (!CompileUnoptimizedCode(info)) return Handle<Code>::null();
635 Compiler::RecordFunctionCompilation(
636 Logger::LAZY_COMPILE_TAG, info, info->shared_info());
637 UpdateSharedFunctionInfo(info);
638 ASSERT_EQ(Code::FUNCTION, info->code()->kind());
639 return info->code();
640 }
641
642
643 Handle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
644 ASSERT(!function->GetIsolate()->has_pending_exception());
645 ASSERT(!function->is_compiled());
646 if (function->shared()->is_compiled()) {
647 return Handle<Code>(function->shared()->code());
648 }
649
650 CompilationInfoWithZone info(function);
651 Handle<Code> result = GetUnoptimizedCodeCommon(&info);
652 ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
653
654 if (FLAG_always_opt &&
655 info.isolate()->use_crankshaft() &&
656 !info.shared_info()->optimization_disabled() &&
657 !info.isolate()->DebuggerHasBreakPoints()) {
658 result = Compiler::GetOptimizedCode(
659 function, result, Compiler::NOT_CONCURRENT);
660 }
661
662 return result;
663 }
664
665
666 Handle<Code> Compiler::GetUnoptimizedCode(Handle<SharedFunctionInfo> shared) {
667 ASSERT(!shared->GetIsolate()->has_pending_exception());
668 ASSERT(!shared->is_compiled());
669
670 CompilationInfoWithZone info(shared);
671 Handle<Code> result = GetUnoptimizedCodeCommon(&info);
672 ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
673 return result;
674 }
675
676
677 bool Compiler::EnsureCompiled(Handle<JSFunction> function,
678 ClearExceptionFlag flag) {
679 if (function->is_compiled()) return true;
680 Handle<Code> code = Compiler::GetUnoptimizedCode(function);
681 if (code.is_null()) {
682 if (flag == CLEAR_EXCEPTION) {
683 function->GetIsolate()->clear_pending_exception();
684 }
685 return false;
686 }
687 function->ReplaceCode(*code);
688 ASSERT(function->is_compiled());
689 return true;
690 }
691
692
693 // Compile full code for debugging. This code will have debug break slots
694 // and deoptimization information. Deoptimization information is required
695 // in case that an optimized version of this function is still activated on
696 // the stack. It will also make sure that the full code is compiled with
697 // the same flags as the previous version, that is flags which can change
698 // the code generated. The current method of mapping from already compiled
699 // full code without debug break slots to full code with debug break slots
700 // depends on the generated code is otherwise exactly the same.
701 // If compilation fails, just keep the existing code.
702 Handle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) {
703 CompilationInfoWithZone info(function);
704 Isolate* isolate = info.isolate();
705 VMState<COMPILER> state(isolate);
706
707 ASSERT(!isolate->has_pending_exception());
708 Handle<Code> old_code(function->shared()->code());
709 ASSERT(old_code->kind() == Code::FUNCTION);
710 ASSERT(!old_code->has_debug_break_slots());
711
712 info.MarkCompilingForDebugging();
713 if (old_code->is_compiled_optimizable()) {
714 info.EnableDeoptimizationSupport();
715 } else {
716 info.MarkNonOptimizable();
717 }
718 Handle<Code> new_code = GetUnoptimizedCodeCommon(&info);
719 if (new_code.is_null()) {
720 isolate->clear_pending_exception();
721 } else {
722 ASSERT_EQ(old_code->is_compiled_optimizable(),
723 new_code->is_compiled_optimizable());
724 }
725 return new_code;
726 }
727
728
729 #ifdef ENABLE_DEBUGGER_SUPPORT
730 void Compiler::CompileForLiveEdit(Handle<Script> script) {
731 // TODO(635): support extensions.
732 CompilationInfoWithZone info(script);
733 VMState<COMPILER> state(info.isolate());
734
735 info.MarkAsGlobal();
736 if (!Parser::Parse(&info)) return;
737 LanguageMode language_mode = info.function()->language_mode();
738 info.SetLanguageMode(language_mode);
739
740 LiveEditFunctionTracker tracker(info.isolate(), info.function());
741 if (!CompileUnoptimizedCode(&info)) return;
742 if (!info.shared_info().is_null()) {
743 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info.scope(),
744 info.zone());
745 info.shared_info()->set_scope_info(*scope_info);
746 }
747 tracker.RecordRootFunctionInfo(info.code());
748 }
749 #endif
750
751
752 static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
753 bool allow_lazy_without_ctx = false) {
754 return LiveEditFunctionTracker::IsActive(info->isolate()) ||
755 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
756 }
757
758
759 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
635 Isolate* isolate = info->isolate(); 760 Isolate* isolate = info->isolate();
636 PostponeInterruptsScope postpone(isolate);
637
638 ASSERT(!isolate->native_context().is_null()); 761 ASSERT(!isolate->native_context().is_null());
639 Handle<Script> script = info->script(); 762 Handle<Script> script = info->script();
763
640 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? 764 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
641 FixedArray* array = isolate->native_context()->embedder_data(); 765 FixedArray* array = isolate->native_context()->embedder_data();
642 script->set_context_data(array->get(0)); 766 script->set_context_data(array->get(0));
643 767
644 #ifdef ENABLE_DEBUGGER_SUPPORT 768 #ifdef ENABLE_DEBUGGER_SUPPORT
645 if (info->is_eval()) {
646 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
647 // For eval scripts add information on the function from which eval was
648 // called.
649 if (info->is_eval()) {
650 StackTraceFrameIterator it(isolate);
651 if (!it.done()) {
652 script->set_eval_from_shared(it.frame()->function()->shared());
653 Code* code = it.frame()->LookupCode();
654 int offset = static_cast<int>(
655 it.frame()->pc() - code->instruction_start());
656 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
657 }
658 }
659 }
660
661 // Notify debugger
662 isolate->debugger()->OnBeforeCompile(script); 769 isolate->debugger()->OnBeforeCompile(script);
663 #endif 770 #endif
664 771
665 // Only allow non-global compiles for eval.
666 ASSERT(info->is_eval() || info->is_global()); 772 ASSERT(info->is_eval() || info->is_global());
667 { 773
668 Parser parser(info); 774 bool parse_allow_lazy =
669 if ((info->pre_parse_data() != NULL || 775 (info->pre_parse_data() != NULL ||
670 String::cast(script->source())->length() > FLAG_min_preparse_length) && 776 String::cast(script->source())->length() > FLAG_min_preparse_length) &&
671 !DebuggerWantsEagerCompilation(info)) 777 !DebuggerWantsEagerCompilation(info);
672 parser.set_allow_lazy(true); 778
673 if (!parser.Parse()) { 779 Handle<SharedFunctionInfo> result;
780
781 { VMState<COMPILER> state(info->isolate());
782 if (!Parser::Parse(info, parse_allow_lazy)) {
674 return Handle<SharedFunctionInfo>::null(); 783 return Handle<SharedFunctionInfo>::null();
675 } 784 }
676 } 785
677 786 FunctionLiteral* lit = info->function();
678 FunctionLiteral* lit = info->function(); 787 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
679 LiveEditFunctionTracker live_edit_tracker(isolate, lit); 788
680 Handle<SharedFunctionInfo> result;
681 {
682 // Measure how long it takes to do the compilation; only take the 789 // Measure how long it takes to do the compilation; only take the
683 // rest of the function into account to avoid overlap with the 790 // rest of the function into account to avoid overlap with the
684 // parsing statistics. 791 // parsing statistics.
685 HistogramTimer* rate = info->is_eval() 792 HistogramTimer* rate = info->is_eval()
686 ? info->isolate()->counters()->compile_eval() 793 ? info->isolate()->counters()->compile_eval()
687 : info->isolate()->counters()->compile(); 794 : info->isolate()->counters()->compile();
688 HistogramTimerScope timer(rate); 795 HistogramTimerScope timer(rate);
689 796
690 // Compile the code. 797 // Compile the code.
691 if (!MakeCode(info)) { 798 if (!CompileUnoptimizedCode(info)) {
692 if (!isolate->has_pending_exception()) isolate->StackOverflow();
693 return Handle<SharedFunctionInfo>::null(); 799 return Handle<SharedFunctionInfo>::null();
694 } 800 }
695 801
696 // Allocate function. 802 // Allocate function.
697 ASSERT(!info->code().is_null()); 803 ASSERT(!info->code().is_null());
698 result = 804 result = isolate->factory()->NewSharedFunctionInfo(
699 isolate->factory()->NewSharedFunctionInfo( 805 lit->name(),
700 lit->name(), 806 lit->materialized_literal_count(),
701 lit->materialized_literal_count(), 807 lit->is_generator(),
702 lit->is_generator(), 808 info->code(),
703 info->code(), 809 ScopeInfo::Create(info->scope(), info->zone()));
704 ScopeInfo::Create(info->scope(), info->zone()));
705 810
706 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); 811 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
707 Compiler::SetFunctionInfo(result, lit, true, script); 812 SetFunctionInfo(result, lit, true, script);
708 813
709 if (script->name()->IsString()) { 814 Handle<String> script_name = script->name()->IsString()
710 PROFILE(isolate, CodeCreateEvent( 815 ? Handle<String>(String::cast(script->name()))
711 info->is_eval() 816 : isolate->factory()->empty_string();
712 ? Logger::EVAL_TAG 817 Logger::LogEventsAndTags log_tag = info->is_eval()
713 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), 818 ? Logger::EVAL_TAG
714 *info->code(), 819 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
715 *result, 820
716 info, 821 PROFILE(isolate, CodeCreateEvent(
717 String::cast(script->name()))); 822 log_tag, *info->code(), *result, info, *script_name));
718 GDBJIT(AddCode(Handle<String>(String::cast(script->name())), 823 GDBJIT(AddCode(script_name, script, info->code(), info));
719 script,
720 info->code(),
721 info));
722 } else {
723 PROFILE(isolate, CodeCreateEvent(
724 info->is_eval()
725 ? Logger::EVAL_TAG
726 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
727 *info->code(),
728 *result,
729 info,
730 isolate->heap()->empty_string()));
731 GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
732 }
733 824
734 // Hint to the runtime system used when allocating space for initial 825 // Hint to the runtime system used when allocating space for initial
735 // property space by setting the expected number of properties for 826 // property space by setting the expected number of properties for
736 // the instances of the function. 827 // the instances of the function.
737 SetExpectedNofPropertiesFromEstimate(result, 828 SetExpectedNofPropertiesFromEstimate(result,
738 lit->expected_property_count()); 829 lit->expected_property_count());
739 830
740 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); 831 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
832
833 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
741 } 834 }
742 835
743 #ifdef ENABLE_DEBUGGER_SUPPORT 836 #ifdef ENABLE_DEBUGGER_SUPPORT
744 // Notify debugger 837 isolate->debugger()->OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
745 isolate->debugger()->OnAfterCompile(
746 script, Debugger::NO_AFTER_COMPILE_FLAGS);
747 #endif 838 #endif
748 839
749 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
750
751 return result; 840 return result;
752 } 841 }
753 842
754 843
755 Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, 844 Handle<JSFunction> Compiler::GetFunctionFromEval(Handle<String> source,
756 Handle<Object> script_name, 845 Handle<Context> context,
757 int line_offset, 846 LanguageMode language_mode,
758 int column_offset, 847 ParseRestriction restriction,
759 bool is_shared_cross_origin, 848 int scope_position) {
760 Handle<Context> context, 849 Isolate* isolate = source->GetIsolate();
761 v8::Extension* extension, 850 int source_length = source->length();
762 ScriptDataImpl* pre_data, 851 isolate->counters()->total_eval_size()->Increment(source_length);
763 Handle<Object> script_data, 852 isolate->counters()->total_compile_size()->Increment(source_length);
764 NativesFlag natives) { 853
854 CompilationCache* compilation_cache = isolate->compilation_cache();
855 Handle<SharedFunctionInfo> shared_info = compilation_cache->LookupEval(
856 source, context, language_mode, scope_position);
857
858 if (shared_info.is_null()) {
859 Handle<Script> script = isolate->factory()->NewScript(source);
860 CompilationInfoWithZone info(script);
861 info.MarkAsEval();
862 if (context->IsNativeContext()) info.MarkAsGlobal();
863 info.SetLanguageMode(language_mode);
864 info.SetParseRestriction(restriction);
865 info.SetContext(context);
866
867 #if ENABLE_DEBUGGER_SUPPORT
868 Debug::RecordEvalCaller(script);
869 #endif // ENABLE_DEBUGGER_SUPPORT
870
871 shared_info = CompileToplevel(&info);
872
873 if (shared_info.is_null()) {
874 return Handle<JSFunction>::null();
875 } else {
876 // Explicitly disable optimization for eval code. We're not yet prepared
877 // to handle eval-code in the optimizing compiler.
878 shared_info->DisableOptimization(kEval);
879
880 // If caller is strict mode, the result must be in strict mode or
881 // extended mode as well, but not the other way around. Consider:
882 // eval("'use strict'; ...");
883 ASSERT(language_mode != STRICT_MODE || !shared_info->is_classic_mode());
884 // If caller is in extended mode, the result must also be in
885 // extended mode.
886 ASSERT(language_mode != EXTENDED_MODE ||
887 shared_info->is_extended_mode());
888 if (!shared_info->dont_cache()) {
889 compilation_cache->PutEval(
890 source, context, shared_info, scope_position);
891 }
892 }
893 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) {
894 shared_info->ResetForNewContext(isolate->heap()->global_ic_age());
895 }
896
897 return isolate->factory()->NewFunctionFromSharedFunctionInfo(
898 shared_info, context, NOT_TENURED);
899 }
900
901
902 Handle<SharedFunctionInfo> Compiler::CompileScript(Handle<String> source,
903 Handle<Object> script_name,
904 int line_offset,
905 int column_offset,
906 bool is_shared_cross_origin,
907 Handle<Context> context,
908 v8::Extension* extension,
909 ScriptDataImpl* pre_data,
910 Handle<Object> script_data,
911 NativesFlag natives) {
765 Isolate* isolate = source->GetIsolate(); 912 Isolate* isolate = source->GetIsolate();
766 int source_length = source->length(); 913 int source_length = source->length();
767 isolate->counters()->total_load_size()->Increment(source_length); 914 isolate->counters()->total_load_size()->Increment(source_length);
768 isolate->counters()->total_compile_size()->Increment(source_length); 915 isolate->counters()->total_compile_size()->Increment(source_length);
769 916
770 // The VM is in the COMPILER state until exiting this function.
771 VMState<COMPILER> state(isolate);
772
773 CompilationCache* compilation_cache = isolate->compilation_cache(); 917 CompilationCache* compilation_cache = isolate->compilation_cache();
774 918
775 // Do a lookup in the compilation cache but not for extensions. 919 // Do a lookup in the compilation cache but not for extensions.
776 Handle<SharedFunctionInfo> result; 920 Handle<SharedFunctionInfo> result;
777 if (extension == NULL) { 921 if (extension == NULL) {
778 result = compilation_cache->LookupScript(source, 922 result = compilation_cache->LookupScript(source,
779 script_name, 923 script_name,
780 line_offset, 924 line_offset,
781 column_offset, 925 column_offset,
782 is_shared_cross_origin, 926 is_shared_cross_origin,
(...skipping 27 matching lines...) Expand all
810 954
811 // Compile the function and add it to the cache. 955 // Compile the function and add it to the cache.
812 CompilationInfoWithZone info(script); 956 CompilationInfoWithZone info(script);
813 info.MarkAsGlobal(); 957 info.MarkAsGlobal();
814 info.SetExtension(extension); 958 info.SetExtension(extension);
815 info.SetPreParseData(pre_data); 959 info.SetPreParseData(pre_data);
816 info.SetContext(context); 960 info.SetContext(context);
817 if (FLAG_use_strict) { 961 if (FLAG_use_strict) {
818 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE); 962 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
819 } 963 }
820 result = MakeFunctionInfo(&info); 964 result = CompileToplevel(&info);
821 if (extension == NULL && !result.is_null() && !result->dont_cache()) { 965 if (extension == NULL && !result.is_null() && !result->dont_cache()) {
822 compilation_cache->PutScript(source, context, result); 966 compilation_cache->PutScript(source, context, result);
823 } 967 }
824 } else { 968 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
825 if (result->ic_age() != isolate->heap()->global_ic_age()) {
826 result->ResetForNewContext(isolate->heap()->global_ic_age()); 969 result->ResetForNewContext(isolate->heap()->global_ic_age());
827 }
828 } 970 }
829 971
830 if (result.is_null()) isolate->ReportPendingMessages(); 972 if (result.is_null()) isolate->ReportPendingMessages();
831 return result; 973 return result;
832 } 974 }
833 975
834 976
835 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, 977 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
836 Handle<Context> context, 978 Handle<Script> script) {
837 bool is_global, 979 // Precondition: code has been parsed and scopes have been analyzed.
838 LanguageMode language_mode, 980 CompilationInfoWithZone info(script);
839 ParseRestriction restriction, 981 info.SetFunction(literal);
840 int scope_position) { 982 info.SetScope(literal->scope());
841 Isolate* isolate = source->GetIsolate(); 983 info.SetLanguageMode(literal->scope()->language_mode());
842 int source_length = source->length();
843 isolate->counters()->total_eval_size()->Increment(source_length);
844 isolate->counters()->total_compile_size()->Increment(source_length);
845 984
846 // The VM is in the COMPILER state until exiting this function. 985 Isolate* isolate = info.isolate();
847 VMState<COMPILER> state(isolate); 986 Factory* factory = isolate->factory();
987 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
988 // Determine if the function can be lazily compiled. This is necessary to
989 // allow some of our builtin JS files to be lazily compiled. These
990 // builtins cannot be handled lazily by the parser, since we have to know
991 // if a function uses the special natives syntax, which is something the
992 // parser records.
993 // If the debugger requests compilation for break points, we cannot be
994 // aggressive about lazy compilation, because it might trigger compilation
995 // of functions without an outer context when setting a breakpoint through
996 // Debug::FindSharedFunctionInfoInScript.
997 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
998 bool allow_lazy = literal->AllowsLazyCompilation() &&
999 !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
848 1000
849 // Do a lookup in the compilation cache; if the entry is not there, invoke 1001 // Generate code
850 // the compiler and add the result to the cache. 1002 Handle<ScopeInfo> scope_info;
851 Handle<SharedFunctionInfo> result; 1003 if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
852 CompilationCache* compilation_cache = isolate->compilation_cache(); 1004 Handle<Code> code = isolate->builtins()->LazyCompile();
853 result = compilation_cache->LookupEval(source, 1005 info.SetCode(code);
854 context, 1006 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
855 is_global, 1007 } else if (FullCodeGenerator::MakeCode(&info)) {
856 language_mode, 1008 ASSERT(!info.code().is_null());
857 scope_position); 1009 scope_info = ScopeInfo::Create(info.scope(), info.zone());
858
859 if (result.is_null()) {
860 // Create a script object describing the script to be compiled.
861 Handle<Script> script = isolate->factory()->NewScript(source);
862 CompilationInfoWithZone info(script);
863 info.MarkAsEval();
864 if (is_global) info.MarkAsGlobal();
865 info.SetLanguageMode(language_mode);
866 info.SetParseRestriction(restriction);
867 info.SetContext(context);
868 result = MakeFunctionInfo(&info);
869 if (!result.is_null()) {
870 // Explicitly disable optimization for eval code. We're not yet prepared
871 // to handle eval-code in the optimizing compiler.
872 result->DisableOptimization(kEval);
873
874 // If caller is strict mode, the result must be in strict mode or
875 // extended mode as well, but not the other way around. Consider:
876 // eval("'use strict'; ...");
877 ASSERT(language_mode != STRICT_MODE || !result->is_classic_mode());
878 // If caller is in extended mode, the result must also be in
879 // extended mode.
880 ASSERT(language_mode != EXTENDED_MODE ||
881 result->is_extended_mode());
882 if (!result->dont_cache()) {
883 compilation_cache->PutEval(
884 source, context, is_global, result, scope_position);
885 }
886 }
887 } else { 1010 } else {
888 if (result->ic_age() != isolate->heap()->global_ic_age()) { 1011 return Handle<SharedFunctionInfo>::null();
889 result->ResetForNewContext(isolate->heap()->global_ic_age());
890 }
891 } 1012 }
892 1013
1014 // Create a shared function info object.
1015 Handle<SharedFunctionInfo> result =
1016 factory->NewSharedFunctionInfo(literal->name(),
1017 literal->materialized_literal_count(),
1018 literal->is_generator(),
1019 info.code(),
1020 scope_info);
1021 SetFunctionInfo(result, literal, false, script);
1022 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1023 result->set_allows_lazy_compilation(allow_lazy);
1024 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1025
1026 // Set the expected number of properties for instances and return
1027 // the resulting function.
1028 SetExpectedNofPropertiesFromEstimate(result,
1029 literal->expected_property_count());
1030 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
893 return result; 1031 return result;
894 } 1032 }
895 1033
896 1034
897 static bool InstallFullCode(CompilationInfo* info) { 1035 static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function) {
898 // Update the shared function info with the compiled code and the 1036 if (FLAG_cache_optimized_code) {
899 // scope info. Please note, that the order of the shared function 1037 Handle<SharedFunctionInfo> shared(function->shared());
900 // info initialization is important since set_scope_info might 1038 DisallowHeapAllocation no_gc;
901 // trigger a GC, causing the ASSERT below to be invalid if the code 1039 int index = shared->SearchOptimizedCodeMap(
902 // was flushed. By setting the code object last we avoid this. 1040 function->context()->native_context());
903 Handle<SharedFunctionInfo> shared = info->shared_info(); 1041 if (index > 0) {
904 Handle<Code> code = info->code(); 1042 if (FLAG_trace_opt) {
905 CHECK(code->kind() == Code::FUNCTION); 1043 PrintF("[found optimized code for ");
906 Handle<JSFunction> function = info->closure(); 1044 function->ShortPrint();
907 Handle<ScopeInfo> scope_info = 1045 PrintF("]\n");
908 ScopeInfo::Create(info->scope(), info->zone()); 1046 }
909 shared->set_scope_info(*scope_info); 1047 FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index);
910 shared->ReplaceCode(*code); 1048 if (literals != NULL) function->set_literals(literals);
911 if (!function.is_null()) { 1049 return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index));
912 function->ReplaceCode(*code);
913 ASSERT(!function->IsOptimized());
914 }
915
916 // Set the expected number of properties for instances.
917 FunctionLiteral* lit = info->function();
918 int expected = lit->expected_property_count();
919 SetExpectedNofPropertiesFromEstimate(shared, expected);
920
921 // Check the function has compiled code.
922 ASSERT(shared->is_compiled());
923 shared->set_dont_optimize_reason(lit->dont_optimize_reason());
924 shared->set_dont_inline(lit->flags()->Contains(kDontInline));
925 shared->set_ast_node_count(lit->ast_node_count());
926
927 if (info->isolate()->use_crankshaft() &&
928 !function.is_null() &&
929 !shared->optimization_disabled()) {
930 // If we're asked to always optimize, we compile the optimized
931 // version of the function right away - unless the debugger is
932 // active as it makes no sense to compile optimized code then.
933 if (FLAG_always_opt &&
934 !info->isolate()->DebuggerHasBreakPoints()) {
935 CompilationInfoWithZone optimized(function);
936 optimized.SetOptimizing(BailoutId::None());
937 return Compiler::CompileLazy(&optimized);
938 } 1050 }
939 } 1051 }
940 return true; 1052 return Handle<Code>::null();
941 } 1053 }
942 1054
943 1055
944 static void InstallCodeCommon(CompilationInfo* info) {
945 Handle<SharedFunctionInfo> shared = info->shared_info();
946 Handle<Code> code = info->code();
947 ASSERT(!code.is_null());
948
949 // Set optimizable to false if this is disallowed by the shared
950 // function info, e.g., we might have flushed the code and must
951 // reset this bit when lazy compiling the code again.
952 if (shared->optimization_disabled()) code->set_optimizable(false);
953
954 if (shared->code() == *code) {
955 // Do not send compilation event for the same code twice.
956 return;
957 }
958 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
959 }
960
961
962 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { 1056 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
963 Handle<Code> code = info->code(); 1057 Handle<Code> code = info->code();
964 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. 1058 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
965 1059
966 // Cache non-OSR optimized code. 1060 // Cache non-OSR optimized code.
967 if (FLAG_cache_optimized_code && !info->is_osr()) { 1061 if (FLAG_cache_optimized_code && !info->is_osr()) {
968 Handle<JSFunction> function = info->closure(); 1062 Handle<JSFunction> function = info->closure();
969 Handle<SharedFunctionInfo> shared(function->shared()); 1063 Handle<SharedFunctionInfo> shared(function->shared());
970 Handle<FixedArray> literals(function->literals()); 1064 Handle<FixedArray> literals(function->literals());
971 Handle<Context> native_context(function->context()->native_context()); 1065 Handle<Context> native_context(function->context()->native_context());
972 SharedFunctionInfo::AddToOptimizedCodeMap( 1066 SharedFunctionInfo::AddToOptimizedCodeMap(
973 shared, native_context, code, literals); 1067 shared, native_context, code, literals);
974 } 1068 }
975 } 1069 }
976 1070
977 1071
978 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { 1072 static bool CompileOptimizedPrologue(CompilationInfo* info) {
979 if (!info->IsOptimizing()) return false; // Nothing to look up. 1073 if (!Parser::Parse(info)) return false;
1074 LanguageMode language_mode = info->function()->language_mode();
1075 info->SetLanguageMode(language_mode);
980 1076
981 // Lookup non-OSR optimized code. 1077 if (!Rewriter::Rewrite(info)) return false;
982 if (FLAG_cache_optimized_code && !info->is_osr()) { 1078 if (!Scope::Analyze(info)) return false;
983 Handle<SharedFunctionInfo> shared = info->shared_info(); 1079 ASSERT(info->scope() != NULL);
984 Handle<JSFunction> function = info->closure(); 1080 return true;
985 ASSERT(!function.is_null());
986 Handle<Context> native_context(function->context()->native_context());
987 int index = shared->SearchOptimizedCodeMap(*native_context);
988 if (index > 0) {
989 if (FLAG_trace_opt) {
990 PrintF("[found optimized code for ");
991 function->ShortPrint();
992 PrintF("]\n");
993 }
994 // Caching of optimized code enabled and optimized code found.
995 shared->InstallFromOptimizedCodeMap(*function, index);
996 return true;
997 }
998 }
999 return false;
1000 } 1081 }
1001 1082
1002 1083
1003 bool Compiler::CompileLazy(CompilationInfo* info) { 1084 static bool GetOptimizedCodeNow(CompilationInfo* info) {
1004 Isolate* isolate = info->isolate(); 1085 if (!CompileOptimizedPrologue(info)) return false;
1005 1086
1006 // The VM is in the COMPILER state until exiting this function. 1087 Logger::TimerEventScope timer(
1007 VMState<COMPILER> state(isolate); 1088 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous);
1008 1089
1009 PostponeInterruptsScope postpone(isolate); 1090 RecompileJob job(info);
1091 if (job.CreateGraph() != RecompileJob::SUCCEEDED) return false;
1092 if (job.OptimizeGraph() != RecompileJob::SUCCEEDED) return false;
1093 if (job.GenerateCode() != RecompileJob::SUCCEEDED) return false;
1010 1094
1011 Handle<SharedFunctionInfo> shared = info->shared_info(); 1095 // Success!
1012 int compiled_size = shared->end_position() - shared->start_position(); 1096 ASSERT(!info->isolate()->has_pending_exception());
1013 isolate->counters()->total_compile_size()->Increment(compiled_size); 1097 InsertCodeIntoOptimizedCodeMap(info);
1014 1098 Compiler::RecordFunctionCompilation(
1015 if (InstallCodeFromOptimizedCodeMap(info)) return true; 1099 Logger::LAZY_COMPILE_TAG, info, info->shared_info());
1016 1100 return true;
1017 // Generate the AST for the lazily compiled function.
1018 if (Parser::Parse(info)) {
1019 // Measure how long it takes to do the lazy compilation; only take the
1020 // rest of the function into account to avoid overlap with the lazy
1021 // parsing statistics.
1022 HistogramTimerScope timer(isolate->counters()->compile_lazy());
1023
1024 // After parsing we know the function's language mode. Remember it.
1025 LanguageMode language_mode = info->function()->language_mode();
1026 info->SetLanguageMode(language_mode);
1027 shared->set_language_mode(language_mode);
1028
1029 // Compile the code.
1030 if (!MakeCode(info)) {
1031 if (!isolate->has_pending_exception()) {
1032 isolate->StackOverflow();
1033 }
1034 } else {
1035 InstallCodeCommon(info);
1036
1037 if (info->IsOptimizing()) {
1038 // Optimized code successfully created.
1039 Handle<Code> code = info->code();
1040 ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate));
1041 // TODO(titzer): Only replace the code if it was not an OSR compile.
1042 info->closure()->ReplaceCode(*code);
1043 InsertCodeIntoOptimizedCodeMap(info);
1044 return true;
1045 } else if (!info->is_osr()) {
1046 // Compilation failed. Replace with full code if not OSR compile.
1047 return InstallFullCode(info);
1048 }
1049 }
1050 }
1051
1052 ASSERT(info->code().is_null());
1053 return false;
1054 } 1101 }
1055 1102
1056 1103
1057 bool Compiler::RecompileConcurrent(Handle<JSFunction> closure, 1104 static bool GetOptimizedCodeLater(CompilationInfo* info) {
1058 Handle<Code> unoptimized, 1105 Isolate* isolate = info->isolate();
1059 uint32_t osr_pc_offset) {
1060 bool compiling_for_osr = (osr_pc_offset != 0);
1061
1062 Isolate* isolate = closure->GetIsolate();
1063 // Here we prepare compile data for the concurrent recompilation thread, but
1064 // this still happens synchronously and interrupts execution.
1065 Logger::TimerEventScope timer(
1066 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
1067
1068 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { 1106 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
1069 if (FLAG_trace_concurrent_recompilation) { 1107 if (FLAG_trace_concurrent_recompilation) {
1070 PrintF(" ** Compilation queue full, will retry optimizing "); 1108 PrintF(" ** Compilation queue full, will retry optimizing ");
1071 closure->PrintName(); 1109 info->closure()->PrintName();
1072 PrintF(" on next run.\n"); 1110 PrintF(" later.\n");
1073 } 1111 }
1074 return false; 1112 return false;
1075 } 1113 }
1076 1114
1077 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); 1115 CompilationHandleScope handle_scope(info);
1116 if (!CompileOptimizedPrologue(info)) return false;
1117 info->SaveHandles(); // Copy handles to the compilation handle scope.
1118
1119 Logger::TimerEventScope timer(
1120 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
1121
1122 RecompileJob* job = new(info->zone()) RecompileJob(info);
1123 RecompileJob::Status status = job->CreateGraph();
1124 if (status != RecompileJob::SUCCEEDED) return false;
1125 isolate->optimizing_compiler_thread()->QueueForOptimization(job);
1126
1127 if (FLAG_trace_concurrent_recompilation) {
1128 PrintF(" ** Queued ");
1129 info->closure()->PrintName();
1130 if (info->is_osr()) {
1131 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
1132 } else {
1133 PrintF(" for concurrent optimization.\n");
1134 }
1135 }
1136 return true;
1137 }
1138
1139
1140 Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
1141 Handle<Code> current_code,
1142 ConcurrencyMode mode,
1143 BailoutId osr_ast_id) {
1144 if (osr_ast_id.IsNone()) { // No cache for OSR.
1145 Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function);
1146 if (!cached_code.is_null()) return cached_code;
1147 }
1148
1149 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function));
1150 Isolate* isolate = info->isolate();
1151 VMState<COMPILER> state(isolate);
1152 ASSERT(!isolate->has_pending_exception());
1153 PostponeInterruptsScope postpone(isolate);
1154
1078 Handle<SharedFunctionInfo> shared = info->shared_info(); 1155 Handle<SharedFunctionInfo> shared = info->shared_info();
1156 ASSERT_NE(ScopeInfo::Empty(isolate), shared->scope_info());
1157 int compiled_size = shared->end_position() - shared->start_position();
1158 isolate->counters()->total_compile_size()->Increment(compiled_size);
1159 current_code->set_profiler_ticks(0);
1079 1160
1080 if (compiling_for_osr) { 1161 info->SetOptimizing(osr_ast_id, current_code);
1081 BailoutId osr_ast_id = unoptimized->TranslatePcOffsetToAstId(osr_pc_offset);
1082 ASSERT(!osr_ast_id.IsNone());
1083 info->SetOptimizing(osr_ast_id);
1084 info->SetOsrInfo(unoptimized, osr_pc_offset);
1085 1162
1086 if (FLAG_trace_osr) { 1163 if (mode == CONCURRENT) {
1087 PrintF("[COSR - attempt to queue "); 1164 if (GetOptimizedCodeLater(info.get())) {
1088 closure->PrintName(); 1165 info.Detach(); // The background recompile job owns this now.
1089 PrintF(" at AST id %d]\n", osr_ast_id.ToInt()); 1166 return Handle<Code>::null();
1090 } 1167 }
1091 } else { 1168 } else {
1092 info->SetOptimizing(BailoutId::None()); 1169 if (GetOptimizedCodeNow(info.get())) return info->code();
1093 } 1170 }
1094 1171
1095 VMState<COMPILER> state(isolate); 1172 // Failed.
1096 PostponeInterruptsScope postpone(isolate); 1173 if (FLAG_trace_opt) {
1097 1174 PrintF("[failed to optimize ");
1098 int compiled_size = shared->end_position() - shared->start_position(); 1175 function->PrintName();
1099 isolate->counters()->total_compile_size()->Increment(compiled_size); 1176 PrintF("]\n");
1100
1101 {
1102 CompilationHandleScope handle_scope(info.get());
1103
1104 if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(info.get())) {
1105 return true;
1106 }
1107
1108 if (Parser::Parse(info.get())) {
1109 LanguageMode language_mode = info->function()->language_mode();
1110 info->SetLanguageMode(language_mode);
1111 shared->set_language_mode(language_mode);
1112 info->SaveHandles();
1113
1114 if (Rewriter::Rewrite(info.get()) && Scope::Analyze(info.get())) {
1115 RecompileJob* job = new(info->zone()) RecompileJob(info.get());
1116 RecompileJob::Status status = job->CreateGraph();
1117 if (status == RecompileJob::SUCCEEDED) {
1118 info.Detach();
1119 unoptimized->set_profiler_ticks(0);
1120 isolate->optimizing_compiler_thread()->QueueForOptimization(job);
1121 ASSERT(!isolate->has_pending_exception());
1122 return true;
1123 } else if (status == RecompileJob::BAILED_OUT) {
1124 isolate->clear_pending_exception();
1125 InstallFullCode(info.get());
1126 }
1127 }
1128 }
1129 } 1177 }
1130 1178
1131 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); 1179 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1132 return false; 1180 return Handle<Code>(shared->code());
1133 } 1181 }
1134 1182
1135 1183
1136 Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) { 1184 Handle<Code> Compiler::GetConcurrentlyOptimizedCode(RecompileJob* job) {
1185 // Take ownership of compilation info. Deleting compilation info
1186 // also tears down the zone and the recompile job.
1137 SmartPointer<CompilationInfo> info(job->info()); 1187 SmartPointer<CompilationInfo> info(job->info());
1138 // The function may have already been optimized by OSR. Simply continue. 1188 Isolate* isolate = info->isolate();
1139 // Except when OSR already disabled optimization for some reason.
1140 if (info->shared_info()->optimization_disabled()) {
1141 info->AbortOptimization();
1142 InstallFullCode(info.get());
1143 if (FLAG_trace_concurrent_recompilation) {
1144 PrintF(" ** aborting optimization for ");
1145 info->closure()->PrintName();
1146 PrintF(" as it has been disabled.\n");
1147 }
1148 ASSERT(!info->closure()->IsInRecompileQueue());
1149 return Handle<Code>::null();
1150 }
1151 1189
1152 Isolate* isolate = info->isolate();
1153 VMState<COMPILER> state(isolate); 1190 VMState<COMPILER> state(isolate);
1154 Logger::TimerEventScope timer( 1191 Logger::TimerEventScope timer(
1155 isolate, Logger::TimerEventScope::v8_recompile_synchronous); 1192 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
1156 // If crankshaft succeeded, install the optimized code else install 1193
1157 // the unoptimized code. 1194 Handle<SharedFunctionInfo> shared = info->shared_info();
1158 RecompileJob::Status status = job->last_status(); 1195 Handle<Code> fallback(shared->code());
1159 if (info->HasAbortedDueToDependencyChange()) { 1196 fallback->set_profiler_ticks(0);
1160 info->set_bailout_reason(kBailedOutDueToDependencyChange); 1197
1161 status = job->AbortOptimization(); 1198 // 1) Optimization may have failed.
1162 } else if (status != RecompileJob::SUCCEEDED) { 1199 // 2) The function may have already been optimized by OSR. Simply continue.
1163 info->set_bailout_reason(kFailedBailedOutLastTime); 1200 // Except when OSR already disabled optimization for some reason.
1164 status = job->AbortOptimization(); 1201 // 3) The code may have already been invalidated due to dependency change.
1165 } else if (isolate->DebuggerHasBreakPoints()) { 1202 // 4) Debugger may have been activated.
1166 info->set_bailout_reason(kDebuggerIsActive); 1203
1167 status = job->AbortOptimization(); 1204 if (job->last_status() != RecompileJob::SUCCEEDED ||
1168 } else { 1205 shared->optimization_disabled() ||
1169 status = job->GenerateAndInstallCode(); 1206 info->HasAbortedDueToDependencyChange() ||
1170 ASSERT(status == RecompileJob::SUCCEEDED || 1207 isolate->DebuggerHasBreakPoints()) {
1171 status == RecompileJob::BAILED_OUT); 1208 return fallback;
1172 } 1209 }
1173 1210
1174 InstallCodeCommon(info.get()); 1211 if (job->GenerateCode() != RecompileJob::SUCCEEDED) {
1175 if (status == RecompileJob::SUCCEEDED) { 1212 return fallback;
1176 Handle<Code> code = info->code();
1177 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
1178 info->closure()->ReplaceCode(*code);
1179 if (info->shared_info()->SearchOptimizedCodeMap(
1180 info->closure()->context()->native_context()) == -1) {
1181 InsertCodeIntoOptimizedCodeMap(info.get());
1182 }
1183 if (FLAG_trace_concurrent_recompilation) {
1184 PrintF(" ** Optimized code for ");
1185 info->closure()->PrintName();
1186 PrintF(" installed.\n");
1187 }
1188 } else {
1189 info->AbortOptimization();
1190 InstallFullCode(info.get());
1191 } 1213 }
1192 // Optimized code is finally replacing unoptimized code. Reset the latter's 1214
1193 // profiler ticks to prevent too soon re-opt after a deopt. 1215 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
titzer 2013/12/09 14:49:28 Don't know why this assert is here.
Yang 2013/12/10 11:22:04 Removed.
1194 info->shared_info()->code()->set_profiler_ticks(0); 1216 Compiler::RecordFunctionCompilation(
1195 ASSERT(!info->closure()->IsInRecompileQueue()); 1217 Logger::LAZY_COMPILE_TAG, info.get(), shared);
1196 return (status == RecompileJob::SUCCEEDED) ? info->code() 1218 if (info->shared_info()->SearchOptimizedCodeMap(
1197 : Handle<Code>::null(); 1219 info->context()->native_context()) == -1) {
1220 InsertCodeIntoOptimizedCodeMap(info.get());
1221 }
1222
1223 if (FLAG_trace_concurrent_recompilation) {
1224 PrintF(" ** Optimized code for ");
1225 info->closure()->PrintName();
1226 PrintF(" generated.\n");
1227 }
1228
1229 return Handle<Code>(*info->code());
1198 } 1230 }
1199 1231
1200 1232
1201 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
1202 Handle<Script> script) {
1203 // Precondition: code has been parsed and scopes have been analyzed.
1204 CompilationInfoWithZone info(script);
1205 info.SetFunction(literal);
1206 info.SetScope(literal->scope());
1207 info.SetLanguageMode(literal->scope()->language_mode());
1208
1209 Isolate* isolate = info.isolate();
1210 Factory* factory = isolate->factory();
1211 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1212 // Determine if the function can be lazily compiled. This is necessary to
1213 // allow some of our builtin JS files to be lazily compiled. These
1214 // builtins cannot be handled lazily by the parser, since we have to know
1215 // if a function uses the special natives syntax, which is something the
1216 // parser records.
1217 // If the debugger requests compilation for break points, we cannot be
1218 // aggressive about lazy compilation, because it might trigger compilation
1219 // of functions without an outer context when setting a breakpoint through
1220 // Debug::FindSharedFunctionInfoInScript.
1221 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
1222 bool allow_lazy = literal->AllowsLazyCompilation() &&
1223 !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
1224
1225 Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate));
1226
1227 // Generate code
1228 if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
1229 Handle<Code> code = isolate->builtins()->LazyCompile();
1230 info.SetCode(code);
1231 } else if (GenerateCode(&info)) {
1232 ASSERT(!info.code().is_null());
1233 scope_info = ScopeInfo::Create(info.scope(), info.zone());
1234 } else {
1235 return Handle<SharedFunctionInfo>::null();
1236 }
1237
1238 // Create a shared function info object.
1239 Handle<SharedFunctionInfo> result =
1240 factory->NewSharedFunctionInfo(literal->name(),
1241 literal->materialized_literal_count(),
1242 literal->is_generator(),
1243 info.code(),
1244 scope_info);
1245 SetFunctionInfo(result, literal, false, script);
1246 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1247 result->set_allows_lazy_compilation(allow_lazy);
1248 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1249
1250 // Set the expected number of properties for instances and return
1251 // the resulting function.
1252 SetExpectedNofPropertiesFromEstimate(result,
1253 literal->expected_property_count());
1254 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1255 return result;
1256 }
1257
1258
1259 // Sets the function info on a function.
1260 // The start_position points to the first '(' character after the function name
1261 // in the full script source. When counting characters in the script source the
1262 // the first character is number 0 (not 1).
1263 void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
1264 FunctionLiteral* lit,
1265 bool is_toplevel,
1266 Handle<Script> script) {
1267 function_info->set_length(lit->parameter_count());
1268 function_info->set_formal_parameter_count(lit->parameter_count());
1269 function_info->set_script(*script);
1270 function_info->set_function_token_position(lit->function_token_position());
1271 function_info->set_start_position(lit->start_position());
1272 function_info->set_end_position(lit->end_position());
1273 function_info->set_is_expression(lit->is_expression());
1274 function_info->set_is_anonymous(lit->is_anonymous());
1275 function_info->set_is_toplevel(is_toplevel);
1276 function_info->set_inferred_name(*lit->inferred_name());
1277 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
1278 function_info->set_allows_lazy_compilation_without_context(
1279 lit->AllowsLazyCompilationWithoutContext());
1280 function_info->set_language_mode(lit->language_mode());
1281 function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
1282 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
1283 function_info->set_ast_node_count(lit->ast_node_count());
1284 function_info->set_is_function(lit->is_function());
1285 function_info->set_dont_optimize_reason(lit->dont_optimize_reason());
1286 function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
1287 function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
1288 function_info->set_is_generator(lit->is_generator());
1289 }
1290
1291
1292 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, 1233 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
1293 CompilationInfo* info, 1234 CompilationInfo* info,
1294 Handle<SharedFunctionInfo> shared) { 1235 Handle<SharedFunctionInfo> shared) {
1295 // SharedFunctionInfo is passed separately, because if CompilationInfo 1236 // SharedFunctionInfo is passed separately, because if CompilationInfo
1296 // was created using Script object, it will not have it. 1237 // was created using Script object, it will not have it.
1297 1238
1298 // Log the code generation. If source information is available include 1239 // Log the code generation. If source information is available include
1299 // script name and line number. Check explicitly whether logging is 1240 // script name and line number. Check explicitly whether logging is
1300 // enabled as finding the line number is not free. 1241 // enabled as finding the line number is not free.
1301 if (info->isolate()->logger()->is_logging_code_events() || 1242 if (info->isolate()->logger()->is_logging_code_events() ||
1302 info->isolate()->cpu_profiler()->is_profiling()) { 1243 info->isolate()->cpu_profiler()->is_profiling()) {
1303 Handle<Script> script = info->script(); 1244 Handle<Script> script = info->script();
1304 Handle<Code> code = info->code(); 1245 Handle<Code> code = info->code();
1305 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile)) 1246 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
1306 return; 1247 return;
1307 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1; 1248 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
1308 int column_num = 1249 int column_num =
1309 GetScriptColumnNumber(script, shared->start_position()) + 1; 1250 GetScriptColumnNumber(script, shared->start_position()) + 1;
1310 USE(line_num); 1251 USE(line_num);
1311 if (script->name()->IsString()) { 1252 String* script_name = script->name()->IsString()
1312 PROFILE(info->isolate(), 1253 ? String::cast(script->name())
1313 CodeCreateEvent(Logger::ToNativeByScript(tag, *script), 1254 : info->isolate()->heap()->empty_string();
1314 *code, 1255 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
1315 *shared, 1256 PROFILE(info->isolate(), CodeCreateEvent(
1316 info, 1257 log_tag, *code, *shared, info, script_name, line_num, column_num));
1317 String::cast(script->name()),
1318 line_num,
1319 column_num));
1320 } else {
1321 PROFILE(info->isolate(),
1322 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
1323 *code,
1324 *shared,
1325 info,
1326 info->isolate()->heap()->empty_string(),
1327 line_num,
1328 column_num));
1329 }
1330 } 1258 }
1331 1259
1332 GDBJIT(AddCode(Handle<String>(shared->DebugName()), 1260 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
1333 Handle<Script>(info->script()), 1261 Handle<Script>(info->script()),
1334 Handle<Code>(info->code()), 1262 Handle<Code>(info->code()),
1335 info)); 1263 info));
1336 } 1264 }
1337 1265
1338 1266
1339 CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info) 1267 CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
(...skipping 20 matching lines...) Expand all
1360 AllowHandleDereference allow_deref; 1288 AllowHandleDereference allow_deref;
1361 bool tracing_on = info()->IsStub() 1289 bool tracing_on = info()->IsStub()
1362 ? FLAG_trace_hydrogen_stubs 1290 ? FLAG_trace_hydrogen_stubs
1363 : (FLAG_trace_hydrogen && 1291 : (FLAG_trace_hydrogen &&
1364 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); 1292 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1365 return (tracing_on && 1293 return (tracing_on &&
1366 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); 1294 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1367 } 1295 }
1368 1296
1369 } } // namespace v8::internal 1297 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698