blob: f65f94156740f86ce945730d0a885b10b390b65d [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()) {
123 info->shared_info()->set_scope_info(
124 *SerializedScopeInfo::Create(info->scope()));
125 }
126 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100127}
128#endif
129
130
131static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
132 bool is_eval,
133 Compiler::ValidationState validate,
134 Handle<Script> script,
135 Handle<Context> context,
136 v8::Extension* extension,
137 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000138 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
139
140 PostponeInterruptsScope postpone;
141
142 ASSERT(!i::Top::global_context().is_null());
143 script->set_context_data((*i::Top::global_context())->data());
144
Steve Blocka7e24c12009-10-30 11:49:00 +0000145 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000146#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000147 if (is_eval || is_json) {
148 script->set_compilation_type(
149 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
150 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
151 // For eval scripts add information on the function from which eval was
152 // called.
153 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000154 StackTraceFrameIterator it;
155 if (!it.done()) {
156 script->set_eval_from_shared(
157 JSFunction::cast(it.frame()->function())->shared());
158 int offset = static_cast<int>(
159 it.frame()->pc() - it.frame()->code()->instruction_start());
160 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
161 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 }
163 }
164
165 // Notify debugger
166 Debugger::OnBeforeCompile(script);
167#endif
168
169 // Only allow non-global compiles for eval.
170 ASSERT(is_eval || is_global);
171
172 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000173 FunctionLiteral* lit =
174 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175
Steve Block6ded16b2010-05-10 14:33:55 +0100176 LiveEditFunctionTracker live_edit_tracker(lit);
177
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 // Check for parse errors.
179 if (lit == NULL) {
180 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100181 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 }
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 // Measure how long it takes to do the compilation; only take the
185 // rest of the function into account to avoid overlap with the
186 // parsing statistics.
187 HistogramTimer* rate = is_eval
188 ? &Counters::compile_eval
189 : &Counters::compile;
190 HistogramTimerScope timer(rate);
191
192 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000193 CompilationInfo info(lit, script, is_eval);
194 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000195
196 // Check for stack-overflow exceptions.
197 if (code.is_null()) {
198 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100199 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 }
201
Steve Block6ded16b2010-05-10 14:33:55 +0100202 if (script->name()->IsString()) {
203 PROFILE(CodeCreateEvent(
204 is_eval ? Logger::EVAL_TAG :
205 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
206 *code, String::cast(script->name())));
207 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
208 code->instruction_start(),
209 code->instruction_size()));
210 } else {
211 PROFILE(CodeCreateEvent(
212 is_eval ? Logger::EVAL_TAG :
213 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
214 *code, ""));
215 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
216 code->instruction_start(),
217 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(),
225 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
282 && FLAG_lazy
283 && source_length >= FLAG_min_preparse_length) {
284 pre_data = PartialPreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000285 }
286
287 // Create a script object describing the script to be compiled.
288 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000289 if (natives == NATIVES_CODE) {
290 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
291 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 if (!script_name.is_null()) {
293 script->set_name(*script_name);
294 script->set_line_offset(Smi::FromInt(line_offset));
295 script->set_column_offset(Smi::FromInt(column_offset));
296 }
297
Andrei Popescu402d9372010-02-26 13:31:12 +0000298 script->set_data(script_data.is_null() ? Heap::undefined_value()
299 : *script_data);
300
Steve Blocka7e24c12009-10-30 11:49:00 +0000301 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100302 result = MakeFunctionInfo(true,
303 false,
304 DONT_VALIDATE_JSON,
305 script,
306 Handle<Context>::null(),
307 extension,
308 pre_data);
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) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 // Note that if validation is required then no path through this
329 // function is allowed to return a value without validating that
330 // the input is legal json.
331
332 int source_length = source->length();
333 Counters::total_eval_size.Increment(source_length);
334 Counters::total_compile_size.Increment(source_length);
335
336 // The VM is in the COMPILER state until exiting this function.
337 VMState state(COMPILER);
338
339 // Do a lookup in the compilation cache; if the entry is not there,
340 // invoke the compiler and add the result to the cache. If we're
341 // evaluating json we bypass the cache since we can't be sure a
342 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100343 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 if (validate == DONT_VALIDATE_JSON)
345 result = CompilationCache::LookupEval(source, context, is_global);
346
347 if (result.is_null()) {
348 // Create a script object describing the script to be compiled.
349 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100350 result = MakeFunctionInfo(is_global,
351 true,
352 validate,
353 script,
354 context,
355 NULL,
356 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000357 if (!result.is_null() && validate != VALIDATE_JSON) {
358 // For json it's unlikely that we'll ever see exactly the same
359 // string again so we don't use the compilation cache.
360 CompilationCache::PutEval(source, context, is_global, result);
361 }
362 }
363
364 return result;
365}
366
367
Leon Clarke4515c472010-02-03 11:58:03 +0000368bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
370
371 // The VM is in the COMPILER state until exiting this function.
372 VMState state(COMPILER);
373
374 PostponeInterruptsScope postpone;
375
376 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000377 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000378 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000379
380 int start_position = shared->start_position();
381 int end_position = shared->end_position();
382 bool is_expression = shared->is_expression();
383 Counters::total_compile_size.Increment(end_position - start_position);
384
385 // Generate the AST for the lazily compiled function. The AST may be
386 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000387 FunctionLiteral* lit = MakeLazyAST(info->script(),
388 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 start_position,
390 end_position,
391 is_expression);
392
393 // Check for parse errors.
394 if (lit == NULL) {
395 ASSERT(Top::has_pending_exception());
396 return false;
397 }
Andrei Popescu31002712010-02-23 13:46:05 +0000398 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000399
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 // Measure how long it takes to do the lazy compilation; only take
401 // the rest of the function into account to avoid overlap with the
402 // lazy parsing statistics.
403 HistogramTimerScope timer(&Counters::compile_lazy);
404
405 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000406 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000407
408 // Check for stack-overflow exception.
409 if (code.is_null()) {
410 Top::StackOverflow();
411 return false;
412 }
413
Steve Block6ded16b2010-05-10 14:33:55 +0100414 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
415 name,
416 Handle<String>(shared->inferred_name()),
417 start_position,
418 info->script(),
419 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000420
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100421 // Update the shared function info with the compiled code and the scope info.
422 // Please note, that the order of the sharedfunction initialization is
423 // important since set_scope_info might trigger a GC, causing the ASSERT
424 // below to be invalid if the code was flushed. By settting the code
425 // object last we avoid this.
426 shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 shared->set_code(*code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100428 if (!info->closure().is_null()) {
429 info->closure()->set_code(*code);
430 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000431
432 // Set the expected number of properties for instances.
433 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
434
435 // Set the optimication hints after performing lazy compilation, as these are
436 // not set when the function is set up as a lazily compiled function.
437 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 lit->has_only_simple_this_property_assignments(),
439 *lit->this_property_assignments());
440
441 // Check the function has compiled code.
442 ASSERT(shared->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100443 shared->set_code_age(0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 return true;
445}
446
447
Steve Block6ded16b2010-05-10 14:33:55 +0100448Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
449 Handle<Script> script,
450 AstVisitor* caller) {
451 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000452#ifdef DEBUG
453 // We should not try to compile the same function literal more than
454 // once.
455 literal->mark_as_compiled();
456#endif
457
458 // Determine if the function can be lazily compiled. This is
459 // necessary to allow some of our builtin JS files to be lazily
460 // compiled. These builtins cannot be handled lazily by the parser,
461 // since we have to know if a function uses the special natives
462 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000463 bool allow_lazy = literal->AllowsLazyCompilation() &&
464 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000465
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100466 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
467
Steve Blockd0582a62009-12-15 09:54:21 +0000468 // Generate code
469 Handle<Code> code;
470 if (FLAG_lazy && allow_lazy) {
Iain Merrick75681382010-08-19 15:07:18 +0100471 code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
Steve Blockd0582a62009-12-15 09:54:21 +0000472 } else {
473 // The bodies of function literals have not yet been visited by
474 // the AST optimizer/analyzer.
475 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100476 return Handle<SharedFunctionInfo>::null();
477 }
478
Leon Clarked91b9f72010-01-27 17:25:45 +0000479 // Generate code and return it. The way that the compilation mode
480 // is controlled by the command-line flags is described in
481 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000482 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000483
Leon Clarked91b9f72010-01-27 17:25:45 +0000484 bool is_run_once = literal->try_full_codegen();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100485 bool use_full = FLAG_full_compiler && !literal->contains_loops();
486 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100487 code = FullCodeGenerator::MakeCode(&info);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100488 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +0000489 // We fall back to the classic V8 code generator.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100490 AssignedVariablesAnalyzer ava(literal);
491 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000492 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000493 }
494
495 // Check for stack-overflow exception.
496 if (code.is_null()) {
497 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100498 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000499 }
500
501 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100502 RecordFunctionCompilation(Logger::FUNCTION_TAG,
503 literal->name(),
504 literal->inferred_name(),
505 literal->start_position(),
506 script,
507 code);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100508 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000509 }
510
Steve Block6ded16b2010-05-10 14:33:55 +0100511 // Create a shared function info object.
512 Handle<SharedFunctionInfo> result =
513 Factory::NewSharedFunctionInfo(literal->name(),
514 literal->materialized_literal_count(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100515 code,
516 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100517 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000518
519 // Set the expected number of properties for instances and return
520 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100521 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000522 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100523 live_edit_tracker.RecordFunctionInfo(result, literal);
524 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000525}
526
527
528// Sets the function info on a function.
529// The start_position points to the first '(' character after the function name
530// in the full script source. When counting characters in the script source the
531// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100532void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000533 FunctionLiteral* lit,
534 bool is_toplevel,
535 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100536 function_info->set_length(lit->num_parameters());
537 function_info->set_formal_parameter_count(lit->num_parameters());
538 function_info->set_script(*script);
539 function_info->set_function_token_position(lit->function_token_position());
540 function_info->set_start_position(lit->start_position());
541 function_info->set_end_position(lit->end_position());
542 function_info->set_is_expression(lit->is_expression());
543 function_info->set_is_toplevel(is_toplevel);
544 function_info->set_inferred_name(*lit->inferred_name());
545 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000546 lit->has_only_simple_this_property_assignments(),
547 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100548 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100549 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000550}
551
552
Steve Block6ded16b2010-05-10 14:33:55 +0100553void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
554 Handle<String> name,
555 Handle<String> inferred_name,
556 int start_position,
557 Handle<Script> script,
558 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000559 // Log the code generation. If source information is available
560 // include script name and line number. Check explicitly whether
561 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100562 if (Logger::is_logging()
563 || OProfileAgent::is_enabled()
564 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000565 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
566 if (script->name()->IsString()) {
567 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100568 USE(line_num);
569 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
570 *code, *func_name,
571 String::cast(script->name()), line_num));
572 OPROFILE(CreateNativeCodeRegion(*func_name,
573 String::cast(script->name()),
574 line_num,
575 code->instruction_start(),
576 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000577 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100578 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
579 *code, *func_name));
580 OPROFILE(CreateNativeCodeRegion(*func_name,
581 code->instruction_start(),
582 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000583 }
584 }
585}
Andrei Popescu31002712010-02-23 13:46:05 +0000586
Steve Blocka7e24c12009-10-30 11:49:00 +0000587} } // namespace v8::internal