blob: 6cc09713d61191b3c9f5f826fd14b62fd6b0a398 [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
Ben Murdochf87a2032010-10-22 12:50:53 +0100155 if (info->is_eval() || info->is_json()) {
156 Script::CompilationType compilation_type = info->is_json()
157 ? Script::COMPILATION_TYPE_JSON
158 : Script::COMPILATION_TYPE_EVAL;
159 script->set_compilation_type(Smi::FromInt(compilation_type));
Steve Blocka7e24c12009-10-30 11:49:00 +0000160 // For eval scripts add information on the function from which eval was
161 // called.
Ben Murdochf87a2032010-10-22 12:50:53 +0100162 if (info->is_eval()) {
Leon Clarke4515c472010-02-03 11:58:03 +0000163 StackTraceFrameIterator it;
164 if (!it.done()) {
165 script->set_eval_from_shared(
166 JSFunction::cast(it.frame()->function())->shared());
167 int offset = static_cast<int>(
168 it.frame()->pc() - it.frame()->code()->instruction_start());
169 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
170 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 }
172 }
173
174 // Notify debugger
175 Debugger::OnBeforeCompile(script);
176#endif
177
178 // Only allow non-global compiles for eval.
Ben Murdochf87a2032010-10-22 12:50:53 +0100179 ASSERT(info->is_eval() || info->is_global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180
Ben Murdochf87a2032010-10-22 12:50:53 +0100181 if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000182
Steve Blocka7e24c12009-10-30 11:49:00 +0000183 // Measure how long it takes to do the compilation; only take the
184 // rest of the function into account to avoid overlap with the
185 // parsing statistics.
Ben Murdochf87a2032010-10-22 12:50:53 +0100186 HistogramTimer* rate = info->is_eval()
Steve Blocka7e24c12009-10-30 11:49:00 +0000187 ? &Counters::compile_eval
188 : &Counters::compile;
189 HistogramTimerScope timer(rate);
190
191 // Compile the code.
Ben Murdochf87a2032010-10-22 12:50:53 +0100192 FunctionLiteral* lit = info->function();
193 LiveEditFunctionTracker live_edit_tracker(lit);
194 if (!MakeCode(info)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100196 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 }
198
Ben Murdochf87a2032010-10-22 12:50:53 +0100199 ASSERT(!info->code().is_null());
Steve Block6ded16b2010-05-10 14:33:55 +0100200 if (script->name()->IsString()) {
201 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100202 info->is_eval()
203 ? Logger::EVAL_TAG
204 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
205 *info->code(),
206 String::cast(script->name())));
Steve Block6ded16b2010-05-10 14:33:55 +0100207 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
Ben Murdochf87a2032010-10-22 12:50:53 +0100208 info->code()->instruction_start(),
209 info->code()->instruction_size()));
Steve Block6ded16b2010-05-10 14:33:55 +0100210 } else {
211 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100212 info->is_eval()
213 ? Logger::EVAL_TAG
214 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
215 *info->code(),
216 ""));
217 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
218 info->code()->instruction_start(),
219 info->code()->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000221
222 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100223 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100224 Factory::NewSharedFunctionInfo(
225 lit->name(),
226 lit->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100227 info->code(),
228 SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000229
230 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100231 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
233 // Hint to the runtime system used when allocating space for initial
234 // property space by setting the expected number of properties for
235 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100236 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000237
238#ifdef ENABLE_DEBUGGER_SUPPORT
239 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100240 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000241#endif
242
Steve Block6ded16b2010-05-10 14:33:55 +0100243 live_edit_tracker.RecordFunctionInfo(result, lit);
244
245 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000246}
247
248
Steve Block6ded16b2010-05-10 14:33:55 +0100249Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
250 Handle<Object> script_name,
251 int line_offset,
252 int column_offset,
253 v8::Extension* extension,
254 ScriptDataImpl* input_pre_data,
255 Handle<Object> script_data,
256 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 int source_length = source->length();
258 Counters::total_load_size.Increment(source_length);
259 Counters::total_compile_size.Increment(source_length);
260
261 // The VM is in the COMPILER state until exiting this function.
262 VMState state(COMPILER);
263
264 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100265 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 if (extension == NULL) {
267 result = CompilationCache::LookupScript(source,
268 script_name,
269 line_offset,
270 column_offset);
271 }
272
273 if (result.is_null()) {
Steve Block59151502010-09-22 15:07:15 +0100274 // No cache entry found. Do pre-parsing, if it makes sense, and compile
275 // the script.
276 // Building preparse data that is only used immediately after is only a
277 // saving if we might skip building the AST for lazily compiled functions.
278 // I.e., preparse data isn't relevant when the lazy flag is off, and
279 // for small sources, odds are that there aren't many functions
280 // that would be compiled lazily anyway, so we skip the preparse step
281 // in that case too.
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 ScriptDataImpl* pre_data = input_pre_data;
Steve Block59151502010-09-22 15:07:15 +0100283 if (pre_data == NULL
284 && FLAG_lazy
285 && source_length >= FLAG_min_preparse_length) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100286 pre_data = Parser::PartialPreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000287 }
288
289 // Create a script object describing the script to be compiled.
290 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000291 if (natives == NATIVES_CODE) {
292 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
293 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 if (!script_name.is_null()) {
295 script->set_name(*script_name);
296 script->set_line_offset(Smi::FromInt(line_offset));
297 script->set_column_offset(Smi::FromInt(column_offset));
298 }
299
Andrei Popescu402d9372010-02-26 13:31:12 +0000300 script->set_data(script_data.is_null() ? Heap::undefined_value()
301 : *script_data);
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 // Compile the function and add it to the cache.
Ben Murdochf87a2032010-10-22 12:50:53 +0100304 CompilationInfo info(script);
305 info.MarkAsGlobal();
306 info.SetExtension(extension);
307 info.SetPreParseData(pre_data);
308 result = MakeFunctionInfo(&info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 if (extension == NULL && !result.is_null()) {
310 CompilationCache::PutScript(source, result);
311 }
312
313 // Get rid of the pre-parsing data (if necessary).
314 if (input_pre_data == NULL && pre_data != NULL) {
315 delete pre_data;
316 }
317 }
318
319 if (result.is_null()) Top::ReportPendingMessages();
320 return result;
321}
322
323
Steve Block6ded16b2010-05-10 14:33:55 +0100324Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
325 Handle<Context> context,
326 bool is_global,
327 ValidationState validate) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100328 // Note that if validation is required then no path through this function
329 // is allowed to return a value without validating that the input is legal
330 // json.
331 bool is_json = (validate == VALIDATE_JSON);
Steve Blocka7e24c12009-10-30 11:49:00 +0000332
333 int source_length = source->length();
334 Counters::total_eval_size.Increment(source_length);
335 Counters::total_compile_size.Increment(source_length);
336
337 // The VM is in the COMPILER state until exiting this function.
338 VMState state(COMPILER);
339
Ben Murdochf87a2032010-10-22 12:50:53 +0100340 // Do a lookup in the compilation cache; if the entry is not there, invoke
341 // the compiler and add the result to the cache. If we're evaluating json
342 // we bypass the cache since we can't be sure a potential value in the
343 // cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100344 Handle<SharedFunctionInfo> result;
Ben Murdochf87a2032010-10-22 12:50:53 +0100345 if (!is_json) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 result = CompilationCache::LookupEval(source, context, is_global);
Ben Murdochf87a2032010-10-22 12:50:53 +0100347 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000348
349 if (result.is_null()) {
350 // Create a script object describing the script to be compiled.
351 Handle<Script> script = Factory::NewScript(source);
Ben Murdochf87a2032010-10-22 12:50:53 +0100352 CompilationInfo info(script);
353 info.MarkAsEval();
354 if (is_global) info.MarkAsGlobal();
355 if (is_json) info.MarkAsJson();
356 info.SetCallingContext(context);
357 result = MakeFunctionInfo(&info);
358 if (!result.is_null() && !is_json) {
359 // For json it's unlikely that we'll ever see exactly the same string
360 // again so we don't use the compilation cache.
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 CompilationCache::PutEval(source, context, is_global, result);
362 }
363 }
364
365 return result;
366}
367
368
Leon Clarke4515c472010-02-03 11:58:03 +0000369bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
371
372 // The VM is in the COMPILER state until exiting this function.
373 VMState state(COMPILER);
374
375 PostponeInterruptsScope postpone;
376
Leon Clarke4515c472010-02-03 11:58:03 +0000377 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochf87a2032010-10-22 12:50:53 +0100378 int compiled_size = shared->end_position() - shared->start_position();
379 Counters::total_compile_size.Increment(compiled_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000380
Ben Murdochf87a2032010-10-22 12:50:53 +0100381 // Generate the AST for the lazily compiled function.
382 if (Parser::Parse(info)) {
383 // Measure how long it takes to do the lazy compilation; only take the
384 // rest of the function into account to avoid overlap with the lazy
385 // parsing statistics.
386 HistogramTimerScope timer(&Counters::compile_lazy);
Steve Blocka7e24c12009-10-30 11:49:00 +0000387
Ben Murdochf87a2032010-10-22 12:50:53 +0100388 // Compile the code.
389 if (!MakeCode(info)) {
390 Top::StackOverflow();
391 } else {
392 ASSERT(!info->code().is_null());
393 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
394 Handle<String>(shared->DebugName()),
395 shared->start_position(),
396 info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000397
Ben Murdochf87a2032010-10-22 12:50:53 +0100398 // Update the shared function info with the compiled code and the
399 // scope info. Please note, that the order of the sharedfunction
400 // initialization is important since SerializedScopeInfo::Create might
401 // trigger a GC, causing the ASSERT below to be invalid if the code
402 // was flushed. By setting the code object last we avoid this.
403 Handle<SerializedScopeInfo> scope_info =
404 SerializedScopeInfo::Create(info->scope());
405 shared->set_scope_info(*scope_info);
406 shared->set_code(*info->code());
407 if (!info->closure().is_null()) {
408 info->closure()->set_code(*info->code());
409 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000410
Ben Murdochf87a2032010-10-22 12:50:53 +0100411 // Set the expected number of properties for instances.
412 FunctionLiteral* lit = info->function();
413 SetExpectedNofPropertiesFromEstimate(shared,
414 lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000415
Ben Murdochf87a2032010-10-22 12:50:53 +0100416 // Set the optimization hints after performing lazy compilation, as
417 // these are not set when the function is set up as a lazily compiled
418 // function.
419 shared->SetThisPropertyAssignmentsInfo(
420 lit->has_only_simple_this_property_assignments(),
421 *lit->this_property_assignments());
Steve Blocka7e24c12009-10-30 11:49:00 +0000422
Ben Murdochf87a2032010-10-22 12:50:53 +0100423 // Check the function has compiled code.
424 ASSERT(shared->is_compiled());
425 shared->set_code_age(0);
426 ASSERT(!info->code().is_null());
427 return true;
428 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 }
430
Ben Murdochf87a2032010-10-22 12:50:53 +0100431 ASSERT(info->code().is_null());
432 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000433}
434
435
Steve Block6ded16b2010-05-10 14:33:55 +0100436Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Ben Murdochf87a2032010-10-22 12:50:53 +0100437 Handle<Script> script) {
Steve Blockd0582a62009-12-15 09:54:21 +0000438#ifdef DEBUG
439 // We should not try to compile the same function literal more than
440 // once.
441 literal->mark_as_compiled();
442#endif
443
Ben Murdochf87a2032010-10-22 12:50:53 +0100444 // Precondition: code has been parsed and scopes have been analyzed.
445 CompilationInfo info(script);
446 info.SetFunction(literal);
447 info.SetScope(literal->scope());
448
449 LiveEditFunctionTracker live_edit_tracker(literal);
450 // Determine if the function can be lazily compiled. This is necessary to
451 // allow some of our builtin JS files to be lazily compiled. These
452 // builtins cannot be handled lazily by the parser, since we have to know
453 // if a function uses the special natives syntax, which is something the
454 // parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000455 bool allow_lazy = literal->AllowsLazyCompilation() &&
456 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000457
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100458 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
459
Steve Blockd0582a62009-12-15 09:54:21 +0000460 // Generate code
Steve Blockd0582a62009-12-15 09:54:21 +0000461 if (FLAG_lazy && allow_lazy) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100462 Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
463 info.SetCode(code);
Steve Blockd0582a62009-12-15 09:54:21 +0000464 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000465 // Generate code and return it. The way that the compilation mode
466 // is controlled by the command-line flags is described in
467 // the static helper function MakeCode.
Ben Murdochf87a2032010-10-22 12:50:53 +0100468 //
469 // The bodies of function literals have not yet been visited by
470 // the AST analyzer.
471 if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
Leon Clarke4515c472010-02-03 11:58:03 +0000472
Leon Clarked91b9f72010-01-27 17:25:45 +0000473 bool is_run_once = literal->try_full_codegen();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100474 bool use_full = FLAG_full_compiler && !literal->contains_loops();
475 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100476 if (!FullCodeGenerator::MakeCode(&info)) {
477 return Handle<SharedFunctionInfo>::null();
478 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100479 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000480 // We fall back to the classic V8 code generator.
Ben Murdochf87a2032010-10-22 12:50:53 +0100481 AssignedVariablesAnalyzer ava;
482 if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
483 if (!CodeGenerator::MakeCode(&info)) {
484 return Handle<SharedFunctionInfo>::null();
485 }
Steve Blockd0582a62009-12-15 09:54:21 +0000486 }
487
488 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100489 RecordFunctionCompilation(Logger::FUNCTION_TAG,
Ben Murdochf87a2032010-10-22 12:50:53 +0100490 literal->debug_name(),
Steve Block6ded16b2010-05-10 14:33:55 +0100491 literal->start_position(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100492 &info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100493 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000494 }
495
Steve Block6ded16b2010-05-10 14:33:55 +0100496 // Create a shared function info object.
497 Handle<SharedFunctionInfo> result =
498 Factory::NewSharedFunctionInfo(literal->name(),
499 literal->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100500 info.code(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100501 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100502 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000503
504 // Set the expected number of properties for instances and return
505 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100506 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000507 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100508 live_edit_tracker.RecordFunctionInfo(result, literal);
509 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000510}
511
512
513// Sets the function info on a function.
514// The start_position points to the first '(' character after the function name
515// in the full script source. When counting characters in the script source the
516// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100517void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000518 FunctionLiteral* lit,
519 bool is_toplevel,
520 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100521 function_info->set_length(lit->num_parameters());
522 function_info->set_formal_parameter_count(lit->num_parameters());
523 function_info->set_script(*script);
524 function_info->set_function_token_position(lit->function_token_position());
525 function_info->set_start_position(lit->start_position());
526 function_info->set_end_position(lit->end_position());
527 function_info->set_is_expression(lit->is_expression());
528 function_info->set_is_toplevel(is_toplevel);
529 function_info->set_inferred_name(*lit->inferred_name());
530 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000531 lit->has_only_simple_this_property_assignments(),
532 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100533 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100534 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000535}
536
537
Steve Block6ded16b2010-05-10 14:33:55 +0100538void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
539 Handle<String> name,
Steve Block6ded16b2010-05-10 14:33:55 +0100540 int start_position,
Ben Murdochf87a2032010-10-22 12:50:53 +0100541 CompilationInfo* info) {
542 // Log the code generation. If source information is available include
543 // script name and line number. Check explicitly whether logging is
544 // enabled as finding the line number is not free.
545 if (Logger::is_logging() ||
546 OProfileAgent::is_enabled() ||
547 CpuProfiler::is_profiling()) {
548 Handle<Script> script = info->script();
549 Handle<Code> code = info->code();
Andrei Popescu31002712010-02-23 13:46:05 +0000550 if (script->name()->IsString()) {
551 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100552 USE(line_num);
553 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100554 *code,
555 *name,
556 String::cast(script->name()),
557 line_num));
558 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100559 String::cast(script->name()),
560 line_num,
561 code->instruction_start(),
562 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000563 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100564 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100565 *code,
566 *name));
567 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100568 code->instruction_start(),
569 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000570 }
571 }
572}
Andrei Popescu31002712010-02-23 13:46:05 +0000573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574} } // namespace v8::internal