blob: bf6d41d85402217ba4cadae2228a316788401f2d [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()) {
272 // No cache entry found. Do pre-parsing and compile the script.
273 ScriptDataImpl* pre_data = input_pre_data;
274 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100275 pre_data = PreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 }
277
278 // Create a script object describing the script to be compiled.
279 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000280 if (natives == NATIVES_CODE) {
281 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
282 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000283 if (!script_name.is_null()) {
284 script->set_name(*script_name);
285 script->set_line_offset(Smi::FromInt(line_offset));
286 script->set_column_offset(Smi::FromInt(column_offset));
287 }
288
Andrei Popescu402d9372010-02-26 13:31:12 +0000289 script->set_data(script_data.is_null() ? Heap::undefined_value()
290 : *script_data);
291
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100293 result = MakeFunctionInfo(true,
294 false,
295 DONT_VALIDATE_JSON,
296 script,
297 Handle<Context>::null(),
298 extension,
299 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 if (extension == NULL && !result.is_null()) {
301 CompilationCache::PutScript(source, result);
302 }
303
304 // Get rid of the pre-parsing data (if necessary).
305 if (input_pre_data == NULL && pre_data != NULL) {
306 delete pre_data;
307 }
308 }
309
310 if (result.is_null()) Top::ReportPendingMessages();
311 return result;
312}
313
314
Steve Block6ded16b2010-05-10 14:33:55 +0100315Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
316 Handle<Context> context,
317 bool is_global,
318 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 // Note that if validation is required then no path through this
320 // function is allowed to return a value without validating that
321 // the input is legal json.
322
323 int source_length = source->length();
324 Counters::total_eval_size.Increment(source_length);
325 Counters::total_compile_size.Increment(source_length);
326
327 // The VM is in the COMPILER state until exiting this function.
328 VMState state(COMPILER);
329
330 // Do a lookup in the compilation cache; if the entry is not there,
331 // invoke the compiler and add the result to the cache. If we're
332 // evaluating json we bypass the cache since we can't be sure a
333 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100334 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000335 if (validate == DONT_VALIDATE_JSON)
336 result = CompilationCache::LookupEval(source, context, is_global);
337
338 if (result.is_null()) {
339 // Create a script object describing the script to be compiled.
340 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100341 result = MakeFunctionInfo(is_global,
342 true,
343 validate,
344 script,
345 context,
346 NULL,
347 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000348 if (!result.is_null() && validate != VALIDATE_JSON) {
349 // For json it's unlikely that we'll ever see exactly the same
350 // string again so we don't use the compilation cache.
351 CompilationCache::PutEval(source, context, is_global, result);
352 }
353 }
354
355 return result;
356}
357
358
Leon Clarke4515c472010-02-03 11:58:03 +0000359bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
361
362 // The VM is in the COMPILER state until exiting this function.
363 VMState state(COMPILER);
364
365 PostponeInterruptsScope postpone;
366
367 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000368 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000370
371 int start_position = shared->start_position();
372 int end_position = shared->end_position();
373 bool is_expression = shared->is_expression();
374 Counters::total_compile_size.Increment(end_position - start_position);
375
376 // Generate the AST for the lazily compiled function. The AST may be
377 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000378 FunctionLiteral* lit = MakeLazyAST(info->script(),
379 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 start_position,
381 end_position,
382 is_expression);
383
384 // Check for parse errors.
385 if (lit == NULL) {
386 ASSERT(Top::has_pending_exception());
387 return false;
388 }
Andrei Popescu31002712010-02-23 13:46:05 +0000389 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 // Measure how long it takes to do the lazy compilation; only take
392 // the rest of the function into account to avoid overlap with the
393 // lazy parsing statistics.
394 HistogramTimerScope timer(&Counters::compile_lazy);
395
396 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000397 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000398
399 // Check for stack-overflow exception.
400 if (code.is_null()) {
401 Top::StackOverflow();
402 return false;
403 }
404
Steve Block6ded16b2010-05-10 14:33:55 +0100405 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
406 name,
407 Handle<String>(shared->inferred_name()),
408 start_position,
409 info->script(),
410 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000411
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100412 // Update the shared function info with the compiled code and the scope info.
413 // Please note, that the order of the sharedfunction initialization is
414 // important since set_scope_info might trigger a GC, causing the ASSERT
415 // below to be invalid if the code was flushed. By settting the code
416 // object last we avoid this.
417 shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000418 shared->set_code(*code);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100419 if (!info->closure().is_null()) {
420 info->closure()->set_code(*code);
421 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000422
423 // Set the expected number of properties for instances.
424 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
425
426 // Set the optimication hints after performing lazy compilation, as these are
427 // not set when the function is set up as a lazily compiled function.
428 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 lit->has_only_simple_this_property_assignments(),
430 *lit->this_property_assignments());
431
432 // Check the function has compiled code.
433 ASSERT(shared->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100434 shared->set_code_age(0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 return true;
436}
437
438
Steve Block6ded16b2010-05-10 14:33:55 +0100439Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
440 Handle<Script> script,
441 AstVisitor* caller) {
442 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000443#ifdef DEBUG
444 // We should not try to compile the same function literal more than
445 // once.
446 literal->mark_as_compiled();
447#endif
448
449 // Determine if the function can be lazily compiled. This is
450 // necessary to allow some of our builtin JS files to be lazily
451 // compiled. These builtins cannot be handled lazily by the parser,
452 // since we have to know if a function uses the special natives
453 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000454 bool allow_lazy = literal->AllowsLazyCompilation() &&
455 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000456
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100457 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
458
Steve Blockd0582a62009-12-15 09:54:21 +0000459 // Generate code
460 Handle<Code> code;
461 if (FLAG_lazy && allow_lazy) {
Iain Merrick75681382010-08-19 15:07:18 +0100462 code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
Steve Blockd0582a62009-12-15 09:54:21 +0000463 } else {
464 // The bodies of function literals have not yet been visited by
465 // the AST optimizer/analyzer.
466 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100467 return Handle<SharedFunctionInfo>::null();
468 }
469
Leon Clarked91b9f72010-01-27 17:25:45 +0000470 // Generate code and return it. The way that the compilation mode
471 // is controlled by the command-line flags is described in
472 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000473 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000474
Leon Clarked91b9f72010-01-27 17:25:45 +0000475 bool is_run_once = literal->try_full_codegen();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100476 bool use_full = FLAG_full_compiler && !literal->contains_loops();
477 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100478 code = FullCodeGenerator::MakeCode(&info);
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.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100481 AssignedVariablesAnalyzer ava(literal);
482 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000483 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000484 }
485
486 // Check for stack-overflow exception.
487 if (code.is_null()) {
488 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100489 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000490 }
491
492 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100493 RecordFunctionCompilation(Logger::FUNCTION_TAG,
494 literal->name(),
495 literal->inferred_name(),
496 literal->start_position(),
497 script,
498 code);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100499 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000500 }
501
Steve Block6ded16b2010-05-10 14:33:55 +0100502 // Create a shared function info object.
503 Handle<SharedFunctionInfo> result =
504 Factory::NewSharedFunctionInfo(literal->name(),
505 literal->materialized_literal_count(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100506 code,
507 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100508 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000509
510 // Set the expected number of properties for instances and return
511 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100512 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000513 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100514 live_edit_tracker.RecordFunctionInfo(result, literal);
515 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000516}
517
518
519// Sets the function info on a function.
520// The start_position points to the first '(' character after the function name
521// in the full script source. When counting characters in the script source the
522// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100523void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000524 FunctionLiteral* lit,
525 bool is_toplevel,
526 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100527 function_info->set_length(lit->num_parameters());
528 function_info->set_formal_parameter_count(lit->num_parameters());
529 function_info->set_script(*script);
530 function_info->set_function_token_position(lit->function_token_position());
531 function_info->set_start_position(lit->start_position());
532 function_info->set_end_position(lit->end_position());
533 function_info->set_is_expression(lit->is_expression());
534 function_info->set_is_toplevel(is_toplevel);
535 function_info->set_inferred_name(*lit->inferred_name());
536 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000537 lit->has_only_simple_this_property_assignments(),
538 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100539 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100540 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000541}
542
543
Steve Block6ded16b2010-05-10 14:33:55 +0100544void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
545 Handle<String> name,
546 Handle<String> inferred_name,
547 int start_position,
548 Handle<Script> script,
549 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000550 // Log the code generation. If source information is available
551 // include script name and line number. Check explicitly whether
552 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100553 if (Logger::is_logging()
554 || OProfileAgent::is_enabled()
555 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000556 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
557 if (script->name()->IsString()) {
558 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100559 USE(line_num);
560 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
561 *code, *func_name,
562 String::cast(script->name()), line_num));
563 OPROFILE(CreateNativeCodeRegion(*func_name,
564 String::cast(script->name()),
565 line_num,
566 code->instruction_start(),
567 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000568 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100569 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
570 *code, *func_name));
571 OPROFILE(CreateNativeCodeRegion(*func_name,
572 code->instruction_start(),
573 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000574 }
575 }
576}
Andrei Popescu31002712010-02-23 13:46:05 +0000577
Steve Blocka7e24c12009-10-30 11:49:00 +0000578} } // namespace v8::internal