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

Side by Side Diff: src/compiler.cc

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

Powered by Google App Engine
This is Rietveld 408576698