blob: 901f2186a05c341504db4856f4f9f1a99519e5dc [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
Steve Block3ce2e202009-11-05 08:53:23 +000047
Andrei Popescu31002712010-02-23 13:46:05 +000048static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
49 FunctionLiteral* function = info->function();
50 ASSERT(function != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000051 // Rewrite the AST by introducing .result assignments where needed.
Steve Block6ded16b2010-05-10 14:33:55 +010052 if (!Rewriter::Process(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000053 // Signal a stack overflow by returning a null handle. The stack
54 // overflow exception will be thrown by the caller.
55 return Handle<Code>::null();
56 }
57
58 {
59 // Compute top scope and allocate variables. For lazy compilation
60 // the top scope only contains the single lazily compiled function,
61 // so this doesn't re-allocate variables repeatedly.
62 HistogramTimerScope timer(&Counters::variable_allocation);
Andrei Popescu31002712010-02-23 13:46:05 +000063 Scope* top = info->scope();
Steve Blocka7e24c12009-10-30 11:49:00 +000064 while (top->outer_scope() != NULL) top = top->outer_scope();
65 top->AllocateVariables(context);
66 }
67
68#ifdef DEBUG
69 if (Bootstrapper::IsActive() ?
70 FLAG_print_builtin_scopes :
71 FLAG_print_scopes) {
Andrei Popescu31002712010-02-23 13:46:05 +000072 info->scope()->Print();
Steve Blocka7e24c12009-10-30 11:49:00 +000073 }
74#endif
75
76 // Optimize the AST.
Andrei Popescu31002712010-02-23 13:46:05 +000077 if (!Rewriter::Optimize(function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000078 // Signal a stack overflow by returning a null handle. The stack
79 // overflow exception will be thrown by the caller.
80 return Handle<Code>::null();
81 }
82
Steve Block6ded16b2010-05-10 14:33:55 +010083 if (function->scope()->num_parameters() > 0 ||
84 function->scope()->num_stack_slots()) {
85 AssignedVariablesAnalyzer ava(function);
86 ava.Analyze();
87 if (ava.HasStackOverflow()) {
88 return Handle<Code>::null();
89 }
90 }
91
92 if (FLAG_use_flow_graph) {
93 FlowGraphBuilder builder;
94 FlowGraph* graph = builder.Build(function);
95 USE(graph);
96
97#ifdef DEBUG
98 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
99 graph->PrintAsText(function->name());
100 }
101#endif
102 }
103
Leon Clarked91b9f72010-01-27 17:25:45 +0000104 // Generate code and return it. Code generator selection is governed by
105 // which backends are enabled and whether the function is considered
106 // run-once code or not:
107 //
108 // --full-compiler enables the dedicated backend for code we expect to be
109 // run once
110 // --fast-compiler enables a speculative optimizing backend (for
111 // non-run-once code)
112 //
113 // The normal choice of backend can be overridden with the flags
114 // --always-full-compiler and --always-fast-compiler, which are mutually
115 // incompatible.
116 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
117
Leon Clarke4515c472010-02-03 11:58:03 +0000118 Handle<SharedFunctionInfo> shared = info->shared_info();
Leon Clarked91b9f72010-01-27 17:25:45 +0000119 bool is_run_once = (shared.is_null())
Andrei Popescu31002712010-02-23 13:46:05 +0000120 ? info->scope()->is_global_scope()
Leon Clarked91b9f72010-01-27 17:25:45 +0000121 : (shared->is_toplevel() || shared->try_full_codegen());
122
123 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) {
124 FullCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000125 checker.Check(function);
Leon Clarked91b9f72010-01-27 17:25:45 +0000126 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000127 return FullCodeGenerator::MakeCode(info);
Steve Block3ce2e202009-11-05 08:53:23 +0000128 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000129 } else if (FLAG_always_fast_compiler ||
130 (FLAG_fast_compiler && !is_run_once)) {
131 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000132 checker.Check(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000133 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000134 return FastCodeGenerator::MakeCode(info);
Leon Clarke4515c472010-02-03 11:58:03 +0000135 }
Steve Block3ce2e202009-11-05 08:53:23 +0000136 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000137
Andrei Popescu31002712010-02-23 13:46:05 +0000138 return CodeGenerator::MakeCode(info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000139}
140
141
Steve Block6ded16b2010-05-10 14:33:55 +0100142#ifdef ENABLE_DEBUGGER_SUPPORT
143Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
144 Handle<Context> context = Handle<Context>::null();
145 return MakeCode(context, info);
146}
147#endif
148
149
150static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
151 bool is_eval,
152 Compiler::ValidationState validate,
153 Handle<Script> script,
154 Handle<Context> context,
155 v8::Extension* extension,
156 ScriptDataImpl* pre_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000157 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
158
159 PostponeInterruptsScope postpone;
160
161 ASSERT(!i::Top::global_context().is_null());
162 script->set_context_data((*i::Top::global_context())->data());
163
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 bool is_json = (validate == Compiler::VALIDATE_JSON);
Leon Clarke4515c472010-02-03 11:58:03 +0000165#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 if (is_eval || is_json) {
167 script->set_compilation_type(
168 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
169 Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
170 // For eval scripts add information on the function from which eval was
171 // called.
172 if (is_eval) {
Leon Clarke4515c472010-02-03 11:58:03 +0000173 StackTraceFrameIterator it;
174 if (!it.done()) {
175 script->set_eval_from_shared(
176 JSFunction::cast(it.frame()->function())->shared());
177 int offset = static_cast<int>(
178 it.frame()->pc() - it.frame()->code()->instruction_start());
179 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
180 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 }
182 }
183
184 // Notify debugger
185 Debugger::OnBeforeCompile(script);
186#endif
187
188 // Only allow non-global compiles for eval.
189 ASSERT(is_eval || is_global);
190
191 // Build AST.
Leon Clarke4515c472010-02-03 11:58:03 +0000192 FunctionLiteral* lit =
193 MakeAST(is_global, script, extension, pre_data, is_json);
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
Steve Block6ded16b2010-05-10 14:33:55 +0100195 LiveEditFunctionTracker live_edit_tracker(lit);
196
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 // Check for parse errors.
198 if (lit == NULL) {
199 ASSERT(Top::has_pending_exception());
Steve Block6ded16b2010-05-10 14:33:55 +0100200 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 }
202
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 // Measure how long it takes to do the compilation; only take the
204 // rest of the function into account to avoid overlap with the
205 // parsing statistics.
206 HistogramTimer* rate = is_eval
207 ? &Counters::compile_eval
208 : &Counters::compile;
209 HistogramTimerScope timer(rate);
210
211 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000212 CompilationInfo info(lit, script, is_eval);
213 Handle<Code> code = MakeCode(context, &info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000214
215 // Check for stack-overflow exceptions.
216 if (code.is_null()) {
217 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100218 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 }
220
Steve Block6ded16b2010-05-10 14:33:55 +0100221 if (script->name()->IsString()) {
222 PROFILE(CodeCreateEvent(
223 is_eval ? Logger::EVAL_TAG :
224 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
225 *code, String::cast(script->name())));
226 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
227 code->instruction_start(),
228 code->instruction_size()));
229 } else {
230 PROFILE(CodeCreateEvent(
231 is_eval ? Logger::EVAL_TAG :
232 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
233 *code, ""));
234 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
235 code->instruction_start(),
236 code->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000238
239 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100240 Handle<SharedFunctionInfo> result =
241 Factory::NewSharedFunctionInfo(lit->name(),
242 lit->materialized_literal_count(),
243 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000244
245 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100246 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000247
248 // Hint to the runtime system used when allocating space for initial
249 // property space by setting the expected number of properties for
250 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100251 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000252
253#ifdef ENABLE_DEBUGGER_SUPPORT
254 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100255 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256#endif
257
Steve Block6ded16b2010-05-10 14:33:55 +0100258 live_edit_tracker.RecordFunctionInfo(result, lit);
259
260 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000261}
262
263
264static StaticResource<SafeStringInputBuffer> safe_string_input_buffer;
265
266
Steve Block6ded16b2010-05-10 14:33:55 +0100267Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
268 Handle<Object> script_name,
269 int line_offset,
270 int column_offset,
271 v8::Extension* extension,
272 ScriptDataImpl* input_pre_data,
273 Handle<Object> script_data,
274 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 int source_length = source->length();
276 Counters::total_load_size.Increment(source_length);
277 Counters::total_compile_size.Increment(source_length);
278
279 // The VM is in the COMPILER state until exiting this function.
280 VMState state(COMPILER);
281
282 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100283 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 if (extension == NULL) {
285 result = CompilationCache::LookupScript(source,
286 script_name,
287 line_offset,
288 column_offset);
289 }
290
291 if (result.is_null()) {
292 // No cache entry found. Do pre-parsing and compile the script.
293 ScriptDataImpl* pre_data = input_pre_data;
294 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
295 Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
296 buf->Reset(source.location());
297 pre_data = PreParse(source, buf.value(), extension);
298 }
299
300 // Create a script object describing the script to be compiled.
301 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000302 if (natives == NATIVES_CODE) {
303 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
304 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 if (!script_name.is_null()) {
306 script->set_name(*script_name);
307 script->set_line_offset(Smi::FromInt(line_offset));
308 script->set_column_offset(Smi::FromInt(column_offset));
309 }
310
Andrei Popescu402d9372010-02-26 13:31:12 +0000311 script->set_data(script_data.is_null() ? Heap::undefined_value()
312 : *script_data);
313
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 // Compile the function and add it to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100315 result = MakeFunctionInfo(true,
316 false,
317 DONT_VALIDATE_JSON,
318 script,
319 Handle<Context>::null(),
320 extension,
321 pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 if (extension == NULL && !result.is_null()) {
323 CompilationCache::PutScript(source, result);
324 }
325
326 // Get rid of the pre-parsing data (if necessary).
327 if (input_pre_data == NULL && pre_data != NULL) {
328 delete pre_data;
329 }
330 }
331
332 if (result.is_null()) Top::ReportPendingMessages();
333 return result;
334}
335
336
Steve Block6ded16b2010-05-10 14:33:55 +0100337Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
338 Handle<Context> context,
339 bool is_global,
340 ValidationState validate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 // Note that if validation is required then no path through this
342 // function is allowed to return a value without validating that
343 // the input is legal json.
344
345 int source_length = source->length();
346 Counters::total_eval_size.Increment(source_length);
347 Counters::total_compile_size.Increment(source_length);
348
349 // The VM is in the COMPILER state until exiting this function.
350 VMState state(COMPILER);
351
352 // Do a lookup in the compilation cache; if the entry is not there,
353 // invoke the compiler and add the result to the cache. If we're
354 // evaluating json we bypass the cache since we can't be sure a
355 // potential value in the cache has been validated.
Steve Block6ded16b2010-05-10 14:33:55 +0100356 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000357 if (validate == DONT_VALIDATE_JSON)
358 result = CompilationCache::LookupEval(source, context, is_global);
359
360 if (result.is_null()) {
361 // Create a script object describing the script to be compiled.
362 Handle<Script> script = Factory::NewScript(source);
Steve Block6ded16b2010-05-10 14:33:55 +0100363 result = MakeFunctionInfo(is_global,
364 true,
365 validate,
366 script,
367 context,
368 NULL,
369 NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 if (!result.is_null() && validate != VALIDATE_JSON) {
371 // For json it's unlikely that we'll ever see exactly the same
372 // string again so we don't use the compilation cache.
373 CompilationCache::PutEval(source, context, is_global, result);
374 }
375 }
376
377 return result;
378}
379
380
Leon Clarke4515c472010-02-03 11:58:03 +0000381bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
383
384 // The VM is in the COMPILER state until exiting this function.
385 VMState state(COMPILER);
386
387 PostponeInterruptsScope postpone;
388
389 // Compute name, source code and script data.
Leon Clarke4515c472010-02-03 11:58:03 +0000390 Handle<SharedFunctionInfo> shared = info->shared_info();
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 Handle<String> name(String::cast(shared->name()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000392
393 int start_position = shared->start_position();
394 int end_position = shared->end_position();
395 bool is_expression = shared->is_expression();
396 Counters::total_compile_size.Increment(end_position - start_position);
397
398 // Generate the AST for the lazily compiled function. The AST may be
399 // NULL in case of parser stack overflow.
Andrei Popescu31002712010-02-23 13:46:05 +0000400 FunctionLiteral* lit = MakeLazyAST(info->script(),
401 name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 start_position,
403 end_position,
404 is_expression);
405
406 // Check for parse errors.
407 if (lit == NULL) {
408 ASSERT(Top::has_pending_exception());
409 return false;
410 }
Andrei Popescu31002712010-02-23 13:46:05 +0000411 info->set_function(lit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 // Measure how long it takes to do the lazy compilation; only take
414 // the rest of the function into account to avoid overlap with the
415 // lazy parsing statistics.
416 HistogramTimerScope timer(&Counters::compile_lazy);
417
418 // Compile the code.
Andrei Popescu31002712010-02-23 13:46:05 +0000419 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000420
421 // Check for stack-overflow exception.
422 if (code.is_null()) {
423 Top::StackOverflow();
424 return false;
425 }
426
Steve Block6ded16b2010-05-10 14:33:55 +0100427 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
428 name,
429 Handle<String>(shared->inferred_name()),
430 start_position,
431 info->script(),
432 code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000433
434 // Update the shared function info with the compiled code.
435 shared->set_code(*code);
436
437 // Set the expected number of properties for instances.
438 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
439
440 // Set the optimication hints after performing lazy compilation, as these are
441 // not set when the function is set up as a lazily compiled function.
442 shared->SetThisPropertyAssignmentsInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 lit->has_only_simple_this_property_assignments(),
444 *lit->this_property_assignments());
445
446 // Check the function has compiled code.
447 ASSERT(shared->is_compiled());
448 return true;
449}
450
451
Steve Block6ded16b2010-05-10 14:33:55 +0100452Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
453 Handle<Script> script,
454 AstVisitor* caller) {
455 LiveEditFunctionTracker live_edit_tracker(literal);
Steve Blockd0582a62009-12-15 09:54:21 +0000456#ifdef DEBUG
457 // We should not try to compile the same function literal more than
458 // once.
459 literal->mark_as_compiled();
460#endif
461
462 // Determine if the function can be lazily compiled. This is
463 // necessary to allow some of our builtin JS files to be lazily
464 // compiled. These builtins cannot be handled lazily by the parser,
465 // since we have to know if a function uses the special natives
466 // syntax, which is something the parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000467 bool allow_lazy = literal->AllowsLazyCompilation() &&
468 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000469
470 // Generate code
471 Handle<Code> code;
472 if (FLAG_lazy && allow_lazy) {
473 code = ComputeLazyCompile(literal->num_parameters());
474 } else {
475 // The bodies of function literals have not yet been visited by
476 // the AST optimizer/analyzer.
477 if (!Rewriter::Optimize(literal)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100478 return Handle<SharedFunctionInfo>::null();
479 }
480
481 if (literal->scope()->num_parameters() > 0 ||
482 literal->scope()->num_stack_slots()) {
483 AssignedVariablesAnalyzer ava(literal);
484 ava.Analyze();
485 if (ava.HasStackOverflow()) {
486 return Handle<SharedFunctionInfo>::null();
487 }
488 }
489
490 if (FLAG_use_flow_graph) {
491 FlowGraphBuilder builder;
492 FlowGraph* graph = builder.Build(literal);
493 USE(graph);
494
495#ifdef DEBUG
496 if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
497 graph->PrintAsText(literal->name());
498 }
499#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000500 }
501
Leon Clarked91b9f72010-01-27 17:25:45 +0000502 // Generate code and return it. The way that the compilation mode
503 // is controlled by the command-line flags is described in
504 // the static helper function MakeCode.
Andrei Popescu31002712010-02-23 13:46:05 +0000505 CompilationInfo info(literal, script, false);
Leon Clarke4515c472010-02-03 11:58:03 +0000506
Leon Clarked91b9f72010-01-27 17:25:45 +0000507 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
508 bool is_run_once = literal->try_full_codegen();
Steve Blockd0582a62009-12-15 09:54:21 +0000509 bool is_compiled = false;
Leon Clarked91b9f72010-01-27 17:25:45 +0000510 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) {
511 FullCodeGenSyntaxChecker checker;
512 checker.Check(literal);
513 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000514 code = FullCodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000515 is_compiled = true;
516 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000517 } else if (FLAG_always_fast_compiler ||
518 (FLAG_fast_compiler && !is_run_once)) {
Leon Clarke4515c472010-02-03 11:58:03 +0000519 // Since we are not lazily compiling we do not have a receiver to
520 // specialize for.
Leon Clarked91b9f72010-01-27 17:25:45 +0000521 FastCodeGenSyntaxChecker checker;
Andrei Popescu31002712010-02-23 13:46:05 +0000522 checker.Check(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000523 if (checker.has_supported_syntax()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000524 code = FastCodeGenerator::MakeCode(&info);
Leon Clarke4515c472010-02-03 11:58:03 +0000525 is_compiled = true;
526 }
Steve Blockd0582a62009-12-15 09:54:21 +0000527 }
528
529 if (!is_compiled) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000530 // We fall back to the classic V8 code generator.
Andrei Popescu31002712010-02-23 13:46:05 +0000531 code = CodeGenerator::MakeCode(&info);
Steve Blockd0582a62009-12-15 09:54:21 +0000532 }
533
534 // Check for stack-overflow exception.
535 if (code.is_null()) {
536 caller->SetStackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100537 return Handle<SharedFunctionInfo>::null();
Steve Blockd0582a62009-12-15 09:54:21 +0000538 }
539
540 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100541 RecordFunctionCompilation(Logger::FUNCTION_TAG,
542 literal->name(),
543 literal->inferred_name(),
544 literal->start_position(),
545 script,
546 code);
Steve Blockd0582a62009-12-15 09:54:21 +0000547 }
548
Steve Block6ded16b2010-05-10 14:33:55 +0100549 // Create a shared function info object.
550 Handle<SharedFunctionInfo> result =
551 Factory::NewSharedFunctionInfo(literal->name(),
552 literal->materialized_literal_count(),
553 code);
554 SetFunctionInfo(result, literal, false, script);
Steve Blockd0582a62009-12-15 09:54:21 +0000555
556 // Set the expected number of properties for instances and return
557 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100558 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000559 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100560 live_edit_tracker.RecordFunctionInfo(result, literal);
561 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000562}
563
564
565// Sets the function info on a function.
566// The start_position points to the first '(' character after the function name
567// in the full script source. When counting characters in the script source the
568// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100569void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000570 FunctionLiteral* lit,
571 bool is_toplevel,
572 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100573 function_info->set_length(lit->num_parameters());
574 function_info->set_formal_parameter_count(lit->num_parameters());
575 function_info->set_script(*script);
576 function_info->set_function_token_position(lit->function_token_position());
577 function_info->set_start_position(lit->start_position());
578 function_info->set_end_position(lit->end_position());
579 function_info->set_is_expression(lit->is_expression());
580 function_info->set_is_toplevel(is_toplevel);
581 function_info->set_inferred_name(*lit->inferred_name());
582 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000583 lit->has_only_simple_this_property_assignments(),
584 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100585 function_info->set_try_full_codegen(lit->try_full_codegen());
Steve Blockd0582a62009-12-15 09:54:21 +0000586}
587
588
Steve Block6ded16b2010-05-10 14:33:55 +0100589void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
590 Handle<String> name,
591 Handle<String> inferred_name,
592 int start_position,
593 Handle<Script> script,
594 Handle<Code> code) {
Andrei Popescu31002712010-02-23 13:46:05 +0000595 // Log the code generation. If source information is available
596 // include script name and line number. Check explicitly whether
597 // logging is enabled as finding the line number is not free.
Steve Block6ded16b2010-05-10 14:33:55 +0100598 if (Logger::is_logging()
599 || OProfileAgent::is_enabled()
600 || CpuProfiler::is_profiling()) {
Andrei Popescu31002712010-02-23 13:46:05 +0000601 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
602 if (script->name()->IsString()) {
603 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100604 USE(line_num);
605 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
606 *code, *func_name,
607 String::cast(script->name()), line_num));
608 OPROFILE(CreateNativeCodeRegion(*func_name,
609 String::cast(script->name()),
610 line_num,
611 code->instruction_start(),
612 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000613 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100614 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
615 *code, *func_name));
616 OPROFILE(CreateNativeCodeRegion(*func_name,
617 code->instruction_start(),
618 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000619 }
620 }
621}
Andrei Popescu31002712010-02-23 13:46:05 +0000622
Steve Blocka7e24c12009-10-30 11:49:00 +0000623} } // namespace v8::internal