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

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

Powered by Google App Engine
This is Rietveld 408576698