v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
compiler.cc
Go to the documentation of this file.
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"
49 #include "scopeinfo.h"
50 #include "scopes.h"
51 #include "vm-state-inl.h"
52 
53 namespace v8 {
54 namespace internal {
55 
56 
58  Zone* zone)
59  : flags_(StrictModeField::encode(SLOPPY)),
60  script_(script),
61  osr_ast_id_(BailoutId::None()),
62  parameter_count_(0),
63  this_has_uses_(true),
64  optimization_id_(-1) {
65  Initialize(script->GetIsolate(), BASE, zone);
66 }
67 
68 
70  Zone* zone)
71  : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
72  shared_info_(shared_info),
73  script_(Handle<Script>(Script::cast(shared_info->script()))),
74  osr_ast_id_(BailoutId::None()),
75  parameter_count_(0),
76  this_has_uses_(true),
77  optimization_id_(-1) {
78  Initialize(script_->GetIsolate(), BASE, zone);
79 }
80 
81 
83  Zone* zone)
84  : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
85  closure_(closure),
86  shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
87  script_(Handle<Script>(Script::cast(shared_info_->script()))),
88  context_(closure->context()),
89  osr_ast_id_(BailoutId::None()),
90  parameter_count_(0),
91  this_has_uses_(true),
92  optimization_id_(-1) {
93  Initialize(script_->GetIsolate(), BASE, zone);
94 }
95 
96 
98  Isolate* isolate,
99  Zone* zone)
100  : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
101  osr_ast_id_(BailoutId::None()),
102  parameter_count_(0),
103  this_has_uses_(true),
104  optimization_id_(-1) {
105  Initialize(isolate, STUB, zone);
106  code_stub_ = stub;
107 }
108 
109 
110 void CompilationInfo::Initialize(Isolate* isolate,
111  Mode mode,
112  Zone* zone) {
113  isolate_ = isolate;
114  function_ = NULL;
115  scope_ = NULL;
116  global_scope_ = NULL;
117  extension_ = NULL;
118  cached_data_ = NULL;
119  cached_data_mode_ = NO_CACHED_DATA;
120  zone_ = zone;
121  deferred_handles_ = NULL;
122  code_stub_ = NULL;
123  prologue_offset_ = Code::kPrologueOffsetNotSet;
124  opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
125  no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
126  ? new List<OffsetRange>(2) : NULL;
127  for (int i = 0; i < DependentCode::kGroupCount; i++) {
128  dependencies_[i] = NULL;
129  }
130  if (mode == STUB) {
131  mode_ = STUB;
132  return;
133  }
134  mode_ = mode;
135  abort_due_to_dependency_ = false;
136  if (script_->type()->value() == Script::TYPE_NATIVE) {
137  MarkAsNative();
138  }
139  if (!shared_info_.is_null()) {
140  ASSERT(strict_mode() == SLOPPY);
141  SetStrictMode(shared_info_->strict_mode());
142  }
143  set_bailout_reason(kUnknown);
144 }
145 
146 
148  delete deferred_handles_;
149  delete no_frame_ranges_;
150 #ifdef DEBUG
151  // Check that no dependent maps have been added or added dependent maps have
152  // been rolled back or committed.
153  for (int i = 0; i < DependentCode::kGroupCount; i++) {
154  ASSERT_EQ(NULL, dependencies_[i]);
155  }
156 #endif // DEBUG
157 }
158 
159 
161  for (int i = 0; i < DependentCode::kGroupCount; i++) {
162  ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
163  if (group_objects == NULL) continue;
164  ASSERT(!object_wrapper_.is_null());
165  for (int j = 0; j < group_objects->length(); j++) {
167  static_cast<DependentCode::DependencyGroup>(i);
169  DependentCode::ForObject(group_objects->at(j), group);
170  dependent_code->UpdateToFinishedCode(group, this, *code);
171  }
172  dependencies_[i] = NULL; // Zone-allocated, no need to delete.
173  }
174 }
175 
176 
178  // Unregister from all dependent maps if not yet committed.
179  for (int i = 0; i < DependentCode::kGroupCount; i++) {
180  ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
181  if (group_objects == NULL) continue;
182  for (int j = 0; j < group_objects->length(); j++) {
184  static_cast<DependentCode::DependencyGroup>(i);
186  DependentCode::ForObject(group_objects->at(j), group);
187  dependent_code->RemoveCompilationInfo(group, this);
188  }
189  dependencies_[i] = NULL; // Zone-allocated, no need to delete.
190  }
191 }
192 
193 
195  if (IsStub()) {
196  ASSERT(parameter_count_ > 0);
197  return parameter_count_;
198  } else {
199  return scope()->num_parameters();
200  }
201 }
202 
203 
205  if (IsStub()) {
206  return 0;
207  } else {
208  return scope()->num_heap_slots();
209  }
210 }
211 
212 
214  if (IsStub()) {
215  return Code::ComputeFlags(code_stub()->GetCodeKind(),
216  code_stub()->GetICState(),
217  code_stub()->GetExtraICState(),
218  code_stub()->GetStubType());
219  } else {
220  return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
221  }
222 }
223 
224 
225 // Disable optimization for the rest of the compilation pipeline.
227  bool is_optimizable_closure =
228  FLAG_optimize_closures &&
229  closure_.is_null() &&
230  !scope_->HasTrivialOuterContext() &&
231  !scope_->outer_scope_calls_sloppy_eval() &&
232  !scope_->inside_with();
233  SetMode(is_optimizable_closure ? BASE : NONOPT);
234 }
235 
236 
237 // Primitive functions are unlikely to be picked up by the stack-walking
238 // profiler, so they trigger their own optimization when they're called
239 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
241  return FLAG_crankshaft &&
242  !function()->flags()->Contains(kDontSelfOptimize) &&
243  !function()->dont_optimize() &&
244  function()->scope()->AllowsLazyCompilation() &&
245  (shared_info().is_null() || !shared_info()->optimization_disabled());
246 }
247 
248 
250  ASSERT(scope_ == NULL);
251  scope_ = scope;
252  function()->ProcessFeedbackSlots(isolate_);
253 }
254 
255 
257  public:
259  : HOptimizedGraphBuilder(info) {
260  }
261 
262 #define DEF_VISIT(type) \
263  virtual void Visit##type(type* node) V8_OVERRIDE { \
264  if (node->position() != RelocInfo::kNoPosition) { \
265  SetSourcePosition(node->position()); \
266  } \
267  HOptimizedGraphBuilder::Visit##type(node); \
268  }
270 #undef DEF_VISIT
271 
272 #define DEF_VISIT(type) \
273  virtual void Visit##type(type* node) V8_OVERRIDE { \
274  if (node->position() != RelocInfo::kNoPosition) { \
275  SetSourcePosition(node->position()); \
276  } \
277  HOptimizedGraphBuilder::Visit##type(node); \
278  }
280 #undef DEF_VISIT
281 
282 #define DEF_VISIT(type) \
283  virtual void Visit##type(type* node) V8_OVERRIDE { \
284  HOptimizedGraphBuilder::Visit##type(node); \
285  }
288 #undef DEF_VISIT
289 };
290 
291 
292 // Determine whether to use the full compiler for all code. If the flag
293 // --always-full-compiler is specified this is the case. For the virtual frame
294 // based compiler the full compiler is also used if a debugger is connected, as
295 // the code from the full compiler supports mode precise break points. For the
296 // crankshaft adaptive compiler debugging the optimized code is not possible at
297 // all. However crankshaft support recompilation of functions, so in this case
298 // the full compiler need not be be used if a debugger is attached, but only if
299 // break points has actually been set.
300 static bool IsDebuggerActive(Isolate* isolate) {
301 #ifdef ENABLE_DEBUGGER_SUPPORT
302  return isolate->use_crankshaft() ?
303  isolate->debug()->has_break_points() :
304  isolate->debugger()->IsDebuggerActive();
305 #else
306  return false;
307 #endif
308 }
309 
310 
312  ASSERT(isolate()->use_crankshaft());
313  ASSERT(info()->IsOptimizing());
314  ASSERT(!info()->IsCompilingForDebugging());
315 
316  // We should never arrive here if there is no code object on the
317  // shared function object.
318  ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION);
319 
320  // We should never arrive here if optimization has been disabled on the
321  // shared function info.
322  ASSERT(!info()->shared_info()->optimization_disabled());
323 
324  // Fall back to using the full code generator if it's not possible
325  // to use the Hydrogen-based optimizing compiler. We already have
326  // generated code for this from the shared function object.
327  if (FLAG_always_full_compiler) return AbortOptimization();
328  if (IsDebuggerActive(isolate())) return AbortOptimization(kDebuggerIsActive);
329 
330  // Limit the number of times we re-compile a functions with
331  // the optimizing compiler.
332  const int kMaxOptCount =
333  FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
334  if (info()->opt_count() > kMaxOptCount) {
335  return AbortAndDisableOptimization(kOptimizedTooManyTimes);
336  }
337 
338  // Due to an encoding limit on LUnallocated operands in the Lithium
339  // language, we cannot optimize functions with too many formal parameters
340  // or perform on-stack replacement for function with too many
341  // stack-allocated local variables.
342  //
343  // The encoding is as a signed value, with parameters and receiver using
344  // the negative indices and locals the non-negative ones.
345  const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
346  Scope* scope = info()->scope();
347  if ((scope->num_parameters() + 1) > parameter_limit) {
348  return AbortAndDisableOptimization(kTooManyParameters);
349  }
350 
351  const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
352  if (info()->is_osr() &&
353  scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
354  return AbortAndDisableOptimization(kTooManyParametersLocals);
355  }
356 
357  // Take --hydrogen-filter into account.
358  if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
359  return AbortOptimization(kHydrogenFilter);
360  }
361 
362  // Recompile the unoptimized version of the code if the current version
363  // doesn't have deoptimization support. Alternatively, we may decide to
364  // run the full code generator to get a baseline for the compile-time
365  // performance of the hydrogen-based compiler.
366  bool should_recompile = !info()->shared_info()->has_deoptimization_support();
367  if (should_recompile || FLAG_hydrogen_stats) {
368  ElapsedTimer timer;
369  if (FLAG_hydrogen_stats) {
370  timer.Start();
371  }
372  CompilationInfoWithZone unoptimized(info()->shared_info());
373  // Note that we use the same AST that we will use for generating the
374  // optimized code.
375  unoptimized.SetFunction(info()->function());
376  unoptimized.PrepareForCompilation(info()->scope());
377  unoptimized.SetContext(info()->context());
378  if (should_recompile) unoptimized.EnableDeoptimizationSupport();
379  bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
380  if (should_recompile) {
381  if (!succeeded) return SetLastStatus(FAILED);
383  shared->EnableDeoptimizationSupport(*unoptimized.code());
384  // The existing unoptimized code was replaced with the new one.
386  Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
387  }
388  if (FLAG_hydrogen_stats) {
389  isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
390  }
391  }
392 
393  // Check that the unoptimized, shared code is ready for
394  // optimizations. When using the always_opt flag we disregard the
395  // optimizable marker in the code object and optimize anyway. This
396  // is safe as long as the unoptimized code has deoptimization
397  // support.
398  ASSERT(FLAG_always_opt || info()->shared_info()->code()->optimizable());
399  ASSERT(info()->shared_info()->has_deoptimization_support());
400 
401  if (FLAG_trace_hydrogen) {
402  Handle<String> name = info()->function()->debug_name();
403  PrintF("-----------------------------------------------------------\n");
404  PrintF("Compiling method %s using hydrogen\n", name->ToCString().get());
405  isolate()->GetHTracer()->TraceCompilation(info());
406  }
407 
408  // Type-check the function.
409  AstTyper::Run(info());
410 
411  graph_builder_ = FLAG_hydrogen_track_positions
413  : new(info()->zone()) HOptimizedGraphBuilder(info());
414 
415  Timer t(this, &time_taken_to_create_graph_);
416  info()->set_this_has_uses(false);
417  graph_ = graph_builder_->CreateGraph();
418 
419  if (isolate()->has_pending_exception()) {
420  return SetLastStatus(FAILED);
421  }
422 
423  // The function being compiled may have bailed out due to an inline
424  // candidate bailing out. In such a case, we don't disable
425  // optimization on the shared_info.
426  ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
427  if (graph_ == NULL) {
428  if (graph_builder_->inline_bailout()) {
429  return AbortOptimization();
430  } else {
432  }
433  }
434 
435  if (info()->HasAbortedDueToDependencyChange()) {
436  return AbortOptimization(kBailedOutDueToDependencyChange);
437  }
438 
439  return SetLastStatus(SUCCEEDED);
440 }
441 
442 
444  DisallowHeapAllocation no_allocation;
445  DisallowHandleAllocation no_handles;
446  DisallowHandleDereference no_deref;
447  DisallowCodeDependencyChange no_dependency_change;
448 
450  Timer t(this, &time_taken_to_optimize_);
451  ASSERT(graph_ != NULL);
452  BailoutReason bailout_reason = kNoReason;
453 
454  if (graph_->Optimize(&bailout_reason)) {
455  chunk_ = LChunk::NewChunk(graph_);
456  if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
457  } else if (bailout_reason != kNoReason) {
458  graph_builder_->Bailout(bailout_reason);
459  }
460 
461  return AbortOptimization();
462 }
463 
464 
467  ASSERT(!info()->HasAbortedDueToDependencyChange());
468  DisallowCodeDependencyChange no_dependency_change;
469  { // Scope for timer.
470  Timer timer(this, &time_taken_to_codegen_);
471  ASSERT(chunk_ != NULL);
472  ASSERT(graph_ != NULL);
473  // Deferred handles reference objects that were accessible during
474  // graph creation. To make sure that we don't encounter inconsistencies
475  // between graph creation and code generation, we disallow accessing
476  // objects through deferred handles during the latter, with exceptions.
477  DisallowDeferredHandleDereference no_deferred_handle_deref;
478  Handle<Code> optimized_code = chunk_->Codegen();
479  if (optimized_code.is_null()) {
480  if (info()->bailout_reason() == kNoReason) {
481  info_->set_bailout_reason(kCodeGenerationFailed);
482  }
484  }
485  info()->SetCode(optimized_code);
486  }
487  RecordOptimizationStats();
488  // Add to the weak list of optimized code objects.
489  info()->context()->native_context()->AddOptimizedCode(*info()->code());
490  return SetLastStatus(SUCCEEDED);
491 }
492 
493 
494 void OptimizedCompileJob::RecordOptimizationStats() {
495  Handle<JSFunction> function = info()->closure();
496  if (!function->IsOptimized()) {
497  // Concurrent recompilation and OSR may race. Increment only once.
498  int opt_count = function->shared()->opt_count();
499  function->shared()->set_opt_count(opt_count + 1);
500  }
501  double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
502  double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
503  double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
504  if (FLAG_trace_opt) {
505  PrintF("[optimizing ");
506  function->ShortPrint();
507  PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
508  ms_codegen);
509  }
510  if (FLAG_trace_opt_stats) {
511  static double compilation_time = 0.0;
512  static int compiled_functions = 0;
513  static int code_size = 0;
514 
515  compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
516  compiled_functions++;
517  code_size += function->shared()->SourceSize();
518  PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
519  compiled_functions,
520  code_size,
521  compilation_time);
522  }
523  if (FLAG_hydrogen_stats) {
524  isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
525  time_taken_to_optimize_,
526  time_taken_to_codegen_);
527  }
528 }
529 
530 
531 // Sets the expected number of properties based on estimate from compiler.
533  int estimate) {
534  // See the comment in SetExpectedNofProperties.
535  if (shared->live_objects_may_exist()) return;
536 
537  // If no properties are added in the constructor, they are more likely
538  // to be added later.
539  if (estimate == 0) estimate = 2;
540 
541  // TODO(yangguo): check whether those heuristics are still up-to-date.
542  // We do not shrink objects that go into a snapshot (yet), so we adjust
543  // the estimate conservatively.
544  if (Serializer::enabled()) {
545  estimate += 2;
546  } else if (FLAG_clever_optimizations) {
547  // Inobject slack tracking will reclaim redundant inobject space later,
548  // so we can afford to adjust the estimate generously.
549  estimate += 8;
550  } else {
551  estimate += 3;
552  }
553 
554  shared->set_expected_nof_properties(estimate);
555 }
556 
557 
558 static void UpdateSharedFunctionInfo(CompilationInfo* info) {
559  // Update the shared function info with the compiled code and the
560  // scope info. Please note, that the order of the shared function
561  // info initialization is important since set_scope_info might
562  // trigger a GC, causing the ASSERT below to be invalid if the code
563  // was flushed. By setting the code object last we avoid this.
564  Handle<SharedFunctionInfo> shared = info->shared_info();
565  Handle<ScopeInfo> scope_info =
566  ScopeInfo::Create(info->scope(), info->zone());
567  shared->set_scope_info(*scope_info);
568 
569  Handle<Code> code = info->code();
570  CHECK(code->kind() == Code::FUNCTION);
571  shared->ReplaceCode(*code);
572  if (shared->optimization_disabled()) code->set_optimizable(false);
573 
574  // Set the expected number of properties for instances.
575  FunctionLiteral* lit = info->function();
576  int expected = lit->expected_property_count();
577  SetExpectedNofPropertiesFromEstimate(shared, expected);
578 
579  // Check the function has compiled code.
580  ASSERT(shared->is_compiled());
581  shared->set_dont_optimize_reason(lit->dont_optimize_reason());
582  shared->set_dont_inline(lit->flags()->Contains(kDontInline));
583  shared->set_ast_node_count(lit->ast_node_count());
584  shared->set_strict_mode(lit->strict_mode());
585 }
586 
587 
588 // Sets the function info on a function.
589 // The start_position points to the first '(' character after the function name
590 // in the full script source. When counting characters in the script source the
591 // the first character is number 0 (not 1).
592 static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
593  FunctionLiteral* lit,
594  bool is_toplevel,
595  Handle<Script> script) {
596  function_info->set_length(lit->parameter_count());
597  function_info->set_formal_parameter_count(lit->parameter_count());
598  function_info->set_script(*script);
599  function_info->set_function_token_position(lit->function_token_position());
600  function_info->set_start_position(lit->start_position());
601  function_info->set_end_position(lit->end_position());
602  function_info->set_is_expression(lit->is_expression());
603  function_info->set_is_anonymous(lit->is_anonymous());
604  function_info->set_is_toplevel(is_toplevel);
605  function_info->set_inferred_name(*lit->inferred_name());
606  function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
607  function_info->set_allows_lazy_compilation_without_context(
608  lit->AllowsLazyCompilationWithoutContext());
609  function_info->set_strict_mode(lit->strict_mode());
610  function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
611  function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
612  function_info->set_ast_node_count(lit->ast_node_count());
613  function_info->set_is_function(lit->is_function());
614  function_info->set_dont_optimize_reason(lit->dont_optimize_reason());
615  function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
616  function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
617  function_info->set_is_generator(lit->is_generator());
618 }
619 
620 
621 static bool CompileUnoptimizedCode(CompilationInfo* info) {
622  ASSERT(info->function() != NULL);
623  if (!Rewriter::Rewrite(info)) return false;
624  if (!Scope::Analyze(info)) return false;
625  ASSERT(info->scope() != NULL);
626 
627  if (!FullCodeGenerator::MakeCode(info)) {
628  Isolate* isolate = info->isolate();
629  if (!isolate->has_pending_exception()) isolate->StackOverflow();
630  return false;
631  }
632  return true;
633 }
634 
635 
636 static Handle<Code> GetUnoptimizedCodeCommon(CompilationInfo* info) {
637  VMState<COMPILER> state(info->isolate());
638  PostponeInterruptsScope postpone(info->isolate());
639  if (!Parser::Parse(info)) return Handle<Code>::null();
640  info->SetStrictMode(info->function()->strict_mode());
641 
642  if (!CompileUnoptimizedCode(info)) return Handle<Code>::null();
644  Logger::LAZY_COMPILE_TAG, info, info->shared_info());
645  UpdateSharedFunctionInfo(info);
646  ASSERT_EQ(Code::FUNCTION, info->code()->kind());
647  return info->code();
648 }
649 
650 
652  ASSERT(!function->GetIsolate()->has_pending_exception());
653  ASSERT(!function->is_compiled());
654  if (function->shared()->is_compiled()) {
655  return Handle<Code>(function->shared()->code());
656  }
657 
658  CompilationInfoWithZone info(function);
659  Handle<Code> result = GetUnoptimizedCodeCommon(&info);
660  ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
661 
662  if (FLAG_always_opt &&
663  !result.is_null() &&
664  info.isolate()->use_crankshaft() &&
665  !info.shared_info()->optimization_disabled() &&
666  !info.isolate()->DebuggerHasBreakPoints()) {
668  function, result, Compiler::NOT_CONCURRENT);
669  if (!opt_code.is_null()) result = opt_code;
670  }
671 
672  return result;
673 }
674 
675 
677  ASSERT(!shared->GetIsolate()->has_pending_exception());
678  ASSERT(!shared->is_compiled());
679 
681  Handle<Code> result = GetUnoptimizedCodeCommon(&info);
682  ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception());
683  return result;
684 }
685 
686 
689  if (function->is_compiled()) return true;
691  if (code.is_null()) {
692  if (flag == CLEAR_EXCEPTION) {
693  function->GetIsolate()->clear_pending_exception();
694  }
695  return false;
696  }
697  function->ReplaceCode(*code);
698  ASSERT(function->is_compiled());
699  return true;
700 }
701 
702 
703 // Compile full code for debugging. This code will have debug break slots
704 // and deoptimization information. Deoptimization information is required
705 // in case that an optimized version of this function is still activated on
706 // the stack. It will also make sure that the full code is compiled with
707 // the same flags as the previous version, that is flags which can change
708 // the code generated. The current method of mapping from already compiled
709 // full code without debug break slots to full code with debug break slots
710 // depends on the generated code is otherwise exactly the same.
711 // If compilation fails, just keep the existing code.
713  CompilationInfoWithZone info(function);
714  Isolate* isolate = info.isolate();
715  VMState<COMPILER> state(isolate);
716 
717  ASSERT(!isolate->has_pending_exception());
718  Handle<Code> old_code(function->shared()->code());
719  ASSERT(old_code->kind() == Code::FUNCTION);
720  ASSERT(!old_code->has_debug_break_slots());
721 
723  if (old_code->is_compiled_optimizable()) {
725  } else {
726  info.MarkNonOptimizable();
727  }
728  Handle<Code> new_code = GetUnoptimizedCodeCommon(&info);
729  if (new_code.is_null()) {
730  isolate->clear_pending_exception();
731  } else {
732  ASSERT_EQ(old_code->is_compiled_optimizable(),
733  new_code->is_compiled_optimizable());
734  }
735  return new_code;
736 }
737 
738 
739 #ifdef ENABLE_DEBUGGER_SUPPORT
740 void Compiler::CompileForLiveEdit(Handle<Script> script) {
741  // TODO(635): support extensions.
743  PostponeInterruptsScope postpone(info.isolate());
744  VMState<COMPILER> state(info.isolate());
745 
746  info.MarkAsGlobal();
747  if (!Parser::Parse(&info)) return;
748  info.SetStrictMode(info.function()->strict_mode());
749 
750  LiveEditFunctionTracker tracker(info.isolate(), info.function());
751  if (!CompileUnoptimizedCode(&info)) return;
752  if (!info.shared_info().is_null()) {
753  Handle<ScopeInfo> scope_info = ScopeInfo::Create(info.scope(),
754  info.zone());
755  info.shared_info()->set_scope_info(*scope_info);
756  }
757  tracker.RecordRootFunctionInfo(info.code());
758 }
759 #endif
760 
761 
762 static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
763  bool allow_lazy_without_ctx = false) {
764  return LiveEditFunctionTracker::IsActive(info->isolate()) ||
765  (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
766 }
767 
768 
769 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
770  Isolate* isolate = info->isolate();
771  PostponeInterruptsScope postpone(isolate);
772  ASSERT(!isolate->native_context().is_null());
773  Handle<Script> script = info->script();
774 
775  // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
776  FixedArray* array = isolate->native_context()->embedder_data();
777  script->set_context_data(array->get(0));
778 
779 #ifdef ENABLE_DEBUGGER_SUPPORT
780  isolate->debugger()->OnBeforeCompile(script);
781 #endif
782 
783  ASSERT(info->is_eval() || info->is_global());
784 
785  bool parse_allow_lazy =
786  (info->cached_data_mode() == CONSUME_CACHED_DATA ||
787  String::cast(script->source())->length() > FLAG_min_preparse_length) &&
788  !DebuggerWantsEagerCompilation(info);
789 
790  if (!parse_allow_lazy && info->cached_data_mode() != NO_CACHED_DATA) {
791  // We are going to parse eagerly, but we either 1) have cached data produced
792  // by lazy parsing or 2) are asked to generate cached data. We cannot use
793  // the existing data, since it won't contain all the symbols we need for
794  // eager parsing. In addition, it doesn't make sense to produce the data
795  // when parsing eagerly. That data would contain all symbols, but no
796  // functions, so it cannot be used to aid lazy parsing later.
797  info->SetCachedData(NULL, NO_CACHED_DATA);
798  }
799 
800  Handle<SharedFunctionInfo> result;
801 
802  { VMState<COMPILER> state(info->isolate());
803  if (!Parser::Parse(info, parse_allow_lazy)) {
805  }
806 
807  FunctionLiteral* lit = info->function();
808  LiveEditFunctionTracker live_edit_tracker(isolate, lit);
809 
810  // Measure how long it takes to do the compilation; only take the
811  // rest of the function into account to avoid overlap with the
812  // parsing statistics.
813  HistogramTimer* rate = info->is_eval()
814  ? info->isolate()->counters()->compile_eval()
815  : info->isolate()->counters()->compile();
816  HistogramTimerScope timer(rate);
817 
818  // Compile the code.
819  if (!CompileUnoptimizedCode(info)) {
821  }
822 
823  // Allocate function.
824  ASSERT(!info->code().is_null());
825  result = isolate->factory()->NewSharedFunctionInfo(
826  lit->name(),
827  lit->materialized_literal_count(),
828  lit->is_generator(),
829  info->code(),
830  ScopeInfo::Create(info->scope(), info->zone()));
831 
832  ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
833  SetFunctionInfo(result, lit, true, script);
834 
835  Handle<String> script_name = script->name()->IsString()
836  ? Handle<String>(String::cast(script->name()))
837  : isolate->factory()->empty_string();
838  Logger::LogEventsAndTags log_tag = info->is_eval()
839  ? Logger::EVAL_TAG
840  : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
841 
842  PROFILE(isolate, CodeCreateEvent(
843  log_tag, *info->code(), *result, info, *script_name));
844  GDBJIT(AddCode(script_name, script, info->code(), info));
845 
846  // Hint to the runtime system used when allocating space for initial
847  // property space by setting the expected number of properties for
848  // the instances of the function.
850  lit->expected_property_count());
851 
852  script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
853 
854  live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
855  }
856 
857 #ifdef ENABLE_DEBUGGER_SUPPORT
858  isolate->debugger()->OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
859 #endif
860 
861  return result;
862 }
863 
864 
866  Handle<Context> context,
867  StrictMode strict_mode,
868  ParseRestriction restriction,
869  int scope_position) {
870  Isolate* isolate = source->GetIsolate();
871  int source_length = source->length();
872  isolate->counters()->total_eval_size()->Increment(source_length);
873  isolate->counters()->total_compile_size()->Increment(source_length);
874 
875  CompilationCache* compilation_cache = isolate->compilation_cache();
876  Handle<SharedFunctionInfo> shared_info = compilation_cache->LookupEval(
877  source, context, strict_mode, scope_position);
878 
879  if (shared_info.is_null()) {
880  Handle<Script> script = isolate->factory()->NewScript(source);
882  info.MarkAsEval();
883  if (context->IsNativeContext()) info.MarkAsGlobal();
884  info.SetStrictMode(strict_mode);
885  info.SetParseRestriction(restriction);
886  info.SetContext(context);
887 
888 #if ENABLE_DEBUGGER_SUPPORT
889  Debug::RecordEvalCaller(script);
890 #endif // ENABLE_DEBUGGER_SUPPORT
891 
892  shared_info = CompileToplevel(&info);
893 
894  if (shared_info.is_null()) {
895  return Handle<JSFunction>::null();
896  } else {
897  // Explicitly disable optimization for eval code. We're not yet prepared
898  // to handle eval-code in the optimizing compiler.
899  shared_info->DisableOptimization(kEval);
900 
901  // If caller is strict mode, the result must be in strict mode as well.
902  ASSERT(strict_mode == SLOPPY || shared_info->strict_mode() == STRICT);
903  if (!shared_info->dont_cache()) {
904  compilation_cache->PutEval(
905  source, context, shared_info, scope_position);
906  }
907  }
908  } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) {
909  shared_info->ResetForNewContext(isolate->heap()->global_ic_age());
910  }
911 
912  return isolate->factory()->NewFunctionFromSharedFunctionInfo(
913  shared_info, context, NOT_TENURED);
914 }
915 
916 
918  Handle<String> source,
919  Handle<Object> script_name,
920  int line_offset,
921  int column_offset,
922  bool is_shared_cross_origin,
923  Handle<Context> context,
924  v8::Extension* extension,
925  ScriptDataImpl** cached_data,
926  CachedDataMode cached_data_mode,
927  NativesFlag natives) {
928  if (cached_data_mode == NO_CACHED_DATA) {
929  cached_data = NULL;
930  } else if (cached_data_mode == PRODUCE_CACHED_DATA) {
931  ASSERT(cached_data && !*cached_data);
932  } else {
933  ASSERT(cached_data_mode == CONSUME_CACHED_DATA);
934  ASSERT(cached_data && *cached_data);
935  }
936  Isolate* isolate = source->GetIsolate();
937  int source_length = source->length();
938  isolate->counters()->total_load_size()->Increment(source_length);
939  isolate->counters()->total_compile_size()->Increment(source_length);
940 
941  CompilationCache* compilation_cache = isolate->compilation_cache();
942 
943  // Do a lookup in the compilation cache but not for extensions.
945  if (extension == NULL) {
946  result = compilation_cache->LookupScript(source,
947  script_name,
948  line_offset,
949  column_offset,
950  is_shared_cross_origin,
951  context);
952  }
953 
954  if (result.is_null()) {
955  // No cache entry found. Do pre-parsing, if it makes sense, and compile
956  // the script.
957  // Building preparse data that is only used immediately after is only a
958  // saving if we might skip building the AST for lazily compiled functions.
959  // I.e., preparse data isn't relevant when the lazy flag is off, and
960  // for small sources, odds are that there aren't many functions
961  // that would be compiled lazily anyway, so we skip the preparse step
962  // in that case too.
963 
964  // Create a script object describing the script to be compiled.
965  Handle<Script> script = isolate->factory()->NewScript(source);
966  if (natives == NATIVES_CODE) {
967  script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
968  }
969  if (!script_name.is_null()) {
970  script->set_name(*script_name);
971  script->set_line_offset(Smi::FromInt(line_offset));
972  script->set_column_offset(Smi::FromInt(column_offset));
973  }
974  script->set_is_shared_cross_origin(is_shared_cross_origin);
975 
976  // Compile the function and add it to the cache.
978  info.MarkAsGlobal();
979  info.SetExtension(extension);
980  info.SetCachedData(cached_data, cached_data_mode);
981  info.SetContext(context);
982  if (FLAG_use_strict) info.SetStrictMode(STRICT);
983  result = CompileToplevel(&info);
984  if (extension == NULL && !result.is_null() && !result->dont_cache()) {
985  compilation_cache->PutScript(source, context, result);
986  }
987  } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
988  result->ResetForNewContext(isolate->heap()->global_ic_age());
989  }
990 
991  if (result.is_null()) isolate->ReportPendingMessages();
992  return result;
993 }
994 
995 
997  Handle<Script> script) {
998  // Precondition: code has been parsed and scopes have been analyzed.
1000  info.SetFunction(literal);
1001  info.PrepareForCompilation(literal->scope());
1002  info.SetStrictMode(literal->scope()->strict_mode());
1003 
1004  Isolate* isolate = info.isolate();
1005  Factory* factory = isolate->factory();
1006  LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1007  // Determine if the function can be lazily compiled. This is necessary to
1008  // allow some of our builtin JS files to be lazily compiled. These
1009  // builtins cannot be handled lazily by the parser, since we have to know
1010  // if a function uses the special natives syntax, which is something the
1011  // parser records.
1012  // If the debugger requests compilation for break points, we cannot be
1013  // aggressive about lazy compilation, because it might trigger compilation
1014  // of functions without an outer context when setting a breakpoint through
1015  // Debug::FindSharedFunctionInfoInScript.
1016  bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
1017  bool allow_lazy = literal->AllowsLazyCompilation() &&
1018  !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
1019 
1020  // Generate code
1021  Handle<ScopeInfo> scope_info;
1022  if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
1023  Handle<Code> code = isolate->builtins()->CompileUnoptimized();
1024  info.SetCode(code);
1025  scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
1026  } else if (FullCodeGenerator::MakeCode(&info)) {
1027  ASSERT(!info.code().is_null());
1028  scope_info = ScopeInfo::Create(info.scope(), info.zone());
1029  } else {
1031  }
1032 
1033  // Create a shared function info object.
1035  factory->NewSharedFunctionInfo(literal->name(),
1036  literal->materialized_literal_count(),
1037  literal->is_generator(),
1038  info.code(),
1039  scope_info);
1040  SetFunctionInfo(result, literal, false, script);
1041  RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1042  result->set_allows_lazy_compilation(allow_lazy);
1043  result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1044 
1045  // Set the expected number of properties for instances and return
1046  // the resulting function.
1048  literal->expected_property_count());
1049  live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1050  return result;
1051 }
1052 
1053 
1054 static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function,
1055  BailoutId osr_ast_id) {
1056  if (FLAG_cache_optimized_code) {
1057  Handle<SharedFunctionInfo> shared(function->shared());
1058  DisallowHeapAllocation no_gc;
1059  int index = shared->SearchOptimizedCodeMap(
1060  function->context()->native_context(), osr_ast_id);
1061  if (index > 0) {
1062  if (FLAG_trace_opt) {
1063  PrintF("[found optimized code for ");
1064  function->ShortPrint();
1065  if (!osr_ast_id.IsNone()) {
1066  PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
1067  }
1068  PrintF("]\n");
1069  }
1070  FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index);
1071  if (literals != NULL) function->set_literals(literals);
1072  return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index));
1073  }
1074  }
1075  return Handle<Code>::null();
1076 }
1077 
1078 
1079 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
1080  Handle<Code> code = info->code();
1081  if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
1082 
1083  // Cache optimized code.
1084  if (FLAG_cache_optimized_code) {
1085  Handle<JSFunction> function = info->closure();
1086  Handle<SharedFunctionInfo> shared(function->shared());
1087  Handle<FixedArray> literals(function->literals());
1088  Handle<Context> native_context(function->context()->native_context());
1090  shared, native_context, code, literals, info->osr_ast_id());
1091  }
1092 }
1093 
1094 
1095 static bool CompileOptimizedPrologue(CompilationInfo* info) {
1096  if (!Parser::Parse(info)) return false;
1097  info->SetStrictMode(info->function()->strict_mode());
1098 
1099  if (!Rewriter::Rewrite(info)) return false;
1100  if (!Scope::Analyze(info)) return false;
1101  ASSERT(info->scope() != NULL);
1102  return true;
1103 }
1104 
1105 
1106 static bool GetOptimizedCodeNow(CompilationInfo* info) {
1107  if (!CompileOptimizedPrologue(info)) return false;
1108 
1109  Logger::TimerEventScope timer(
1111 
1112  OptimizedCompileJob job(info);
1113  if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false;
1114  if (job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED) return false;
1115  if (job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) return false;
1116 
1117  // Success!
1118  ASSERT(!info->isolate()->has_pending_exception());
1119  InsertCodeIntoOptimizedCodeMap(info);
1121  Logger::LAZY_COMPILE_TAG, info, info->shared_info());
1122  return true;
1123 }
1124 
1125 
1126 static bool GetOptimizedCodeLater(CompilationInfo* info) {
1127  Isolate* isolate = info->isolate();
1128  if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
1129  if (FLAG_trace_concurrent_recompilation) {
1130  PrintF(" ** Compilation queue full, will retry optimizing ");
1131  info->closure()->PrintName();
1132  PrintF(" later.\n");
1133  }
1134  return false;
1135  }
1136 
1137  CompilationHandleScope handle_scope(info);
1138  if (!CompileOptimizedPrologue(info)) return false;
1139  info->SaveHandles(); // Copy handles to the compilation handle scope.
1140 
1141  Logger::TimerEventScope timer(
1143 
1144  OptimizedCompileJob* job = new(info->zone()) OptimizedCompileJob(info);
1145  OptimizedCompileJob::Status status = job->CreateGraph();
1146  if (status != OptimizedCompileJob::SUCCEEDED) return false;
1147  isolate->optimizing_compiler_thread()->QueueForOptimization(job);
1148 
1149  if (FLAG_trace_concurrent_recompilation) {
1150  PrintF(" ** Queued ");
1151  info->closure()->PrintName();
1152  if (info->is_osr()) {
1153  PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
1154  } else {
1155  PrintF(" for concurrent optimization.\n");
1156  }
1157  }
1158  return true;
1159 }
1160 
1161 
1163  Handle<Code> current_code,
1164  ConcurrencyMode mode,
1165  BailoutId osr_ast_id) {
1166  Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function, osr_ast_id);
1167  if (!cached_code.is_null()) return cached_code;
1168 
1170  Isolate* isolate = info->isolate();
1171  VMState<COMPILER> state(isolate);
1172  ASSERT(!isolate->has_pending_exception());
1173  PostponeInterruptsScope postpone(isolate);
1174 
1175  Handle<SharedFunctionInfo> shared = info->shared_info();
1176  ASSERT_NE(ScopeInfo::Empty(isolate), shared->scope_info());
1177  int compiled_size = shared->end_position() - shared->start_position();
1178  isolate->counters()->total_compile_size()->Increment(compiled_size);
1179  current_code->set_profiler_ticks(0);
1180 
1181  info->SetOptimizing(osr_ast_id, current_code);
1182 
1183  if (mode == CONCURRENT) {
1184  if (GetOptimizedCodeLater(info.get())) {
1185  info.Detach(); // The background recompile job owns this now.
1186  return isolate->builtins()->InOptimizationQueue();
1187  }
1188  } else {
1189  if (GetOptimizedCodeNow(info.get())) return info->code();
1190  }
1191 
1192  // Failed.
1193  if (FLAG_trace_opt) {
1194  PrintF("[failed to optimize ");
1195  function->PrintName();
1196  PrintF(": %s]\n", GetBailoutReason(info->bailout_reason()));
1197  }
1198 
1199  if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1200  return Handle<Code>::null();
1201 }
1202 
1203 
1205  // Take ownership of compilation info. Deleting compilation info
1206  // also tears down the zone and the recompile job.
1208  Isolate* isolate = info->isolate();
1209 
1210  VMState<COMPILER> state(isolate);
1213 
1214  Handle<SharedFunctionInfo> shared = info->shared_info();
1215  shared->code()->set_profiler_ticks(0);
1216 
1217  // 1) Optimization may have failed.
1218  // 2) The function may have already been optimized by OSR. Simply continue.
1219  // Except when OSR already disabled optimization for some reason.
1220  // 3) The code may have already been invalidated due to dependency change.
1221  // 4) Debugger may have been activated.
1222 
1224  shared->optimization_disabled() ||
1225  info->HasAbortedDueToDependencyChange() ||
1226  isolate->DebuggerHasBreakPoints()) {
1227  return Handle<Code>::null();
1228  }
1229 
1231  return Handle<Code>::null();
1232  }
1233 
1235  Logger::LAZY_COMPILE_TAG, info.get(), shared);
1236  if (info->shared_info()->SearchOptimizedCodeMap(
1237  info->context()->native_context(), info->osr_ast_id()) == -1) {
1238  InsertCodeIntoOptimizedCodeMap(info.get());
1239  }
1240 
1241  if (FLAG_trace_concurrent_recompilation) {
1242  PrintF(" ** Optimized code for ");
1243  info->closure()->PrintName();
1244  PrintF(" generated.\n");
1245  }
1246 
1247  return Handle<Code>(*info->code());
1248 }
1249 
1250 
1252  CompilationInfo* info,
1253  Handle<SharedFunctionInfo> shared) {
1254  // SharedFunctionInfo is passed separately, because if CompilationInfo
1255  // was created using Script object, it will not have it.
1256 
1257  // Log the code generation. If source information is available include
1258  // script name and line number. Check explicitly whether logging is
1259  // enabled as finding the line number is not free.
1260  if (info->isolate()->logger()->is_logging_code_events() ||
1261  info->isolate()->cpu_profiler()->is_profiling()) {
1262  Handle<Script> script = info->script();
1263  Handle<Code> code = info->code();
1264  if (code.is_identical_to(info->isolate()->builtins()->CompileUnoptimized()))
1265  return;
1266  int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
1267  int column_num =
1268  GetScriptColumnNumber(script, shared->start_position()) + 1;
1269  USE(line_num);
1270  String* script_name = script->name()->IsString()
1271  ? String::cast(script->name())
1272  : info->isolate()->heap()->empty_string();
1273  Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
1274  PROFILE(info->isolate(), CodeCreateEvent(
1275  log_tag, *code, *shared, info, script_name, line_num, column_num));
1276  }
1277 
1278  GDBJIT(AddCode(Handle<String>(shared->DebugName()),
1279  Handle<Script>(info->script()),
1280  Handle<Code>(info->code()),
1281  info));
1282 }
1283 
1284 
1285 CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
1286  : name_(name), info_(info), zone_(info->isolate()) {
1287  if (FLAG_hydrogen_stats) {
1288  info_zone_start_allocation_size_ = info->zone()->allocation_size();
1289  timer_.Start();
1290  }
1291 }
1292 
1293 
1294 CompilationPhase::~CompilationPhase() {
1295  if (FLAG_hydrogen_stats) {
1296  unsigned size = zone()->allocation_size();
1297  size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1298  isolate()->GetHStatistics()->SaveTiming(name_, timer_.Elapsed(), size);
1299  }
1300 }
1301 
1302 
1303 bool CompilationPhase::ShouldProduceTraceOutput() const {
1304  // Trace if the appropriate trace flag is set and the phase name's first
1305  // character is in the FLAG_trace_phase command line parameter.
1306  AllowHandleDereference allow_deref;
1307  bool tracing_on = info()->IsStub()
1308  ? FLAG_trace_hydrogen_stubs
1309  : (FLAG_trace_hydrogen &&
1310  info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1311  return (tracing_on &&
1312  OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1313 }
1314 
1315 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
Failure * StackOverflow()
Definition: isolate.cc:871
BailoutReason bailout_reason() const
Definition: compiler.h:280
static DependentCode * ForObject(Handle< HeapObject > object, DependencyGroup group)
Definition: objects.cc:11527
Handle< JSFunction > NewFunctionFromSharedFunctionInfo(Handle< SharedFunctionInfo > function_info, Handle< Context > context, PretenureFlag pretenure=TENURED)
Definition: factory.cc:944
static bool IsActive(Isolate *isolate)
Definition: liveedit.cc:2128
#define PROFILE(IsolateGetter, Call)
Definition: cpu-profiler.h:194
static Handle< SharedFunctionInfo > CompileScript(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, bool is_shared_cross_origin, Handle< Context > context, v8::Extension *extension, ScriptDataImpl **cached_data, CachedDataMode cached_data_mode, NativesFlag is_natives_code)
Definition: compiler.cc:917
static Handle< Code > GetCodeForDebugging(Handle< JSFunction > function)
Definition: compiler.cc:712
void PrepareForCompilation(Scope *scope)
Definition: compiler.cc:249
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
CompilationCache * compilation_cache()
Definition: isolate.h:867
void SetParseRestriction(ParseRestriction restriction)
Definition: compiler.h:169
void PrintF(const char *format,...)
Definition: v8utils.cc:40
static String * cast(Object *obj)
void SetCode(Handle< Code > code)
Definition: compiler.h:187
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static bool MakeCode(CompilationInfo *info)
static Handle< Code > GetUnoptimizedCode(Handle< JSFunction > function)
Definition: compiler.cc:651
Handle< Script > NewScript(Handle< String > source)
Definition: factory.cc:699
static Handle< JSFunction > GetFunctionFromEval(Handle< String > source, Handle< Context > context, StrictMode strict_mode, ParseRestriction restriction, int scope_position)
Definition: compiler.cc:865
Handle< Script > script() const
Definition: compiler.h:83
#define DEF_VISIT(type)
Definition: compiler.cc:282
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:278
MUST_USE_RESULT Status AbortOptimization(BailoutReason reason=kNoReason)
Definition: compiler.h:550
Handle< SharedFunctionInfo > LookupScript(Handle< String > source, Handle< Object > name, int line_offset, int column_offset, bool is_shared_cross_origin, Handle< Context > context)
bool is_logging_code_events()
Definition: log.h:358
Builtins * builtins()
Definition: isolate.h:948
void set_this_has_uses(bool has_no_uses)
Definition: compiler.h:111
void set_bailout_reason(BailoutReason reason)
Definition: compiler.h:281
HOptimizedGraphBuilderWithPositions(CompilationInfo *info)
Definition: compiler.cc:258
Handle< SharedFunctionInfo > LookupEval(Handle< String > source, Handle< Context > context, StrictMode strict_mode, int scope_position)
static bool enabled()
Definition: serialize.h:485
static ScopeInfo * Empty(Isolate *isolate)
Definition: scopeinfo.cc:151
uint32_t Flags
Definition: objects.h:5184
Isolate * isolate() const
Definition: compiler.h:67
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: compiler.cc:687
Handle< Code > Codegen()
Definition: lithium.cc:425
#define ASSERT(condition)
Definition: checks.h:329
void set_optimizable(bool value)
Definition: objects-inl.h:4391
void clear_pending_exception()
Definition: isolate.h:579
void SetExtension(v8::Extension *extension)
Definition: compiler.h:188
int global_ic_age()
Definition: heap.h:1862
#define CHECK(condition)
Definition: checks.h:75
int GetScriptColumnNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:389
MUST_USE_RESULT MaybeObject * AddToOptimizedCodeMap(Context *native_context, Code *code, FixedArray *literals, BailoutId osr_ast_id)
Definition: objects.cc:9503
Factory * factory()
Definition: isolate.h:995
void SetExpectedNofPropertiesFromEstimate(Handle< SharedFunctionInfo > shared, int estimate)
Definition: compiler.cc:532
static const int kMaxFixedSlotIndex
Definition: lithium.h:195
int ToInt() const
Definition: utils.h:1162
#define STATEMENT_NODE_LIST(V)
Definition: ast.h:78
static Handle< ScopeInfo > Create(Scope *scope, Zone *zone)
Definition: scopeinfo.cc:39
void PutScript(Handle< String > source, Handle< Context > context, Handle< SharedFunctionInfo > function_info)
kInstanceClassNameOffset flag
Definition: objects-inl.h:5115
bool HasTrivialOuterContext() const
Definition: scopes.cc:683
bool AllowsLazyCompilation() const
Definition: scopes.cc:711
Code * GetCodeFromOptimizedCodeMap(int index)
Definition: objects.cc:9569
Handle< SharedFunctionInfo > NewSharedFunctionInfo(Handle< String > name, int number_of_literals, bool is_generator, Handle< Code > code, Handle< ScopeInfo > scope_info)
Definition: factory.cc:1569
void Bailout(BailoutReason reason)
Definition: hydrogen.cc:3868
static Handle< Code > GetConcurrentlyOptimizedCode(OptimizedCompileJob *job)
Definition: compiler.cc:1204
void RemoveCompilationInfo(DependentCode::DependencyGroup group, CompilationInfo *info)
Definition: objects.cc:11605
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
void ReportPendingMessages()
Definition: isolate.cc:1268
void PutEval(Handle< String > source, Handle< Context > context, Handle< SharedFunctionInfo > function_info, int scope_position)
int num_stack_slots() const
Definition: scopes.h:368
Handle< Code > code() const
Definition: compiler.h:80
FunctionLiteral * function() const
Definition: compiler.h:77
static Handle< Code > GetOptimizedCode(Handle< JSFunction > function, Handle< Code > current_code, ConcurrencyMode mode, BailoutId osr_ast_id=BailoutId::None())
Definition: compiler.cc:1162
Code::Flags flags() const
Definition: compiler.cc:213
bool IsNone() const
Definition: utils.h:1170
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static LChunk * NewChunk(HGraph *graph)
Definition: lithium.cc:398
int num_parameters() const
Definition: scopes.h:338
bool has_pending_exception()
Definition: isolate.h:587
Definition: v8.h:123
CompilationInfo * info() const
Definition: compiler.h:547
Handle< JSFunction > closure() const
Definition: compiler.h:81
bool use_crankshaft() const
Definition: isolate.h:1017
void RecordFunctionInfo(Handle< SharedFunctionInfo > info, FunctionLiteral *lit, Zone *zone)
Definition: liveedit.cc:2118
#define GDBJIT(action)
Definition: gdb-jit.h:137
void set_dont_optimize_reason(BailoutReason reason)
Definition: objects.h:7069
Definition: v8.h:2107
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:363
void SetContext(Handle< Context > context)
Definition: compiler.h:202
HydrogenCodeStub * code_stub() const
Definition: compiler.h:84
int num_heap_slots() const
Definition: scopes.h:369
const char * GetBailoutReason(BailoutReason reason)
Definition: objects.cc:16437
Isolate * isolate() const
Definition: compiler.h:548
bool is_null() const
Definition: handles.h:81
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
Handle< Context > context() const
Definition: compiler.h:90
CpuProfiler * cpu_profiler() const
Definition: isolate.h:984
void CommitDependencies(Handle< Code > code)
Definition: compiler.cc:160
void SetStrictMode(StrictMode strict_mode)
Definition: compiler.h:117
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:4601
FixedArray * GetLiteralsFromOptimizedCodeMap(int index)
Definition: objects.cc:9557
static const char * v8_recompile_synchronous
Definition: log.h:335
Handle< SharedFunctionInfo > shared_info() const
Definition: compiler.h:82
static const int kPrologueOffsetNotSet
Definition: objects.h:5227
bool DebuggerHasBreakPoints()
Definition: isolate-inl.h:66
void set_strict_mode(StrictMode strict_mode)
Definition: objects-inl.h:5271
MUST_USE_RESULT Status GenerateCode()
Definition: compiler.cc:465
static Handle< T > null()
Definition: handles.h:80
#define MODULE_NODE_LIST(V)
Definition: ast.h:72
MUST_USE_RESULT Status CreateGraph()
Definition: compiler.cc:311
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script)
Definition: compiler.cc:996
void USE(T)
Definition: globals.h:341
bool inside_with() const
Definition: scopes.h:308
HStatistics * GetHStatistics()
Definition: isolate.cc:2217
Counters * counters()
Definition: isolate.h:859
#define ASSERT_NE(v1, v2)
Definition: checks.h:331
#define DECLARATION_NODE_LIST(V)
Definition: ast.h:65
kSerializedDataOffset kPrototypeTemplateOffset kIndexedPropertyHandlerOffset kInstanceCallHandlerOffset kInternalFieldCountOffset dependent_code
Definition: objects-inl.h:5047
Logger * logger()
Definition: isolate.h:868
bool outer_scope_calls_sloppy_eval() const
Definition: scopes.h:303
unsigned allocation_size()
Definition: zone.h:88
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric literals(0o77, 0b11)") DEFINE_bool(harmony_strings
static const int kMinFixedSlotIndex
Definition: lithium.h:196
void SetCachedData(ScriptDataImpl **cached_data, CachedDataMode cached_data_mode)
Definition: compiler.h:192
int SearchOptimizedCodeMap(Context *native_context, BailoutId osr_ast_id)
Definition: objects.cc:10193
PerThreadAssertScopeDebugOnly< HANDLE_DEREFERENCE_ASSERT, true > AllowHandleDereference
Definition: assert-scope.h:226
#define EXPRESSION_NODE_LIST(V)
Definition: ast.h:98
void UpdateToFinishedCode(DependencyGroup group, CompilationInfo *info, Code *code)
Definition: objects.cc:11581
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, CompilationInfo *info, Handle< SharedFunctionInfo > shared)
Definition: compiler.cc:1251
CompilationInfo(Handle< JSFunction > closure, Zone *zone)
Definition: compiler.cc:82
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
StrictMode strict_mode() const
Definition: compiler.h:75
void SetFunction(FunctionLiteral *literal)
Definition: compiler.h:177
static bool Rewrite(CompilationInfo *info)
Definition: rewriter.cc:251
MUST_USE_RESULT Status AbortAndDisableOptimization(BailoutReason reason=kNoReason)
Definition: compiler.h:556
static char * StrChr(char *str, int c)
MUST_USE_RESULT Status OptimizeGraph()
Definition: compiler.cc:443
HTracer * GetHTracer()
Definition: isolate.cc:2223
Scope * scope() const
Definition: compiler.h:78
static void Run(CompilationInfo *info)
Definition: typing.cc:57