[V8] Allow a script to be flagged as "native"
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / compiler.cc
1 // Copyright 2011 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 "debug.h"
36 #include "full-codegen.h"
37 #include "gdb-jit.h"
38 #include "hydrogen.h"
39 #include "isolate-inl.h"
40 #include "lithium.h"
41 #include "liveedit.h"
42 #include "parser.h"
43 #include "rewriter.h"
44 #include "runtime-profiler.h"
45 #include "scanner-character-streams.h"
46 #include "scopeinfo.h"
47 #include "scopes.h"
48 #include "vm-state-inl.h"
49
50 namespace v8 {
51 namespace internal {
52
53
54 CompilationInfo::CompilationInfo(Handle<Script> script)
55     : isolate_(script->GetIsolate()),
56       flags_(0),
57       function_(NULL),
58       scope_(NULL),
59       script_(script),
60       extension_(NULL),
61       pre_parse_data_(NULL),
62       osr_ast_id_(AstNode::kNoNumber) {
63   Initialize(NONOPT);
64 }
65
66
67 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
68     : isolate_(shared_info->GetIsolate()),
69       flags_(IsLazy::encode(true)),
70       function_(NULL),
71       scope_(NULL),
72       shared_info_(shared_info),
73       script_(Handle<Script>(Script::cast(shared_info->script()))),
74       extension_(NULL),
75       pre_parse_data_(NULL),
76       osr_ast_id_(AstNode::kNoNumber) {
77   Initialize(BASE);
78 }
79
80
81 CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
82     : isolate_(closure->GetIsolate()),
83       flags_(IsLazy::encode(true)),
84       function_(NULL),
85       scope_(NULL),
86       closure_(closure),
87       shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
88       script_(Handle<Script>(Script::cast(shared_info_->script()))),
89       extension_(NULL),
90       pre_parse_data_(NULL),
91       osr_ast_id_(AstNode::kNoNumber) {
92   Initialize(BASE);
93 }
94
95
96 // Disable optimization for the rest of the compilation pipeline.
97 void CompilationInfo::DisableOptimization() {
98   bool is_optimizable_closure =
99     FLAG_optimize_closures &&
100     closure_.is_null() &&
101     !scope_->HasTrivialOuterContext() &&
102     !scope_->outer_scope_calls_non_strict_eval() &&
103     !scope_->inside_with();
104   SetMode(is_optimizable_closure ? BASE : NONOPT);
105 }
106
107
108 void CompilationInfo::AbortOptimization() {
109   Handle<Code> code(shared_info()->code());
110   SetCode(code);
111 }
112
113
114 // Determine whether to use the full compiler for all code. If the flag
115 // --always-full-compiler is specified this is the case. For the virtual frame
116 // based compiler the full compiler is also used if a debugger is connected, as
117 // the code from the full compiler supports mode precise break points. For the
118 // crankshaft adaptive compiler debugging the optimized code is not possible at
119 // all. However crankshaft support recompilation of functions, so in this case
120 // the full compiler need not be be used if a debugger is attached, but only if
121 // break points has actually been set.
122 static bool is_debugging_active() {
123 #ifdef ENABLE_DEBUGGER_SUPPORT
124   Isolate* isolate = Isolate::Current();
125   return V8::UseCrankshaft() ?
126     isolate->debug()->has_break_points() :
127     isolate->debugger()->IsDebuggerActive();
128 #else
129   return false;
130 #endif
131 }
132
133
134 static bool AlwaysFullCompiler() {
135   return FLAG_always_full_compiler || is_debugging_active();
136 }
137
138
139 static void FinishOptimization(Handle<JSFunction> function, int64_t start) {
140   int opt_count = function->shared()->opt_count();
141   function->shared()->set_opt_count(opt_count + 1);
142   double ms = static_cast<double>(OS::Ticks() - start) / 1000;
143   if (FLAG_trace_opt) {
144     PrintF("[optimizing: ");
145     function->PrintName();
146     PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
147     PrintF(" - took %0.3f ms]\n", ms);
148   }
149   if (FLAG_trace_opt_stats) {
150     static double compilation_time = 0.0;
151     static int compiled_functions = 0;
152     static int code_size = 0;
153
154     compilation_time += ms;
155     compiled_functions++;
156     code_size += function->shared()->SourceSize();
157     PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
158            compiled_functions,
159            code_size,
160            compilation_time);
161   }
162 }
163
164
165 static bool MakeCrankshaftCode(CompilationInfo* info) {
166   // Test if we can optimize this function when asked to. We can only
167   // do this after the scopes are computed.
168   if (!info->AllowOptimize()) info->DisableOptimization();
169
170   // In case we are not optimizing simply return the code from
171   // the full code generator.
172   if (!info->IsOptimizing()) {
173     return FullCodeGenerator::MakeCode(info);
174   }
175
176   // We should never arrive here if there is not code object on the
177   // shared function object.
178   Handle<Code> code(info->shared_info()->code());
179   ASSERT(code->kind() == Code::FUNCTION);
180
181   // We should never arrive here if optimization has been disabled on the
182   // shared function info.
183   ASSERT(!info->shared_info()->optimization_disabled());
184
185   // Fall back to using the full code generator if it's not possible
186   // to use the Hydrogen-based optimizing compiler. We already have
187   // generated code for this from the shared function object.
188   if (AlwaysFullCompiler() || !FLAG_use_hydrogen) {
189     info->SetCode(code);
190     return true;
191   }
192
193   // Limit the number of times we re-compile a functions with
194   // the optimizing compiler.
195   const int kMaxOptCount =
196       FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
197   if (info->shared_info()->opt_count() > kMaxOptCount) {
198     info->AbortOptimization();
199     Handle<JSFunction> closure = info->closure();
200     info->shared_info()->DisableOptimization(*closure);
201     // True indicates the compilation pipeline is still going, not
202     // necessarily that we optimized the code.
203     return true;
204   }
205
206   // Due to an encoding limit on LUnallocated operands in the Lithium
207   // language, we cannot optimize functions with too many formal parameters
208   // or perform on-stack replacement for function with too many
209   // stack-allocated local variables.
210   //
211   // The encoding is as a signed value, with parameters and receiver using
212   // the negative indices and locals the non-negative ones.
213   const int parameter_limit = -LUnallocated::kMinFixedIndex;
214   const int locals_limit = LUnallocated::kMaxFixedIndex;
215   Scope* scope = info->scope();
216   if ((scope->num_parameters() + 1) > parameter_limit ||
217       (info->osr_ast_id() != AstNode::kNoNumber &&
218        scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
219     info->AbortOptimization();
220     Handle<JSFunction> closure = info->closure();
221     info->shared_info()->DisableOptimization(*closure);
222     // True indicates the compilation pipeline is still going, not
223     // necessarily that we optimized the code.
224     return true;
225   }
226
227   // Take --hydrogen-filter into account.
228   Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
229   Handle<String> name = info->function()->debug_name();
230   bool match = filter.is_empty() || name->IsEqualTo(filter);
231   if (!match) {
232     info->SetCode(code);
233     return true;
234   }
235
236   // Recompile the unoptimized version of the code if the current version
237   // doesn't have deoptimization support. Alternatively, we may decide to
238   // run the full code generator to get a baseline for the compile-time
239   // performance of the hydrogen-based compiler.
240   int64_t start = OS::Ticks();
241   bool should_recompile = !info->shared_info()->has_deoptimization_support();
242   if (should_recompile || FLAG_hydrogen_stats) {
243     HPhase phase(HPhase::kFullCodeGen);
244     CompilationInfo unoptimized(info->shared_info());
245     // Note that we use the same AST that we will use for generating the
246     // optimized code.
247     unoptimized.SetFunction(info->function());
248     unoptimized.SetScope(info->scope());
249     if (should_recompile) unoptimized.EnableDeoptimizationSupport();
250     bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
251     if (should_recompile) {
252       if (!succeeded) return false;
253       Handle<SharedFunctionInfo> shared = info->shared_info();
254       shared->EnableDeoptimizationSupport(*unoptimized.code());
255       // The existing unoptimized code was replaced with the new one.
256       Compiler::RecordFunctionCompilation(
257           Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
258     }
259   }
260
261   // Check that the unoptimized, shared code is ready for
262   // optimizations.  When using the always_opt flag we disregard the
263   // optimizable marker in the code object and optimize anyway. This
264   // is safe as long as the unoptimized code has deoptimization
265   // support.
266   ASSERT(FLAG_always_opt || code->optimizable());
267   ASSERT(info->shared_info()->has_deoptimization_support());
268
269   if (FLAG_trace_hydrogen) {
270     PrintF("-----------------------------------------------------------\n");
271     PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
272     HTracer::Instance()->TraceCompilation(info->function());
273   }
274
275   Handle<Context> global_context(info->closure()->context()->global_context());
276   TypeFeedbackOracle oracle(code, global_context, info->isolate());
277   HGraphBuilder builder(info, &oracle);
278   HPhase phase(HPhase::kTotal);
279   HGraph* graph = builder.CreateGraph();
280   if (info->isolate()->has_pending_exception()) {
281     info->SetCode(Handle<Code>::null());
282     return false;
283   }
284
285   if (graph != NULL && FLAG_build_lithium) {
286     Handle<Code> optimized_code = graph->Compile(info);
287     if (!optimized_code.is_null()) {
288       info->SetCode(optimized_code);
289       FinishOptimization(info->closure(), start);
290       return true;
291     }
292   }
293
294   // Keep using the shared code.
295   info->AbortOptimization();
296   if (!builder.inline_bailout()) {
297     // Mark the shared code as unoptimizable unless it was an inlined
298     // function that bailed out.
299     Handle<JSFunction> closure = info->closure();
300     info->shared_info()->DisableOptimization(*closure);
301   }
302   // True indicates the compilation pipeline is still going, not necessarily
303   // that we optimized the code.
304   return true;
305 }
306
307
308 static bool GenerateCode(CompilationInfo* info) {
309   return info->IsCompilingForDebugging() || !V8::UseCrankshaft() ?
310       FullCodeGenerator::MakeCode(info) :
311       MakeCrankshaftCode(info);
312 }
313
314
315 static bool MakeCode(CompilationInfo* info) {
316   // Precondition: code has been parsed.  Postcondition: the code field in
317   // the compilation info is set if compilation succeeded.
318   ASSERT(info->function() != NULL);
319   return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
320 }
321
322
323 #ifdef ENABLE_DEBUGGER_SUPPORT
324 bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
325   // Precondition: code has been parsed.  Postcondition: the code field in
326   // the compilation info is set if compilation succeeded.
327   bool succeeded = MakeCode(info);
328   if (!info->shared_info().is_null()) {
329     Handle<SerializedScopeInfo> scope_info =
330         SerializedScopeInfo::Create(info->scope());
331     info->shared_info()->set_scope_info(*scope_info);
332   }
333   return succeeded;
334 }
335 #endif
336
337
338 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
339   Isolate* isolate = info->isolate();
340   ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
341   PostponeInterruptsScope postpone(isolate);
342
343   ASSERT(!isolate->global_context().is_null());
344   Handle<Script> script = info->script();
345   script->set_context_data((*isolate->global_context())->data());
346
347 #ifdef ENABLE_DEBUGGER_SUPPORT
348   if (info->is_eval()) {
349     Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
350     script->set_compilation_type(Smi::FromInt(compilation_type));
351     // For eval scripts add information on the function from which eval was
352     // called.
353     if (info->is_eval()) {
354       StackTraceFrameIterator it(isolate);
355       if (!it.done()) {
356         script->set_eval_from_shared(
357             JSFunction::cast(it.frame()->function())->shared());
358         Code* code = it.frame()->LookupCode();
359         int offset = static_cast<int>(
360             it.frame()->pc() - code->instruction_start());
361         script->set_eval_from_instructions_offset(Smi::FromInt(offset));
362       }
363     }
364   }
365
366   // Notify debugger
367   isolate->debugger()->OnBeforeCompile(script);
368 #endif
369
370   // Only allow non-global compiles for eval.
371   ASSERT(info->is_eval() || info->is_global());
372
373   if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
374
375   // Measure how long it takes to do the compilation; only take the
376   // rest of the function into account to avoid overlap with the
377   // parsing statistics.
378   HistogramTimer* rate = info->is_eval()
379       ? info->isolate()->counters()->compile_eval()
380       : info->isolate()->counters()->compile();
381   HistogramTimerScope timer(rate);
382
383   // Compile the code.
384   FunctionLiteral* lit = info->function();
385   LiveEditFunctionTracker live_edit_tracker(isolate, lit);
386   if (!MakeCode(info)) {
387     isolate->StackOverflow();
388     return Handle<SharedFunctionInfo>::null();
389   }
390
391   // Allocate function.
392   ASSERT(!info->code().is_null());
393   Handle<SharedFunctionInfo> result =
394       isolate->factory()->NewSharedFunctionInfo(
395           lit->name(),
396           lit->materialized_literal_count(),
397           info->code(),
398           SerializedScopeInfo::Create(info->scope()));
399
400   ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
401   Compiler::SetFunctionInfo(result, lit, true, script);
402
403   if (script->name()->IsString()) {
404     PROFILE(isolate, CodeCreateEvent(
405         info->is_eval()
406             ? Logger::EVAL_TAG
407             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
408         *info->code(),
409         *result,
410         String::cast(script->name())));
411     GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
412                    script,
413                    info->code(),
414                    info));
415   } else {
416     PROFILE(isolate, CodeCreateEvent(
417         info->is_eval()
418             ? Logger::EVAL_TAG
419             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
420         *info->code(),
421         *result,
422         isolate->heap()->empty_string()));
423     GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
424   }
425
426   // Hint to the runtime system used when allocating space for initial
427   // property space by setting the expected number of properties for
428   // the instances of the function.
429   SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
430
431 #ifdef ENABLE_DEBUGGER_SUPPORT
432   // Notify debugger
433   isolate->debugger()->OnAfterCompile(
434       script, Debugger::NO_AFTER_COMPILE_FLAGS);
435 #endif
436
437   live_edit_tracker.RecordFunctionInfo(result, lit);
438
439   return result;
440 }
441
442
443 Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
444                                              Handle<Object> script_name,
445                                              int line_offset,
446                                              int column_offset,
447                                              v8::Extension* extension,
448                                              ScriptDataImpl* input_pre_data,
449                                              Handle<Object> script_data,
450                                              NativesFlag natives,
451                                              v8::Script::CompileFlags compile_flags) {
452   Isolate* isolate = source->GetIsolate();
453   int source_length = source->length();
454   isolate->counters()->total_load_size()->Increment(source_length);
455   isolate->counters()->total_compile_size()->Increment(source_length);
456
457   // The VM is in the COMPILER state until exiting this function.
458   VMState state(isolate, COMPILER);
459
460   CompilationCache* compilation_cache = isolate->compilation_cache();
461
462   // Do a lookup in the compilation cache but not for extensions.
463   Handle<SharedFunctionInfo> result;
464   if (extension == NULL) {
465     result = compilation_cache->LookupScript(source,
466                                              script_name,
467                                              line_offset,
468                                              column_offset);
469   }
470
471   if (result.is_null()) {
472     // No cache entry found. Do pre-parsing, if it makes sense, and compile
473     // the script.
474     // Building preparse data that is only used immediately after is only a
475     // saving if we might skip building the AST for lazily compiled functions.
476     // I.e., preparse data isn't relevant when the lazy flag is off, and
477     // for small sources, odds are that there aren't many functions
478     // that would be compiled lazily anyway, so we skip the preparse step
479     // in that case too.
480     ScriptDataImpl* pre_data = input_pre_data;
481     int flags = kNoParsingFlags;
482     if ((natives == NATIVES_CODE) || FLAG_allow_natives_syntax) {
483       flags |= kAllowNativesSyntax;
484     }
485     if (natives != NATIVES_CODE && FLAG_harmony_scoping) {
486       flags |= kHarmonyScoping;
487     }
488     if (pre_data == NULL
489         && source_length >= FLAG_min_preparse_length) {
490       if (source->IsExternalTwoByteString()) {
491         ExternalTwoByteStringUC16CharacterStream stream(
492             Handle<ExternalTwoByteString>::cast(source), 0, source->length());
493         pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
494       } else {
495         GenericStringUC16CharacterStream stream(source, 0, source->length());
496         pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
497       }
498     }
499
500     // Create a script object describing the script to be compiled.
501     Handle<Script> script = FACTORY->NewScript(source);
502     if (natives == NATIVES_CODE || compile_flags & v8::Script::NativeMode) {
503       script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
504     }
505     if (!script_name.is_null()) {
506       script->set_name(*script_name);
507       script->set_line_offset(Smi::FromInt(line_offset));
508       script->set_column_offset(Smi::FromInt(column_offset));
509     }
510
511     script->set_data(script_data.is_null() ? HEAP->undefined_value()
512                                            : *script_data);
513
514     // Compile the function and add it to the cache.
515     CompilationInfo info(script);
516     info.MarkAsGlobal();
517     info.SetExtension(extension);
518     info.SetPreParseData(pre_data);
519     if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode();
520     result = MakeFunctionInfo(&info);
521     if (extension == NULL && !result.is_null()) {
522       compilation_cache->PutScript(source, result);
523     }
524
525     // Get rid of the pre-parsing data (if necessary).
526     if (input_pre_data == NULL && pre_data != NULL) {
527       delete pre_data;
528     }
529   }
530
531   if (result.is_null()) isolate->ReportPendingMessages();
532   return result;
533 }
534
535
536 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
537                                                  Handle<Context> context,
538                                                  bool is_global,
539                                                  StrictModeFlag strict_mode,
540                                                  bool qml_mode) {
541   Isolate* isolate = source->GetIsolate();
542   int source_length = source->length();
543   isolate->counters()->total_eval_size()->Increment(source_length);
544   isolate->counters()->total_compile_size()->Increment(source_length);
545
546   // The VM is in the COMPILER state until exiting this function.
547   VMState state(isolate, COMPILER);
548
549   // Do a lookup in the compilation cache; if the entry is not there, invoke
550   // the compiler and add the result to the cache.
551   Handle<SharedFunctionInfo> result;
552   CompilationCache* compilation_cache = isolate->compilation_cache();
553   result = compilation_cache->LookupEval(source,
554                                          context,
555                                          is_global,
556                                          strict_mode);
557
558   if (result.is_null()) {
559     // Create a script object describing the script to be compiled.
560     Handle<Script> script = isolate->factory()->NewScript(source);
561     CompilationInfo info(script);
562     info.MarkAsEval();
563     if (is_global) info.MarkAsGlobal();
564     info.SetStrictModeFlag(strict_mode);
565     if (qml_mode) info.MarkAsQmlMode();
566     info.SetCallingContext(context);
567     result = MakeFunctionInfo(&info);
568     if (!result.is_null()) {
569       CompilationCache* compilation_cache = isolate->compilation_cache();
570       // If caller is strict mode, the result must be strict as well,
571       // but not the other way around. Consider:
572       // eval("'use strict'; ...");
573       // TODO(keuchel): adapt this for extended mode.
574       ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
575       compilation_cache->PutEval(source, context, is_global, result);
576     }
577   }
578
579   return result;
580 }
581
582
583 bool Compiler::CompileLazy(CompilationInfo* info) {
584   Isolate* isolate = info->isolate();
585
586   ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
587
588   // The VM is in the COMPILER state until exiting this function.
589   VMState state(isolate, COMPILER);
590
591   PostponeInterruptsScope postpone(isolate);
592
593   Handle<SharedFunctionInfo> shared = info->shared_info();
594   int compiled_size = shared->end_position() - shared->start_position();
595   isolate->counters()->total_compile_size()->Increment(compiled_size);
596
597   // Generate the AST for the lazily compiled function.
598   if (ParserApi::Parse(info)) {
599     // Measure how long it takes to do the lazy compilation; only take the
600     // rest of the function into account to avoid overlap with the lazy
601     // parsing statistics.
602     HistogramTimerScope timer(isolate->counters()->compile_lazy());
603
604     // After parsing we know function's strict mode. Remember it.
605     StrictModeFlag strict_mode = info->function()->strict_mode_flag();
606     ASSERT(info->strict_mode_flag() == kNonStrictMode ||
607            info->strict_mode_flag() == strict_mode);
608     ASSERT(shared->strict_mode_flag() == kNonStrictMode ||
609            shared->strict_mode_flag() == strict_mode);
610     info->SetStrictModeFlag(strict_mode);
611     shared->set_strict_mode_flag(strict_mode);
612
613     // After parsing we know function's qml mode. Remember it.
614     if (info->function()->qml_mode()) {
615       shared->set_qml_mode(true);
616       info->MarkAsQmlMode();
617     }
618
619     // Compile the code.
620     if (!MakeCode(info)) {
621       if (!isolate->has_pending_exception()) {
622         isolate->StackOverflow();
623       }
624     } else {
625       ASSERT(!info->code().is_null());
626       Handle<Code> code = info->code();
627       // Set optimizable to false if this is disallowed by the shared
628       // function info, e.g., we might have flushed the code and must
629       // reset this bit when lazy compiling the code again.
630       if (shared->optimization_disabled()) code->set_optimizable(false);
631
632       Handle<JSFunction> function = info->closure();
633       RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
634
635       if (info->IsOptimizing()) {
636         ASSERT(shared->scope_info() != SerializedScopeInfo::Empty());
637         function->ReplaceCode(*code);
638       } else {
639         // Update the shared function info with the compiled code and the
640         // scope info.  Please note, that the order of the shared function
641         // info initialization is important since set_scope_info might
642         // trigger a GC, causing the ASSERT below to be invalid if the code
643         // was flushed. By settting the code object last we avoid this.
644         Handle<SerializedScopeInfo> scope_info =
645             SerializedScopeInfo::Create(info->scope());
646         shared->set_scope_info(*scope_info);
647         shared->set_code(*code);
648         if (!function.is_null()) {
649           function->ReplaceCode(*code);
650           ASSERT(!function->IsOptimized());
651         }
652
653         // Set the expected number of properties for instances.
654         FunctionLiteral* lit = info->function();
655         int expected = lit->expected_property_count();
656         SetExpectedNofPropertiesFromEstimate(shared, expected);
657
658         // Set the optimization hints after performing lazy compilation, as
659         // these are not set when the function is set up as a lazily
660         // compiled function.
661         shared->SetThisPropertyAssignmentsInfo(
662             lit->has_only_simple_this_property_assignments(),
663             *lit->this_property_assignments());
664
665         // Check the function has compiled code.
666         ASSERT(shared->is_compiled());
667         shared->set_code_age(0);
668
669         if (info->AllowOptimize() && !shared->optimization_disabled()) {
670           // If we're asked to always optimize, we compile the optimized
671           // version of the function right away - unless the debugger is
672           // active as it makes no sense to compile optimized code then.
673           if (FLAG_always_opt &&
674               !Isolate::Current()->DebuggerHasBreakPoints()) {
675             CompilationInfo optimized(function);
676             optimized.SetOptimizing(AstNode::kNoNumber);
677             return CompileLazy(&optimized);
678           }
679         }
680       }
681
682       return true;
683     }
684   }
685
686   ASSERT(info->code().is_null());
687   return false;
688 }
689
690
691 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
692                                                        Handle<Script> script) {
693   // Precondition: code has been parsed and scopes have been analyzed.
694   CompilationInfo info(script);
695   info.SetFunction(literal);
696   info.SetScope(literal->scope());
697   info.SetStrictModeFlag(literal->scope()->strict_mode_flag());
698
699   LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
700   // Determine if the function can be lazily compiled. This is necessary to
701   // allow some of our builtin JS files to be lazily compiled. These
702   // builtins cannot be handled lazily by the parser, since we have to know
703   // if a function uses the special natives syntax, which is something the
704   // parser records.
705   bool allow_lazy = literal->AllowsLazyCompilation() &&
706       !LiveEditFunctionTracker::IsActive(info.isolate());
707
708   Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
709
710   // Generate code
711   if (FLAG_lazy && allow_lazy) {
712     Handle<Code> code = info.isolate()->builtins()->LazyCompile();
713     info.SetCode(code);
714   } else if ((V8::UseCrankshaft() && MakeCrankshaftCode(&info)) ||
715              (!V8::UseCrankshaft() && FullCodeGenerator::MakeCode(&info))) {
716     ASSERT(!info.code().is_null());
717     scope_info = SerializedScopeInfo::Create(info.scope());
718   } else {
719     return Handle<SharedFunctionInfo>::null();
720   }
721
722   // Create a shared function info object.
723   Handle<SharedFunctionInfo> result =
724       FACTORY->NewSharedFunctionInfo(literal->name(),
725                                      literal->materialized_literal_count(),
726                                      info.code(),
727                                      scope_info);
728   SetFunctionInfo(result, literal, false, script);
729   RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
730   result->set_allows_lazy_compilation(allow_lazy);
731
732   // Set the expected number of properties for instances and return
733   // the resulting function.
734   SetExpectedNofPropertiesFromEstimate(result,
735                                        literal->expected_property_count());
736   live_edit_tracker.RecordFunctionInfo(result, literal);
737   return result;
738 }
739
740
741 // Sets the function info on a function.
742 // The start_position points to the first '(' character after the function name
743 // in the full script source. When counting characters in the script source the
744 // the first character is number 0 (not 1).
745 void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
746                                FunctionLiteral* lit,
747                                bool is_toplevel,
748                                Handle<Script> script) {
749   function_info->set_length(lit->num_parameters());
750   function_info->set_formal_parameter_count(lit->num_parameters());
751   function_info->set_script(*script);
752   function_info->set_function_token_position(lit->function_token_position());
753   function_info->set_start_position(lit->start_position());
754   function_info->set_end_position(lit->end_position());
755   function_info->set_is_expression(lit->is_expression());
756   function_info->set_is_anonymous(lit->is_anonymous());
757   function_info->set_is_toplevel(is_toplevel);
758   function_info->set_inferred_name(*lit->inferred_name());
759   function_info->SetThisPropertyAssignmentsInfo(
760       lit->has_only_simple_this_property_assignments(),
761       *lit->this_property_assignments());
762   function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
763   function_info->set_strict_mode_flag(lit->strict_mode_flag());
764   function_info->set_qml_mode(lit->qml_mode());
765   function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
766   function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
767 }
768
769
770 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
771                                          CompilationInfo* info,
772                                          Handle<SharedFunctionInfo> shared) {
773   // SharedFunctionInfo is passed separately, because if CompilationInfo
774   // was created using Script object, it will not have it.
775
776   // Log the code generation. If source information is available include
777   // script name and line number. Check explicitly whether logging is
778   // enabled as finding the line number is not free.
779   if (info->isolate()->logger()->is_logging() ||
780       CpuProfiler::is_profiling(info->isolate())) {
781     Handle<Script> script = info->script();
782     Handle<Code> code = info->code();
783     if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
784       return;
785     if (script->name()->IsString()) {
786       int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
787       USE(line_num);
788       PROFILE(info->isolate(),
789               CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
790                               *code,
791                               *shared,
792                               String::cast(script->name()),
793                               line_num));
794     } else {
795       PROFILE(info->isolate(),
796               CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
797                               *code,
798                               *shared,
799                               shared->DebugName()));
800     }
801   }
802
803   GDBJIT(AddCode(Handle<String>(shared->DebugName()),
804                  Handle<Script>(info->script()),
805                  Handle<Code>(info->code()),
806                  info));
807 }
808
809 } }  // namespace v8::internal