blob: ca92ed9213833811d7450a7eac0e60c10b392195 [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 Clarkeeab96aa2010-01-27 16:31:12 +000036#include "fast-codegen.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "flow-graph.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000038#include "full-codegen.h"
Steve Block6ded16b2010-05-10 14:33:55 +010039#include "liveedit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "oprofile-agent.h"
41#include "rewriter.h"
42#include "scopes.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
122 // --fast-compiler enables a speculative optimizing backend (for
123 // non-run-once code)
124 //
125 // The normal choice of backend can be overridden with the flags
126 // --always-full-compiler and --always-fast-compiler, which are mutually
127 // incompatible.
128 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
129
Leon Clarke4515c472010-02-03 11:58:03 +0000130 Handle<SharedFunctionInfo> shared = info->shared_info();
Leon Clarked91b9f72010-01-27 17:25:45 +0000131 bool is_run_once = (shared.is_null())
Andrei Popescu31002712010-02-23 13:46:05 +0000132 ? info->scope()->is_global_scope()
Leon Clarked91b9f72010-01-27 17:25:45 +0000133 : (shared->is_toplevel() || shared->try_full_codegen());
134
Leon Clarkef7060e22010-06-03 12:02:55 +0100135 if (AlwaysFullCompiler()) {
136 return FullCodeGenerator::MakeCode(info);
137 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000138 FullCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000139 checker.Check(function);
Leon Clarked91b9f72010-01-27 17:25:45 +0000140 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000141 return FullCodeGenerator::MakeCode(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000142 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000143 } else if (FLAG_always_fast_compiler ||
144 (FLAG_fast_compiler && !is_run_once)) {
145 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000146 checker.Check(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000147 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000148 return FastCodeGenerator::MakeCode(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000149 }
Steve Block3ce2e202009-11-05 08:53:23 +0000150 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000151
Andrei Popescu31002712010-02-23 13:46:05 +0000152 return CodeGenerator::MakeCode(info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000153}
154
155
Steve Block6ded16b2010-05-10 14:33:55 +0100156#ifdef ENABLE_DEBUGGER_SUPPORT
157Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
158 Handle<Context> context = Handle<Context>::null();
159 return MakeCode(context, info);
160}
161#endif
162
163
164static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
165 bool is_eval,
166 Compiler::ValidationState validate,
167 Handle<Script> script,
168 Handle<Context> context,
169 v8::Extension* extension,
170 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
172
173 PostponeInterruptsScope postpone;
174
175 ASSERT(!i::Top::global_context().is_null());
176 script->set_context_data((*i::Top::global_context())->data());
177
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000179#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 if (is_eval || is_json) {
181 script->set_compilation_type(
182 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
183 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
184 // For eval scripts add information on the function from which eval was
185 // called.
186 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000187 StackTraceFrameIterator it;
188 if (!it.done()) {
189 script->set_eval_from_shared(
190 JSFunction::cast(it.frame()->function())->shared());
191 int offset = static_cast<int>(
192 it.frame()->pc() - it.frame()->code()->instruction_start());
193 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
194 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 }
196 }
197
198 // Notify debugger
199 Debugger::OnBeforeCompile(script);
200#endif
201
202 // Only allow non-global compiles for eval.
203 ASSERT(is_eval || is_global);
204
205 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000206 FunctionLiteral* lit =
207 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000208
Steve Block6ded16b2010-05-10 14:33:55 +0100209 LiveEditFunctionTracker live_edit_tracker(lit);
210
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 // Check for parse errors.
212 if (lit == NULL) {
213 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100214 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 }
216
Steve Blocka7e24c12009-10-30 11:49:00 +0000217 // Measure how long it takes to do the compilation; only take the
218 // rest of the function into account to avoid overlap with the
219 // parsing statistics.
220 HistogramTimer* rate = is_eval
221 ? &Counters::compile_eval
222 : &Counters::compile;
223 HistogramTimerScope timer(rate);
224
225 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000226 CompilationInfo info(lit, script, is_eval);
227 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000228
229 // Check for stack-overflow exceptions.
230 if (code.is_null()) {
231 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100232 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 }
234
Steve Block6ded16b2010-05-10 14:33:55 +0100235 if (script->name()->IsString()) {
236 PROFILE(CodeCreateEvent(
237 is_eval ? Logger::EVAL_TAG :
238 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
239 *code, String::cast(script->name())));
240 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
241 code->instruction_start(),
242 code->instruction_size()));
243 } else {
244 PROFILE(CodeCreateEvent(
245 is_eval ? Logger::EVAL_TAG :
246 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
247 *code, ""));
248 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
249 code->instruction_start(),
250 code->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000252
253 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100254 Handle<SharedFunctionInfo> result =
255 Factory::NewSharedFunctionInfo(lit->name(),
256 lit->materialized_literal_count(),
257 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000258
259 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100260 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000261
262 // Hint to the runtime system used when allocating space for initial
263 // property space by setting the expected number of properties for
264 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100265 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000266
267#ifdef ENABLE_DEBUGGER_SUPPORT
268 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100269 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270#endif
271
Steve Block6ded16b2010-05-10 14:33:55 +0100272 live_edit_tracker.RecordFunctionInfo(result, lit);
273
274 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000275}
276
277
278static StaticResource<SafeStringInputBuffer> safe_string_input_buffer;
279
280
Steve Block6ded16b2010-05-10 14:33:55 +0100281Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
282 Handle<Object> script_name,
283 int line_offset,
284 int column_offset,
285 v8::Extension* extension,
286 ScriptDataImpl* input_pre_data,
287 Handle<Object> script_data,
288 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 int source_length = source->length();
290 Counters::total_load_size.Increment(source_length);
291 Counters::total_compile_size.Increment(source_length);
292
293 // The VM is in the COMPILER state until exiting this function.
294 VMState state(COMPILER);
295
296 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100297 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000298 if (extension == NULL) {
299 result = CompilationCache::LookupScript(source,
300 script_name,
301 line_offset,
302 column_offset);
303 }
304
305 if (result.is_null()) {
306 // No cache entry found. Do pre-parsing and compile the script.
307 ScriptDataImpl* pre_data = input_pre_data;
308 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
309 Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
310 buf->Reset(source.location());
311 pre_data = PreParse(source, buf.value(), extension);
312 }
313
314 // Create a script object describing the script to be compiled.
315 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000316 if (natives == NATIVES_CODE) {
317 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
318 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 if (!script_name.is_null()) {
320 script->set_name(*script_name);
321 script->set_line_offset(Smi::FromInt(line_offset));
322 script->set_column_offset(Smi::FromInt(column_offset));
323 }
324
Andrei Popescu402d9372010-02-26 13:31:12 +0000325 script->set_data(script_data.is_null() ? Heap::undefined_value()
326 : *script_data);
327
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100329 result = MakeFunctionInfo(true,
330 false,
331 DONT_VALIDATE_JSON,
332 script,
333 Handle<Context>::null(),
334 extension,
335 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000336 if (extension == NULL && !result.is_null()) {
337 CompilationCache::PutScript(source, result);
338 }
339
340 // Get rid of the pre-parsing data (if necessary).
341 if (input_pre_data == NULL && pre_data != NULL) {
342 delete pre_data;
343 }
344 }
345
346 if (result.is_null()) Top::ReportPendingMessages();
347 return result;
348}
349
350
Steve Block6ded16b2010-05-10 14:33:55 +0100351Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
352 Handle<Context> context,
353 bool is_global,
354 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 // Note that if validation is required then no path through this
356 // function is allowed to return a value without validating that
357 // the input is legal json.
358
359 int source_length = source->length();
360 Counters::total_eval_size.Increment(source_length);
361 Counters::total_compile_size.Increment(source_length);
362
363 // The VM is in the COMPILER state until exiting this function.
364 VMState state(COMPILER);
365
366 // Do a lookup in the compilation cache; if the entry is not there,
367 // invoke the compiler and add the result to the cache. If we're
368 // evaluating json we bypass the cache since we can't be sure a
369 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100370 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 if (validate == DONT_VALIDATE_JSON)
372 result = CompilationCache::LookupEval(source, context, is_global);
373
374 if (result.is_null()) {
375 // Create a script object describing the script to be compiled.
376 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100377 result = MakeFunctionInfo(is_global,
378 true,
379 validate,
380 script,
381 context,
382 NULL,
383 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 if (!result.is_null() && validate != VALIDATE_JSON) {
385 // For json it's unlikely that we'll ever see exactly the same
386 // string again so we don't use the compilation cache.
387 CompilationCache::PutEval(source, context, is_global, result);
388 }
389 }
390
391 return result;
392}
393
394
Leon Clarke4515c472010-02-03 11:58:03 +0000395bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
397
398 // The VM is in the COMPILER state until exiting this function.
399 VMState state(COMPILER);
400
401 PostponeInterruptsScope postpone;
402
403 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000404 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000406
407 int start_position = shared->start_position();
408 int end_position = shared->end_position();
409 bool is_expression = shared->is_expression();
410 Counters::total_compile_size.Increment(end_position - start_position);
411
412 // Generate the AST for the lazily compiled function. The AST may be
413 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000414 FunctionLiteral* lit = MakeLazyAST(info->script(),
415 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 start_position,
417 end_position,
418 is_expression);
419
420 // Check for parse errors.
421 if (lit == NULL) {
422 ASSERT(Top::has_pending_exception());
423 return false;
424 }
Andrei Popescu31002712010-02-23 13:46:05 +0000425 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 // Measure how long it takes to do the lazy compilation; only take
428 // the rest of the function into account to avoid overlap with the
429 // lazy parsing statistics.
430 HistogramTimerScope timer(&Counters::compile_lazy);
431
432 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000433 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000434
435 // Check for stack-overflow exception.
436 if (code.is_null()) {
437 Top::StackOverflow();
438 return false;
439 }
440
Steve Block6ded16b2010-05-10 14:33:55 +0100441 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
442 name,
443 Handle<String>(shared->inferred_name()),
444 start_position,
445 info->script(),
446 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447
448 // Update the shared function info with the compiled code.
449 shared->set_code(*code);
450
451 // Set the expected number of properties for instances.
452 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
453
454 // Set the optimication hints after performing lazy compilation, as these are
455 // not set when the function is set up as a lazily compiled function.
456 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 lit->has_only_simple_this_property_assignments(),
458 *lit->this_property_assignments());
459
460 // Check the function has compiled code.
461 ASSERT(shared->is_compiled());
462 return true;
463}
464
465
Steve Block6ded16b2010-05-10 14:33:55 +0100466Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
467 Handle<Script> script,
468 AstVisitor* caller) {
469 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000470#ifdef DEBUG
471 // We should not try to compile the same function literal more than
472 // once.
473 literal->mark_as_compiled();
474#endif
475
476 // Determine if the function can be lazily compiled. This is
477 // necessary to allow some of our builtin JS files to be lazily
478 // compiled. These builtins cannot be handled lazily by the parser,
479 // since we have to know if a function uses the special natives
480 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000481 bool allow_lazy = literal->AllowsLazyCompilation() &&
482 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000483
484 // Generate code
485 Handle<Code> code;
486 if (FLAG_lazy && allow_lazy) {
487 code = ComputeLazyCompile(literal->num_parameters());
488 } else {
489 // The bodies of function literals have not yet been visited by
490 // the AST optimizer/analyzer.
491 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100492 return Handle<SharedFunctionInfo>::null();
493 }
494
495 if (literal->scope()->num_parameters() > 0 ||
496 literal->scope()->num_stack_slots()) {
497 AssignedVariablesAnalyzer ava(literal);
498 ava.Analyze();
499 if (ava.HasStackOverflow()) {
500 return Handle<SharedFunctionInfo>::null();
501 }
502 }
503
504 if (FLAG_use_flow_graph) {
505 FlowGraphBuilder builder;
506 FlowGraph* graph = builder.Build(literal);
507 USE(graph);
508
509#ifdef DEBUG
510 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
511 graph->PrintAsText(literal->name());
512 }
513#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000514 }
515
Leon Clarked91b9f72010-01-27 17:25:45 +0000516 // Generate code and return it. The way that the compilation mode
517 // is controlled by the command-line flags is described in
518 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000519 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000520
Leon Clarked91b9f72010-01-27 17:25:45 +0000521 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
522 bool is_run_once = literal->try_full_codegen();
Steve Blockd0582a62009-12-15 09:54:21 +0000523 bool is_compiled = false;
Leon Clarkef7060e22010-06-03 12:02:55 +0100524
525 if (AlwaysFullCompiler()) {
526 code = FullCodeGenerator::MakeCode(&info);
527 is_compiled = true;
528 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000529 FullCodeGenSyntaxChecker checker;
530 checker.Check(literal);
531 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000532 code = FullCodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000533 is_compiled = true;
534 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000535 } else if (FLAG_always_fast_compiler ||
536 (FLAG_fast_compiler && !is_run_once)) {
Leon Clarke4515c472010-02-03 11:58:03 +0000537 // Since we are not lazily compiling we do not have a receiver to
538 // specialize for.
Leon Clarked91b9f72010-01-27 17:25:45 +0000539 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000540 checker.Check(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000541 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000542 code = FastCodeGenerator::MakeCode(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000543 is_compiled = true;
544 }
Steve Blockd0582a62009-12-15 09:54:21 +0000545 }
546
547 if (!is_compiled) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000548 // We fall back to the classic V8 code generator.
Andrei Popescu31002712010-02-23 13:46:05 +0000549 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000550 }
551
552 // Check for stack-overflow exception.
553 if (code.is_null()) {
554 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100555 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000556 }
557
558 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100559 RecordFunctionCompilation(Logger::FUNCTION_TAG,
560 literal->name(),
561 literal->inferred_name(),
562 literal->start_position(),
563 script,
564 code);
Steve Blockd0582a62009-12-15 09:54:21 +0000565 }
566
Steve Block6ded16b2010-05-10 14:33:55 +0100567 // Create a shared function info object.
568 Handle<SharedFunctionInfo> result =
569 Factory::NewSharedFunctionInfo(literal->name(),
570 literal->materialized_literal_count(),
571 code);
572 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000573
574 // Set the expected number of properties for instances and return
575 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100576 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000577 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100578 live_edit_tracker.RecordFunctionInfo(result, literal);
579 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000580}
581
582
583// Sets the function info on a function.
584// The start_position points to the first '(' character after the function name
585// in the full script source. When counting characters in the script source the
586// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100587void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000588 FunctionLiteral* lit,
589 bool is_toplevel,
590 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100591 function_info->set_length(lit->num_parameters());
592 function_info->set_formal_parameter_count(lit->num_parameters());
593 function_info->set_script(*script);
594 function_info->set_function_token_position(lit->function_token_position());
595 function_info->set_start_position(lit->start_position());
596 function_info->set_end_position(lit->end_position());
597 function_info->set_is_expression(lit->is_expression());
598 function_info->set_is_toplevel(is_toplevel);
599 function_info->set_inferred_name(*lit->inferred_name());
600 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000601 lit->has_only_simple_this_property_assignments(),
602 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100603 function_info->set_try_full_codegen(lit->try_full_codegen());
Steve Blockd0582a62009-12-15 09:54:21 +0000604}
605
606
Steve Block6ded16b2010-05-10 14:33:55 +0100607void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
608 Handle<String> name,
609 Handle<String> inferred_name,
610 int start_position,
611 Handle<Script> script,
612 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000613 // Log the code generation. If source information is available
614 // include script name and line number. Check explicitly whether
615 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100616 if (Logger::is_logging()
617 || OProfileAgent::is_enabled()
618 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000619 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
620 if (script->name()->IsString()) {
621 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100622 USE(line_num);
623 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
624 *code, *func_name,
625 String::cast(script->name()), line_num));
626 OPROFILE(CreateNativeCodeRegion(*func_name,
627 String::cast(script->name()),
628 line_num,
629 code->instruction_start(),
630 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000631 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100632 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
633 *code, *func_name));
634 OPROFILE(CreateNativeCodeRegion(*func_name,
635 code->instruction_start(),
636 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000637 }
638 }
639}
Andrei Popescu31002712010-02-23 13:46:05 +0000640
Steve Blocka7e24c12009-10-30 11:49:00 +0000641} } // namespace v8::internal