blob: 29bbbc7034e92deef346bb0d85e7c3e2aad4e4f8 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdochf87a2032010-10-22 12:50:53 +010030#include "compiler.h"
31
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
33#include "codegen-inl.h"
34#include "compilation-cache.h"
Steve Block6ded16b2010-05-10 14:33:55 +010035#include "data-flow.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036#include "debug.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000037#include "full-codegen.h"
Steve Block6ded16b2010-05-10 14:33:55 +010038#include "liveedit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "oprofile-agent.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010040#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "rewriter.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010042#include "scopeinfo.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010043#include "scopes.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044
45namespace v8 {
46namespace internal {
47
Ben Murdochf87a2032010-10-22 12:50:53 +010048
49CompilationInfo::CompilationInfo(Handle<Script> script)
50 : flags_(0),
51 function_(NULL),
52 scope_(NULL),
53 script_(script),
54 extension_(NULL),
55 pre_parse_data_(NULL) {
56}
57
58
59CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
60 : flags_(IsLazy::encode(true)),
61 function_(NULL),
62 scope_(NULL),
63 shared_info_(shared_info),
64 script_(Handle<Script>(Script::cast(shared_info->script()))),
65 extension_(NULL),
66 pre_parse_data_(NULL) {
67}
68
69
70CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
71 : flags_(IsLazy::encode(true)),
72 function_(NULL),
73 scope_(NULL),
74 closure_(closure),
75 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
76 script_(Handle<Script>(Script::cast(shared_info_->script()))),
77 extension_(NULL),
78 pre_parse_data_(NULL) {
79}
80
81
Leon Clarkef7060e22010-06-03 12:02:55 +010082// For normal operation the syntax checker is used to determine whether to
83// use the full compiler for top level code or not. However if the flag
84// --always-full-compiler is specified or debugging is active the full
85// compiler will be used for all code.
86static bool AlwaysFullCompiler() {
87#ifdef ENABLE_DEBUGGER_SUPPORT
88 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
89#else
90 return FLAG_always_full_compiler;
91#endif
92}
93
Steve Block3ce2e202009-11-05 08:53:23 +000094
Ben Murdochf87a2032010-10-22 12:50:53 +010095static bool MakeCode(CompilationInfo* info) {
96 // Precondition: code has been parsed. Postcondition: the code field in
97 // the compilation info is set if compilation succeeded.
98 ASSERT(info->function() != NULL);
99
100 if (Rewriter::Rewrite(info) &&
101 Scope::Analyze(info) &&
102 Rewriter::Analyze(info)) {
103 // Generate code and return it. Code generator selection is governed by
104 // which backends are enabled and whether the function is considered
105 // run-once code or not.
106 //
107 // --full-compiler enables the dedicated backend for code we expect to
108 // be run once
109 //
110 // The normal choice of backend can be overridden with the flags
111 // --always-full-compiler.
112 Handle<SharedFunctionInfo> shared = info->shared_info();
113 bool is_run_once = (shared.is_null())
114 ? info->scope()->is_global_scope()
115 : (shared->is_toplevel() || shared->try_full_codegen());
116 bool can_use_full =
117 FLAG_full_compiler && !info->function()->contains_loops();
118 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
119 return FullCodeGenerator::MakeCode(info);
120 } else {
121 AssignedVariablesAnalyzer ava;
122 return ava.Analyze(info) && CodeGenerator::MakeCode(info);
123 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 }
125
Ben Murdochf87a2032010-10-22 12:50:53 +0100126 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000127}
128
129
Steve Block6ded16b2010-05-10 14:33:55 +0100130#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdochf87a2032010-10-22 12:50:53 +0100131bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
132 // Precondition: code has been parsed. Postcondition: the code field in
133 // the compilation info is set if compilation succeeded.
134 bool succeeded = MakeCode(info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100135 if (!info->shared_info().is_null()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100136 Handle<SerializedScopeInfo> scope_info =
137 SerializedScopeInfo::Create(info->scope());
138 info->shared_info()->set_scope_info(*scope_info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100139 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100140 return succeeded;
Steve Block6ded16b2010-05-10 14:33:55 +0100141}
142#endif
143
144
Ben Murdochf87a2032010-10-22 12:50:53 +0100145static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
147
148 PostponeInterruptsScope postpone;
149
150 ASSERT(!i::Top::global_context().is_null());
Ben Murdochf87a2032010-10-22 12:50:53 +0100151 Handle<Script> script = info->script();
Steve Blocka7e24c12009-10-30 11:49:00 +0000152 script->set_context_data((*i::Top::global_context())->data());
153
Leon Clarke4515c472010-02-03 11:58:03 +0000154#ifdef ENABLE_DEBUGGER_SUPPORT
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800155 if (info->is_eval()) {
156 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
Ben Murdochf87a2032010-10-22 12:50:53 +0100157 script->set_compilation_type(Smi::FromInt(compilation_type));
Steve Blocka7e24c12009-10-30 11:49:00 +0000158 // For eval scripts add information on the function from which eval was
159 // called.
Ben Murdochf87a2032010-10-22 12:50:53 +0100160 if (info->is_eval()) {
Leon Clarke4515c472010-02-03 11:58:03 +0000161 StackTraceFrameIterator it;
162 if (!it.done()) {
163 script->set_eval_from_shared(
164 JSFunction::cast(it.frame()->function())->shared());
165 int offset = static_cast<int>(
166 it.frame()->pc() - it.frame()->code()->instruction_start());
167 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
168 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 }
170 }
171
172 // Notify debugger
173 Debugger::OnBeforeCompile(script);
174#endif
175
176 // Only allow non-global compiles for eval.
Ben Murdochf87a2032010-10-22 12:50:53 +0100177 ASSERT(info->is_eval() || info->is_global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000178
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800179 if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000180
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 // Measure how long it takes to do the compilation; only take the
182 // rest of the function into account to avoid overlap with the
183 // parsing statistics.
Ben Murdochf87a2032010-10-22 12:50:53 +0100184 HistogramTimer* rate = info->is_eval()
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 ? &Counters::compile_eval
186 : &Counters::compile;
187 HistogramTimerScope timer(rate);
188
189 // Compile the code.
Ben Murdochf87a2032010-10-22 12:50:53 +0100190 FunctionLiteral* lit = info->function();
191 LiveEditFunctionTracker live_edit_tracker(lit);
192 if (!MakeCode(info)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100194 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 }
196
Ben Murdochf87a2032010-10-22 12:50:53 +0100197 ASSERT(!info->code().is_null());
Steve Block6ded16b2010-05-10 14:33:55 +0100198 if (script->name()->IsString()) {
199 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100200 info->is_eval()
201 ? Logger::EVAL_TAG
202 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
203 *info->code(),
204 String::cast(script->name())));
Steve Block6ded16b2010-05-10 14:33:55 +0100205 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
Ben Murdochf87a2032010-10-22 12:50:53 +0100206 info->code()->instruction_start(),
207 info->code()->instruction_size()));
Steve Block6ded16b2010-05-10 14:33:55 +0100208 } else {
209 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100210 info->is_eval()
211 ? Logger::EVAL_TAG
212 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
213 *info->code(),
214 ""));
215 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
216 info->code()->instruction_start(),
217 info->code()->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000219
220 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100221 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100222 Factory::NewSharedFunctionInfo(
223 lit->name(),
224 lit->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100225 info->code(),
226 SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
228 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100229 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000230
231 // Hint to the runtime system used when allocating space for initial
232 // property space by setting the expected number of properties for
233 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100234 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
236#ifdef ENABLE_DEBUGGER_SUPPORT
237 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100238 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000239#endif
240
Steve Block6ded16b2010-05-10 14:33:55 +0100241 live_edit_tracker.RecordFunctionInfo(result, lit);
242
243 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000244}
245
246
Steve Block6ded16b2010-05-10 14:33:55 +0100247Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
248 Handle<Object> script_name,
249 int line_offset,
250 int column_offset,
251 v8::Extension* extension,
252 ScriptDataImpl* input_pre_data,
253 Handle<Object> script_data,
254 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000255 int source_length = source->length();
256 Counters::total_load_size.Increment(source_length);
257 Counters::total_compile_size.Increment(source_length);
258
259 // The VM is in the COMPILER state until exiting this function.
260 VMState state(COMPILER);
261
262 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100263 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 if (extension == NULL) {
265 result = CompilationCache::LookupScript(source,
266 script_name,
267 line_offset,
268 column_offset);
269 }
270
271 if (result.is_null()) {
Steve Block59151502010-09-22 15:07:15 +0100272 // No cache entry found. Do pre-parsing, if it makes sense, and compile
273 // the script.
274 // Building preparse data that is only used immediately after is only a
275 // saving if we might skip building the AST for lazily compiled functions.
276 // I.e., preparse data isn't relevant when the lazy flag is off, and
277 // for small sources, odds are that there aren't many functions
278 // that would be compiled lazily anyway, so we skip the preparse step
279 // in that case too.
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 ScriptDataImpl* pre_data = input_pre_data;
Steve Block59151502010-09-22 15:07:15 +0100281 if (pre_data == NULL
Steve Block59151502010-09-22 15:07:15 +0100282 && source_length >= FLAG_min_preparse_length) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800283 pre_data = ParserApi::PartialPreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 }
285
286 // Create a script object describing the script to be compiled.
287 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000288 if (natives == NATIVES_CODE) {
289 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
290 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 if (!script_name.is_null()) {
292 script->set_name(*script_name);
293 script->set_line_offset(Smi::FromInt(line_offset));
294 script->set_column_offset(Smi::FromInt(column_offset));
295 }
296
Andrei Popescu402d9372010-02-26 13:31:12 +0000297 script->set_data(script_data.is_null() ? Heap::undefined_value()
298 : *script_data);
299
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 // Compile the function and add it to the cache.
Ben Murdochf87a2032010-10-22 12:50:53 +0100301 CompilationInfo info(script);
302 info.MarkAsGlobal();
303 info.SetExtension(extension);
304 info.SetPreParseData(pre_data);
305 result = MakeFunctionInfo(&info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 if (extension == NULL && !result.is_null()) {
307 CompilationCache::PutScript(source, result);
308 }
309
310 // Get rid of the pre-parsing data (if necessary).
311 if (input_pre_data == NULL && pre_data != NULL) {
312 delete pre_data;
313 }
314 }
315
316 if (result.is_null()) Top::ReportPendingMessages();
317 return result;
318}
319
320
Steve Block6ded16b2010-05-10 14:33:55 +0100321Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
322 Handle<Context> context,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800323 bool is_global) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000324 int source_length = source->length();
325 Counters::total_eval_size.Increment(source_length);
326 Counters::total_compile_size.Increment(source_length);
327
328 // The VM is in the COMPILER state until exiting this function.
329 VMState state(COMPILER);
330
Ben Murdochf87a2032010-10-22 12:50:53 +0100331 // Do a lookup in the compilation cache; if the entry is not there, invoke
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800332 // the compiler and add the result to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100333 Handle<SharedFunctionInfo> result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800334 result = CompilationCache::LookupEval(source, context, is_global);
Steve Blocka7e24c12009-10-30 11:49:00 +0000335
336 if (result.is_null()) {
337 // Create a script object describing the script to be compiled.
338 Handle<Script> script = Factory::NewScript(source);
Ben Murdochf87a2032010-10-22 12:50:53 +0100339 CompilationInfo info(script);
340 info.MarkAsEval();
341 if (is_global) info.MarkAsGlobal();
Ben Murdochf87a2032010-10-22 12:50:53 +0100342 info.SetCallingContext(context);
343 result = MakeFunctionInfo(&info);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800344 if (!result.is_null()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 CompilationCache::PutEval(source, context, is_global, result);
346 }
347 }
348
349 return result;
350}
351
352
Leon Clarke4515c472010-02-03 11:58:03 +0000353bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
355
356 // The VM is in the COMPILER state until exiting this function.
357 VMState state(COMPILER);
358
359 PostponeInterruptsScope postpone;
360
Leon Clarke4515c472010-02-03 11:58:03 +0000361 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochf87a2032010-10-22 12:50:53 +0100362 int compiled_size = shared->end_position() - shared->start_position();
363 Counters::total_compile_size.Increment(compiled_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000364
Ben Murdochf87a2032010-10-22 12:50:53 +0100365 // Generate the AST for the lazily compiled function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800366 if (ParserApi::Parse(info)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100367 // Measure how long it takes to do the lazy compilation; only take the
368 // rest of the function into account to avoid overlap with the lazy
369 // parsing statistics.
370 HistogramTimerScope timer(&Counters::compile_lazy);
Steve Blocka7e24c12009-10-30 11:49:00 +0000371
Ben Murdochf87a2032010-10-22 12:50:53 +0100372 // Compile the code.
373 if (!MakeCode(info)) {
374 Top::StackOverflow();
375 } else {
376 ASSERT(!info->code().is_null());
377 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
378 Handle<String>(shared->DebugName()),
379 shared->start_position(),
380 info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000381
Ben Murdochf87a2032010-10-22 12:50:53 +0100382 // Update the shared function info with the compiled code and the
383 // scope info. Please note, that the order of the sharedfunction
384 // initialization is important since SerializedScopeInfo::Create might
385 // trigger a GC, causing the ASSERT below to be invalid if the code
386 // was flushed. By setting the code object last we avoid this.
387 Handle<SerializedScopeInfo> scope_info =
388 SerializedScopeInfo::Create(info->scope());
389 shared->set_scope_info(*scope_info);
390 shared->set_code(*info->code());
391 if (!info->closure().is_null()) {
392 info->closure()->set_code(*info->code());
393 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
Ben Murdochf87a2032010-10-22 12:50:53 +0100395 // Set the expected number of properties for instances.
396 FunctionLiteral* lit = info->function();
397 SetExpectedNofPropertiesFromEstimate(shared,
398 lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000399
Ben Murdochf87a2032010-10-22 12:50:53 +0100400 // Set the optimization hints after performing lazy compilation, as
401 // these are not set when the function is set up as a lazily compiled
402 // function.
403 shared->SetThisPropertyAssignmentsInfo(
404 lit->has_only_simple_this_property_assignments(),
405 *lit->this_property_assignments());
Steve Blocka7e24c12009-10-30 11:49:00 +0000406
Ben Murdochf87a2032010-10-22 12:50:53 +0100407 // Check the function has compiled code.
408 ASSERT(shared->is_compiled());
409 shared->set_code_age(0);
410 ASSERT(!info->code().is_null());
411 return true;
412 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 }
414
Ben Murdochf87a2032010-10-22 12:50:53 +0100415 ASSERT(info->code().is_null());
416 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000417}
418
419
Steve Block6ded16b2010-05-10 14:33:55 +0100420Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Ben Murdochf87a2032010-10-22 12:50:53 +0100421 Handle<Script> script) {
Steve Blockd0582a62009-12-15 09:54:21 +0000422#ifdef DEBUG
423 // We should not try to compile the same function literal more than
424 // once.
425 literal->mark_as_compiled();
426#endif
427
Ben Murdochf87a2032010-10-22 12:50:53 +0100428 // Precondition: code has been parsed and scopes have been analyzed.
429 CompilationInfo info(script);
430 info.SetFunction(literal);
431 info.SetScope(literal->scope());
432
433 LiveEditFunctionTracker live_edit_tracker(literal);
434 // Determine if the function can be lazily compiled. This is necessary to
435 // allow some of our builtin JS files to be lazily compiled. These
436 // builtins cannot be handled lazily by the parser, since we have to know
437 // if a function uses the special natives syntax, which is something the
438 // parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000439 bool allow_lazy = literal->AllowsLazyCompilation() &&
440 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000441
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100442 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
443
Steve Blockd0582a62009-12-15 09:54:21 +0000444 // Generate code
Steve Blockd0582a62009-12-15 09:54:21 +0000445 if (FLAG_lazy && allow_lazy) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100446 Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
447 info.SetCode(code);
Steve Blockd0582a62009-12-15 09:54:21 +0000448 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000449 // Generate code and return it. The way that the compilation mode
450 // is controlled by the command-line flags is described in
451 // the static helper function MakeCode.
Ben Murdochf87a2032010-10-22 12:50:53 +0100452 //
453 // The bodies of function literals have not yet been visited by
454 // the AST analyzer.
455 if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
Leon Clarke4515c472010-02-03 11:58:03 +0000456
Leon Clarked91b9f72010-01-27 17:25:45 +0000457 bool is_run_once = literal->try_full_codegen();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100458 bool use_full = FLAG_full_compiler && !literal->contains_loops();
459 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100460 if (!FullCodeGenerator::MakeCode(&info)) {
461 return Handle<SharedFunctionInfo>::null();
462 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100463 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000464 // We fall back to the classic V8 code generator.
Ben Murdochf87a2032010-10-22 12:50:53 +0100465 AssignedVariablesAnalyzer ava;
466 if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
467 if (!CodeGenerator::MakeCode(&info)) {
468 return Handle<SharedFunctionInfo>::null();
469 }
Steve Blockd0582a62009-12-15 09:54:21 +0000470 }
471
472 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100473 RecordFunctionCompilation(Logger::FUNCTION_TAG,
Ben Murdochf87a2032010-10-22 12:50:53 +0100474 literal->debug_name(),
Steve Block6ded16b2010-05-10 14:33:55 +0100475 literal->start_position(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100476 &info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100477 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000478 }
479
Steve Block6ded16b2010-05-10 14:33:55 +0100480 // Create a shared function info object.
481 Handle<SharedFunctionInfo> result =
482 Factory::NewSharedFunctionInfo(literal->name(),
483 literal->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100484 info.code(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100485 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100486 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000487
488 // Set the expected number of properties for instances and return
489 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100490 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000491 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100492 live_edit_tracker.RecordFunctionInfo(result, literal);
493 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000494}
495
496
497// Sets the function info on a function.
498// The start_position points to the first '(' character after the function name
499// in the full script source. When counting characters in the script source the
500// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100501void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000502 FunctionLiteral* lit,
503 bool is_toplevel,
504 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100505 function_info->set_length(lit->num_parameters());
506 function_info->set_formal_parameter_count(lit->num_parameters());
507 function_info->set_script(*script);
508 function_info->set_function_token_position(lit->function_token_position());
509 function_info->set_start_position(lit->start_position());
510 function_info->set_end_position(lit->end_position());
511 function_info->set_is_expression(lit->is_expression());
512 function_info->set_is_toplevel(is_toplevel);
513 function_info->set_inferred_name(*lit->inferred_name());
514 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000515 lit->has_only_simple_this_property_assignments(),
516 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100517 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100518 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000519}
520
521
Steve Block6ded16b2010-05-10 14:33:55 +0100522void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
523 Handle<String> name,
Steve Block6ded16b2010-05-10 14:33:55 +0100524 int start_position,
Ben Murdochf87a2032010-10-22 12:50:53 +0100525 CompilationInfo* info) {
526 // Log the code generation. If source information is available include
527 // script name and line number. Check explicitly whether logging is
528 // enabled as finding the line number is not free.
529 if (Logger::is_logging() ||
530 OProfileAgent::is_enabled() ||
531 CpuProfiler::is_profiling()) {
532 Handle<Script> script = info->script();
533 Handle<Code> code = info->code();
Andrei Popescu31002712010-02-23 13:46:05 +0000534 if (script->name()->IsString()) {
535 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100536 USE(line_num);
537 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100538 *code,
539 *name,
540 String::cast(script->name()),
541 line_num));
542 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100543 String::cast(script->name()),
544 line_num,
545 code->instruction_start(),
546 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000547 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100548 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100549 *code,
550 *name));
551 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100552 code->instruction_start(),
553 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000554 }
555 }
556}
Andrei Popescu31002712010-02-23 13:46:05 +0000557
Steve Blocka7e24c12009-10-30 11:49:00 +0000558} } // namespace v8::internal