blob: 825198edbd0a37f04fec2b8c774cc803cfaaf5fb [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
30#include "bootstrapper.h"
31#include "codegen-inl.h"
32#include "compilation-cache.h"
33#include "compiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034#include "data-flow.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "debug.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000036#include "full-codegen.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "liveedit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "oprofile-agent.h"
39#include "rewriter.h"
40#include "scopes.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042
43namespace v8 {
44namespace internal {
45
Leon Clarkef7060e22010-06-03 12:02:55 +010046// For normal operation the syntax checker is used to determine whether to
47// use the full compiler for top level code or not. However if the flag
48// --always-full-compiler is specified or debugging is active the full
49// compiler will be used for all code.
50static bool AlwaysFullCompiler() {
51#ifdef ENABLE_DEBUGGER_SUPPORT
52 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
53#else
54 return FLAG_always_full_compiler;
55#endif
56}
57
Steve Block3ce2e202009-11-05 08:53:23 +000058
Andrei Popescu31002712010-02-23 13:46:05 +000059static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
60 FunctionLiteral* function = info->function();
61 ASSERT(function != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000062 // Rewrite the AST by introducing .result assignments where needed.
Steve Block6ded16b2010-05-10 14:33:55 +010063 if (!Rewriter::Process(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000064 // Signal a stack overflow by returning a null handle. The stack
65 // overflow exception will be thrown by the caller.
66 return Handle<Code>::null();
67 }
68
69 {
70 // Compute top scope and allocate variables. For lazy compilation
71 // the top scope only contains the single lazily compiled function,
72 // so this doesn't re-allocate variables repeatedly.
73 HistogramTimerScope timer(&Counters::variable_allocation);
Andrei Popescu31002712010-02-23 13:46:05 +000074 Scope* top = info->scope();
Steve Blocka7e24c12009-10-30 11:49:00 +000075 while (top->outer_scope() != NULL) top = top->outer_scope();
76 top->AllocateVariables(context);
77 }
78
79#ifdef DEBUG
80 if (Bootstrapper::IsActive() ?
81 FLAG_print_builtin_scopes :
82 FLAG_print_scopes) {
Andrei Popescu31002712010-02-23 13:46:05 +000083 info->scope()->Print();
Steve Blocka7e24c12009-10-30 11:49:00 +000084 }
85#endif
86
87 // Optimize the AST.
Andrei Popescu31002712010-02-23 13:46:05 +000088 if (!Rewriter::Optimize(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000089 // Signal a stack overflow by returning a null handle. The stack
90 // overflow exception will be thrown by the caller.
91 return Handle<Code>::null();
92 }
93
Leon Clarked91b9f72010-01-27 17:25:45 +000094 // Generate code and return it. Code generator selection is governed by
95 // which backends are enabled and whether the function is considered
96 // run-once code or not:
97 //
98 // --full-compiler enables the dedicated backend for code we expect to be
99 // run once
Leon Clarked91b9f72010-01-27 17:25:45 +0000100 //
101 // The normal choice of backend can be overridden with the flags
Iain Merrick75681382010-08-19 15:07:18 +0100102 // --always-full-compiler.
Leon Clarke4515c472010-02-03 11:58:03 +0000103 Handle<SharedFunctionInfo> shared = info->shared_info();
Leon Clarked91b9f72010-01-27 17:25:45 +0000104 bool is_run_once = (shared.is_null())
Andrei Popescu31002712010-02-23 13:46:05 +0000105 ? info->scope()->is_global_scope()
Leon Clarked91b9f72010-01-27 17:25:45 +0000106 : (shared->is_toplevel() || shared->try_full_codegen());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100107 bool use_full = FLAG_full_compiler && !function->contains_loops();
108 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100109 return FullCodeGenerator::MakeCode(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000110 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000111
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100112 AssignedVariablesAnalyzer ava(function);
113 if (!ava.Analyze()) return Handle<Code>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000114 return CodeGenerator::MakeCode(info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000115}
116
117
Steve Block6ded16b2010-05-10 14:33:55 +0100118#ifdef ENABLE_DEBUGGER_SUPPORT
119Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
120 Handle<Context> context = Handle<Context>::null();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100121 Handle<Code> code = MakeCode(context, info);
122 if (!info->shared_info().is_null()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100123 Handle<SerializedScopeInfo> scope_info =
124 SerializedScopeInfo::Create(info->scope());
125 info->shared_info()->set_scope_info(*scope_info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100126 }
127 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100128}
129#endif
130
131
132static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
133 bool is_eval,
134 Compiler::ValidationState validate,
135 Handle<Script> script,
136 Handle<Context> context,
137 v8::Extension* extension,
138 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
140
141 PostponeInterruptsScope postpone;
142
143 ASSERT(!i::Top::global_context().is_null());
144 script->set_context_data((*i::Top::global_context())->data());
145
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000147#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 if (is_eval || is_json) {
149 script->set_compilation_type(
150 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
151 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
152 // For eval scripts add information on the function from which eval was
153 // called.
154 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000155 StackTraceFrameIterator it;
156 if (!it.done()) {
157 script->set_eval_from_shared(
158 JSFunction::cast(it.frame()->function())->shared());
159 int offset = static_cast<int>(
160 it.frame()->pc() - it.frame()->code()->instruction_start());
161 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
162 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000163 }
164 }
165
166 // Notify debugger
167 Debugger::OnBeforeCompile(script);
168#endif
169
170 // Only allow non-global compiles for eval.
171 ASSERT(is_eval || is_global);
172
173 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000174 FunctionLiteral* lit =
175 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000176
Steve Block6ded16b2010-05-10 14:33:55 +0100177 LiveEditFunctionTracker live_edit_tracker(lit);
178
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 // Check for parse errors.
180 if (lit == NULL) {
181 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100182 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000183 }
184
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 // Measure how long it takes to do the compilation; only take the
186 // rest of the function into account to avoid overlap with the
187 // parsing statistics.
188 HistogramTimer* rate = is_eval
189 ? &Counters::compile_eval
190 : &Counters::compile;
191 HistogramTimerScope timer(rate);
192
193 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000194 CompilationInfo info(lit, script, is_eval);
195 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000196
197 // Check for stack-overflow exceptions.
198 if (code.is_null()) {
199 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100200 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 }
202
Steve Block6ded16b2010-05-10 14:33:55 +0100203 if (script->name()->IsString()) {
204 PROFILE(CodeCreateEvent(
205 is_eval ? Logger::EVAL_TAG :
206 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
207 *code, String::cast(script->name())));
208 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
209 code->instruction_start(),
210 code->instruction_size()));
211 } else {
212 PROFILE(CodeCreateEvent(
213 is_eval ? Logger::EVAL_TAG :
214 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
215 *code, ""));
216 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
217 code->instruction_start(),
218 code->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000220
221 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100222 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100223 Factory::NewSharedFunctionInfo(
224 lit->name(),
225 lit->materialized_literal_count(),
226 code,
227 SerializedScopeInfo::Create(info.scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000228
229 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100230 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000231
232 // Hint to the runtime system used when allocating space for initial
233 // property space by setting the expected number of properties for
234 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100235 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000236
237#ifdef ENABLE_DEBUGGER_SUPPORT
238 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100239 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000240#endif
241
Steve Block6ded16b2010-05-10 14:33:55 +0100242 live_edit_tracker.RecordFunctionInfo(result, lit);
243
244 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000245}
246
247
Steve Block6ded16b2010-05-10 14:33:55 +0100248Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
249 Handle<Object> script_name,
250 int line_offset,
251 int column_offset,
252 v8::Extension* extension,
253 ScriptDataImpl* input_pre_data,
254 Handle<Object> script_data,
255 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 int source_length = source->length();
257 Counters::total_load_size.Increment(source_length);
258 Counters::total_compile_size.Increment(source_length);
259
260 // The VM is in the COMPILER state until exiting this function.
261 VMState state(COMPILER);
262
263 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100264 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 if (extension == NULL) {
266 result = CompilationCache::LookupScript(source,
267 script_name,
268 line_offset,
269 column_offset);
270 }
271
272 if (result.is_null()) {
Steve Block59151502010-09-22 15:07:15 +0100273 // No cache entry found. Do pre-parsing, if it makes sense, and compile
274 // the script.
275 // Building preparse data that is only used immediately after is only a
276 // saving if we might skip building the AST for lazily compiled functions.
277 // I.e., preparse data isn't relevant when the lazy flag is off, and
278 // for small sources, odds are that there aren't many functions
279 // that would be compiled lazily anyway, so we skip the preparse step
280 // in that case too.
Steve Blocka7e24c12009-10-30 11:49:00 +0000281 ScriptDataImpl* pre_data = input_pre_data;
Steve Block59151502010-09-22 15:07:15 +0100282 if (pre_data == NULL
283 && FLAG_lazy
284 && source_length >= FLAG_min_preparse_length) {
285 pre_data = PartialPreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 }
287
288 // Create a script object describing the script to be compiled.
289 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000290 if (natives == NATIVES_CODE) {
291 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
292 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000293 if (!script_name.is_null()) {
294 script->set_name(*script_name);
295 script->set_line_offset(Smi::FromInt(line_offset));
296 script->set_column_offset(Smi::FromInt(column_offset));
297 }
298
Andrei Popescu402d9372010-02-26 13:31:12 +0000299 script->set_data(script_data.is_null() ? Heap::undefined_value()
300 : *script_data);
301
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100303 result = MakeFunctionInfo(true,
304 false,
305 DONT_VALIDATE_JSON,
306 script,
307 Handle<Context>::null(),
308 extension,
309 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 if (extension == NULL && !result.is_null()) {
311 CompilationCache::PutScript(source, result);
312 }
313
314 // Get rid of the pre-parsing data (if necessary).
315 if (input_pre_data == NULL && pre_data != NULL) {
316 delete pre_data;
317 }
318 }
319
320 if (result.is_null()) Top::ReportPendingMessages();
321 return result;
322}
323
324
Steve Block6ded16b2010-05-10 14:33:55 +0100325Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
326 Handle<Context> context,
327 bool is_global,
328 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000329 // Note that if validation is required then no path through this
330 // function is allowed to return a value without validating that
331 // the input is legal json.
332
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
340 // Do a lookup in the compilation cache; if the entry is not there,
341 // invoke the compiler and add the result to the cache. If we're
342 // evaluating json we bypass the cache since we can't be sure a
343 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100344 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 if (validate == DONT_VALIDATE_JSON)
346 result = CompilationCache::LookupEval(source, context, is_global);
347
348 if (result.is_null()) {
349 // Create a script object describing the script to be compiled.
350 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100351 result = MakeFunctionInfo(is_global,
352 true,
353 validate,
354 script,
355 context,
356 NULL,
357 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 if (!result.is_null() && validate != VALIDATE_JSON) {
359 // For json it's unlikely that we'll ever see exactly the same
360 // string again so we don't use the compilation cache.
361 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
377 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000378 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000380
381 int start_position = shared->start_position();
382 int end_position = shared->end_position();
383 bool is_expression = shared->is_expression();
384 Counters::total_compile_size.Increment(end_position - start_position);
385
386 // Generate the AST for the lazily compiled function. The AST may be
387 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000388 FunctionLiteral* lit = MakeLazyAST(info->script(),
389 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 start_position,
391 end_position,
392 is_expression);
393
394 // Check for parse errors.
395 if (lit == NULL) {
396 ASSERT(Top::has_pending_exception());
397 return false;
398 }
Andrei Popescu31002712010-02-23 13:46:05 +0000399 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000400
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 // Measure how long it takes to do the lazy compilation; only take
402 // the rest of the function into account to avoid overlap with the
403 // lazy parsing statistics.
404 HistogramTimerScope timer(&Counters::compile_lazy);
405
406 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000407 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000408
409 // Check for stack-overflow exception.
410 if (code.is_null()) {
411 Top::StackOverflow();
412 return false;
413 }
414
Steve Block6ded16b2010-05-10 14:33:55 +0100415 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
416 name,
417 Handle<String>(shared->inferred_name()),
418 start_position,
419 info->script(),
420 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000421
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100422 // Update the shared function info with the compiled code and the scope info.
423 // Please note, that the order of the sharedfunction initialization is
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100424 // important since SerializedScopeInfo::Create might trigger a GC, causing
425 // the ASSERT below to be invalid if the code was flushed. By setting the code
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100426 // object last we avoid this.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100427 Handle<SerializedScopeInfo> scope_info =
428 SerializedScopeInfo::Create(info->scope());
429 shared->set_scope_info(*scope_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 shared->set_code(*code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100431 if (!info->closure().is_null()) {
432 info->closure()->set_code(*code);
433 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000434
435 // Set the expected number of properties for instances.
436 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
437
438 // Set the optimication hints after performing lazy compilation, as these are
439 // not set when the function is set up as a lazily compiled function.
440 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 lit->has_only_simple_this_property_assignments(),
442 *lit->this_property_assignments());
443
444 // Check the function has compiled code.
445 ASSERT(shared->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100446 shared->set_code_age(0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 return true;
448}
449
450
Steve Block6ded16b2010-05-10 14:33:55 +0100451Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
452 Handle<Script> script,
453 AstVisitor* caller) {
454 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000455#ifdef DEBUG
456 // We should not try to compile the same function literal more than
457 // once.
458 literal->mark_as_compiled();
459#endif
460
461 // Determine if the function can be lazily compiled. This is
462 // necessary to allow some of our builtin JS files to be lazily
463 // compiled. These builtins cannot be handled lazily by the parser,
464 // since we have to know if a function uses the special natives
465 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000466 bool allow_lazy = literal->AllowsLazyCompilation() &&
467 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000468
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100469 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
470
Steve Blockd0582a62009-12-15 09:54:21 +0000471 // Generate code
472 Handle<Code> code;
473 if (FLAG_lazy && allow_lazy) {
Iain Merrick75681382010-08-19 15:07:18 +0100474 code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
Steve Blockd0582a62009-12-15 09:54:21 +0000475 } else {
476 // The bodies of function literals have not yet been visited by
477 // the AST optimizer/analyzer.
478 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100479 return Handle<SharedFunctionInfo>::null();
480 }
481
Leon Clarked91b9f72010-01-27 17:25:45 +0000482 // Generate code and return it. The way that the compilation mode
483 // is controlled by the command-line flags is described in
484 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000485 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000486
Leon Clarked91b9f72010-01-27 17:25:45 +0000487 bool is_run_once = literal->try_full_codegen();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100488 bool use_full = FLAG_full_compiler && !literal->contains_loops();
489 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100490 code = FullCodeGenerator::MakeCode(&info);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100491 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000492 // We fall back to the classic V8 code generator.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100493 AssignedVariablesAnalyzer ava(literal);
494 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000495 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000496 }
497
498 // Check for stack-overflow exception.
499 if (code.is_null()) {
500 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100501 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000502 }
503
504 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100505 RecordFunctionCompilation(Logger::FUNCTION_TAG,
506 literal->name(),
507 literal->inferred_name(),
508 literal->start_position(),
509 script,
510 code);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100511 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000512 }
513
Steve Block6ded16b2010-05-10 14:33:55 +0100514 // Create a shared function info object.
515 Handle<SharedFunctionInfo> result =
516 Factory::NewSharedFunctionInfo(literal->name(),
517 literal->materialized_literal_count(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100518 code,
519 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100520 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000521
522 // Set the expected number of properties for instances and return
523 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100524 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000525 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100526 live_edit_tracker.RecordFunctionInfo(result, literal);
527 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000528}
529
530
531// Sets the function info on a function.
532// The start_position points to the first '(' character after the function name
533// in the full script source. When counting characters in the script source the
534// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100535void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000536 FunctionLiteral* lit,
537 bool is_toplevel,
538 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100539 function_info->set_length(lit->num_parameters());
540 function_info->set_formal_parameter_count(lit->num_parameters());
541 function_info->set_script(*script);
542 function_info->set_function_token_position(lit->function_token_position());
543 function_info->set_start_position(lit->start_position());
544 function_info->set_end_position(lit->end_position());
545 function_info->set_is_expression(lit->is_expression());
546 function_info->set_is_toplevel(is_toplevel);
547 function_info->set_inferred_name(*lit->inferred_name());
548 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000549 lit->has_only_simple_this_property_assignments(),
550 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100551 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100552 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000553}
554
555
Steve Block6ded16b2010-05-10 14:33:55 +0100556void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
557 Handle<String> name,
558 Handle<String> inferred_name,
559 int start_position,
560 Handle<Script> script,
561 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000562 // Log the code generation. If source information is available
563 // include script name and line number. Check explicitly whether
564 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100565 if (Logger::is_logging()
566 || OProfileAgent::is_enabled()
567 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000568 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
569 if (script->name()->IsString()) {
570 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100571 USE(line_num);
572 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
573 *code, *func_name,
574 String::cast(script->name()), line_num));
575 OPROFILE(CreateNativeCodeRegion(*func_name,
576 String::cast(script->name()),
577 line_num,
578 code->instruction_start(),
579 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000580 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100581 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
582 *code, *func_name));
583 OPROFILE(CreateNativeCodeRegion(*func_name,
584 code->instruction_start(),
585 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000586 }
587 }
588}
Andrei Popescu31002712010-02-23 13:46:05 +0000589
Steve Blocka7e24c12009-10-30 11:49:00 +0000590} } // namespace v8::internal