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
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.
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.
32 #include "bootstrapper.h"
34 #include "compilation-cache.h"
36 #include "full-codegen.h"
39 #include "isolate-inl.h"
44 #include "runtime-profiler.h"
45 #include "scanner-character-streams.h"
46 #include "scopeinfo.h"
48 #include "vm-state-inl.h"
54 CompilationInfo::CompilationInfo(Handle<Script> script)
55 : isolate_(script->GetIsolate()),
61 pre_parse_data_(NULL),
62 osr_ast_id_(AstNode::kNoNumber) {
67 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
68 : isolate_(shared_info->GetIsolate()),
69 flags_(IsLazy::encode(true)),
72 shared_info_(shared_info),
73 script_(Handle<Script>(Script::cast(shared_info->script()))),
75 pre_parse_data_(NULL),
76 osr_ast_id_(AstNode::kNoNumber) {
81 CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
82 : isolate_(closure->GetIsolate()),
83 flags_(IsLazy::encode(true)),
87 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
88 script_(Handle<Script>(Script::cast(shared_info_->script()))),
90 pre_parse_data_(NULL),
91 osr_ast_id_(AstNode::kNoNumber) {
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);
108 void CompilationInfo::AbortOptimization() {
109 Handle<Code> code(shared_info()->code());
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();
134 static bool AlwaysFullCompiler() {
135 return FLAG_always_full_compiler || is_debugging_active();
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);
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;
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",
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();
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);
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);
181 // We should never arrive here if optimization has been disabled on the
182 // shared function info.
183 ASSERT(!info->shared_info()->optimization_disabled());
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) {
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.
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.
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.
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);
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
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);
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
266 ASSERT(FLAG_always_opt || code->optimizable());
267 ASSERT(info->shared_info()->has_deoptimization_support());
269 if (FLAG_trace_hydrogen) {
270 PrintF("-----------------------------------------------------------\n");
271 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
272 HTracer::Instance()->TraceCompilation(info->function());
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());
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);
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);
302 // True indicates the compilation pipeline is still going, not necessarily
303 // that we optimized the code.
308 static bool GenerateCode(CompilationInfo* info) {
309 return info->IsCompilingForDebugging() || !V8::UseCrankshaft() ?
310 FullCodeGenerator::MakeCode(info) :
311 MakeCrankshaftCode(info);
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);
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);
338 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
339 Isolate* isolate = info->isolate();
340 ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
341 PostponeInterruptsScope postpone(isolate);
343 ASSERT(!isolate->global_context().is_null());
344 Handle<Script> script = info->script();
345 script->set_context_data((*isolate->global_context())->data());
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
353 if (info->is_eval()) {
354 StackTraceFrameIterator it(isolate);
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));
367 isolate->debugger()->OnBeforeCompile(script);
370 // Only allow non-global compiles for eval.
371 ASSERT(info->is_eval() || info->is_global());
373 if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
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);
384 FunctionLiteral* lit = info->function();
385 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
386 if (!MakeCode(info)) {
387 isolate->StackOverflow();
388 return Handle<SharedFunctionInfo>::null();
391 // Allocate function.
392 ASSERT(!info->code().is_null());
393 Handle<SharedFunctionInfo> result =
394 isolate->factory()->NewSharedFunctionInfo(
396 lit->materialized_literal_count(),
398 SerializedScopeInfo::Create(info->scope()));
400 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
401 Compiler::SetFunctionInfo(result, lit, true, script);
403 if (script->name()->IsString()) {
404 PROFILE(isolate, CodeCreateEvent(
407 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
410 String::cast(script->name())));
411 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
416 PROFILE(isolate, CodeCreateEvent(
419 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
422 isolate->heap()->empty_string()));
423 GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
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());
431 #ifdef ENABLE_DEBUGGER_SUPPORT
433 isolate->debugger()->OnAfterCompile(
434 script, Debugger::NO_AFTER_COMPILE_FLAGS);
437 live_edit_tracker.RecordFunctionInfo(result, lit);
443 Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
444 Handle<Object> script_name,
447 v8::Extension* extension,
448 ScriptDataImpl* input_pre_data,
449 Handle<Object> script_data,
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);
457 // The VM is in the COMPILER state until exiting this function.
458 VMState state(isolate, COMPILER);
460 CompilationCache* compilation_cache = isolate->compilation_cache();
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,
471 if (result.is_null()) {
472 // No cache entry found. Do pre-parsing, if it makes sense, and compile
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
480 ScriptDataImpl* pre_data = input_pre_data;
481 int flags = kNoParsingFlags;
482 if ((natives == NATIVES_CODE) || FLAG_allow_natives_syntax) {
483 flags |= kAllowNativesSyntax;
485 if (natives != NATIVES_CODE && FLAG_harmony_scoping) {
486 flags |= kHarmonyScoping;
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);
495 GenericStringUC16CharacterStream stream(source, 0, source->length());
496 pre_data = ParserApi::PartialPreParse(&stream, extension, flags);
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));
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));
511 script->set_data(script_data.is_null() ? HEAP->undefined_value()
514 // Compile the function and add it to the cache.
515 CompilationInfo info(script);
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);
525 // Get rid of the pre-parsing data (if necessary).
526 if (input_pre_data == NULL && pre_data != NULL) {
531 if (result.is_null()) isolate->ReportPendingMessages();
536 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
537 Handle<Context> context,
539 StrictModeFlag strict_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);
546 // The VM is in the COMPILER state until exiting this function.
547 VMState state(isolate, COMPILER);
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,
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);
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);
583 bool Compiler::CompileLazy(CompilationInfo* info) {
584 Isolate* isolate = info->isolate();
586 ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
588 // The VM is in the COMPILER state until exiting this function.
589 VMState state(isolate, COMPILER);
591 PostponeInterruptsScope postpone(isolate);
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);
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());
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);
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();
620 if (!MakeCode(info)) {
621 if (!isolate->has_pending_exception()) {
622 isolate->StackOverflow();
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);
632 Handle<JSFunction> function = info->closure();
633 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
635 if (info->IsOptimizing()) {
636 ASSERT(shared->scope_info() != SerializedScopeInfo::Empty());
637 function->ReplaceCode(*code);
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());
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);
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());
665 // Check the function has compiled code.
666 ASSERT(shared->is_compiled());
667 shared->set_code_age(0);
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);
686 ASSERT(info->code().is_null());
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());
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
705 bool allow_lazy = literal->AllowsLazyCompilation() &&
706 !LiveEditFunctionTracker::IsActive(info.isolate());
708 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
711 if (FLAG_lazy && allow_lazy) {
712 Handle<Code> code = info.isolate()->builtins()->LazyCompile();
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());
719 return Handle<SharedFunctionInfo>::null();
722 // Create a shared function info object.
723 Handle<SharedFunctionInfo> result =
724 FACTORY->NewSharedFunctionInfo(literal->name(),
725 literal->materialized_literal_count(),
728 SetFunctionInfo(result, literal, false, script);
729 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
730 result->set_allows_lazy_compilation(allow_lazy);
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);
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,
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());
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.
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))
785 if (script->name()->IsString()) {
786 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
788 PROFILE(info->isolate(),
789 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
792 String::cast(script->name()),
795 PROFILE(info->isolate(),
796 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
799 shared->DebugName()));
803 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
804 Handle<Script>(info->script()),
805 Handle<Code>(info->code()),
809 } } // namespace v8::internal