blob: ff3cb7a8328e93a1640424bb37d9a241562bad6d [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"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "flow-graph.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"
40#include "rewriter.h"
41#include "scopes.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010042#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043
44namespace v8 {
45namespace internal {
46
Leon Clarkef7060e22010-06-03 12:02:55 +010047// For normal operation the syntax checker is used to determine whether to
48// use the full compiler for top level code or not. However if the flag
49// --always-full-compiler is specified or debugging is active the full
50// compiler will be used for all code.
51static bool AlwaysFullCompiler() {
52#ifdef ENABLE_DEBUGGER_SUPPORT
53 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
54#else
55 return FLAG_always_full_compiler;
56#endif
57}
58
Steve Block3ce2e202009-11-05 08:53:23 +000059
Andrei Popescu31002712010-02-23 13:46:05 +000060static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
61 FunctionLiteral* function = info->function();
62 ASSERT(function != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000063 // Rewrite the AST by introducing .result assignments where needed.
Steve Block6ded16b2010-05-10 14:33:55 +010064 if (!Rewriter::Process(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000065 // Signal a stack overflow by returning a null handle. The stack
66 // overflow exception will be thrown by the caller.
67 return Handle<Code>::null();
68 }
69
70 {
71 // Compute top scope and allocate variables. For lazy compilation
72 // the top scope only contains the single lazily compiled function,
73 // so this doesn't re-allocate variables repeatedly.
74 HistogramTimerScope timer(&Counters::variable_allocation);
Andrei Popescu31002712010-02-23 13:46:05 +000075 Scope* top = info->scope();
Steve Blocka7e24c12009-10-30 11:49:00 +000076 while (top->outer_scope() != NULL) top = top->outer_scope();
77 top->AllocateVariables(context);
78 }
79
80#ifdef DEBUG
81 if (Bootstrapper::IsActive() ?
82 FLAG_print_builtin_scopes :
83 FLAG_print_scopes) {
Andrei Popescu31002712010-02-23 13:46:05 +000084 info->scope()->Print();
Steve Blocka7e24c12009-10-30 11:49:00 +000085 }
86#endif
87
88 // Optimize the AST.
Andrei Popescu31002712010-02-23 13:46:05 +000089 if (!Rewriter::Optimize(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000090 // Signal a stack overflow by returning a null handle. The stack
91 // overflow exception will be thrown by the caller.
92 return Handle<Code>::null();
93 }
94
Steve Block6ded16b2010-05-10 14:33:55 +010095 if (function->scope()->num_parameters() > 0 ||
96 function->scope()->num_stack_slots()) {
97 AssignedVariablesAnalyzer ava(function);
98 ava.Analyze();
99 if (ava.HasStackOverflow()) {
100 return Handle<Code>::null();
101 }
102 }
103
104 if (FLAG_use_flow_graph) {
105 FlowGraphBuilder builder;
106 FlowGraph* graph = builder.Build(function);
107 USE(graph);
108
109#ifdef DEBUG
110 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
111 graph->PrintAsText(function->name());
112 }
113#endif
114 }
115
Leon Clarked91b9f72010-01-27 17:25:45 +0000116 // Generate code and return it. Code generator selection is governed by
117 // which backends are enabled and whether the function is considered
118 // run-once code or not:
119 //
120 // --full-compiler enables the dedicated backend for code we expect to be
121 // run once
Leon Clarked91b9f72010-01-27 17:25:45 +0000122 //
123 // The normal choice of backend can be overridden with the flags
Iain Merrick75681382010-08-19 15:07:18 +0100124 // --always-full-compiler.
Leon Clarke4515c472010-02-03 11:58:03 +0000125 Handle<SharedFunctionInfo> shared = info->shared_info();
Leon Clarked91b9f72010-01-27 17:25:45 +0000126 bool is_run_once = (shared.is_null())
Andrei Popescu31002712010-02-23 13:46:05 +0000127 ? info->scope()->is_global_scope()
Leon Clarked91b9f72010-01-27 17:25:45 +0000128 : (shared->is_toplevel() || shared->try_full_codegen());
129
Leon Clarkef7060e22010-06-03 12:02:55 +0100130 if (AlwaysFullCompiler()) {
131 return FullCodeGenerator::MakeCode(info);
132 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000133 FullCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000134 checker.Check(function);
Leon Clarked91b9f72010-01-27 17:25:45 +0000135 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000136 return FullCodeGenerator::MakeCode(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000137 }
Steve Block3ce2e202009-11-05 08:53:23 +0000138 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000139
Andrei Popescu31002712010-02-23 13:46:05 +0000140 return CodeGenerator::MakeCode(info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000141}
142
143
Steve Block6ded16b2010-05-10 14:33:55 +0100144#ifdef ENABLE_DEBUGGER_SUPPORT
145Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
146 Handle<Context> context = Handle<Context>::null();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100147 Handle<Code> code = MakeCode(context, info);
148 if (!info->shared_info().is_null()) {
149 info->shared_info()->set_scope_info(
150 *SerializedScopeInfo::Create(info->scope()));
151 }
152 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100153}
154#endif
155
156
157static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
158 bool is_eval,
159 Compiler::ValidationState validate,
160 Handle<Script> script,
161 Handle<Context> context,
162 v8::Extension* extension,
163 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
165
166 PostponeInterruptsScope postpone;
167
168 ASSERT(!i::Top::global_context().is_null());
169 script->set_context_data((*i::Top::global_context())->data());
170
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000172#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000173 if (is_eval || is_json) {
174 script->set_compilation_type(
175 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
176 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
177 // For eval scripts add information on the function from which eval was
178 // called.
179 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000180 StackTraceFrameIterator it;
181 if (!it.done()) {
182 script->set_eval_from_shared(
183 JSFunction::cast(it.frame()->function())->shared());
184 int offset = static_cast<int>(
185 it.frame()->pc() - it.frame()->code()->instruction_start());
186 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
187 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000188 }
189 }
190
191 // Notify debugger
192 Debugger::OnBeforeCompile(script);
193#endif
194
195 // Only allow non-global compiles for eval.
196 ASSERT(is_eval || is_global);
197
198 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000199 FunctionLiteral* lit =
200 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000201
Steve Block6ded16b2010-05-10 14:33:55 +0100202 LiveEditFunctionTracker live_edit_tracker(lit);
203
Steve Blocka7e24c12009-10-30 11:49:00 +0000204 // Check for parse errors.
205 if (lit == NULL) {
206 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100207 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 }
209
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 // Measure how long it takes to do the compilation; only take the
211 // rest of the function into account to avoid overlap with the
212 // parsing statistics.
213 HistogramTimer* rate = is_eval
214 ? &Counters::compile_eval
215 : &Counters::compile;
216 HistogramTimerScope timer(rate);
217
218 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000219 CompilationInfo info(lit, script, is_eval);
220 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000221
222 // Check for stack-overflow exceptions.
223 if (code.is_null()) {
224 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100225 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 }
227
Steve Block6ded16b2010-05-10 14:33:55 +0100228 if (script->name()->IsString()) {
229 PROFILE(CodeCreateEvent(
230 is_eval ? Logger::EVAL_TAG :
231 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
232 *code, String::cast(script->name())));
233 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
234 code->instruction_start(),
235 code->instruction_size()));
236 } else {
237 PROFILE(CodeCreateEvent(
238 is_eval ? Logger::EVAL_TAG :
239 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
240 *code, ""));
241 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
242 code->instruction_start(),
243 code->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000245
246 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100247 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100248 Factory::NewSharedFunctionInfo(
249 lit->name(),
250 lit->materialized_literal_count(),
251 code,
252 SerializedScopeInfo::Create(info.scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
254 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100255 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256
257 // Hint to the runtime system used when allocating space for initial
258 // property space by setting the expected number of properties for
259 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100260 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000261
262#ifdef ENABLE_DEBUGGER_SUPPORT
263 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100264 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000265#endif
266
Steve Block6ded16b2010-05-10 14:33:55 +0100267 live_edit_tracker.RecordFunctionInfo(result, lit);
268
269 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000270}
271
272
Steve Block6ded16b2010-05-10 14:33:55 +0100273Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
274 Handle<Object> script_name,
275 int line_offset,
276 int column_offset,
277 v8::Extension* extension,
278 ScriptDataImpl* input_pre_data,
279 Handle<Object> script_data,
280 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000281 int source_length = source->length();
282 Counters::total_load_size.Increment(source_length);
283 Counters::total_compile_size.Increment(source_length);
284
285 // The VM is in the COMPILER state until exiting this function.
286 VMState state(COMPILER);
287
288 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100289 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 if (extension == NULL) {
291 result = CompilationCache::LookupScript(source,
292 script_name,
293 line_offset,
294 column_offset);
295 }
296
297 if (result.is_null()) {
298 // No cache entry found. Do pre-parsing and compile the script.
299 ScriptDataImpl* pre_data = input_pre_data;
300 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100301 pre_data = PreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 }
303
304 // Create a script object describing the script to be compiled.
305 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000306 if (natives == NATIVES_CODE) {
307 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
308 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 if (!script_name.is_null()) {
310 script->set_name(*script_name);
311 script->set_line_offset(Smi::FromInt(line_offset));
312 script->set_column_offset(Smi::FromInt(column_offset));
313 }
314
Andrei Popescu402d9372010-02-26 13:31:12 +0000315 script->set_data(script_data.is_null() ? Heap::undefined_value()
316 : *script_data);
317
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100319 result = MakeFunctionInfo(true,
320 false,
321 DONT_VALIDATE_JSON,
322 script,
323 Handle<Context>::null(),
324 extension,
325 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000326 if (extension == NULL && !result.is_null()) {
327 CompilationCache::PutScript(source, result);
328 }
329
330 // Get rid of the pre-parsing data (if necessary).
331 if (input_pre_data == NULL && pre_data != NULL) {
332 delete pre_data;
333 }
334 }
335
336 if (result.is_null()) Top::ReportPendingMessages();
337 return result;
338}
339
340
Steve Block6ded16b2010-05-10 14:33:55 +0100341Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
342 Handle<Context> context,
343 bool is_global,
344 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 // Note that if validation is required then no path through this
346 // function is allowed to return a value without validating that
347 // the input is legal json.
348
349 int source_length = source->length();
350 Counters::total_eval_size.Increment(source_length);
351 Counters::total_compile_size.Increment(source_length);
352
353 // The VM is in the COMPILER state until exiting this function.
354 VMState state(COMPILER);
355
356 // Do a lookup in the compilation cache; if the entry is not there,
357 // invoke the compiler and add the result to the cache. If we're
358 // evaluating json we bypass the cache since we can't be sure a
359 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100360 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 if (validate == DONT_VALIDATE_JSON)
362 result = CompilationCache::LookupEval(source, context, is_global);
363
364 if (result.is_null()) {
365 // Create a script object describing the script to be compiled.
366 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100367 result = MakeFunctionInfo(is_global,
368 true,
369 validate,
370 script,
371 context,
372 NULL,
373 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 if (!result.is_null() && validate != VALIDATE_JSON) {
375 // For json it's unlikely that we'll ever see exactly the same
376 // string again so we don't use the compilation cache.
377 CompilationCache::PutEval(source, context, is_global, result);
378 }
379 }
380
381 return result;
382}
383
384
Leon Clarke4515c472010-02-03 11:58:03 +0000385bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
387
388 // The VM is in the COMPILER state until exiting this function.
389 VMState state(COMPILER);
390
391 PostponeInterruptsScope postpone;
392
393 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000394 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000396
397 int start_position = shared->start_position();
398 int end_position = shared->end_position();
399 bool is_expression = shared->is_expression();
400 Counters::total_compile_size.Increment(end_position - start_position);
401
402 // Generate the AST for the lazily compiled function. The AST may be
403 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000404 FunctionLiteral* lit = MakeLazyAST(info->script(),
405 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 start_position,
407 end_position,
408 is_expression);
409
410 // Check for parse errors.
411 if (lit == NULL) {
412 ASSERT(Top::has_pending_exception());
413 return false;
414 }
Andrei Popescu31002712010-02-23 13:46:05 +0000415 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000416
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 // Measure how long it takes to do the lazy compilation; only take
418 // the rest of the function into account to avoid overlap with the
419 // lazy parsing statistics.
420 HistogramTimerScope timer(&Counters::compile_lazy);
421
422 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000423 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000424
425 // Check for stack-overflow exception.
426 if (code.is_null()) {
427 Top::StackOverflow();
428 return false;
429 }
430
Steve Block6ded16b2010-05-10 14:33:55 +0100431 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
432 name,
433 Handle<String>(shared->inferred_name()),
434 start_position,
435 info->script(),
436 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000437
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100438 // Update the shared function info with the compiled code and the scope info.
439 // Please note, that the order of the sharedfunction initialization is
440 // important since set_scope_info might trigger a GC, causing the ASSERT
441 // below to be invalid if the code was flushed. By settting the code
442 // object last we avoid this.
443 shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 shared->set_code(*code);
445
446 // Set the expected number of properties for instances.
447 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
448
449 // Set the optimication hints after performing lazy compilation, as these are
450 // not set when the function is set up as a lazily compiled function.
451 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 lit->has_only_simple_this_property_assignments(),
453 *lit->this_property_assignments());
454
455 // Check the function has compiled code.
456 ASSERT(shared->is_compiled());
Iain Merrick75681382010-08-19 15:07:18 +0100457 shared->set_code_age(0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 return true;
459}
460
461
Steve Block6ded16b2010-05-10 14:33:55 +0100462Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
463 Handle<Script> script,
464 AstVisitor* caller) {
465 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000466#ifdef DEBUG
467 // We should not try to compile the same function literal more than
468 // once.
469 literal->mark_as_compiled();
470#endif
471
472 // Determine if the function can be lazily compiled. This is
473 // necessary to allow some of our builtin JS files to be lazily
474 // compiled. These builtins cannot be handled lazily by the parser,
475 // since we have to know if a function uses the special natives
476 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000477 bool allow_lazy = literal->AllowsLazyCompilation() &&
478 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000479
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100480 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
481
Steve Blockd0582a62009-12-15 09:54:21 +0000482 // Generate code
483 Handle<Code> code;
484 if (FLAG_lazy && allow_lazy) {
Iain Merrick75681382010-08-19 15:07:18 +0100485 code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
Steve Blockd0582a62009-12-15 09:54:21 +0000486 } else {
487 // The bodies of function literals have not yet been visited by
488 // the AST optimizer/analyzer.
489 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100490 return Handle<SharedFunctionInfo>::null();
491 }
492
493 if (literal->scope()->num_parameters() > 0 ||
494 literal->scope()->num_stack_slots()) {
495 AssignedVariablesAnalyzer ava(literal);
496 ava.Analyze();
497 if (ava.HasStackOverflow()) {
498 return Handle<SharedFunctionInfo>::null();
499 }
500 }
501
502 if (FLAG_use_flow_graph) {
503 FlowGraphBuilder builder;
504 FlowGraph* graph = builder.Build(literal);
505 USE(graph);
506
507#ifdef DEBUG
508 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
509 graph->PrintAsText(literal->name());
510 }
511#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000512 }
513
Leon Clarked91b9f72010-01-27 17:25:45 +0000514 // Generate code and return it. The way that the compilation mode
515 // is controlled by the command-line flags is described in
516 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000517 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000518
Leon Clarked91b9f72010-01-27 17:25:45 +0000519 bool is_run_once = literal->try_full_codegen();
Steve Blockd0582a62009-12-15 09:54:21 +0000520 bool is_compiled = false;
Leon Clarkef7060e22010-06-03 12:02:55 +0100521
522 if (AlwaysFullCompiler()) {
523 code = FullCodeGenerator::MakeCode(&info);
524 is_compiled = true;
525 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000526 FullCodeGenSyntaxChecker checker;
527 checker.Check(literal);
528 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000529 code = FullCodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000530 is_compiled = true;
531 }
532 }
533
534 if (!is_compiled) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000535 // We fall back to the classic V8 code generator.
Andrei Popescu31002712010-02-23 13:46:05 +0000536 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000537 }
538
539 // Check for stack-overflow exception.
540 if (code.is_null()) {
541 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100542 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000543 }
544
545 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100546 RecordFunctionCompilation(Logger::FUNCTION_TAG,
547 literal->name(),
548 literal->inferred_name(),
549 literal->start_position(),
550 script,
551 code);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100552 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000553 }
554
Steve Block6ded16b2010-05-10 14:33:55 +0100555 // Create a shared function info object.
556 Handle<SharedFunctionInfo> result =
557 Factory::NewSharedFunctionInfo(literal->name(),
558 literal->materialized_literal_count(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100559 code,
560 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100561 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000562
563 // Set the expected number of properties for instances and return
564 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100565 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000566 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100567 live_edit_tracker.RecordFunctionInfo(result, literal);
568 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000569}
570
571
572// Sets the function info on a function.
573// The start_position points to the first '(' character after the function name
574// in the full script source. When counting characters in the script source the
575// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100576void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000577 FunctionLiteral* lit,
578 bool is_toplevel,
579 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100580 function_info->set_length(lit->num_parameters());
581 function_info->set_formal_parameter_count(lit->num_parameters());
582 function_info->set_script(*script);
583 function_info->set_function_token_position(lit->function_token_position());
584 function_info->set_start_position(lit->start_position());
585 function_info->set_end_position(lit->end_position());
586 function_info->set_is_expression(lit->is_expression());
587 function_info->set_is_toplevel(is_toplevel);
588 function_info->set_inferred_name(*lit->inferred_name());
589 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000590 lit->has_only_simple_this_property_assignments(),
591 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100592 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100593 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000594}
595
596
Steve Block6ded16b2010-05-10 14:33:55 +0100597void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
598 Handle<String> name,
599 Handle<String> inferred_name,
600 int start_position,
601 Handle<Script> script,
602 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000603 // Log the code generation. If source information is available
604 // include script name and line number. Check explicitly whether
605 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100606 if (Logger::is_logging()
607 || OProfileAgent::is_enabled()
608 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000609 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
610 if (script->name()->IsString()) {
611 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100612 USE(line_num);
613 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
614 *code, *func_name,
615 String::cast(script->name()), line_num));
616 OPROFILE(CreateNativeCodeRegion(*func_name,
617 String::cast(script->name()),
618 line_num,
619 code->instruction_start(),
620 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000621 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100622 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
623 *code, *func_name));
624 OPROFILE(CreateNativeCodeRegion(*func_name,
625 code->instruction_start(),
626 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000627 }
628 }
629}
Andrei Popescu31002712010-02-23 13:46:05 +0000630
Steve Blocka7e24c12009-10-30 11:49:00 +0000631} } // namespace v8::internal