1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "compiler.h"
31
32#include "bootstrapper.h"
33#include "codegen.h"
34#include "compilation-cache.h"
35#include "cpu-profiler.h"
36#include "debug.h"
37#include "deoptimizer.h"
38#include "full-codegen.h"
39#include "gdb-jit.h"
40#include "typing.h"
41#include "hydrogen.h"
42#include "isolate-inl.h"
43#include "lithium.h"
44#include "liveedit.h"
45#include "parser.h"
46#include "rewriter.h"
47#include "runtime-profiler.h"
48#include "scanner-character-streams.h"
49#include "scopeinfo.h"
50#include "scopes.h"
51#include "vm-state-inl.h"
52
53namespace v8 {
54namespace internal {
55
56
57CompilationInfo::CompilationInfo(Handle<Script> script,
58                                 Zone* zone)
59    : flags_(LanguageModeField::encode(CLASSIC_MODE)),
60      script_(script),
61      osr_ast_id_(BailoutId::None()) {
62  Initialize(script->GetIsolate(), BASE, zone);
63}
64
65
66CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
67                                 Zone* zone)
68    : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
69      shared_info_(shared_info),
70      script_(Handle<Script>(Script::cast(shared_info->script()))),
71      osr_ast_id_(BailoutId::None()) {
72  Initialize(script_->GetIsolate(), BASE, zone);
73}
74
75
76CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
77                                 Zone* zone)
78    : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
79      closure_(closure),
80      shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
81      script_(Handle<Script>(Script::cast(shared_info_->script()))),
82      context_(closure->context()),
83      osr_ast_id_(BailoutId::None()) {
84  Initialize(script_->GetIsolate(), BASE, zone);
85}
86
87
88CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
89                                 Isolate* isolate,
90                                 Zone* zone)
91    : flags_(LanguageModeField::encode(CLASSIC_MODE) |
92             IsLazy::encode(true)),
93      osr_ast_id_(BailoutId::None()) {
94  Initialize(isolate, STUB, zone);
95  code_stub_ = stub;
96}
97
98
99void CompilationInfo::Initialize(Isolate* isolate,
100                                 Mode mode,
101                                 Zone* zone) {
102  isolate_ = isolate;
103  function_ = NULL;
104  scope_ = NULL;
105  global_scope_ = NULL;
106  extension_ = NULL;
107  pre_parse_data_ = NULL;
108  zone_ = zone;
109  deferred_handles_ = NULL;
110  code_stub_ = NULL;
111  prologue_offset_ = kPrologueOffsetNotSet;
112  opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
113  no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
114                   ? new List<OffsetRange>(2) : NULL;
115  for (int i = 0; i < DependentCode::kGroupCount; i++) {
116    dependencies_[i] = NULL;
117  }
118  if (mode == STUB) {
119    mode_ = STUB;
120    return;
121  }
122  mode_ = V8::UseCrankshaft() ? mode : NONOPT;
123  abort_due_to_dependency_ = false;
124  if (script_->type()->value() == Script::TYPE_NATIVE) {
125    MarkAsNative();
126  }
127  if (!shared_info_.is_null()) {
128    ASSERT(language_mode() == CLASSIC_MODE);
129    SetLanguageMode(shared_info_->language_mode());
130  }
131  set_bailout_reason(kUnknown);
132}
133
134
135CompilationInfo::~CompilationInfo() {
136  delete deferred_handles_;
137  delete no_frame_ranges_;
138#ifdef DEBUG
139  // Check that no dependent maps have been added or added dependent maps have
140  // been rolled back or committed.
141  for (int i = 0; i < DependentCode::kGroupCount; i++) {
142    ASSERT_EQ(NULL, dependencies_[i]);
143  }
144#endif  // DEBUG
145}
146
147
148void CompilationInfo::CommitDependencies(Handle<Code> code) {
149  for (int i = 0; i < DependentCode::kGroupCount; i++) {
150    ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
151    if (group_objects == NULL) continue;
152    ASSERT(!object_wrapper_.is_null());
153    for (int j = 0; j < group_objects->length(); j++) {
154      DependentCode::DependencyGroup group =
155          static_cast<DependentCode::DependencyGroup>(i);
156      DependentCode* dependent_code =
157          DependentCode::ForObject(group_objects->at(j), group);
158      dependent_code->UpdateToFinishedCode(group, this, *code);
159    }
160    dependencies_[i] = NULL;  // Zone-allocated, no need to delete.
161  }
162}
163
164
165void CompilationInfo::RollbackDependencies() {
166  // Unregister from all dependent maps if not yet committed.
167  for (int i = 0; i < DependentCode::kGroupCount; i++) {
168    ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
169    if (group_objects == NULL) continue;
170    for (int j = 0; j < group_objects->length(); j++) {
171      DependentCode::DependencyGroup group =
172          static_cast<DependentCode::DependencyGroup>(i);
173      DependentCode* dependent_code =
174          DependentCode::ForObject(group_objects->at(j), group);
175      dependent_code->RemoveCompilationInfo(group, this);
176    }
177    dependencies_[i] = NULL;  // Zone-allocated, no need to delete.
178  }
179}
180
181
182int CompilationInfo::num_parameters() const {
183  ASSERT(!IsStub());
184  return scope()->num_parameters();
185}
186
187
188int CompilationInfo::num_heap_slots() const {
189  if (IsStub()) {
190    return 0;
191  } else {
192    return scope()->num_heap_slots();
193  }
194}
195
196
197Code::Flags CompilationInfo::flags() const {
198  if (IsStub()) {
199    return Code::ComputeFlags(code_stub()->GetCodeKind(),
200                              code_stub()->GetICState(),
201                              code_stub()->GetExtraICState(),
202                              code_stub()->GetStubType(),
203                              code_stub()->GetStubFlags());
204  } else {
205    return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
206  }
207}
208
209
210// Disable optimization for the rest of the compilation pipeline.
211void CompilationInfo::DisableOptimization() {
212  bool is_optimizable_closure =
213    FLAG_optimize_closures &&
214    closure_.is_null() &&
215    !scope_->HasTrivialOuterContext() &&
216    !scope_->outer_scope_calls_non_strict_eval() &&
217    !scope_->inside_with();
218  SetMode(is_optimizable_closure ? BASE : NONOPT);
219}
220
221
222// Primitive functions are unlikely to be picked up by the stack-walking
223// profiler, so they trigger their own optimization when they're called
224// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
225bool CompilationInfo::ShouldSelfOptimize() {
226  return FLAG_self_optimization &&
227      FLAG_crankshaft &&
228      !function()->flags()->Contains(kDontSelfOptimize) &&
229      !function()->flags()->Contains(kDontOptimize) &&
230      function()->scope()->AllowsLazyCompilation() &&
231      (shared_info().is_null() || !shared_info()->optimization_disabled());
232}
233
234
235void CompilationInfo::AbortOptimization() {
236  Handle<Code> code(shared_info()->code());
237  SetCode(code);
238}
239
240
241// Determine whether to use the full compiler for all code. If the flag
242// --always-full-compiler is specified this is the case. For the virtual frame
243// based compiler the full compiler is also used if a debugger is connected, as
244// the code from the full compiler supports mode precise break points. For the
245// crankshaft adaptive compiler debugging the optimized code is not possible at
246// all. However crankshaft support recompilation of functions, so in this case
247// the full compiler need not be be used if a debugger is attached, but only if
248// break points has actually been set.
249static bool IsDebuggerActive(Isolate* isolate) {
250#ifdef ENABLE_DEBUGGER_SUPPORT
251  return V8::UseCrankshaft() ?
252    isolate->debug()->has_break_points() :
253    isolate->debugger()->IsDebuggerActive();
254#else
255  return false;
256#endif
257}
258
259
260static bool AlwaysFullCompiler(Isolate* isolate) {
261  return FLAG_always_full_compiler || IsDebuggerActive(isolate);
262}
263
264
265void OptimizingCompiler::RecordOptimizationStats() {
266  Handle<JSFunction> function = info()->closure();
267  int opt_count = function->shared()->opt_count();
268  function->shared()->set_opt_count(opt_count + 1);
269  double ms_creategraph =
270      static_cast<double>(time_taken_to_create_graph_) / 1000;
271  double ms_optimize = static_cast<double>(time_taken_to_optimize_) / 1000;
272  double ms_codegen = static_cast<double>(time_taken_to_codegen_) / 1000;
273  if (FLAG_trace_opt) {
274    PrintF("[optimizing ");
275    function->ShortPrint();
276    PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
277           ms_codegen);
278  }
279  if (FLAG_trace_opt_stats) {
280    static double compilation_time = 0.0;
281    static int compiled_functions = 0;
282    static int code_size = 0;
283
284    compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
285    compiled_functions++;
286    code_size += function->shared()->SourceSize();
287    PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
288           compiled_functions,
289           code_size,
290           compilation_time);
291  }
292  if (FLAG_hydrogen_stats) {
293    isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
294                                                    time_taken_to_optimize_,
295                                                    time_taken_to_codegen_);
296  }
297}
298
299
300// A return value of true indicates the compilation pipeline is still
301// going, not necessarily that we optimized the code.
302static bool MakeCrankshaftCode(CompilationInfo* info) {
303  OptimizingCompiler compiler(info);
304  OptimizingCompiler::Status status = compiler.CreateGraph();
305
306  if (status != OptimizingCompiler::SUCCEEDED) {
307    return status != OptimizingCompiler::FAILED;
308  }
309  status = compiler.OptimizeGraph();
310  if (status != OptimizingCompiler::SUCCEEDED) {
311    status = compiler.AbortOptimization();
312    return status != OptimizingCompiler::FAILED;
313  }
314  status = compiler.GenerateAndInstallCode();
315  return status != OptimizingCompiler::FAILED;
316}
317
318
319OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
320  ASSERT(V8::UseCrankshaft());
321  ASSERT(info()->IsOptimizing());
322  ASSERT(!info()->IsCompilingForDebugging());
323
324  // We should never arrive here if there is no code object on the
325  // shared function object.
326  Handle<Code> code(info()->shared_info()->code());
327  ASSERT(code->kind() == Code::FUNCTION);
328
329  // We should never arrive here if optimization has been disabled on the
330  // shared function info.
331  ASSERT(!info()->shared_info()->optimization_disabled());
332
333  // Fall back to using the full code generator if it's not possible
334  // to use the Hydrogen-based optimizing compiler. We already have
335  // generated code for this from the shared function object.
336  if (AlwaysFullCompiler(isolate())) {
337    info()->SetCode(code);
338    return SetLastStatus(BAILED_OUT);
339  }
340
341  // Limit the number of times we re-compile a functions with
342  // the optimizing compiler.
343  const int kMaxOptCount =
344      FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
345  if (info()->opt_count() > kMaxOptCount) {
346    info()->set_bailout_reason(kOptimizedTooManyTimes);
347    return AbortOptimization();
348  }
349
350  // Due to an encoding limit on LUnallocated operands in the Lithium
351  // language, we cannot optimize functions with too many formal parameters
352  // or perform on-stack replacement for function with too many
353  // stack-allocated local variables.
354  //
355  // The encoding is as a signed value, with parameters and receiver using
356  // the negative indices and locals the non-negative ones.
357  const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
358  Scope* scope = info()->scope();
359  if ((scope->num_parameters() + 1) > parameter_limit) {
360    info()->set_bailout_reason(kTooManyParameters);
361    return AbortOptimization();
362  }
363
364  const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
365  if (!info()->osr_ast_id().IsNone() &&
366      scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
367    info()->set_bailout_reason(kTooManyParametersLocals);
368    return AbortOptimization();
369  }
370
371  // Take --hydrogen-filter into account.
372  if (!info()->closure()->PassesHydrogenFilter()) {
373      info()->SetCode(code);
374      return SetLastStatus(BAILED_OUT);
375  }
376
377  // Recompile the unoptimized version of the code if the current version
378  // doesn't have deoptimization support. Alternatively, we may decide to
379  // run the full code generator to get a baseline for the compile-time
380  // performance of the hydrogen-based compiler.
381  bool should_recompile = !info()->shared_info()->has_deoptimization_support();
382  if (should_recompile || FLAG_hydrogen_stats) {
383    int64_t start_ticks = 0;
384    if (FLAG_hydrogen_stats) {
385      start_ticks = OS::Ticks();
386    }
387    CompilationInfoWithZone unoptimized(info()->shared_info());
388    // Note that we use the same AST that we will use for generating the
389    // optimized code.
390    unoptimized.SetFunction(info()->function());
391    unoptimized.SetScope(info()->scope());
392    unoptimized.SetContext(info()->context());
393    if (should_recompile) unoptimized.EnableDeoptimizationSupport();
394    bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
395    if (should_recompile) {
396      if (!succeeded) return SetLastStatus(FAILED);
397      Handle<SharedFunctionInfo> shared = info()->shared_info();
398      shared->EnableDeoptimizationSupport(*unoptimized.code());
399      // The existing unoptimized code was replaced with the new one.
400      Compiler::RecordFunctionCompilation(
401          Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
402    }
403    if (FLAG_hydrogen_stats) {
404      int64_t ticks = OS::Ticks() - start_ticks;
405      isolate()->GetHStatistics()->IncrementFullCodeGen(ticks);
406    }
407  }
408
409  // Check that the unoptimized, shared code is ready for
410  // optimizations.  When using the always_opt flag we disregard the
411  // optimizable marker in the code object and optimize anyway. This
412  // is safe as long as the unoptimized code has deoptimization
413  // support.
414  ASSERT(FLAG_always_opt || code->optimizable());
415  ASSERT(info()->shared_info()->has_deoptimization_support());
416
417  if (FLAG_trace_hydrogen) {
418    Handle<String> name = info()->function()->debug_name();
419    PrintF("-----------------------------------------------------------\n");
420    PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
421    isolate()->GetHTracer()->TraceCompilation(info());
422  }
423
424  // Type-check the function.
425  AstTyper::Run(info());
426
427  graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());
428
429  Timer t(this, &time_taken_to_create_graph_);
430  graph_ = graph_builder_->CreateGraph();
431
432  if (isolate()->has_pending_exception()) {
433    info()->SetCode(Handle<Code>::null());
434    return SetLastStatus(FAILED);
435  }
436
437  // The function being compiled may have bailed out due to an inline
438  // candidate bailing out.  In such a case, we don't disable
439  // optimization on the shared_info.
440  ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
441  if (graph_ == NULL) {
442    if (graph_builder_->inline_bailout()) {
443      info_->AbortOptimization();
444      return SetLastStatus(BAILED_OUT);
445    } else {
446      return AbortOptimization();
447    }
448  }
449
450  if (info()->HasAbortedDueToDependencyChange()) {
451    info_->set_bailout_reason(kBailedOutDueToDependencyChange);
452    info_->AbortOptimization();
453    return SetLastStatus(BAILED_OUT);
454  }
455
456  return SetLastStatus(SUCCEEDED);
457}
458
459
460OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
461  DisallowHeapAllocation no_allocation;
462  DisallowHandleAllocation no_handles;
463  DisallowHandleDereference no_deref;
464  DisallowCodeDependencyChange no_dependency_change;
465
466  ASSERT(last_status() == SUCCEEDED);
467  Timer t(this, &time_taken_to_optimize_);
468  ASSERT(graph_ != NULL);
469  BailoutReason bailout_reason = kNoReason;
470  if (!graph_->Optimize(&bailout_reason)) {
471    if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason);
472    return SetLastStatus(BAILED_OUT);
473  } else {
474    chunk_ = LChunk::NewChunk(graph_);
475    if (chunk_ == NULL) {
476      return SetLastStatus(BAILED_OUT);
477    }
478  }
479  return SetLastStatus(SUCCEEDED);
480}
481
482
483OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
484  ASSERT(last_status() == SUCCEEDED);
485  ASSERT(!info()->HasAbortedDueToDependencyChange());
486  DisallowCodeDependencyChange no_dependency_change;
487  {  // Scope for timer.
488    Timer timer(this, &time_taken_to_codegen_);
489    ASSERT(chunk_ != NULL);
490    ASSERT(graph_ != NULL);
491    // Deferred handles reference objects that were accessible during
492    // graph creation.  To make sure that we don't encounter inconsistencies
493    // between graph creation and code generation, we disallow accessing
494    // objects through deferred handles during the latter, with exceptions.
495    DisallowDeferredHandleDereference no_deferred_handle_deref;
496    Handle<Code> optimized_code = chunk_->Codegen();
497    if (optimized_code.is_null()) {
498      if (info()->bailout_reason() == kNoReason) {
499        info()->set_bailout_reason(kCodeGenerationFailed);
500      }
501      return AbortOptimization();
502    }
503    info()->SetCode(optimized_code);
504  }
505  RecordOptimizationStats();
506  return SetLastStatus(SUCCEEDED);
507}
508
509
510static bool GenerateCode(CompilationInfo* info) {
511  bool is_optimizing = V8::UseCrankshaft() &&
512                       !info->IsCompilingForDebugging() &&
513                       info->IsOptimizing();
514  if (is_optimizing) {
515    Logger::TimerEventScope timer(
516        info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous);
517    return MakeCrankshaftCode(info);
518  } else {
519    if (info->IsOptimizing()) {
520      // Have the CompilationInfo decide if the compilation should be
521      // BASE or NONOPT.
522      info->DisableOptimization();
523    }
524    Logger::TimerEventScope timer(
525        info->isolate(), Logger::TimerEventScope::v8_compile_full_code);
526    return FullCodeGenerator::MakeCode(info);
527  }
528}
529
530
531static bool MakeCode(CompilationInfo* info) {
532  // Precondition: code has been parsed.  Postcondition: the code field in
533  // the compilation info is set if compilation succeeded.
534  ASSERT(info->function() != NULL);
535  return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
536}
537
538
539#ifdef ENABLE_DEBUGGER_SUPPORT
540bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
541  // Precondition: code has been parsed.  Postcondition: the code field in
542  // the compilation info is set if compilation succeeded.
543  bool succeeded = MakeCode(info);
544  if (!info->shared_info().is_null()) {
545    Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(),
546                                                     info->zone());
547    info->shared_info()->set_scope_info(*scope_info);
548  }
549  return succeeded;
550}
551#endif
552
553
554static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
555                                          bool allow_lazy_without_ctx = false) {
556  return LiveEditFunctionTracker::IsActive(info->isolate()) ||
557         (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
558}
559
560
561static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
562  Isolate* isolate = info->isolate();
563  PostponeInterruptsScope postpone(isolate);
564
565  ASSERT(!isolate->native_context().is_null());
566  Handle<Script> script = info->script();
567  // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
568  FixedArray* array = isolate->native_context()->embedder_data();
569  script->set_context_data(array->get(0));
570
571#ifdef ENABLE_DEBUGGER_SUPPORT
572  if (info->is_eval()) {
573    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
574    // For eval scripts add information on the function from which eval was
575    // called.
576    if (info->is_eval()) {
577      StackTraceFrameIterator it(isolate);
578      if (!it.done()) {
579        script->set_eval_from_shared(it.frame()->function()->shared());
580        Code* code = it.frame()->LookupCode();
581        int offset = static_cast<int>(
582            it.frame()->pc() - code->instruction_start());
583        script->set_eval_from_instructions_offset(Smi::FromInt(offset));
584      }
585    }
586  }
587
588  // Notify debugger
589  isolate->debugger()->OnBeforeCompile(script);
590#endif
591
592  // Only allow non-global compiles for eval.
593  ASSERT(info->is_eval() || info->is_global());
594  {
595    Parser parser(info);
596    if ((info->pre_parse_data() != NULL ||
597         String::cast(script->source())->length() > FLAG_min_preparse_length) &&
598        !DebuggerWantsEagerCompilation(info))
599      parser.set_allow_lazy(true);
600    if (!parser.Parse()) {
601      return Handle<SharedFunctionInfo>::null();
602    }
603  }
604
605  // Measure how long it takes to do the compilation; only take the
606  // rest of the function into account to avoid overlap with the
607  // parsing statistics.
608  HistogramTimer* rate = info->is_eval()
609      ? info->isolate()->counters()->compile_eval()
610      : info->isolate()->counters()->compile();
611  HistogramTimerScope timer(rate);
612
613  // Compile the code.
614  FunctionLiteral* lit = info->function();
615  LiveEditFunctionTracker live_edit_tracker(isolate, lit);
616  if (!MakeCode(info)) {
617    if (!isolate->has_pending_exception()) isolate->StackOverflow();
618    return Handle<SharedFunctionInfo>::null();
619  }
620
621  // Allocate function.
622  ASSERT(!info->code().is_null());
623  Handle<SharedFunctionInfo> result =
624      isolate->factory()->NewSharedFunctionInfo(
625          lit->name(),
626          lit->materialized_literal_count(),
627          lit->is_generator(),
628          info->code(),
629          ScopeInfo::Create(info->scope(), info->zone()));
630
631  ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
632  Compiler::SetFunctionInfo(result, lit, true, script);
633
634  if (script->name()->IsString()) {
635    PROFILE(isolate, CodeCreateEvent(
636        info->is_eval()
637            ? Logger::EVAL_TAG
638            : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
639        *info->code(),
640        *result,
641        info,
642        String::cast(script->name())));
643    GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
644                   script,
645                   info->code(),
646                   info));
647  } else {
648    PROFILE(isolate, CodeCreateEvent(
649        info->is_eval()
650            ? Logger::EVAL_TAG
651            : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
652        *info->code(),
653        *result,
654        info,
655        isolate->heap()->empty_string()));
656    GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
657  }
658
659  // Hint to the runtime system used when allocating space for initial
660  // property space by setting the expected number of properties for
661  // the instances of the function.
662  SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
663
664  script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
665
666#ifdef ENABLE_DEBUGGER_SUPPORT
667  // Notify debugger
668  isolate->debugger()->OnAfterCompile(
669      script, Debugger::NO_AFTER_COMPILE_FLAGS);
670#endif
671
672  live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
673
674  return result;
675}
676
677
678Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
679                                             Handle<Object> script_name,
680                                             int line_offset,
681                                             int column_offset,
682                                             bool is_shared_cross_origin,
683                                             Handle<Context> context,
684                                             v8::Extension* extension,
685                                             ScriptDataImpl* pre_data,
686                                             Handle<Object> script_data,
687                                             NativesFlag natives) {
688  Isolate* isolate = source->GetIsolate();
689  int source_length = source->length();
690  isolate->counters()->total_load_size()->Increment(source_length);
691  isolate->counters()->total_compile_size()->Increment(source_length);
692
693  // The VM is in the COMPILER state until exiting this function.
694  VMState<COMPILER> state(isolate);
695
696  CompilationCache* compilation_cache = isolate->compilation_cache();
697
698  // Do a lookup in the compilation cache but not for extensions.
699  Handle<SharedFunctionInfo> result;
700  if (extension == NULL) {
701    result = compilation_cache->LookupScript(source,
702                                             script_name,
703                                             line_offset,
704                                             column_offset,
705                                             is_shared_cross_origin,
706                                             context);
707  }
708
709  if (result.is_null()) {
710    // No cache entry found. Do pre-parsing, if it makes sense, and compile
711    // the script.
712    // Building preparse data that is only used immediately after is only a
713    // saving if we might skip building the AST for lazily compiled functions.
714    // I.e., preparse data isn't relevant when the lazy flag is off, and
715    // for small sources, odds are that there aren't many functions
716    // that would be compiled lazily anyway, so we skip the preparse step
717    // in that case too.
718
719    // Create a script object describing the script to be compiled.
720    Handle<Script> script = isolate->factory()->NewScript(source);
721    if (natives == NATIVES_CODE) {
722      script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
723    }
724    if (!script_name.is_null()) {
725      script->set_name(*script_name);
726      script->set_line_offset(Smi::FromInt(line_offset));
727      script->set_column_offset(Smi::FromInt(column_offset));
728    }
729    script->set_is_shared_cross_origin(is_shared_cross_origin);
730
731    script->set_data(script_data.is_null() ? HEAP->undefined_value()
732                                           : *script_data);
733
734    // Compile the function and add it to the cache.
735    CompilationInfoWithZone info(script);
736    info.MarkAsGlobal();
737    info.SetExtension(extension);
738    info.SetPreParseData(pre_data);
739    info.SetContext(context);
740    if (FLAG_use_strict) {
741      info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
742    }
743    result = MakeFunctionInfo(&info);
744    if (extension == NULL && !result.is_null() && !result->dont_cache()) {
745      compilation_cache->PutScript(source, context, result);
746    }
747  } else {
748    if (result->ic_age() != HEAP->global_ic_age()) {
749      result->ResetForNewContext(HEAP->global_ic_age());
750    }
751  }
752
753  if (result.is_null()) isolate->ReportPendingMessages();
754  return result;
755}
756
757
758Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
759                                                 Handle<Context> context,
760                                                 bool is_global,
761                                                 LanguageMode language_mode,
762                                                 ParseRestriction restriction,
763                                                 int scope_position) {
764  Isolate* isolate = source->GetIsolate();
765  int source_length = source->length();
766  isolate->counters()->total_eval_size()->Increment(source_length);
767  isolate->counters()->total_compile_size()->Increment(source_length);
768
769  // The VM is in the COMPILER state until exiting this function.
770  VMState<COMPILER> state(isolate);
771
772  // Do a lookup in the compilation cache; if the entry is not there, invoke
773  // the compiler and add the result to the cache.
774  Handle<SharedFunctionInfo> result;
775  CompilationCache* compilation_cache = isolate->compilation_cache();
776  result = compilation_cache->LookupEval(source,
777                                         context,
778                                         is_global,
779                                         language_mode,
780                                         scope_position);
781
782  if (result.is_null()) {
783    // Create a script object describing the script to be compiled.
784    Handle<Script> script = isolate->factory()->NewScript(source);
785    CompilationInfoWithZone info(script);
786    info.MarkAsEval();
787    if (is_global) info.MarkAsGlobal();
788    info.SetLanguageMode(language_mode);
789    info.SetParseRestriction(restriction);
790    info.SetContext(context);
791    result = MakeFunctionInfo(&info);
792    if (!result.is_null()) {
793      // Explicitly disable optimization for eval code. We're not yet prepared
794      // to handle eval-code in the optimizing compiler.
795      result->DisableOptimization(kEval);
796
797      // If caller is strict mode, the result must be in strict mode or
798      // extended mode as well, but not the other way around. Consider:
799      // eval("'use strict'; ...");
800      ASSERT(language_mode != STRICT_MODE || !result->is_classic_mode());
801      // If caller is in extended mode, the result must also be in
802      // extended mode.
803      ASSERT(language_mode != EXTENDED_MODE ||
804             result->is_extended_mode());
805      if (!result->dont_cache()) {
806        compilation_cache->PutEval(
807            source, context, is_global, result, scope_position);
808      }
809    }
810  } else {
811    if (result->ic_age() != HEAP->global_ic_age()) {
812      result->ResetForNewContext(HEAP->global_ic_age());
813    }
814  }
815
816  return result;
817}
818
819
820static bool InstallFullCode(CompilationInfo* info) {
821  // Update the shared function info with the compiled code and the
822  // scope info.  Please note, that the order of the shared function
823  // info initialization is important since set_scope_info might
824  // trigger a GC, causing the ASSERT below to be invalid if the code
825  // was flushed. By setting the code object last we avoid this.
826  Handle<SharedFunctionInfo> shared = info->shared_info();
827  Handle<Code> code = info->code();
828  CHECK(code->kind() == Code::FUNCTION);
829  Handle<JSFunction> function = info->closure();
830  Handle<ScopeInfo> scope_info =
831      ScopeInfo::Create(info->scope(), info->zone());
832  shared->set_scope_info(*scope_info);
833  shared->ReplaceCode(*code);
834  if (!function.is_null()) {
835    function->ReplaceCode(*code);
836    ASSERT(!function->IsOptimized());
837  }
838
839  // Set the expected number of properties for instances.
840  FunctionLiteral* lit = info->function();
841  int expected = lit->expected_property_count();
842  SetExpectedNofPropertiesFromEstimate(shared, expected);
843
844  // Check the function has compiled code.
845  ASSERT(shared->is_compiled());
846  shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
847  shared->set_dont_inline(lit->flags()->Contains(kDontInline));
848  shared->set_ast_node_count(lit->ast_node_count());
849
850  if (V8::UseCrankshaft() &&
851      !function.is_null() &&
852      !shared->optimization_disabled()) {
853    // If we're asked to always optimize, we compile the optimized
854    // version of the function right away - unless the debugger is
855    // active as it makes no sense to compile optimized code then.
856    if (FLAG_always_opt &&
857        !Isolate::Current()->DebuggerHasBreakPoints()) {
858      CompilationInfoWithZone optimized(function);
859      optimized.SetOptimizing(BailoutId::None());
860      return Compiler::CompileLazy(&optimized);
861    }
862  }
863  return true;
864}
865
866
867static void InstallCodeCommon(CompilationInfo* info) {
868  Handle<SharedFunctionInfo> shared = info->shared_info();
869  Handle<Code> code = info->code();
870  ASSERT(!code.is_null());
871
872  // Set optimizable to false if this is disallowed by the shared
873  // function info, e.g., we might have flushed the code and must
874  // reset this bit when lazy compiling the code again.
875  if (shared->optimization_disabled()) code->set_optimizable(false);
876
877  if (shared->code() == *code) {
878    // Do not send compilation event for the same code twice.
879    return;
880  }
881  Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
882}
883
884
885static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
886  Handle<Code> code = info->code();
887  if (FLAG_cache_optimized_code &&
888      info->osr_ast_id().IsNone() &&
889      code->kind() == Code::OPTIMIZED_FUNCTION) {
890    Handle<JSFunction> function = info->closure();
891    Handle<SharedFunctionInfo> shared(function->shared());
892    Handle<FixedArray> literals(function->literals());
893    Handle<Context> native_context(function->context()->native_context());
894    SharedFunctionInfo::AddToOptimizedCodeMap(
895        shared, native_context, code, literals);
896  }
897}
898
899
900static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
901  if (FLAG_cache_optimized_code &&
902      info->osr_ast_id().IsNone() &&
903      info->IsOptimizing()) {
904    Handle<SharedFunctionInfo> shared = info->shared_info();
905    Handle<JSFunction> function = info->closure();
906    ASSERT(!function.is_null());
907    Handle<Context> native_context(function->context()->native_context());
908    int index = shared->SearchOptimizedCodeMap(*native_context);
909    if (index > 0) {
910      if (FLAG_trace_opt) {
911        PrintF("[found optimized code for ");
912        function->ShortPrint();
913        PrintF("]\n");
914      }
915      // Caching of optimized code enabled and optimized code found.
916      shared->InstallFromOptimizedCodeMap(*function, index);
917      return true;
918    }
919  }
920  return false;
921}
922
923
924bool Compiler::CompileLazy(CompilationInfo* info) {
925  Isolate* isolate = info->isolate();
926
927  // The VM is in the COMPILER state until exiting this function.
928  VMState<COMPILER> state(isolate);
929
930  PostponeInterruptsScope postpone(isolate);
931
932  Handle<SharedFunctionInfo> shared = info->shared_info();
933  int compiled_size = shared->end_position() - shared->start_position();
934  isolate->counters()->total_compile_size()->Increment(compiled_size);
935
936  if (InstallCodeFromOptimizedCodeMap(info)) return true;
937
938  // Generate the AST for the lazily compiled function.
939  if (Parser::Parse(info)) {
940    // Measure how long it takes to do the lazy compilation; only take the
941    // rest of the function into account to avoid overlap with the lazy
942    // parsing statistics.
943    HistogramTimerScope timer(isolate->counters()->compile_lazy());
944
945    // After parsing we know the function's language mode. Remember it.
946    LanguageMode language_mode = info->function()->language_mode();
947    info->SetLanguageMode(language_mode);
948    shared->set_language_mode(language_mode);
949
950    // Compile the code.
951    if (!MakeCode(info)) {
952      if (!isolate->has_pending_exception()) {
953        isolate->StackOverflow();
954      }
955    } else {
956      InstallCodeCommon(info);
957
958      if (info->IsOptimizing()) {
959        Handle<Code> code = info->code();
960        ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate));
961        info->closure()->ReplaceCode(*code);
962        InsertCodeIntoOptimizedCodeMap(info);
963        return true;
964      } else {
965        return InstallFullCode(info);
966      }
967    }
968  }
969
970  ASSERT(info->code().is_null());
971  return false;
972}
973
974
975void Compiler::RecompileParallel(Handle<JSFunction> closure) {
976  ASSERT(closure->IsMarkedForParallelRecompilation());
977
978  Isolate* isolate = closure->GetIsolate();
979  // Here we prepare compile data for the parallel recompilation thread, but
980  // this still happens synchronously and interrupts execution.
981  Logger::TimerEventScope timer(
982      isolate, Logger::TimerEventScope::v8_recompile_synchronous);
983
984  if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
985    if (FLAG_trace_parallel_recompilation) {
986      PrintF("  ** Compilation queue full, will retry optimizing ");
987      closure->PrintName();
988      PrintF(" on next run.\n");
989    }
990    return;
991  }
992
993  SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
994  VMState<COMPILER> state(isolate);
995  PostponeInterruptsScope postpone(isolate);
996
997  Handle<SharedFunctionInfo> shared = info->shared_info();
998  int compiled_size = shared->end_position() - shared->start_position();
999  isolate->counters()->total_compile_size()->Increment(compiled_size);
1000  info->SetOptimizing(BailoutId::None());
1001
1002  {
1003    CompilationHandleScope handle_scope(*info);
1004
1005    if (InstallCodeFromOptimizedCodeMap(*info)) {
1006      return;
1007    }
1008
1009    if (Parser::Parse(*info)) {
1010      LanguageMode language_mode = info->function()->language_mode();
1011      info->SetLanguageMode(language_mode);
1012      shared->set_language_mode(language_mode);
1013      info->SaveHandles();
1014
1015      if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) {
1016        OptimizingCompiler* compiler =
1017            new(info->zone()) OptimizingCompiler(*info);
1018        OptimizingCompiler::Status status = compiler->CreateGraph();
1019        if (status == OptimizingCompiler::SUCCEEDED) {
1020          info.Detach();
1021          shared->code()->set_profiler_ticks(0);
1022          isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
1023        } else if (status == OptimizingCompiler::BAILED_OUT) {
1024          isolate->clear_pending_exception();
1025          InstallFullCode(*info);
1026        }
1027      }
1028    }
1029  }
1030
1031  if (shared->code()->back_edges_patched_for_osr()) {
1032    // At this point we either put the function on recompilation queue or
1033    // aborted optimization.  In either case we want to continue executing
1034    // the unoptimized code without running into OSR.  If the unoptimized
1035    // code has been patched for OSR, unpatch it.
1036    InterruptStub interrupt_stub;
1037    Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate);
1038    Handle<Code> replacement_code =
1039        isolate->builtins()->OnStackReplacement();
1040    Deoptimizer::RevertInterruptCode(shared->code(),
1041                                     *interrupt_code,
1042                                     *replacement_code);
1043  }
1044
1045  if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1046}
1047
1048
1049void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
1050  SmartPointer<CompilationInfo> info(optimizing_compiler->info());
1051  // The function may have already been optimized by OSR.  Simply continue.
1052  // Except when OSR already disabled optimization for some reason.
1053  if (info->shared_info()->optimization_disabled()) {
1054    info->AbortOptimization();
1055    InstallFullCode(*info);
1056    if (FLAG_trace_parallel_recompilation) {
1057      PrintF("  ** aborting optimization for ");
1058      info->closure()->PrintName();
1059      PrintF(" as it has been disabled.\n");
1060    }
1061    ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1062    return;
1063  }
1064
1065  Isolate* isolate = info->isolate();
1066  VMState<COMPILER> state(isolate);
1067  Logger::TimerEventScope timer(
1068      isolate, Logger::TimerEventScope::v8_recompile_synchronous);
1069  // If crankshaft succeeded, install the optimized code else install
1070  // the unoptimized code.
1071  OptimizingCompiler::Status status = optimizing_compiler->last_status();
1072  if (info->HasAbortedDueToDependencyChange()) {
1073    info->set_bailout_reason(kBailedOutDueToDependencyChange);
1074    status = optimizing_compiler->AbortOptimization();
1075  } else if (status != OptimizingCompiler::SUCCEEDED) {
1076    info->set_bailout_reason(kFailedBailedOutLastTime);
1077    status = optimizing_compiler->AbortOptimization();
1078  } else if (isolate->DebuggerHasBreakPoints()) {
1079    info->set_bailout_reason(kDebuggerIsActive);
1080    status = optimizing_compiler->AbortOptimization();
1081  } else {
1082    status = optimizing_compiler->GenerateAndInstallCode();
1083    ASSERT(status == OptimizingCompiler::SUCCEEDED ||
1084           status == OptimizingCompiler::BAILED_OUT);
1085  }
1086
1087  InstallCodeCommon(*info);
1088  if (status == OptimizingCompiler::SUCCEEDED) {
1089    Handle<Code> code = info->code();
1090    ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
1091    info->closure()->ReplaceCode(*code);
1092    if (info->shared_info()->SearchOptimizedCodeMap(
1093            info->closure()->context()->native_context()) == -1) {
1094      InsertCodeIntoOptimizedCodeMap(*info);
1095    }
1096    if (FLAG_trace_parallel_recompilation) {
1097      PrintF("  ** Optimized code for ");
1098      info->closure()->PrintName();
1099      PrintF(" installed.\n");
1100    }
1101  } else {
1102    info->SetCode(Handle<Code>(info->shared_info()->code()));
1103    InstallFullCode(*info);
1104  }
1105  // Optimized code is finally replacing unoptimized code.  Reset the latter's
1106  // profiler ticks to prevent too soon re-opt after a deopt.
1107  info->shared_info()->code()->set_profiler_ticks(0);
1108  ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1109}
1110
1111
1112Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
1113                                                       Handle<Script> script) {
1114  // Precondition: code has been parsed and scopes have been analyzed.
1115  CompilationInfoWithZone info(script);
1116  info.SetFunction(literal);
1117  info.SetScope(literal->scope());
1118  info.SetLanguageMode(literal->scope()->language_mode());
1119
1120  Isolate* isolate = info.isolate();
1121  Factory* factory = isolate->factory();
1122  LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1123  // Determine if the function can be lazily compiled. This is necessary to
1124  // allow some of our builtin JS files to be lazily compiled. These
1125  // builtins cannot be handled lazily by the parser, since we have to know
1126  // if a function uses the special natives syntax, which is something the
1127  // parser records.
1128  // If the debugger requests compilation for break points, we cannot be
1129  // aggressive about lazy compilation, because it might trigger compilation
1130  // of functions without an outer context when setting a breakpoint through
1131  // Debug::FindSharedFunctionInfoInScript.
1132  bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
1133  bool allow_lazy = literal->AllowsLazyCompilation() &&
1134      !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
1135
1136  Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate));
1137
1138  // Generate code
1139  if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
1140    Handle<Code> code = isolate->builtins()->LazyCompile();
1141    info.SetCode(code);
1142  } else if (GenerateCode(&info)) {
1143    ASSERT(!info.code().is_null());
1144    scope_info = ScopeInfo::Create(info.scope(), info.zone());
1145  } else {
1146    return Handle<SharedFunctionInfo>::null();
1147  }
1148
1149  // Create a shared function info object.
1150  Handle<SharedFunctionInfo> result =
1151      factory->NewSharedFunctionInfo(literal->name(),
1152                                     literal->materialized_literal_count(),
1153                                     literal->is_generator(),
1154                                     info.code(),
1155                                     scope_info);
1156  SetFunctionInfo(result, literal, false, script);
1157  RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1158  result->set_allows_lazy_compilation(allow_lazy);
1159  result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1160
1161  // Set the expected number of properties for instances and return
1162  // the resulting function.
1163  SetExpectedNofPropertiesFromEstimate(result,
1164                                       literal->expected_property_count());
1165  live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1166  return result;
1167}
1168
1169
1170// Sets the function info on a function.
1171// The start_position points to the first '(' character after the function name
1172// in the full script source. When counting characters in the script source the
1173// the first character is number 0 (not 1).
1174void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
1175                               FunctionLiteral* lit,
1176                               bool is_toplevel,
1177                               Handle<Script> script) {
1178  function_info->set_length(lit->parameter_count());
1179  function_info->set_formal_parameter_count(lit->parameter_count());
1180  function_info->set_script(*script);
1181  function_info->set_function_token_position(lit->function_token_position());
1182  function_info->set_start_position(lit->start_position());
1183  function_info->set_end_position(lit->end_position());
1184  function_info->set_is_expression(lit->is_expression());
1185  function_info->set_is_anonymous(lit->is_anonymous());
1186  function_info->set_is_toplevel(is_toplevel);
1187  function_info->set_inferred_name(*lit->inferred_name());
1188  function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
1189  function_info->set_allows_lazy_compilation_without_context(
1190      lit->AllowsLazyCompilationWithoutContext());
1191  function_info->set_language_mode(lit->language_mode());
1192  function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
1193  function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
1194  function_info->set_ast_node_count(lit->ast_node_count());
1195  function_info->set_is_function(lit->is_function());
1196  function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
1197  function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
1198  function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
1199  function_info->set_is_generator(lit->is_generator());
1200}
1201
1202
1203void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
1204                                         CompilationInfo* info,
1205                                         Handle<SharedFunctionInfo> shared) {
1206  // SharedFunctionInfo is passed separately, because if CompilationInfo
1207  // was created using Script object, it will not have it.
1208
1209  // Log the code generation. If source information is available include
1210  // script name and line number. Check explicitly whether logging is
1211  // enabled as finding the line number is not free.
1212  if (info->isolate()->logger()->is_logging_code_events() ||
1213      info->isolate()->cpu_profiler()->is_profiling()) {
1214    Handle<Script> script = info->script();
1215    Handle<Code> code = info->code();
1216    if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
1217      return;
1218    int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
1219    USE(line_num);
1220    if (script->name()->IsString()) {
1221      PROFILE(info->isolate(),
1222              CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
1223                              *code,
1224                              *shared,
1225                              info,
1226                              String::cast(script->name()),
1227                              line_num));
1228    } else {
1229      PROFILE(info->isolate(),
1230              CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
1231                              *code,
1232                              *shared,
1233                              info,
1234                              info->isolate()->heap()->empty_string(),
1235                              line_num));
1236    }
1237  }
1238
1239  GDBJIT(AddCode(Handle<String>(shared->DebugName()),
1240                 Handle<Script>(info->script()),
1241                 Handle<Code>(info->code()),
1242                 info));
1243}
1244
1245
1246CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
1247    : name_(name), info_(info), zone_(info->isolate()) {
1248  if (FLAG_hydrogen_stats) {
1249    info_zone_start_allocation_size_ = info->zone()->allocation_size();
1250    start_ticks_ = OS::Ticks();
1251  }
1252}
1253
1254
1255CompilationPhase::~CompilationPhase() {
1256  if (FLAG_hydrogen_stats) {
1257    unsigned size = zone()->allocation_size();
1258    size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1259    int64_t ticks = OS::Ticks() - start_ticks_;
1260    isolate()->GetHStatistics()->SaveTiming(name_, ticks, size);
1261  }
1262}
1263
1264
1265bool CompilationPhase::ShouldProduceTraceOutput() const {
1266  // Trace if the appropriate trace flag is set and the phase name's first
1267  // character is in the FLAG_trace_phase command line parameter.
1268  bool tracing_on = info()->IsStub() ?
1269      FLAG_trace_hydrogen_stubs :
1270      FLAG_trace_hydrogen;
1271  return (tracing_on &&
1272      OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1273}
1274
1275} }  // namespace v8::internal
1276