Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |