blob: d87d9da89bd55bd9d37b2b8d2027fe39c0f1f1da [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"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010043#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044
45namespace v8 {
46namespace internal {
47
Leon Clarkef7060e22010-06-03 12:02:55 +010048// For normal operation the syntax checker is used to determine whether to
49// use the full compiler for top level code or not. However if the flag
50// --always-full-compiler is specified or debugging is active the full
51// compiler will be used for all code.
52static bool AlwaysFullCompiler() {
53#ifdef ENABLE_DEBUGGER_SUPPORT
54 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
55#else
56 return FLAG_always_full_compiler;
57#endif
58}
59
Steve Block3ce2e202009-11-05 08:53:23 +000060
Andrei Popescu31002712010-02-23 13:46:05 +000061static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
62 FunctionLiteral* function = info->function();
63 ASSERT(function != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000064 // Rewrite the AST by introducing .result assignments where needed.
Steve Block6ded16b2010-05-10 14:33:55 +010065 if (!Rewriter::Process(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000066 // Signal a stack overflow by returning a null handle. The stack
67 // overflow exception will be thrown by the caller.
68 return Handle<Code>::null();
69 }
70
71 {
72 // Compute top scope and allocate variables. For lazy compilation
73 // the top scope only contains the single lazily compiled function,
74 // so this doesn't re-allocate variables repeatedly.
75 HistogramTimerScope timer(&Counters::variable_allocation);
Andrei Popescu31002712010-02-23 13:46:05 +000076 Scope* top = info->scope();
Steve Blocka7e24c12009-10-30 11:49:00 +000077 while (top->outer_scope() != NULL) top = top->outer_scope();
78 top->AllocateVariables(context);
79 }
80
81#ifdef DEBUG
82 if (Bootstrapper::IsActive() ?
83 FLAG_print_builtin_scopes :
84 FLAG_print_scopes) {
Andrei Popescu31002712010-02-23 13:46:05 +000085 info->scope()->Print();
Steve Blocka7e24c12009-10-30 11:49:00 +000086 }
87#endif
88
89 // Optimize the AST.
Andrei Popescu31002712010-02-23 13:46:05 +000090 if (!Rewriter::Optimize(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000091 // Signal a stack overflow by returning a null handle. The stack
92 // overflow exception will be thrown by the caller.
93 return Handle<Code>::null();
94 }
95
Steve Block6ded16b2010-05-10 14:33:55 +010096 if (function->scope()->num_parameters() > 0 ||
97 function->scope()->num_stack_slots()) {
98 AssignedVariablesAnalyzer ava(function);
99 ava.Analyze();
100 if (ava.HasStackOverflow()) {
101 return Handle<Code>::null();
102 }
103 }
104
105 if (FLAG_use_flow_graph) {
106 FlowGraphBuilder builder;
107 FlowGraph* graph = builder.Build(function);
108 USE(graph);
109
110#ifdef DEBUG
111 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
112 graph->PrintAsText(function->name());
113 }
114#endif
115 }
116
Leon Clarked91b9f72010-01-27 17:25:45 +0000117 // Generate code and return it. Code generator selection is governed by
118 // which backends are enabled and whether the function is considered
119 // run-once code or not:
120 //
121 // --full-compiler enables the dedicated backend for code we expect to be
122 // run once
123 // --fast-compiler enables a speculative optimizing backend (for
124 // non-run-once code)
125 //
126 // The normal choice of backend can be overridden with the flags
127 // --always-full-compiler and --always-fast-compiler, which are mutually
128 // incompatible.
129 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
130
Leon Clarke4515c472010-02-03 11:58:03 +0000131 Handle<SharedFunctionInfo> shared = info->shared_info();
Leon Clarked91b9f72010-01-27 17:25:45 +0000132 bool is_run_once = (shared.is_null())
Andrei Popescu31002712010-02-23 13:46:05 +0000133 ? info->scope()->is_global_scope()
Leon Clarked91b9f72010-01-27 17:25:45 +0000134 : (shared->is_toplevel() || shared->try_full_codegen());
135
Leon Clarkef7060e22010-06-03 12:02:55 +0100136 if (AlwaysFullCompiler()) {
137 return FullCodeGenerator::MakeCode(info);
138 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000139 FullCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000140 checker.Check(function);
Leon Clarked91b9f72010-01-27 17:25:45 +0000141 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000142 return FullCodeGenerator::MakeCode(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000143 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000144 } else if (FLAG_always_fast_compiler ||
145 (FLAG_fast_compiler && !is_run_once)) {
146 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000147 checker.Check(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000148 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000149 return FastCodeGenerator::MakeCode(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000150 }
Steve Block3ce2e202009-11-05 08:53:23 +0000151 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000152
Andrei Popescu31002712010-02-23 13:46:05 +0000153 return CodeGenerator::MakeCode(info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000154}
155
156
Steve Block6ded16b2010-05-10 14:33:55 +0100157#ifdef ENABLE_DEBUGGER_SUPPORT
158Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
159 Handle<Context> context = Handle<Context>::null();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100160 Handle<Code> code = MakeCode(context, info);
161 if (!info->shared_info().is_null()) {
162 info->shared_info()->set_scope_info(
163 *SerializedScopeInfo::Create(info->scope()));
164 }
165 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100166}
167#endif
168
169
170static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
171 bool is_eval,
172 Compiler::ValidationState validate,
173 Handle<Script> script,
174 Handle<Context> context,
175 v8::Extension* extension,
176 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
178
179 PostponeInterruptsScope postpone;
180
181 ASSERT(!i::Top::global_context().is_null());
182 script->set_context_data((*i::Top::global_context())->data());
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000185#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000186 if (is_eval || is_json) {
187 script->set_compilation_type(
188 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
189 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
190 // For eval scripts add information on the function from which eval was
191 // called.
192 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000193 StackTraceFrameIterator it;
194 if (!it.done()) {
195 script->set_eval_from_shared(
196 JSFunction::cast(it.frame()->function())->shared());
197 int offset = static_cast<int>(
198 it.frame()->pc() - it.frame()->code()->instruction_start());
199 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
200 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 }
202 }
203
204 // Notify debugger
205 Debugger::OnBeforeCompile(script);
206#endif
207
208 // Only allow non-global compiles for eval.
209 ASSERT(is_eval || is_global);
210
211 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000212 FunctionLiteral* lit =
213 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000214
Steve Block6ded16b2010-05-10 14:33:55 +0100215 LiveEditFunctionTracker live_edit_tracker(lit);
216
Steve Blocka7e24c12009-10-30 11:49:00 +0000217 // Check for parse errors.
218 if (lit == NULL) {
219 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100220 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000221 }
222
Steve Blocka7e24c12009-10-30 11:49:00 +0000223 // Measure how long it takes to do the compilation; only take the
224 // rest of the function into account to avoid overlap with the
225 // parsing statistics.
226 HistogramTimer* rate = is_eval
227 ? &Counters::compile_eval
228 : &Counters::compile;
229 HistogramTimerScope timer(rate);
230
231 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000232 CompilationInfo info(lit, script, is_eval);
233 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000234
235 // Check for stack-overflow exceptions.
236 if (code.is_null()) {
237 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100238 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000239 }
240
Steve Block6ded16b2010-05-10 14:33:55 +0100241 if (script->name()->IsString()) {
242 PROFILE(CodeCreateEvent(
243 is_eval ? Logger::EVAL_TAG :
244 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
245 *code, String::cast(script->name())));
246 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
247 code->instruction_start(),
248 code->instruction_size()));
249 } else {
250 PROFILE(CodeCreateEvent(
251 is_eval ? Logger::EVAL_TAG :
252 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
253 *code, ""));
254 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
255 code->instruction_start(),
256 code->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000258
259 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100260 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100261 Factory::NewSharedFunctionInfo(
262 lit->name(),
263 lit->materialized_literal_count(),
264 code,
265 SerializedScopeInfo::Create(info.scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000266
267 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100268 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000269
270 // Hint to the runtime system used when allocating space for initial
271 // property space by setting the expected number of properties for
272 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100273 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000274
275#ifdef ENABLE_DEBUGGER_SUPPORT
276 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100277 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000278#endif
279
Steve Block6ded16b2010-05-10 14:33:55 +0100280 live_edit_tracker.RecordFunctionInfo(result, lit);
281
282 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000283}
284
285
Steve Block6ded16b2010-05-10 14:33:55 +0100286Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
287 Handle<Object> script_name,
288 int line_offset,
289 int column_offset,
290 v8::Extension* extension,
291 ScriptDataImpl* input_pre_data,
292 Handle<Object> script_data,
293 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 int source_length = source->length();
295 Counters::total_load_size.Increment(source_length);
296 Counters::total_compile_size.Increment(source_length);
297
298 // The VM is in the COMPILER state until exiting this function.
299 VMState state(COMPILER);
300
301 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100302 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 if (extension == NULL) {
304 result = CompilationCache::LookupScript(source,
305 script_name,
306 line_offset,
307 column_offset);
308 }
309
310 if (result.is_null()) {
311 // No cache entry found. Do pre-parsing and compile the script.
312 ScriptDataImpl* pre_data = input_pre_data;
313 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100314 pre_data = PreParse(source, NULL, extension);
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 }
316
317 // Create a script object describing the script to be compiled.
318 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000319 if (natives == NATIVES_CODE) {
320 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
321 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 if (!script_name.is_null()) {
323 script->set_name(*script_name);
324 script->set_line_offset(Smi::FromInt(line_offset));
325 script->set_column_offset(Smi::FromInt(column_offset));
326 }
327
Andrei Popescu402d9372010-02-26 13:31:12 +0000328 script->set_data(script_data.is_null() ? Heap::undefined_value()
329 : *script_data);
330
Steve Blocka7e24c12009-10-30 11:49:00 +0000331 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100332 result = MakeFunctionInfo(true,
333 false,
334 DONT_VALIDATE_JSON,
335 script,
336 Handle<Context>::null(),
337 extension,
338 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 if (extension == NULL && !result.is_null()) {
340 CompilationCache::PutScript(source, result);
341 }
342
343 // Get rid of the pre-parsing data (if necessary).
344 if (input_pre_data == NULL && pre_data != NULL) {
345 delete pre_data;
346 }
347 }
348
349 if (result.is_null()) Top::ReportPendingMessages();
350 return result;
351}
352
353
Steve Block6ded16b2010-05-10 14:33:55 +0100354Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
355 Handle<Context> context,
356 bool is_global,
357 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 // Note that if validation is required then no path through this
359 // function is allowed to return a value without validating that
360 // the input is legal json.
361
362 int source_length = source->length();
363 Counters::total_eval_size.Increment(source_length);
364 Counters::total_compile_size.Increment(source_length);
365
366 // The VM is in the COMPILER state until exiting this function.
367 VMState state(COMPILER);
368
369 // Do a lookup in the compilation cache; if the entry is not there,
370 // invoke the compiler and add the result to the cache. If we're
371 // evaluating json we bypass the cache since we can't be sure a
372 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100373 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 if (validate == DONT_VALIDATE_JSON)
375 result = CompilationCache::LookupEval(source, context, is_global);
376
377 if (result.is_null()) {
378 // Create a script object describing the script to be compiled.
379 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100380 result = MakeFunctionInfo(is_global,
381 true,
382 validate,
383 script,
384 context,
385 NULL,
386 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 if (!result.is_null() && validate != VALIDATE_JSON) {
388 // For json it's unlikely that we'll ever see exactly the same
389 // string again so we don't use the compilation cache.
390 CompilationCache::PutEval(source, context, is_global, result);
391 }
392 }
393
394 return result;
395}
396
397
Leon Clarke4515c472010-02-03 11:58:03 +0000398bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
400
401 // The VM is in the COMPILER state until exiting this function.
402 VMState state(COMPILER);
403
404 PostponeInterruptsScope postpone;
405
406 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000407 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000408 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000409
410 int start_position = shared->start_position();
411 int end_position = shared->end_position();
412 bool is_expression = shared->is_expression();
413 Counters::total_compile_size.Increment(end_position - start_position);
414
415 // Generate the AST for the lazily compiled function. The AST may be
416 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000417 FunctionLiteral* lit = MakeLazyAST(info->script(),
418 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 start_position,
420 end_position,
421 is_expression);
422
423 // Check for parse errors.
424 if (lit == NULL) {
425 ASSERT(Top::has_pending_exception());
426 return false;
427 }
Andrei Popescu31002712010-02-23 13:46:05 +0000428 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000429
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 // Measure how long it takes to do the lazy compilation; only take
431 // the rest of the function into account to avoid overlap with the
432 // lazy parsing statistics.
433 HistogramTimerScope timer(&Counters::compile_lazy);
434
435 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000436 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000437
438 // Check for stack-overflow exception.
439 if (code.is_null()) {
440 Top::StackOverflow();
441 return false;
442 }
443
Steve Block6ded16b2010-05-10 14:33:55 +0100444 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
445 name,
446 Handle<String>(shared->inferred_name()),
447 start_position,
448 info->script(),
449 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000450
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100451 // Update the shared function info with the compiled code and the scope info.
452 // Please note, that the order of the sharedfunction initialization is
453 // important since set_scope_info might trigger a GC, causing the ASSERT
454 // below to be invalid if the code was flushed. By settting the code
455 // object last we avoid this.
456 shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 shared->set_code(*code);
458
459 // Set the expected number of properties for instances.
460 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
461
462 // Set the optimication hints after performing lazy compilation, as these are
463 // not set when the function is set up as a lazily compiled function.
464 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 lit->has_only_simple_this_property_assignments(),
466 *lit->this_property_assignments());
467
468 // Check the function has compiled code.
469 ASSERT(shared->is_compiled());
470 return true;
471}
472
473
Steve Block6ded16b2010-05-10 14:33:55 +0100474Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
475 Handle<Script> script,
476 AstVisitor* caller) {
477 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000478#ifdef DEBUG
479 // We should not try to compile the same function literal more than
480 // once.
481 literal->mark_as_compiled();
482#endif
483
484 // Determine if the function can be lazily compiled. This is
485 // necessary to allow some of our builtin JS files to be lazily
486 // compiled. These builtins cannot be handled lazily by the parser,
487 // since we have to know if a function uses the special natives
488 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000489 bool allow_lazy = literal->AllowsLazyCompilation() &&
490 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000491
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100492 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
493
Steve Blockd0582a62009-12-15 09:54:21 +0000494 // Generate code
495 Handle<Code> code;
496 if (FLAG_lazy && allow_lazy) {
497 code = ComputeLazyCompile(literal->num_parameters());
498 } else {
499 // The bodies of function literals have not yet been visited by
500 // the AST optimizer/analyzer.
501 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100502 return Handle<SharedFunctionInfo>::null();
503 }
504
505 if (literal->scope()->num_parameters() > 0 ||
506 literal->scope()->num_stack_slots()) {
507 AssignedVariablesAnalyzer ava(literal);
508 ava.Analyze();
509 if (ava.HasStackOverflow()) {
510 return Handle<SharedFunctionInfo>::null();
511 }
512 }
513
514 if (FLAG_use_flow_graph) {
515 FlowGraphBuilder builder;
516 FlowGraph* graph = builder.Build(literal);
517 USE(graph);
518
519#ifdef DEBUG
520 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
521 graph->PrintAsText(literal->name());
522 }
523#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000524 }
525
Leon Clarked91b9f72010-01-27 17:25:45 +0000526 // Generate code and return it. The way that the compilation mode
527 // is controlled by the command-line flags is described in
528 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000529 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000530
Leon Clarked91b9f72010-01-27 17:25:45 +0000531 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
532 bool is_run_once = literal->try_full_codegen();
Steve Blockd0582a62009-12-15 09:54:21 +0000533 bool is_compiled = false;
Leon Clarkef7060e22010-06-03 12:02:55 +0100534
535 if (AlwaysFullCompiler()) {
536 code = FullCodeGenerator::MakeCode(&info);
537 is_compiled = true;
538 } else if (FLAG_full_compiler && is_run_once) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000539 FullCodeGenSyntaxChecker checker;
540 checker.Check(literal);
541 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000542 code = FullCodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000543 is_compiled = true;
544 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000545 } else if (FLAG_always_fast_compiler ||
546 (FLAG_fast_compiler && !is_run_once)) {
Leon Clarke4515c472010-02-03 11:58:03 +0000547 // Since we are not lazily compiling we do not have a receiver to
548 // specialize for.
Leon Clarked91b9f72010-01-27 17:25:45 +0000549 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000550 checker.Check(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000551 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000552 code = FastCodeGenerator::MakeCode(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000553 is_compiled = true;
554 }
Steve Blockd0582a62009-12-15 09:54:21 +0000555 }
556
557 if (!is_compiled) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000558 // We fall back to the classic V8 code generator.
Andrei Popescu31002712010-02-23 13:46:05 +0000559 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000560 }
561
562 // Check for stack-overflow exception.
563 if (code.is_null()) {
564 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100565 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000566 }
567
568 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100569 RecordFunctionCompilation(Logger::FUNCTION_TAG,
570 literal->name(),
571 literal->inferred_name(),
572 literal->start_position(),
573 script,
574 code);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100575 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000576 }
577
Steve Block6ded16b2010-05-10 14:33:55 +0100578 // Create a shared function info object.
579 Handle<SharedFunctionInfo> result =
580 Factory::NewSharedFunctionInfo(literal->name(),
581 literal->materialized_literal_count(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100582 code,
583 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100584 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000585
586 // Set the expected number of properties for instances and return
587 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100588 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000589 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100590 live_edit_tracker.RecordFunctionInfo(result, literal);
591 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000592}
593
594
595// Sets the function info on a function.
596// The start_position points to the first '(' character after the function name
597// in the full script source. When counting characters in the script source the
598// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100599void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000600 FunctionLiteral* lit,
601 bool is_toplevel,
602 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100603 function_info->set_length(lit->num_parameters());
604 function_info->set_formal_parameter_count(lit->num_parameters());
605 function_info->set_script(*script);
606 function_info->set_function_token_position(lit->function_token_position());
607 function_info->set_start_position(lit->start_position());
608 function_info->set_end_position(lit->end_position());
609 function_info->set_is_expression(lit->is_expression());
610 function_info->set_is_toplevel(is_toplevel);
611 function_info->set_inferred_name(*lit->inferred_name());
612 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000613 lit->has_only_simple_this_property_assignments(),
614 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100615 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100616 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000617}
618
619
Steve Block6ded16b2010-05-10 14:33:55 +0100620void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
621 Handle<String> name,
622 Handle<String> inferred_name,
623 int start_position,
624 Handle<Script> script,
625 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000626 // Log the code generation. If source information is available
627 // include script name and line number. Check explicitly whether
628 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100629 if (Logger::is_logging()
630 || OProfileAgent::is_enabled()
631 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000632 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
633 if (script->name()->IsString()) {
634 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100635 USE(line_num);
636 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
637 *code, *func_name,
638 String::cast(script->name()), line_num));
639 OPROFILE(CreateNativeCodeRegion(*func_name,
640 String::cast(script->name()),
641 line_num,
642 code->instruction_start(),
643 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000644 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100645 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
646 *code, *func_name));
647 OPROFILE(CreateNativeCodeRegion(*func_name,
648 code->instruction_start(),
649 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000650 }
651 }
652}
Andrei Popescu31002712010-02-23 13:46:05 +0000653
Steve Blocka7e24c12009-10-30 11:49:00 +0000654} } // namespace v8::internal